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

Vue.js之slot深度復(fù)制詳解

 更新時間:2017年03月10日 14:18:25   作者:jingsam  
這篇文章主要介紹了Vue.js之slot深度復(fù)制的相關(guān)資料,文中介紹的很詳細,對大家具有一定的參考價值,需要的朋友們來一起看看吧。

前言

在Vue中,slot是一個很有用的特性,可以用來向組件內(nèi)部插入一些內(nèi)容。slot就是“插槽”的意思,用大白話說就是:定義組件的時候留幾個口子,由用戶來決定插入的內(nèi)容。

例如我們定義一個組件MyComponent,其包含一個slot:

Vue.component('MyComponent', {
 template: `
 <div>
  <slot></slot>
 </div>
 `
})

當(dāng)調(diào)用<MyComponent>123</MyComponent>時,會渲染為如下DOM結(jié)構(gòu):

<div>
 123
</div>

現(xiàn)在又有新需求了,我們希望調(diào)用<MyComponent>123</MyComponent>時,渲染出這樣的DOM結(jié)構(gòu):

<div>
 123
 123
</div>

看起來很容易實現(xiàn),即再為MyComponent添加一個slot:

Vue.component('MyComponent', {
 template: `
 <div>
  <slot></slot>
  <slot></slot>
 </div>
 `
})

渲染出的結(jié)構(gòu)也確實如你所愿,唯一美中不足的是控制臺有一個小小的Warning:

Duplicate presence of slot "default" found in the same render tree

如果你不是強迫癥患者,這時候你可以收工安心回家睡覺了。直到有一天你的同事向你抱怨,為什么向MyComponent插入一個自定義組件會渲染不出來?

例如有一自定義組件MyComponent2:

Vue.component('MyComponent2', {
 template: `
 <div>456</div>
 `
})

當(dāng)調(diào)用<MyComponent><MyComponent2></MyComponent2></MyComponent>時,預(yù)期渲染為如下DOM結(jié)構(gòu):

<div>
 <div>456</div>
 <div>456</div>
</div>

為什么不能正常工作呢?估計是前面的那個Warning搞得鬼,通過查詢發(fā)現(xiàn)在Vue 2.0中不允許有重名的slot:

重名的 Slots 移除

同一模板中的重名 已經(jīng)棄用。當(dāng)一個 slot 已經(jīng)被渲染過了,那么就不能在同一模板其它地方被再次渲染了。如果要在不同位置渲染同一內(nèi)容,可一用 prop 來傳遞。

文檔中提示可以用props來實現(xiàn),然而在我的用例中顯然是不合適的。經(jīng)過搜索后,最靠譜的方法是手寫render函數(shù),將slot中的內(nèi)容復(fù)制到其他的位置。

將之前的MyComponent改為render函數(shù)的方式定義:

Vue.component('MyComponent', {
 render (createElement) {
 return createElement('div', [
  ...this.$slots.default,
  ...this.$slots.default
 ])
 }
})

在上面的定義中我們插入了兩個this.$slots.default,測試下能不能正常工作。然而并沒有什么卵用,Vue文檔在render函數(shù)這一章有以下說明:

VNodes 必須唯一

所有組件樹中的 VNodes 必須唯一

這意味著我們不能簡單地在不同位置引用this.$slots.default,必須對slot進行深度復(fù)制。深度復(fù)制的函數(shù)如下:

function deepClone(vnodes, createElement) {
 function cloneVNode (vnode) {
 const clonedChildren = vnode.children && vnode.children.map(vnode => cloneVNode(vnode));
 const cloned = createElement(vnode.tag, vnode.data, clonedChildren);
 cloned.text = vnode.text;
 cloned.isComment = vnode.isComment;
 cloned.componentOptions = vnode.componentOptions;
 cloned.elm = vnode.elm;
 cloned.context = vnode.context;
 cloned.ns = vnode.ns;
 cloned.isStatic = vnode.isStatic;
 cloned.key = vnode.key;
 return cloned;
 }
 const clonedVNodes = vnodes.map(vnode => cloneVNode(vnode))
 return clonedVNodes;
}

上面的核心函數(shù)就是cloneVNode() ,它遞歸地創(chuàng)建VNode,實現(xiàn)深度復(fù)制。VNode的屬性很多,我并不了解哪些是關(guān)鍵屬性,只是參照著Vue的源碼一并地復(fù)制過來。

