有3步html
首選建立一個單文件組價,因爲咱們是使用的slot(父組件傳進來的),因此,咱們只須要建立js文件便可,而不用建立.vue文件vue
// slot.js export default { name: 'Slot', // slot的名字,調試使用 functional: true, // 使組件無狀態 (沒有 data ) 和無實例 (沒有 this 上下文)。他們用一個簡單的 render 函數返回虛擬節點使他們更容易渲染。 inject: ['Root'], // 父組件的映射 props: { // 此組件接受的props data: Object, options: Object }, render: (h, ctx) => { // dom渲染函數 return h('div', ctx.injections.Root.$scopedSlots['icon']({ // 獲得名爲icon的做用域插槽 data: ctx.props.data, // 給slot的組件傳遞props options: ctx.props.options })); } };
// 導入子組件 import IconSlot from 'slot.js'; // 切換到父組件 export default { name: 'IconTable', components: {IconSlot}, provide () { // 該對象包含可注入其子孫的屬性 在這裏把父組件自身傳遞給子組件 return { Root: this }; }, data() { return { list: [], options: {} }; } }
在模板中使用node
<template> <div v-for="(item, index) in list" :key="index"> <icon-slot :data="item" :options="options"></icon-slot> </div> </template>
<icon-table> <template slot="icon" slot-scope="{ list, options }"> <div v-if="list.length > 1"><Icon type="add"></Icon></div> <div v-else><Icon type="del"></Icon></div> </template> </icon-table>
若是在父組件直接取this.$slot
或this.$scopedSlots
的話,
其實只能用一次
若是在模板中使用 slot 標籤來接收的話,其實也只能只用一次dom
因此核心思路是;每次使用都必須從新建立VNode節點,那隻能每次都使用createElement生成node,
那只有一個辦法使用render渲染了,而後第一個參數建立dom後,dom附帶的數據,均可以是一個對象,只要保證節點是惟一的便可,數據其實無所謂,怎麼傳均可以ide