Vue.js 組件庫事件系統設計

咱們拿 input-number 爲例:app

@v-on 指令的簡寫,用來綁定事件監聽器iview

<InputNumber @on-change="change" :max="10" :min="1" v-model="value1">
</InputNumber>

咱們使用組件的時候,會註冊了一個自定義的事件:函數

methods: {
    change (v) {
        console.log(v)
    }
}

在組件內部觸發的方式也很簡單:this

調用了 $emit 來觸發當前實例上的事件,事件名爲 on-change
this.$emit('on-change', val);

那思路來了,若是 InputNumber 外層嵌套在了某一個 FormItem 組件裏面,事件之間的互相調用也是相似的,只是多了個假設:spa

嵌套關係,可能有多級父子

elementiview 多設計了一個 mixins,裏面提供了一個方法:dispatch設計

它接受 3 個參數:code

  • componentName 組件名
  • eventName 自定義事件名稱
  • params 事件傳遞的參數
dispatch(componentName, eventName, params) {
}

好比相似 input-number,不少這種表單內嵌的組件,都會設計和 FormItem 的互動:component

this.dispatch('FormItem', 'on-form-change', val);

咱們在設計 FormItem組件的時候,注意:orm

export default {
    name: 'FormItem'
}

而後註冊一個自定義事件,方式也是同樣的:事件

<Form-item @on-form-change="test">
</Form-item>

咱們來看一下 dispatch 函數的內部:

思路是一層一層往上找父元素:

  • $parent -- 父實例
  • $root -- 組件樹的根 Vue 實例
var parent = this.$parent || this.$root;

獲取父組件的 name:

var name = parent.$options.name;

開始循環判斷:

while (parent && (!name || name !== componentName)) {
    // ...
}

好比上面的input-number 內部調用了 dispatch,傳入了參數,就是一直找父元素 nameFormItem

在 while 的內部:

接着找它的父示例,而後獲取 name

parent = parent.$parent;
if (parent) {
    name = parent.$options.name;
}

最終若是找到了:

和最開始觸發自定義事件是同樣的:$emit

if (parent) {
    parent.$emit.apply(parent, [eventName].concat(params));
}
相關文章
相關標籤/搜索