vue.js 可複用性&組合- 混合 - 自定義指令 - 插件 基礎

vue的複用性與組合

混合

混合 (mixins) 是一種分發 Vue 組件中可複用功能的很是靈活的方式。混合對象能夠包含任意組件選項。以組件使用混合對象時,全部混合對象的選項將被混入該組件自己的選項。javascript

Vue.extend()用以建立沒有掛載的的子類,可使用該子累建立多個實例
[javascript] view plain copy

var Profile = Vue.extend({  
             template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',  
             data: function () {  
               return {  
                 firstName: 'Walter',  
                 lastName: 'White',  
                 alias: 'Heisenberg'  
               }  
             }  
           })  
           // 建立 Profile 實例,並掛載到一個元素上。  
           new Profile().$mount('#mount-point')
mixins 將兩個的對象的混合爲一個數組,彼此均可以被調用,下面爲演示代碼及其結果

當對象鍵值對 鍵名衝突時,保留非mixin對象的鍵值對
<div id="app"></div>  
       <script>  
           var myMixin={  
               template:'<h1>holle mixin</h1>',  
               methods:{  
                   hello:function(){  
                       console.log('this is mixin')  
                   },  
                   say:function(){  
                       console.log('I am mixin')  
                   }  
               }  
           };  
  
           var Component=Vue.extend({  
               mixins:[myMixin],  
               methods:{  
                   lsit:function(){  
                       console.log('I am lsit')  
                   },  
                   say:function(){  
                        console.log('I am mixin say')  
                   }  
               }  
  
           });  
           var newcom=new Component().$mount('#app')  
           newcom.hello();  
           newcom.lsit();  
           newcom.say();  
       </script>

全局混合

也能夠全局註冊混合對象。 注意使用! 一旦使用全局混合對象,將會影響到 全部 以後建立的 Vue 實例。使用恰當時,能夠爲自定義對象注入處理邏輯。html

