vue中插槽作用是什么?就是子組件寫一個<slot>標簽占一個坑,父組件在使用這個子組件的時候,在子組件標簽中加入一些內容,這些內容將在占坑的地方出現
作用域插槽是什么?父組件通過在子組件中使用插槽填充內容的時候,可以通過slot-scope屬性獲取 子組件中<slot>標簽 通過屬性 傳遞過來的子組件的作用域 的值。
//parent.vue <child :data="data"> //這個scope隨意起名,代表的就是子組件slot標簽所有屬性組成的對象 <span slot-scope="scope">{{ scope.name }}</span> </child> //child.vue <div> 子組件{{data}} <slot :name="name"></slot> </div>
想象第一個場景:一個商品列表,點擊每個商品跳轉到詳情頁知道了什么意思,以及用法,那他的應用場景是什么呢?
首先將商品卡片寫成一個組件GoodsCard.vue,在GoodsList.vue中一個v-for循環商品card
<goods-card v-for="(item,index) in goodsList" @clickGoods="onGoodsClick"></goods-card>
第一個場景實現了,沒啥問題,現在想象第二個場景,比如,淘寶網站上,有兩組商品列表子組件只需要在點擊商品的時候觸發this.$emmit("clickGoods",item),將數據傳給父組件進行跳轉
此時GoodsList.vue就需要抽成組件了,在商品GoodsPage中v-for調用GoodsList.vue,產生多個商品列表
這樣跳轉詳情頁的話,如果還用this.$emit就需要三層傳遞click,card->goodsList->goodspage,那這樣子組件跟業務扯上關系,顯得不純粹,這個時候就用上了作用於插槽
<el-row :gutter="20"> //columnList 存儲多個商品列表 <el-col :span="12" v-for="(column, index) in columnList" :key="index"> <goods-list :goodsList="column.goodsList"> <template slot-scope="scope"> <!-- 這里只需要給GoodsCard組件傳入數據,響應GoodsCard組件的onGoodsClick事件即可。 事件不必攜帶參數,完全符合父到子的數據流向,而不會發生子組件又給父組件反向發數據的情況 --> <goods-card @click="onGoodsClick(scope.row)"></goods-card> </template> </goods-list> </el-col> </el-row>
<el-row :gutter="20"> <el-col :span="8" v-for="(item, index) in goodsList" :key="index"> <slot :row="item"></slot> </el-col> </el-row>
GoodsList.vue應該是這樣的,<slot>設置屬性item,這樣父組件就可以通過作用域插槽訪問到點擊的項,而無需觸發this.$emit
知道了作用域插槽使用場景,但是這就是作用域插槽的全部嗎?不是
官方提供了兩個API,分別是this.$slots和this.$scopedSlots,並且官方提示:vm.$slots和vm.$scopedSlots在使用渲染函數開發一個組件時特別有用。
首先看一下這兩個在使用的時候輸出什么
<template> <test> <div slot="header">slot: header</div> <div slot-scope="scope">slot: {{scope}}</div> <div slot="footer">slot: footer</div> </test> </template> <script> import Test from './test.vue' export default { components: { Test } } </script>
<template> <div> <slot name="header"></slot> <slot></slot> <slot name="footer"></slot> </div> </template> <script> export default { data () { return { test: { name: 'default' } } }, mounted () { console.log(this.$slots, '$slots') console.log(this.$scopedSlots, '$scopedSlots') } } </script>
可以看出是否是$scopedSlots,就是使用插槽時是否有slot-scope特性
!!!通過控制台打印結果,明晰this.$slots和this.$scopedSlots[name](),結果是vnode,相當於<slot>作用
我們用jsx寫一個例子看一下:
<script> export default { props: { data: { type: Array, default () { return [] } } }, data () { return { } }, render (h, vm) { return ( <ul> {this.data.map(item => ( <li> //傳遞給作用域對象 插槽內容 父級傳過來的數據 {this.$scopedSlots.default(item)|| this.$slots.default || item.name} //意思就是告訴父組件你插槽內容是哪一項 </li> ))} </ul> ) } } </script>
<template> <test :data="data"> //scope就是this.$scopedSlots.default(item)傳遞過來的item <span slot-scope="scope">{{scope.name}} | vm.scopedSlots的使用</span> </test> </template> <script> import Test from './test.vue' export default { components: { Test }, data () { return { data: [ { name: 111 }, { name: 222 }, { name: 333 } ] } } } </script>