昨天看vue的官網文件,在slot-scope這塊不是特別的明白,今天自己做了一個小例子,便於理解。
先說一下我們假設的應用常用場景,我們已經開發了一個代辦事項列表的元件,很多模組在用,現在要求在不影響已測試通過的模組功能和展示的情況下,給已完成的代辦項增加一個對勾效果。
也就是說,代辦事項列表元件要滿足一下幾點
- 之前資料格式和引用介面不變,正常展示
- 新的功能模組增加對勾
解決辦法很多,不過為了解釋元件作用域插槽,我們就用slot-scope了,寫列一下之前元件的程式碼。
todo-list.vue 元件
<template>
<ul>
<li v-for="item in todoList" v-bind:key="item.id">
<slot v-bind:itemValue = "item" >
{{ item.test }}
</slot>
</li>
</ul>
</template>
<script>
export default {
name: 'todoList',
props: {
todos: Array
},
data(){
return {
todoList:this.todos
}
}
}
</script>
複製程式碼
元件程式碼
<template>
<ul>
<li v-for="item in todoList" v-bind:key="item.id">
<slot>
{{ item.test }}
</slot>
</li>
</ul>
</template>
<script>
export default {
name: 'todoList',
props: {
todos: Array
},
data(){
return {
todoList:this.todos
}
}
}
</script>
複製程式碼
父元件程式碼
<template>
<div id="app">
<h2>之前元件呼叫</h2>
<todo-list v-bind:todos="todosBefore" ></todo-list>
</div>
</template>
<script>
import todoList from './components/todo-list.vue'
export default {
name: 'app',
data:function(){
return {
todosBefore:[
{
test:'詢問時間',
id:12312313123
},
{
test:'代辦1',
id:123123123423423
},
{
test:'愛你地方年底見覅',
id:12312313123234234
},
{
test:'時間2',
id:1231231312323333
},
{
test:'師生情是行情',
id:12313333333
}
]
}
},
components: {
todoList
}
}
</script>
複製程式碼
展示效果
步驟
為了實現代辦事項增加對勾效果,我們要在data中調整資料結構,新增todosAfter
陣列,並給每一項增加isComplete
標識。
todosAfter:[
{
test:'詢問時間',
isComplete:true,
id:12312313123
},
{
test:'代辦1',
isComplete:false,
id:123123123423423
},
{
test:'愛你地方年底見覅',
isComplete:false,
id:12312313123234234
},
{
test:'時間2',
isComplete:true,
id:1231231312323333
},
{
test:'師生情是行情',
isComplete:true,
id:12313333333
}
],
複製程式碼
理解插槽和資料傳遞
自己在看別人的帖子比較吃力的地方就是弄不清楚這個插槽作用域到底是什麼,有什麼功能,我用大白話來屢屢思路。 弄清楚兩個問題
- 插槽solt程式碼在哪裡編寫? 當然在父元件內,solt是子元件暴露給父元件的介面,需要父元件傳給子元件。
- 插槽作用域,作用域插槽字面理解,僅僅只對插槽生效。
那傳遞步驟是
- 父元件把資料給子元件,父=>子
- 子元件把資料給插槽,並暴露給父元件介面
- 父元件呼叫子元件的插槽slot介面和資料
我們之前給資料資料增加了isComplete
屬性,現在要將子元件item
傳遞給插槽,並給父元件暴露資料介面itemValue
,重點在 v-bind:itemValue = "item"
這一句 。
<template>
<ul>
<li v-for="item in todoList" v-bind:key="item.id">
<slot v-bind:itemValue = "item" >
{{ item.test }}
</slot>
</li>
</ul>
</template>
複製程式碼
接下來是父元件呼叫子元件的slot和itemValue
資料。
<h2>之前元件呼叫</h2>
<todo-list v-bind:todos="todosAfter">
<template slot-scope="slotProps">
<!-- 列印itemvalue資料-->
<div style="background:red; border-bottom:2px solid blue;">
{{slotProps.itemvalue}}
</div>
<!-- 根據判斷條件展示對號元素 -->
<span v-if="slotProps.itemValue.isComplete">✓</span>
<!-- 顯示代辦事項名稱 -->
{{ slotProps.itemValue.test }}
</template>
</todo-list>
複製程式碼
效果如下
附例項程式碼:github link
總結
其實作用域插槽很類似於入參函式,元件相當於cb,而cb的入參就相當與slotProps接收的引數,只不過名稱和形式變了個樣子。
<!-- 函式 -->
function foo(str,cb){
var msg = str + '你好';
cb(msg);
}
<!-- 呼叫 -->
foo('愚坤',function(msg){
alert(msg)
})
foo('愚坤',function(msg){
console.log(msg)
})
複製程式碼