iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 22
1
Modern Web

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

Vue 產品列表實作(Part3)

  • 分享至 

  • xImage
  •  

如果人有選擇,真的只會選擇容易走的路或容易成為的自己嗎?不見得吧!?

有時候我們希望使用者在進入頁面時,會自動的將滑鼠停留在某個輸入框,例如登入頁面或是搜尋頁面,這部分在實做 Vue 的時候改怎麼處理呢?我們將以自定義 Vue 的全域指令 Vue.directive 來完成。

接著我們希望在某些輸入框輸入內容時樣式會不一樣,這點除了在樣式上可以辦到,也可以用自定義過濾器捯到一樣的效果。

如果希望頁面有時間戳的顯示,以往我們會以new Date()會來取得當下的時間,但是所取到的卻不是我們希望的格式,這時會想到的處理方式是另外載入「處理時間」的套件,列如moment.js來管理時間顯示的問題,但今年九月中moment.js官網公布了不再維護的消息。其實替代方案 Vue 是做的到的,只要利用「自定義過濾器」的特性,就可辦到。

在前幾篇有提到,過濾器的功能是要對顯示的資料進行特定的格式化後再顯示,且過濾器並不會去改變原本的資料,而是產生一個新的對應的資料格式。

自定義過濾器可以定義為全域或是局部,我們今天實做的以全域為主,這樣的複用性比較高,但如果全域的自定義過氯氣和局部的同名,那麼會以就近為原則,優先權是局部的過濾器。

先來看一下Codepen的範例。

使用自訂義指令來改變輸入框對焦

在輸入框的元素上,我們加上了v-focus(自定義指令)和v-color(自定義過濾器)的屬性。

Search:<input
          type="text"
          v-model="keywords"
          @keyup.enter="search"
          id="search"
          v-focus
          v-color="'blue'"
        />

我們所定義的指令名為focus,關於自定義指令的說明可以看前幾天的Vue 自定義指令 Custom Directives
定義全域指令的語法為 Vue.directive('指令名',物件),可以用原生的focus()掛載到 Vue 的 inserted hook 鉤子上,在以下的 hook 鉤子函式中,第一個參數永遠都是 el,表示被綁定了指令的那個元素,這個 el 參數是一個原生的 JS 物件。inserted hook 的時間點是當我們有插入值時,才會執行。

focus()的 JS 原生寫法為 document.querySelector('#search').focus();

HTMLElement.focus() - Web API 接口參考 | MDN

Vue.directive('focus', {
  bind: function (el) {
    // 綁定 bind 時:每當指令綁定到元素上時,會立刻執行這個bind韓式,且只執行一次。
    // 在元素剛被綁定的時候,還沒有插入到DOM中去,這時呼叫focus方法不會執行,因為一個元素只有插入(inserted)DOM之後才會有聚焦效果。
  },
  inserted: function (el) {
    // 插入值時:inserted 表示元素插入到DOM中時會執行inserted 函式。(觸發一次)
    // 和JS有關的操作,最好在inserted的階段中去執行,防止JS行為不生效。
    el.focus();
  },
});

使用過濾器來格式化時間規格和樣式

由於我們希望是在新增產品時就增加顯示時間,所以我們會以new Date()會來取得當下的時間,再用自定義過濾器來改變時間格式。
過濾器使用的語法為:

// 使用過濾器
<div>{{ 綁定的元素 | 自定義過濾器名稱 }}</div>
<div>{{ myData | filterName(arg) }}</div>

新增全域過濾器的語法為:Vue.filter('自定義過濾器名稱', callback 函式)
把年月份與時分秒一一取出處理,在放到各自代表的變數裡,確認時間格式皆為小寫,並回傳我們希望的格式。

// 全域時間過濾器
Vue.filter('showDateTime', (dateNow, pattern = '') => {
  // 根據給的時間字串,得到特定的時間
  let dateTime = new Date(dateNow);
  // yyyy/mm/dd
  let year = dateTime.getFullYear();
  let month = (dateTime.getMonth() + 1).toString().padStart(2, '0');
  let day = dateTime.getDate().toString().padStart(2, '0');

  // 讓時間格式皆為小寫
  if (pattern.toLowerCase() === 'dd.mm.yyyy') {
    return `${day}.${month}.${year}`;
  } else {
    let hour = dateTime.getHours().toString().padStart(2, '0');
    let minute = dateTime.getMinutes().toString().padStart(2, '0');
    let second = dateTime.getSeconds().toString().padStart(2, '0');
    return `${day}.${month}.${year} | ${hour}:${minute}:${second}`;
  }
});

我們可以使用自定義過濾器來改變某元素的樣式,,一樣會使用到生命週期的鉤子bind來綁定執行函式的時機。

// 自定義改變字體顏色
Vue.directive('color', {
  bind: function (el, binding) {
    console.log(binding.value);
    console.log(binding.expression);
    el.style.color = binding.value;
  },
});

每日一句法文有益身心:C'est mignon ! --> say.瞇.扭! --> 好可愛喔。


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

尚未有邦友留言

立即登入留言