" />

最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Vue 動(dòng)態(tài)添加模板的幾種方法

 更新時(shí)間:2017年04月25日 15:33:09   作者:稀土掘金  
本篇文章主要介紹了詳解Vue 動(dòng)態(tài)添加模板的幾種方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

以下方法只適用于 Vue1.0 版本,推薦系數(shù)由高到低排列。

通常我們會(huì)在組件里的 template 屬性定義模板,或者是在 *.vue 文件里的 template 標(biāo)簽里寫模板。但是有時(shí)候會(huì)需要?jiǎng)討B(tài)生成模板的需求,例如讓用戶自定義組件模板,或者設(shè)置組件的布局。

例如要做一個(gè)類 select 的組件,用戶傳入 options 數(shù)據(jù),通過 value prop 獲取選中值,最基本的原型如下。

Vue.component('XSelect', {
 template: `
 <div class="select">
 <input :value="value" readonly />
 <div
 class="option"
 v-for="option in options"
 @click="value = option.value">
 <span v-text="option.label"></span>
 </div>
 </div>`,

 props: ['value','options']
})

如果此時(shí)需要增加一個(gè) API 支持讓用戶自定義 option 部分的模板。此處用 slot 并不能解決問題。

通過 $options.template 修改

通過打印組件對(duì)象可以獲得一個(gè)信息,在 $options 里定義了一個(gè) template 屬性,寫在 template 標(biāo)簽里的模板,最終編譯后也會(huì)在 $options.template 里。通過文檔的生命周期 可以得知,在 created 的時(shí)候, 實(shí)例已經(jīng)結(jié)束解析選項(xiàng), 但是還沒有開始 DOM 編譯 也就是說,如果用戶通過 prop 的數(shù)據(jù)我們可以獲得,但是模板其實(shí)還沒有渲染成 DOM。經(jīng)過測(cè)試,在 created 修改 this.$options.template 是可以改變最終生成的 DOM 的,同時(shí)也能拿到 props 的內(nèi)容。

那么我們可以修改下代碼,使其支持自定義模板

Vue.component('XSelect', {
 props: [
'value',
'options',
 {
 name: 'template',
default:'<span v-text="option.label"></span>'
 }
 ],

 created() {
varoptionTpl =this.template

this.$options.template =`
 <div class="select">
 <input :value="value" readonly />
 <div
 class="option"
 v-for="option in options"
 @click="value = option.value">
${optionTpl}
 </div>
 </div>`
 }
})

用戶使用是就可以傳入模板了

<x-select
:value.sync="value"
template="<span>標(biāo)簽: {{ option.label }}, 值: {{ option.value }}</span>"
:options="[
 {value: 1, label: 'a'},
 {value: 2, label: 'b'},
 {value: 3, label: 'c'}
 ]">
</x-select>

可能存在的問題

我們知道 Vue 在內(nèi)部幫我們做了許多優(yōu)化,但是在這里可能會(huì)由于某些優(yōu)化導(dǎo)致動(dòng)態(tài)拼接的模板無法渲染成功。例如這里我們不使用 v-for 而是手工遍歷 options 生成需要的 HTML

consttpl = options.map(opt =>`<div>${this.optionTpl}</div>`)

this.$options.template =`
 <div class="select">
 <input :value="value" readonly>
${tpl}
 </div>`

這里會(huì)導(dǎo)致一個(gè) BUG,如果一個(gè)頁面有多個(gè) x-select 組件,并且 options 長(zhǎng)度不一樣,會(huì)導(dǎo)致長(zhǎng)的 options 的組件后面幾個(gè)選項(xiàng)渲染不出來。究其原因是 Vue 會(huì)幫我們緩存模板編譯結(jié)果。翻看代碼可以找到 vue/src/instance/internal/lifecycle.js 里有做優(yōu)化,同時(shí)提供的 _linkerCachable 本意是給 內(nèi)聯(lián)模板 使用。我們可以通過設(shè)置 this.$options._linkerCachable = false 達(dá)到我們的目的。

這樣我們就可以開發(fā)讓用戶自定義布局的組件了,用戶傳入布局參數(shù),通過手工拼接模板,設(shè)置了 _linkerCachable = false 也不會(huì)被緩存。

