国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Vue中你不知道但卻很實用的黑科技

Heier / 2074人閱讀

摘要:最近數(shù)月一直投身于的開源工作中,完成了大大小小多個組件,在組件化開發(fā)中積累了不少經(jīng)驗。在開發(fā)全局提示組件通知提醒組件對話框組件時,內(nèi)部都是使用來渲染,但卻是來隱式地創(chuàng)建這些實例,這樣我們就可以像標(biāo)題這樣使用,但其內(nèi)部還是通過來管理。

最近數(shù)月一直投身于 iView 的開源工作中,完成了大大小小 30 多個 UI 組件,在 Vue 組件化開發(fā)中積累了不少經(jīng)驗。其中也有很多帶有技巧性和黑科技的組件,這些特性有的是 Vue 文檔中提到但卻容易被忽略的,有的更是沒有寫在文檔里,今天就說說 Vue 組件的高級玩法。

寫在前面

本文所講內(nèi)容大多在 iView 項目中使用,大家可以前往關(guān)注,并結(jié)合源代碼來研究其中的奧妙。項目地址:
https://github.com/iview/iview

目錄

遞歸組件

自定義組件使用 v-model

使用$compile()在指定上下文中手動編譯組件

內(nèi)聯(lián)模板inline-template

隱式創(chuàng)建 Vue 實例

遞歸組件

遞歸組件在文檔中有介紹,只要給組件指定一個 name字段,就可以在該組件遞歸地調(diào)用自己,例如:

var iview = Vue.extend({
  name: "iview",
  template:
    "
" + // 遞歸地調(diào)用它自己 "" + "
" })

這種用法在業(yè)務(wù)中并不常見,在 iView 的級聯(lián)選擇組件中使用了該特性
(https://github.com/iview/iview/tree/master/src/components/cascader)
效果如下圖所示:

圖中每一列是一個組件(caspanel.vue),一開始想到用 v-for來渲染列表,但后面發(fā)現(xiàn)擴(kuò)展性極低,而且隨著功能的豐富,實現(xiàn)起來很困難,處理的邏輯很多,于是改寫成了遞歸組件:

props 比較多,可以忽略,但其中關(guān)鍵的兩個是datasublist,即當(dāng)前列數(shù)據(jù)和子集的數(shù)據(jù),因為預(yù)先不知道有多少下級,所以只需傳遞下級數(shù)據(jù)給組件本身,如果為空時,遞歸就結(jié)束了,Vue 這樣設(shè)計的確很精妙。
注:該方法在 Vue 1.x 和 2.x 中都支持。

自定義組件使用 v-model

我們知道,v-model是在表單類元素上進(jìn)行雙向綁定時使用的,比如:


這時data就是雙向綁定的,輸入的內(nèi)容會實時顯示在頁面上。在 Vue 1.x 中,自定義組件可以使用 props 的.sync雙向綁定,比如:

在 Vue 2.x 中,可以直接在自定義組件上使用 v-model了,比如:

在組件my-component中,通過this.$emit("input")就可以改變data的值了。
雖然 Vue 1.x 中無法這樣使用,但是如果你的組件的模板外層是 inputselecttextarea等支持綁定 v-model 特性的元素,也是可以使用的,比如 my-component 的代碼是:

那也可以使用上面2.x的寫法。

使用$compile()在指定上下文中手動編譯組件

注:該方法是在 Vue 1.x 中的使用介紹,官方文檔并沒有給出該方法的任何說明,不可過多依賴此方法。
使用$compile()方法,可以在任何一個指定的上下文(Vue實例)上手動編譯組件,該方法在 iView 新發(fā)布的表格組件 Table 中有使用:
https://github.com/iview/iview/tree/master/src/components/table/cell.vue
由于表格的列配置是通過一個 Object 傳入 props 的,因此不能像 slot 那樣自動編譯帶有 Vue 代碼的部分,因為傳入的都是字符串,比如:

{
    render (row) {
        return `${row.name}`
    }
}

render函數(shù)最終返回一個字符串,里面含有一個自定義組件 i-button,如果直接用{{{ }}}顯示,i-button 是不會被編譯的,那為了實現(xiàn)在單元格內(nèi)支持渲染自定義組件,就用到了$compile()方法。
比如我們在組件的父級編譯:

// 代碼片段
const template = this.render(this.row);    // 通過上面的render函數(shù)得到字符串
const div = document.createElement("div");
div.innerHTML = template;
this.$parent.$compile(div);    // 在父級上下文編譯組件
this.$el.appendChild(cell);    // 將編譯后的html插入當(dāng)前組件

這樣一來, i-button就被編譯了。
在某些時候使用$compile()確實能帶來益處,不過也會遇到很多問題值得思考:

這樣編譯容易把作用域搞混,所以要知道是在哪個Vue實例上編譯的;

手動編譯后,也需要在合適的時候使用$destroy()手動銷毀;

有時候容易重復(fù)編譯,所以要記得保存當(dāng)前編譯實例的id,這里可以通過 Vue 組件的_uid來唯一標(biāo)識(每個Vue實例都會有一個遞增的id,可以通過this._uid獲取)

另外,Vue 1.x 文檔也有提到另一個$mount()方法,可以實現(xiàn)類似的效果,在 Vue 2.x 文檔中,有 Vue.compile()方法,用于在render函數(shù)中編譯模板字符串,讀者可以結(jié)合來看。

內(nèi)聯(lián)模板inline-template

內(nèi)聯(lián)模板并不是什么新鮮東西,文檔中也有說明,只是平時幾乎用不到,所以也容易忽略。簡短解說,就是把組件的 slot 當(dāng)做這個組件的模板來使用,這樣更為靈活:



    {{ data }}



因為使用了 inline-template 內(nèi)聯(lián)模板,所以子組件不需要