回覆列表
  • 1 # 使用者6035328607251

    通常我們會在元件裡的 template 屬性定義模板,或者是在 *.vue 檔案裡的 template 標籤裡寫模板。但是有時候會需要動態生成模板的需求,例如讓使用者自定義元件模板,或者設定元件的佈局。 例如要做一個類 select 的元件,使用者傳入 options 資料,透過 value prop 獲取選中值,最基本的原型如下。 Vue.component("XSelect", { template: `

    `, props: ["value","options"] }) 如果此時需要增加一個 API 支援讓使用者自定義 option 部分的模板。此處用 slot 並不能解決問題。 透過 $options.template 修改 透過列印元件物件可以獲得一個資訊,在 $options 裡定義了一個 template 屬性,寫在 template 標籤裡的模板,最終編譯後也會在 $options.template 裡。透過文件的生命週期 可以得知,在 created 的時候, 例項已經結束解析選項, 但是還沒有開始 DOM 編譯 也就是說,如果使用者透過 prop 的資料我們可以獲得,但是模板其實還沒有渲染成 DOM。經過測試,在 created 修改 this.$options.template 是可以改變最終生成的 DOM 的,同時也能拿到 props 的內容。 那麼我們可以修改下程式碼,使其支援自定義模板 Vue.component("XSelect", { props: [ "value", "options", { name: "template", default:"" } ], created() { varoptionTpl =this.template this.$options.template =` ${optionTpl} ` } }) 使用者使用是就可以傳入模板了 可能存在的問題 我們知道 Vue 在內部幫我們做了許多最佳化,但是在這裡可能會由於某些最佳化導致動態拼接的模板無法渲染成功。例如這裡我們不使用 v-for 而是手工遍歷 options 生成需要的 HTML consttpl = options.map(opt =>`${this.optionTpl}`) this.$options.template =` ${tpl} ` 這裡會導致一個 BUG,如果一個頁面有多個 x-select 元件,並且 options 長度不一樣,會導致長的 options 的元件後面幾個選項渲染不出來。究其原因是 Vue 會幫我們快取模板編譯結果。翻看程式碼可以找到 vue/src/instance/internal/lifecycle.js 裡有做最佳化,同時提供的 _linkerCachable 本意是給 內聯模板 使用。我們可以透過設定 this.$options._linkerCachable = false 達到我們的目的。 這樣我們就可以開發讓使用者自定義佈局的元件了,使用者傳入佈局引數,透過手工拼接模板,設定了 _linkerCachable = false 也不會被快取。 透過 $options.partials 動態新增 partial 使用 partials 也能達到新增自定義模板的目的,但是通常的做法是要全域性註冊 partial,這麼做並不優雅。 vue-strap 就是這麼做的。如果重名了會被覆蓋(初次渲染不會,但是資料更新重新渲染 DOM 時就會被覆蓋)。 透過文件我們知道可以在元件內部透過 partials 屬性註冊區域性的 partial,因此自然而然也可以在 this.$options.partials 去動態添加了。

  • 中秋節和大豐收的關聯?
  • 春毛豆後期的膨大施肥方法?