iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
0
Modern Web

Déjà-vu ? 要 Vue 過才知道系列 第 21

Vue 產品列表實作(Part2)

程式設計是可以玩一輩子的東西,你認為呢?

在上一篇我們已經把基本的產品列表渲染出來頁面了,並且可以新增或刪除產品,我們可以發現在新增產品時,出現的時間規格並不是我們要的,這部分我們會留到後續再處理。

我們希望可以利用關鍵字keywords來搜尋產品,在使用者輸入搜尋的 input 文字框時,按下 enter 就會把所有包含有關鍵字的產品渲染到頁面來。在還沒增加搜尋功能之前,我們的列表來源是以v-for來渲染 lists所得到的所有內容,但如果要增加搜尋功能,列表會依搜尋的結果而渲染列表,所以遍歷的目標則是以我們為搜尋寫的方法search(keywords)加上搜尋關鍵字為參數,透過傳參數的方式,傳給search()方法。

在這之前,可以先了解一下以下五個 JavaScript 內建方法forEach(), some(), filter(), findIndex() 的差異,這四個方法都可以對陣列中的每一各元素進行遍歷,執行相關的操作,達到以關鍵字過濾的效果。

方法 作用
Array.prototype.forEach() 遍歷時無法終止。
Array.prototype.some() 透過回傳 true 讓它終止。
Array.prototype.filter() 過濾用,檢查陣列裡面的值是否符合條件,把符合條件的存入成為一個新陣列。
Array.prototype.findIndex() 依據提供的測試函式,尋找陣列中符合的元素,並返回其 index(索引)。如果沒有符合的對象,將返回 -1 。
String.prototype.includes() string.prototype('要包含的字串'),有包含會回傳 true 否則 false。用於判斷一個字符串是否包含在另一個字符串中,根據情況返回 true 或 false。includes() 方法是區分大小寫的。

第一個forEach()是我們常用的,但是無論有無搜尋到我們要的關鍵字,forEach()都會把陣列從頭到尾遍歷一遍。

搜尋結果處理

在以關鍵字keywords搜尋的search()方法裡,透過迴圈遍歷,把符合搜尋關鍵字的資料保存到另一個搜尋結果的列表,再以這個新列表渲染頁面。

來看一下Codepen 的範例

HTML 的部分
先把搜尋的輸入框寫好,並以v-on綁定監聽事件,使用修飾符.enter,在輸入搜尋內容按下 enter 鍵時去呼叫search方法,同時以v-model雙向綁定,並在Date裡初始化資料為空字串''

<div id="app">
      <h3>增加商品</h3>
      <div>
        ID:<input type="text" v-model="id" /> | Name:<input
          type="text"
          v-model="name"
        /><input type="button" value="Add" @click="addItem" /> | Search:<input
          type="text"
          v-model="keywords"
          @keyup.enter="search"
        />
      </div>
      <table>
        <thead>
          <tr>
            <td>Id</td>
            <td>Name</td>
            <td>Time & Date</td>
            <td>Operation</td>
          </tr>
        </thead>
        <tbody>
          <!-- <tr v-for="item in lists" :key="item.id"> -->
          <!-- 以搜尋結果渲染頁面 -->
          <tr v-for="item in search(keywords)" :key="item.id">
            <td>{{ item.id }}</td>
            <td v-text="item.name"></td>
            <td>{{ item.timeDate}}</td>
            <td><a href="" @click.prevent="deleteItem(item.id)">Delete</a></td>
          </tr>
        </tbody>
      </table>
    </div>

當搜尋時沒有給字符串也就等於空的字符串''但為什麼空字符串卻會顯示所有的列表內容?因為我們使用indexOf()時,如果給''會回傳 0,indexOf()回傳-1 表示沒找到,也就是說''空字符串是包含在有找到目標之內的,也因此可以顯示所有內容。

JavaScript 的部分

const vm = new Vue({
  el: '#app',
  data: {
    id: '',
    name: '',
    keywords: '',
    lists: [
      {
        id: 1,
        name: 'Vue',
        timeData: new Date(),
      },
      {
        id: 2,
        name: 'React',
        timeData: new Date(),
      },
      {
        id: 3,
        name: 'JavaScript',
        timeData: new Date(),
      },
    ],
  },
  methods: {
    addItem: function () {
      var item = { id: this.id, name: this.name, timeDate: new Date() };
      console.log(item);
      this.lists.push(item);
      this.id = '';
      this.name = '';
      // this.id=this.name=''
    },
    deleteItem: function (id) {
      // 使用some()來循環,找到會回傳true並立即中止
      // 用迴圈去找index
      this.lists.some((item, i) => {
        if (item.id == id) {
          this.lists.splice(i, 1);
          return true;
        }
      });
      // 另一種抓index的方式
      // let index = this.lists.findIndex((item) => {
      //   if (item.id == id) return true;
      // });
      // console.log(index);
      // this.splice(index. 1)
    },
    // 搜尋方法
    search: function (keywords) {
      // 第一種寫法:將搜尋結果存在searchLists ,遍歷完之後再回傳新資料列表
      // let searchLists = [];
      // this.lists.forEach((item) => {
      //   if (item.name.indexOf(keywords) != -1) {
      //     searchLists.push(item);
      //   }
      //   return searchLists;
      // });
      // 第一種寫法:直接將結果回傳
      return this.lists.filter((item) => {
        // if(item.name.indexOF(keywords != -1))
        if (item.name.includes(keywords)) {
          return item;
        }
      });
    },
  },
});

利用 JavaScript 不同的方法特性,可以很簡潔地寫出搜尋的功能,是不是很方便!

每日一句法文有益身心:Il fait froid ! --> 以.飛.發! --> 好冷喔!是冷的。


上一篇
Vue.js 產品列表實作 (Part1)
下一篇
Vue 產品列表實作(Part3)
系列文
Déjà-vu ? 要 Vue 過才知道30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言