日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > vue >内容正文

vue

vue clone html,Vue.js之slot深度复制详解

發(fā)布時間:2023/12/19 vue 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 vue clone html,Vue.js之slot深度复制详解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

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

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

Vue.component('MyComponent', {

template: `

`

})

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

123

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

123

123

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

Vue.component('MyComponent', {

template: `

`

})

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

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

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

例如有一自定義組件MyComponent2:

Vue.component('MyComponent2', {

template: `

456

`

})

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

456456

為什么不能正常工作呢?估計是前面的那個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進(jìn)行深度復(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í)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。

總結(jié)

以上是生活随笔為你收集整理的vue clone html,Vue.js之slot深度复制详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。