基于以上函數(shù),我們更改MyComponent的定義:

Vue.component('MyComponent', {
 render (createElement) {
 return createElement('div', [
  ...this.$slots.default,
  ...deepClone(this.$slots.default, createElement)
 ])
 }
})

經(jīng)測試,一切正常。

總結(jié)

在Vue 1.0中重名的slots并不會出現(xiàn)什么問題,不知道為什么在2.0中取消了這個功能。我聽說React提供了復(fù)制Element的標(biāo)準(zhǔn)函數(shù),希望Vue也能提供這個函數(shù),免得大家踩坑。以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。

相關(guān)文章

  • Vue3中嵌套路由和編程式路由的實現(xiàn)

    Vue3中嵌套路由和編程式路由的實現(xiàn)

    Vue?Router在Vue.js的核心庫上提供了路由的功能,使得我們可以在單頁應(yīng)用中實現(xiàn)頁面的切換、跳轉(zhuǎn)和參數(shù)傳遞等功能,本文主要介紹了Vue3中嵌套路由和編程式路由的實現(xiàn),感興趣的可以了解一下
    2023-12-12
  • 利用vue控制元素的顯示與隱藏

    利用vue控制元素的顯示與隱藏

    大家都知道在vue中我們可以使用v-if或者v-show去做隱藏顯示,下面這篇文章主要給大家介紹了關(guān)于如何利用vue控制元素的顯示與隱藏的相關(guān)資料,需要的朋友可以參考下
    2022-12-12
  • vue.js單文件組件中非父子組件的傳值實例

    vue.js單文件組件中非父子組件的傳值實例

    今天小編就為大家分享一篇vue.js單文件組件中非父子組件的傳值實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • Vue實現(xiàn)簡單基礎(chǔ)的圖片裁剪功能

    Vue實現(xiàn)簡單基礎(chǔ)的圖片裁剪功能

    這篇文章主要為大家詳細介紹了如何利用Vue2實現(xiàn)簡單基礎(chǔ)的圖片裁剪功能,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起了解一下
    2022-09-09
  • vue3前端導(dǎo)出excel表格的兩種實現(xiàn)方法

    vue3前端導(dǎo)出excel表格的兩種實現(xiàn)方法

    這篇文章主要給大家介紹了關(guān)于vue3前端導(dǎo)出excel表格的兩種實現(xiàn)方法,文中通過代碼以及圖文介紹的非常詳細,對大家學(xué)習(xí)或者使用vue3具有一定的參考借鑒價值,需要的朋友可以參考下
    2024-11-11
  • Vue.js中v-for指令的用法介紹

    Vue.js中v-for指令的用法介紹

    這篇文章介紹了Vue.js中v-for指令的用法,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03
  • 淺析vue cli3 封裝Svgicon組件正確姿勢(推薦)

    淺析vue cli3 封裝Svgicon組件正確姿勢(推薦)

    這篇文章主要介紹了vue cli3 封裝Svgicon組件正確姿勢,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • vue webuploader 文件上傳組件開發(fā)

    vue webuploader 文件上傳組件開發(fā)

    本篇文章主要介紹了vue webuploader 文件上傳組件開發(fā),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • vue 點擊按鈕實現(xiàn)動態(tài)掛載子組件的方法

    vue 點擊按鈕實現(xiàn)動態(tài)掛載子組件的方法

    今天小編就為大家分享一篇vue 點擊按鈕實現(xiàn)動態(tài)掛載子組件的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • Vue3+Element-Plus實現(xiàn)左側(cè)菜單折疊與展開功能示例

    Vue3+Element-Plus實現(xiàn)左側(cè)菜單折疊與展開功能示例

    本文主要介紹了Vue3+Element-Plus實現(xiàn)左側(cè)菜單折疊與展開功能示例,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04

最新評論

图们市| 泰和县| 璧山县| 南澳县| 大田县| 宕昌县| 华亭县| 合阳县| 永春县| 台湾省| 蒙城县| 镇沅| 沛县| 蓬安县| 南通市| 汶上县| 开远市| 芜湖市| 蕉岭县| 伊吾县| 东丽区| 张家港市| 云霄县| 吉木乃县| 莱西市| 南城县| 革吉县| 乌鲁木齐县| 休宁县| 台中县| 黄陵县| 高青县| 廊坊市| 玉树县| 喀什市| 丁青县| 松滋市| 齐河县| 襄汾县| 雷山县| 临澧县|