// 爲自定義的選項 'myOption' 注入一個處理器。
Vue.mixin({
  created: function () {
    var myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})
new Vue({
  myOption: 'hello!'
})
// => "hello!"

謹慎使用全局混合對象,由於會影響到每一個單首創建的 Vue 實例(包括第三方模板)。大多數狀況下,只應當應用於自定義選項,就像上面示例同樣。 也能夠將其用做 Plugins 以免產生重複應用vue

自定義指令

Vue.js 容許你註冊自定義指令,實質上是讓你教 Vue 一些新技巧:怎樣將數據的變化映射到 DOM 的行爲。你可使用Vue.directive(id, definition)的方法傳入指令id和定義對象來註冊一個全局自定義指令。定義對象須要提供一些鉤子函數(所有可選):java

  • bind: 僅調用一次,當指令第一次綁定元素的時候。node

  • update: 第一次是緊跟在 bind 以後調用,得到的參數是綁定的初始值;之後每當綁定的值發生變化就會被調用,得到新值與舊值兩個參數。webpack

  • unbind:僅調用一次,當指令解綁元素的時候。web

例子:vue-router

Vue.directive('my-directive', {
  bind: function () {
    // 作綁定的準備工做
    // 好比添加事件監聽器,或是其餘只須要執行一次的複雜操做
  },
  update: function (newValue, oldValue) {
    // 根據得到的新值執行對應的更新
    // 對於初始值也會被調用一次
  },
  unbind: function () {
    // 作清理工做
    // 好比移除在 bind() 中添加的事件監聽器
  }
})
一旦註冊好自定義指令,你就能夠在 Vue.js 模板中像這樣來使用它(須要添加 Vue.js 的指令前綴,默認爲 v-):
<div v-my-directive="someValue"></div>
若是你只須要 update 函數,你能夠只傳入一個函數,而不用傳定義對象:
Vue.directive('my-directive', function (value) {
  // 這個函數會被做爲 update() 函數使用
})

全部的鉤子函數會被複制到實際的指令對象中,而這個指令對象將會是全部鉤子函數的this
上下文環境。指令對象上暴露了一些有用的公開屬性:express

  • el: 指令綁定的元素數組

  • vm: 擁有該指令的上下文 ViewModel

  • expression: 指令的表達式,不包括參數和過濾器

  • arg: 指令的參數

  • raw: 未被解析的原始表達式

  • name: 不帶前綴的指令名

這些屬性是隻讀的,不要修改它們。你也能夠給指令對象附加自定義的屬性,可是注意不要覆蓋已有的內部屬性。

鉤子函數

指令定義函數提供了幾個鉤子函數(可選):

* bind: 只調用一次,指令第一次綁定到元素時調用,用這個鉤子函數能夠定義一個在綁定時執行一次的初始化動做。

* inserted: 被綁定元素插入父節點時調用(父節點存在便可調用,沒必要存在於 document 中)。

* update: 所在組件的 VNode 更新時調用,可是可能發生在其孩子的 VNode 更新以前。指令的值可能發生了改變也可能沒有。可是你能夠經過比較更新先後的值來忽略沒必要要的模板更新 (詳細的鉤子函數參數見下)。

* componentUpdated: 所在組件的 VNode 及其孩子的 VNode 所有更新時調用。

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

* 接下來咱們來看一下鉤子函數的參數 (包括 el,binding,vnode,oldVnode) 。

鉤子函數參數

鉤子函數被賦予瞭如下參數:

*el: 指令所綁定的元素,能夠用來直接操做 DOM 。
* binding: 一個對象,包含如下屬性:

* name: 指令名,不包括 v- 前綴。
* value: 指令的綁定值, 例如: v-my-directive="1 + 1", value 的值是 2。
* oldValue: 指令綁定的前一個值,僅在 update 和 componentUpdated 鉤子中可用。不管值是否改變均可用。
* expression: 綁定值的字符串形式。 例如 v-my-directive="1 + 1" , expression 的值是 "1 + 1"。
* arg: 傳給指令的參數。例如 v-my-directive:foo, arg 的值是 "foo"。
* modifiers: 一個包含修飾符的對象。 例如: v-my-directive.foo.bar, 修飾符對象 modifiers 的值是 { foo: true, bar: true }。
* vnode: Vue 編譯生成的虛擬節點,查閱 VNode API 瞭解更多詳情。
* oldVnode: 上一個虛擬節點,僅在 update 和 componentUpdated 鉤子中可用。
  • 除了 el 以外,其它參數都應該是隻讀的,儘可能不要修改他們。若是須要在鉤子之間共享數據,建議經過元素的 dataset 來進行。

多重從句

同一個特性內部,逗號分隔的多個從句將被綁定爲多個指令實例。在下面的例子中,指令會被建立和調用兩次:

<div v-demo="color: 'white', text: 'hello!'"></div>

若是想要用單個指令實例處理多個參數,能夠利用字面量對象做爲表達式:

<div v-demo="{color: 'white', text: 'hello!'}"></div>

    Vue.directive('demo', function (value) {
    
          console.log(value) // Object {color: 'white', text: 'hello!'}
})

字面指令

若是在建立自定義指令的時候傳入 isLiteral: true ,那麼特性值就會被當作直接字符串,並被賦值給該指令的 expression。字面指令不會試圖創建數據監視。

例子:

<div v-literal-dir="foo"></div>
Vue.directive('literal-dir', {
      isLiteral: true,
      bind: function () {
        console.log(this.expression) // 'foo'
      }
    })

動態字面指令

然而,在字面指令含有 Mustache 標籤的情形下,指令的行爲以下:

指令實例會有一個屬性,this._isDynamicLiteral被設爲true;

若是沒有提供update函數,Mustache 表達式只會被求值一次,並將該值賦給this.expression。不會對錶達式進行數據監視。

若是提供了update函數,指令將會爲表達式創建一個數據監視,而且在計算結果變化的時候調用update。

雙向指令

若是你的指令想向 Vue 實例寫回數據,你須要傳入 twoWay: true 。該選項容許在指令中使用
this.set(value)。

Vue.directive('example', {
  twoWay: true,
  bind: function () {
    this.handler = function () {
      // 把數據寫回 vm
      // 若是指令這樣綁定 v-example="a.b.c",
      // 這裏將會給 `vm.a.b.c` 賦值
      this.set(this.el.value)
    }.bind(this)
    this.el.addEventListener('input', this.handler)
  },
  unbind: function () {
    this.el.removeEventListener('input', this.handler)
  }
})

內聯語句

傳入 acceptStatement: true 可讓自定義指令像 v-on 同樣接受內聯語句:

<div v-my-directive="a++"></div>
Vue.directive('my-directive', {
  acceptStatement: true,
  update: function (fn) {
    // the passed in value is a function which when called,
    // will execute the "a++" statement in the owner vm's
    // scope.
  }
})

可是請明智地使用此功能,由於一般咱們但願避免在模板中產生反作用。

元素指令

有時候,咱們可能想要咱們的指令能夠以自定義元素的形式被使用,而不是做爲一個特性。這與 Angular 的 E 類指令的概念很是類似。元素指令能夠看作是一個輕量的自定義組件(後面會講到)。你能夠像下面這樣註冊一個自定義的元素指令:

Vue.elementDirective('my-directive', {
  // 和普通指令的 API 一致
  bind: function () {
    // 對 this.el 進行操做...
  }
})

使用時咱們再也不用這樣的寫法:

<div v-my-directive></div>

而是寫成:

<my-directive></my-directive>

元素指令不能接受參數或表達式,可是它能夠讀取元素的特性,來決定它的行爲。與一般的指令有個很大的不一樣,元素指令是終結性的,這意味着,一旦 Vue 遇到一個元素指令,它將跳過對該元素和其子元素的編譯 - 即只有該元素指令自己能夠操做該元素及其子元素。

插件

開發插件

  • 插件一般會爲Vue添加全局功能。插件的範圍沒有限制——通常有下面幾種:

  • 添加全局方法或者屬性,如: vue-custom-element

  • 添加全局資源:指令/過濾器/過渡等,如 vue-touch

  • 經過全局 mixin 方法添加一些組件選項,如: vue-router

  • 添加 Vue 實例方法,經過把它們添加到 Vue.prototype 上實現。

  • 一個庫,提供本身的 API,同時提供上面提到的一個或多個功能,如 vue-router

Vue.js 的插件應當有一個公開方法 install 。這個方法的第一個參數是 Vue 構造器 , 第二個參數是一個可選的選項對象:

MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或屬性
  Vue.myGlobalMethod = function () {
    // 邏輯...
  }
  // 2. 添加全局資源
  Vue.directive('my-directive', {
    bind (el, binding, vnode, oldVnode) {
      // 邏輯...
    }
    ...
  })
  // 3. 注入組件
  Vue.mixin({
    created: function () {
      // 邏輯...
    }
    ...
  })
  // 4. 添加實例方法
  Vue.prototype.$myMethod = function (methodOptions) {
    // 邏輯...
  }
}

使用插件

經過全局方法 Vue.use() 使用插件:
// 調用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)
也能夠傳入一個選項對象:
Vue.use(MyPlugin, { someOption: true })

Vue.use 會自動阻止註冊相同插件屢次,屆時只會註冊一次該插件。

Vue.js 官方提供的一些插件 (例如 vue-router) 在檢測到 Vue 是可訪問的全局變量時會自動調用 Vue.use()。

然而在例如 CommonJS 的模塊環境中,你應該始終顯式地調用 Vue.use():

// 用 Browserify 或 webpack 提供的 CommonJS 模塊環境時
var Vue = require('vue')
var VueRouter = require('vue-router')
// 不要忘了調用此方法
Vue.use(VueRouter)

本章已完結 (待續 ……)

文章來自 : 搜狗搜到你
                        
                        我的網站 :huai.ye2012vip@qq.com
相關文章
相關標籤/搜索