1. 程式人生 > >Vue可複用性&組合

Vue可複用性&組合

 

二、自定義指令

除了核心功能預設內建的指令(v-model和v-show),Vue也允許註冊自定義指令。在Vue2.0中,程式碼複用和抽象的主要形式是元件,然而有的情況下,你仍然需要對普通DOM元素進行底層操作,這時會用到自定義指令。如當頁面載入時,輸入框將獲得焦點,只要你在開啟這個頁面後還沒點選過任何內容,這個輸入框就應當還是處於聚焦狀態。

// 如果不使用指令,就需要操作DOM元素,這是vue不提倡的
document.getElementById('search').focus();

指令的名稱:定義時,指令的名稱不需要加v-字首;呼叫時,必須加v-字首。

一個物件:包含指令相關的函式,這些函式在特定的階段執行相關的操作。

註冊一個全域性自定義指令。

Vue.directive('focus',{
  // 當被繫結的元素插入到DOM中時
  inserted:function(el){
    // 聚焦元素,一個元素只有插入DOM之後,才能獲取焦點
    el.focus()
  }
})

註冊區域性指令,元件中接受一個directives的選項。

directives:{
  focus:{
    inserted:function(el){
      el.focus()
    }
  }
}

然後可以在模板中任何元素上使用新的v-focus屬性。

<input v-focus>

1、鉤子函式

一個指令定義物件可以提供如下幾個鉤子函式(均為可選):

bind:只調用一次,指令第一次繫結到元素時呼叫。在這裡可以進行一次性的初始化設定,如用於繫結樣式,只要通過指令繫結給了元素,不管該元素有沒有被插入到頁面中去,肯定有了一個內聯的樣式。

inserted:只調用一次,被繫結元素插入父節點(DOM樹中)時呼叫(僅保證父節點存在,但不一定已被插入文件中)。可繫結和JS行為有關的操作,防止JS行為不生效。

update:可能呼叫多次,所在元件的VNode更新時呼叫,但是可能發生在其子 VNode 更新之前。指令的值可能發生了改變,也可能沒有。但是你可以通過比較更新前後的值來忽略不必要的模板更新。

componentUpdated:指令所在元件的VNode及其子VNode全部更新後呼叫。

unbind:只調用一次,指令與元素解綁時呼叫。

2、鉤子函式的引數

el:指令所繫結的元素,是一個原生JS物件,可直接操作DOM。

binding:一個物件,包含以下屬性:
    name:指令名,不包括v-字首。
    value:指令的繫結值,如v-my-directive="1+1"中,繫結值為2。
    expression:繫結值的字串形式,如v-my-directive="1+1"中,表示式為1+1。
    oldValue:指令繫結的前一個值,僅在update和componentUpdated鉤子中可用,無論值是否改變都可用。
    arg:傳遞指令的引數,如v-my-directive:foo中,引數為foo。
    modifiers:一個包含修飾符的物件,如v-my-directive:foo.bar中,修飾符物件為{foo:true,bar:true}。

vnode:Vue編譯生成的虛擬節點。

oldVnode:上一個虛擬節點,僅在update和componentUpdated鉤子中可用

除了el之外,其它引數都應該是隻讀的,切勿進行修改。如果需要在鉤子之間共享資料,建議通過元素的dataset來進行。

3、函式簡寫

自定義指令的簡寫形式,等同於定義了 bind 和 update 兩個鉤子函式,而不關心其它的鉤子。

Vue.directive('color-swatch', function (el, binding) {
  el.style.backgroundColor = binding.value
})

 

五、過濾器

Vue.js允許自定義過濾器,可被用於一些常見的文字格式化。過濾器可以用在兩個地方:雙花括號插值和v-bind表示式(後者從 2.1.0+開始支援)。過濾器應該被新增在JavaScript表示式的尾部,由“管道”符號指示。過濾器呼叫時的格式:

<!-- 在雙花括號中 -->
{{ message | 過濾器的名稱 }}
<!-- 在`v-bind`中 -->
<div v-bind:id="rawId | formatId"></div>

過濾器的定義語法:

(1)在一個元件的選項中定義本地的過濾器

filters:{
  過濾器名稱:function(data){
    return data+'123';
  }
}

(2)在建立Vue例項之前定義全域性過濾器,所有vm例項共享

Vue.filter('過濾器名稱',function(data){
  return data+'123';
})

var vm=new Vue({
  // ...
});

{{ message | filterA | filterB }}  過濾器可以串聯,過濾器函式總接收表示式的值 (之前的操作鏈的結果) 作為第一個引數。

{{ message | filterA('data', arg1, arg2) }}  過濾器可以有多個引數,第一個引數是過濾器管道符前面傳來的資料。

<body>
  <div id="app">
    <p>{{msg | filterA('無敵','可愛') | filterB}}</p>
  </div>
  <script>
    Vue.filter('filterA',function(msg,arg1,arg2){
      return msg.replace(/無情/g,arg1+arg2);
    });

    Vue.filter('filterB',function(msg){
      return '===='+msg+'====';
    })
    
    var vm=new Vue({
      el:'#app',
      data:{
        msg:'你無情,你殘酷! 那你就不無情,不殘酷!? 我哪裡無情,哪裡殘酷!?'
      },
      filters:{
        filterA:function(msg,arg1,arg2){
          return msg.replace(/殘酷/g,arg1+arg2);
        }
      }
    });
  </script>
</body>

當有區域性和全域性兩個名稱相同的過濾器時,以就近原則進行呼叫,即區域性過濾器優先於全域性過濾器。