插槽

Vue实现了一套内容分发的API,将<slot>元素作为承载分发内容的出口。插槽内可以包含任何模板代码,包含HTML。插槽就是子组件提供的可替换模板,父组件可以根据需求改变模板的内容。

具名插槽比较简单,通过阅读官网就可以得到很好的理解,不过作用域插槽可能会有理解上的困难,我这里分别写了具名插槽和作用域插槽的demo,有助于大家的理解。

具名插槽

利用了<slot>的name属性,利用这个属性可以用来定义额外的插槽,一个不带name<slot>出口会带有隐含的名字“default”

在向具名插槽提供内容的收可以在<template>上的v-slot指令,然后<template>中的所有内容会被传入到相应的插槽中,任何没有被包裹在带有v-slot<template>中的内容都会被视为默认插槽的内容

子组件中的<slot name='aa'></slot>和父组件中的<template v-slot:aa></template>相对应

注意:v-slot只能添加到<template>标签上,v-slot的简写形式#,例如 v-slot:header 等价于 #header

DEMO

app.vue
<template>  <div id="app">       <slotChild>            {{this.syncShow}}            <template v-slot:footer>                <p>这里是footer</p>            </template>            <template v-slot:head>                <p>这里是head</p>            </template>        </slotChild>  </div></template><script>import slotChild from '@components/slot-child.vue'export default {    name: 'app',    data () {        return {            syncShow:false        }    }}</script>
slot-child.vue
<template>    <div>        这里是slot-child组件        <br>        <slot></slot>        <slot name="head"></slot>        <slot name="footer"></slot>    </div></template><script>export default {    name: 'slotChild',    data () {        return {}    }}</script>

作用域插槽

作用域插槽提供了一种新玩法,“插槽prop”(demo中会更直观的介绍),通过“插槽prop”,父组件可以接收到子组件的数据,并且可以对数据进行操作,展现成父组件想要实现的样子。

插槽 prop允许我们将插槽转换为可复用的模板,这些模板可以基于输入的 prop 渲染出不同的内容。这在设计封装数据逻辑同时允许父级组件自定义部分布局的可复用组件时是最有用的

DEMO

app.vue
<template><slotChild :slotList='slotList'>    <template v-slot:slot-scope="item">    <!-- 这里的`v-slot`指向的是name='slot-scope'的`<slot>`,通过item可以接收到子组件的返回值,这个值是自定义的,被称为插槽prop -->        <li>书名:<span style="color: red">《{{item.title}}》</span> 作者:<span style='color: green'>{{item.name}}</span></li>        <!-- 接收到子组件的返回值item,这里父组件重新对数据进行排版以满足自己的需求,从而提高组件的复用程度 -->    </template></slotChild></template><script>import slotChild from '@components/slot-child.vue'export default {    name: 'app',    data () {        return {            slotList: [                {                  title: '围城',                  name: '钱钟书'                },                 {                  title: '追风筝的人',                  name: '卡勒德·胡赛尼'                },                 {                  title: '灿烂千阳',                  name: '卡勒德·胡赛尼'                }            ]        }    }</script>}
slot-child.vue
<template>    <div>        <ul>            <slot name="slot-scope" v-for="item in slotList" v-bind="item">                <li>书名:《{{item.title}}》; 作者:{{item.name}}</li>            </slot>        </ul>    </div></template><script>export default {    name: 'slotChild',    props:{        slotList: {          type: Array,          default: () => []        }    },    data () {        return {}    }}</script>

最终效果