iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 23
0
Modern Web

實作小範例入門 Vue & Vuex 2.0系列 第 23

vue & vuex 23 - Open Data - III (搜尋條件、select option、v-else、watch)

  • 分享至 

  • xImage
  •  

vue & vuex 23 - Open Data

今天目標:

  1. 加上地區搜尋。
  2. 加上關鍵字搜尋。

HTML select option 下拉式選單

在下拉式選單中 select tag 上使用 v-model option 的選擇將會是 model 的 value

ex:

<h3>晚餐吃什麼?</h3>
<select v-model="dinner">
  <option value='A'>1、帕瑪森和牛咖喱飯</option>
  <option value='B'>2、石安松板丼飯</option>
  <option value='C'>3、炙燒戰斧拉麵</option>
</select>

// 如果選擇: 3、炙燒戰斧拉麵
// dinner: 'C'

範例中我們使用在 搜尋高雄地區選項 ,因此我們在 option 的顯示文字value 中都綁定上地區值。

而預設的 全部(all) 就手動加個 tag

<select id="searchRegion"class="form-control" v-model="searchRegion">
  <option value='all'>全部</option>
  <option v-for="option in regionOption" :value="option">
    {{ option }}
  </option>
</select>

Vue Option watch

watch 用於監聽 model,

key 為 model name

匿名參數將會是 model value

以範例來說,當 select 改變時,會雙向綁定 option value

因此我們監聽 searchRegion(預設是 all)

將改變的 value 發出 action 改變 state

state 改變 getter 將會重新計算,因此我們得到新的搜尋結果。

watch: {
  searchRegion (val) {
    this.$store.dispatch('opendataSearchRegion', val);
  }
},

這樣的功能在 select tag 使用 @change 事件,一樣可以做到同樣功能 Performance 也會好一點點。

Vue v-else, v-else-if

Vue v-else, v-else-if
這是 if 家族系列 directive 使用如程式中的 if else 條件判斷,還滿直覺的知道幾組 tag 是同一個 group !

今天我們把它用在搜尋結果顯示上,

如果無搜尋結果會顯示一段文字告訴使用者找不到相關內容,

如果有會顯示結果列表與數量。

如果使用系列會建議把這些 directive 放在第一個,否則未來維護的同事會.. OOXX#%!
不放在第一個不容易看呀!


搜尋功能實作:

搜尋功能的實現,設計在 getter 裡面,改變取得資料的結果,而原始資料不動,應該是最理想的,最後做了一個比較直覺的函式,大家參考一下囉..

將原始資料儲存在另一變數下_opendata,出現搜尋條件的時候,使用 filter 過濾條件,回傳結果。

UI 只要判斷結果的長度,0 = 搜尋不到。

region

比較簡單使用 filter 判斷每筆資料的 ZipName_ 既可。

keyword

這邊打算可以搜尋每筆資料所有的內容,後來想到把每個 item 用 JSON.stringify 變成 String

在與 keyword 做判斷indexOf( state.search.keyword ) != -1 既可。

store/modules/opendata.js

const getters = {
  getOpen1999: state => {
    let _opendata = state.opendata;

    if (state.search.region !== 'all') {
      _opendata = _opendata.filter( item => (item.ZipName_ === state.search.region) );
    }
    if (state.search.keyword !== '') {
      _opendata = _opendata.filter( item => (JSON.stringify( item ).indexOf( state.search.keyword ) != -1) );
    }

    return _opendata;
  }
}

page/open1999.vue

<template>
  <div class="container">
    <nav class="navbar navbar-default">
	  <!-- 略.. -->
      <div class="container-fluid">
        <div class="navbar-form navbar-left">
          <div class="form-group">
            <label for="searchRegion">搜尋地區:</label>
			<!-- select 使用 v-model 會與 option value 綁定 -->
            <select id="searchRegion"class="form-control" v-model="searchRegion">
              <option value='all'>全部</option>
              <option v-for="option in regionOption" :value="option">
                {{ option }}
              </option>
            </select>
          </div>
          <div class="input-group">
            <input 
              type="text"
              class="form-control"
              placeholder="Search"
              v-model="searchKeyword"
              @keyup.enter="handleWorkSearch">
            <div class="input-group-btn">
              <button class="btn btn-default" @click="handleWorkSearch">
                <i class="glyphicon glyphicon-search"></i>
              </button>
            </div>
          </div>
        </div>

      </div>
    </nav>
  
    <hr>
    
<!-- if -->
    <div v-if="opendate.length===0" class="alert alert-info" role="alert">
      很抱歉!找不到您要的資訊。
    </div>
<!-- else -->
    <div v-else>
      <div class="alert alert-success" role="alert">
        總共查到:{{ opendate.length }} 筆資料。
      </div>
      <!-- card 略.. -->
    </div>

  </div>
</template>

<script>
import { mapGetters, mapActions } from 'vuex';

export default {
  data() {
    return {
      searchRegion: 'all',
      searchKeyword: '',
    }
  },
  created () {
    // created Hook 發出 action call API
    this.$store.dispatch('open1999');
  },
  computed: mapGetters({
    opendate: 'getOpen1999',
    regionOption: 'getRegionOption'
  }),
  methods: {
    ...mapActions([
    ]),
    getGoogleMap(address) {
      // Template literals
      // ${裡面可以放變數}
      // ES5: "https://www.google.com/maps/place/" + address;
      return `https://www.google.com/maps/place/${address}`;
    },
    handleWorkSearch () {
      this.$store.dispatch('opendataSearchKeyword', this.searchKeyword);
    },
  },
  watch: {
    searchRegion (val) {
      this.$store.dispatch('opendataSearchRegion', val);
    }
  },
};
</script>

github 完整範例:

實作小範例入門 Vue & Vuex 2.0 - github 完整範例

使用 git checkout 切換每天範例。


上一篇
vue & vuex 22 - Open Data - II (高雄市 opendata、加上過場 loading 效果)
下一篇
vue & vuex 24 - Login - I (action Promise、rouetr change)
系列文
實作小範例入門 Vue & Vuex 2.030
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言