最近在官方文檔中看到,vue新增了一種插槽機制,叫做作用域插槽。要求的版本是2.1.0+。
首先來說一下:顧名思義,所謂作用域插槽,主要就在作用域,需要注意的是(以下幾點看不懂不要緊,配合下面的例子,你會一看就懂):
1. 組件中的slot標籤只能有有一個,而這一個slot用於替代組件調用時的多個標籤。即一個slot代替一組範圍的標籤,即爲作用域。
2. 作用域插槽的特殊在於:可在上層作用域中通過臨時變量拿到組件定義時通過作用域插槽傳遞的數據。
3. 作用域插槽的技巧在於:可在上層作用域中通過拿到的數據選擇性地渲染標籤(即修改slot對應的標籤範圍)。
下面通過實際例子來一步一步地細說:
**擁有作用域插槽的組件定義(實際代碼中組件要在根實例創建之前定義):
Vue.component("list-tpl", { props: ["list"], template: ` <ul> <li style="display:block;" v-for="(item, index) in list"> <slot :item="item"></slot> // item爲向上層傳遞的數據,單個slot在調用時轉化爲作用域內的多個標籤 </li> </ul> ` })
*根實例代碼,主要包括測試數據:
var app = new Vue({ el: "#app", data: { list: [ { name: "tate", age: 26, single: true, // 是否單身 stu: false // 是否是學生 }, { name: "kevin", age: 23, single: true, stu: true }, { name: "harden", age: 28, single: false, stu: false }, { name: "Jimmy", age: 29, single: false, stu: true } ] } })
*最重要的 組件調用
<list-tpl :list="list"> <!-- 調用的時候 a 爲臨時變量,只用於獲取數據 --> <template slot-scope="a"> <!-- 若不加任何判斷,整個template中的標籤都會替換爲定義時的slot --> <h4>{{a.item.name}}</h4> <h5>{{a.item.age}}</h5> <!-- 技巧就在於通過a拿到的數據選擇性地渲染標籤,即修改單個slot對應的作用域範圍 --> <span v-if="a.item.single">我是單身</span> <span v-if="a.item.stu">我是學生</span> <span v-if="!a.item.single">我不是單身</span> <span v-if="!a.item.stu">我不是學生</span> </template> </list-tpl>
綜上:作用於插槽主要應用在:需要在實際調用組件時選擇性渲染插槽內容,而不是在定義時用js寫。
*下面看一下本例子的實際效果:
*本例的全部代碼如下,可自行運行查看效果:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <slot-test> <template slot="top">定製top</template> </slot-test> <list-tpl :list="list"> <!-- 調用的時候 a 爲臨時變量,只用於獲取變量 --> <template slot-scope="a"> <!-- 若不加任何判斷,整個template中的標籤都會替換爲定義時的slot --> <h4>{{a.item.name}}</h4> <h5>{{a.item.age}}</h5> <!-- 技巧就在於通過a拿到的數據選擇性地渲染標籤,即修改單個slot對應的作用域範圍 --> <span v-if="a.item.single">我是單身</span> <span v-if="a.item.stu">我是學生</span> <span v-if="!a.item.single">我不是單身</span> <span v-if="!a.item.stu">我不是學生</span> </template> </list-tpl> </div> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> <script> Vue.component("slot-test", { template: "<div>\ <slot name='top'>\ <p>默認top</p>\ </slot>\ <slot name='mid'>\ <p>默認mid</p>\ </slot>\ <slot name='bottom'>\ <p>默認bototm</p>\ </slot>\ </div>" }) Vue.component("list-tpl", { props: ["list"], template: ` <ul> <li style="display:block;" v-for="(item, index) in list"> <slot :item="item"></slot> // item爲向上層傳遞的數據,單個slot在調用時轉化爲作用域內的多個標籤 </li> </ul> ` }) var app = new Vue({ el: "#app", data: { list: [ { name: "tate", age: 26, single: true, stu: false }, { name: "kevin", age: 23, single: true, stu: true }, { name: "harden", age: 28, single: false, stu: false }, { name: "Jimmy", age: 29, single: false, stu: true } ] } }) </script> </body> </html>