通過 $options.partials 動(dòng)態(tài)添加 partial

使用 partials 也能達(dá)到添加自定義模板的目的,但是通常的做法是要全局注冊(cè) partial,這么做并不優(yōu)雅。 vue-strap 就是這么做的。如果重名了會(huì)被覆蓋(初次渲染不會(huì),但是數(shù)據(jù)更新重新渲染 DOM 時(shí)就會(huì)被覆蓋)。

通過文檔我們知道可以在組件內(nèi)部通過 partials 屬性注冊(cè)局部的 partial,因此自然而然也可以在 this.$options.partials 去動(dòng)態(tài)添加了。

Vue.component('XSelect', {
 template: `
 <div class="select">
 <input :value="value" readonly />
 <div
 class="option"
 v-for="option in options"
 @click="value = option.value">
 <partial name="option"></partial>
 </div>
 </div>`,

 props: ['template','value','options'],

 partials: {
 option: '<span v-text="option.label"></span>'
 },

 created() {
if(this.template) {
this.$options.partials.option =this.template
 }
 }
})

用 interpolate 渲染模板

這種方式就略顯、、、,而且效率最差。 interpolate 也是我最開始做動(dòng)態(tài)渲染模板想到的方式,不推薦使用。

Vue.component('XSelect', {
 template: `
 <div class="select">
 <input :value="value" readonly />
 <div
 class="option"
 v-for="option in options"
 @click="value = option.value"
 v-html="renderOption(option)">
 </div>
 </div>`,

 props: [
'value',
'options',
 {
 name: 'template',
default:'<span v-text="option.label"></span>'
 }
 ],

 methods: {
 renderOption(option) {
this.option = option
returnthis.$interpolate(this.template)
 }
 }
})

Vue2.0

目前并沒有找到合適的解決方案。2.0 的 Vue 將 compile 工作提前,并且 compiler 也是單獨(dú)一個(gè)包(除非你直接引用的是 vue.js 文件,包含 compiler 和 runtime,那么第一種方法是適用的),那么并不能動(dòng)態(tài)的生成模板。除非用戶傳入的是 render 能識(shí)別的 DOM tree。

按照這樣的思路,其實(shí)可以讓用戶傳入的模板預(yù)先編譯好,傳入到組件內(nèi),拼接 DOM tree 看起來也能解決問題。那么可以這么玩。

看看就好, 性能太渣

首先要安裝 Vue JSX 的 相關(guān)插件

組件

Vue.component({
 name: 'XSelect',

 render(h) {
// 這里獲得的 this.template 其實(shí)是一個(gè)函數(shù),調(diào)用該函數(shù)返回 DOM
// 因此這里的關(guān)鍵代碼是拼接一個(gè)新的函數(shù),接受 `option` 參數(shù)以及上下文
// 使用 new Function 創(chuàng)建一個(gè)新函數(shù)

return(
<divclass="select">
<inputvalue={this.value}readonly/>
 {
 this.options.map(option =>
<div
on-click={() => this.$emit('input', option.value) }
 class="option">
 { new Function('option', 'return ' + this.template)(option)(h) }
</div>
 )
 }
</div>)
 },

 props: ['template', 'value', 'options']
})

入口文件

newVue({
 el: '#app',

 data () {
return{
 value: ''
 }
 },

 created() {
// 初始化需要傳入的模板,這里會(huì)被 Vue 的 JSX 插件轉(zhuǎn)成 DOM tree
this.template = h =><span>標(biāo)簽: { option.label }, 值: { option.value }</span>
 },

 render(h) {
return(
<x-select
v-model="value"
:template="template"
:options="[
 {value: 1, label: 'a'},
 {value: 2, label: 'b'},
 {value: 3, label: 'c'}
 ]">
</x-select>)
 }
})

綜上,在 Vue 1.x 里不存在 預(yù)編譯 的概念,所以想動(dòng)態(tài)修改模板還是有許多方式的,甚至還可以結(jié)合 <slot></slot> 取到 slot 里的內(nèi)容拼接進(jìn)模板里。但 2.0 就麻煩了,并找不到理想的方法。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Vue3插槽Slot實(shí)現(xiàn)原理詳解

    Vue3插槽Slot實(shí)現(xiàn)原理詳解

    這篇文章主要為大家介紹了Vue3插槽Slot實(shí)現(xiàn)原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • vue cli中env的使用指南

    vue cli中env的使用指南

    眾所周知,一個(gè)項(xiàng)目在開發(fā)、測(cè)試與生產(chǎn)環(huán)境的各種配置變量是不一樣的,但在vue cli 3中通過指令vue create xxx創(chuàng)建的項(xiàng)目取消了默認(rèn)的 config 和 build 文件夾,這導(dǎo)致剛?cè)胧值男』锇椴恢涝谀膬号渲铆h(huán)境變量,不過官方也提供了相應(yīng)的配置方法,本文就來介紹一下
    2021-08-08
  • openlayers6之地圖覆蓋物overlay詳解

    openlayers6之地圖覆蓋物overlay詳解

    overlay就是在地圖上以另外一種形式浮現(xiàn)在地圖上,常見的地圖覆蓋物為這三種類型,如:popup 彈窗、label標(biāo)注信息、text文本信息等,接下來跟隨小編看下openlayers6之地圖覆蓋物overlay詳解,一起看看吧
    2021-09-09
  • vue3中vuex與pinia的踩坑筆記記錄

    vue3中vuex與pinia的踩坑筆記記錄

    Vuex是一個(gè)專為Vue.js應(yīng)用程序開發(fā)的狀態(tài)管理模式,它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化,這篇文章主要給大家介紹了關(guān)于vue3中vuex與pinia踩坑的相關(guān)資料,需要的朋友可以參考下
    2021-12-12
  • 基于Vue的側(cè)邊目錄組件的實(shí)現(xiàn)

    基于Vue的側(cè)邊目錄組件的實(shí)現(xiàn)

    這篇文章主要介紹了基于Vue的側(cè)邊目錄組件的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • Element input樹型下拉框的實(shí)現(xiàn)代碼

    Element input樹型下拉框的實(shí)現(xiàn)代碼

    這篇文章主要介紹了Element input樹型下拉框的實(shí)現(xiàn)代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-12-12
  • 一文帶你搞懂Vue3中Pinia的使用

    一文帶你搞懂Vue3中Pinia的使用

    用官網(wǎng)的一句話來說:Pinia?是?Vue的專屬狀態(tài)管理庫,Pinia就是為vue3而生。本文將通過一些示例詳細(xì)介紹一些Pinia的使用,希望對(duì)大家有所幫助
    2022-11-11
  • vue組件props不同數(shù)據(jù)類型傳參的默認(rèn)值問題

    vue組件props不同數(shù)據(jù)類型傳參的默認(rèn)值問題

    這篇文章主要介紹了vue組件props不同數(shù)據(jù)類型傳參的默認(rèn)值問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Vue3?實(shí)現(xiàn)一個(gè)自定義toast?小彈窗功能

    Vue3?實(shí)現(xiàn)一個(gè)自定義toast?小彈窗功能

    這篇文章主要介紹了Vue3?實(shí)現(xiàn)一個(gè)自定義toast?小彈窗,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-09-09
  • el-table點(diǎn)擊某一行高亮并顯示小圓點(diǎn)的實(shí)現(xiàn)代碼

    el-table點(diǎn)擊某一行高亮并顯示小圓點(diǎn)的實(shí)現(xiàn)代碼

    這篇文章主要介紹了el-table點(diǎn)擊某一行高亮并顯示小圓點(diǎn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08

最新評(píng)論

绥棱县| 浦县| 普格县| 西丰县| 婺源县| 县级市| 牡丹江市| 应城市| 思茅市| 岑巩县| 墨玉县| 改则县| 南雄市| 黄石市| 慈溪市| 读书| 永胜县| 六安市| 乌审旗| 泾阳县| 柘城县| 灵丘县| 曲靖市| 红安县| 泾川县| 扶沟县| 贞丰县| 仙居县| 乌鲁木齐县| 松阳县| 岳池县| 东光县| 云安县| 延庆县| 汉寿县| 彭阳县| 石城县| 噶尔县| 东山县| 雷山县| 水富县|