转自:https://www.w3cplus.com/vue/vue-slot.html
在Vue中,slot
也分多种,从Vue的官网中可以获知,其主要分为:单个插槽、具名插槽和作用域插槽三种
- 父组件的内容是在父组件作用域编译,子组件的内容是在子组件作用域编译。
- Vue的
slot
一般用在父组件向子组件分发内容,该内容的编译作用域名为父组件作用域。 - 父组件分发内容给子组件,子组件需要一个<slot></slot>标签进行接收,分发和接收同时才能真正实现分发
如果子组件template
中没有包含任何一个<slot>
时,就算父组件分发再多的内容也将会被丢弃。只有子组件模板只要有一个没有属性的slot
(因为在模板中可以有多个带属性的slot
,后面的内容会介绍),父组件传入的整个内容片段将插入到slot
所在的DOM位置,并将替换掉slot
本身。
最初在<slot>
中的任何内容都被视为备用内容(也可以在最初的<slot>
中不放置任何默认内容)。备用内容在子组件的作用域内编译,并且只有在宿主元素(父组件没有分发任何内容)为空,且没有要插入的内容时才显示备用内容。
单个插槽
子组件中使用一个默认的<slot></slot>接收分发的所有内容。
具名插槽
<slot>
可以用一个特殊的属性name
来进一步配置父组件如何分发内容。多个插槽可以有不同的名字。具名插槽将匹配内容片段中有对应slot
特性的元素。
仍然可以有一个匿名插槽,它是默认插槽,作为找不到匹配的内容片段的备用插槽。如果没有默认插槽,这些找不到匹配的内容片段将被抛弃。
//子组件根据名称接收分发的内容 <template id="modal"> <div class="modal-backdrop"> <div class="modal" @click.stop> <slot name="header"></slot> <slot name="body"></slot> <slot name="footer"></slot> </div> </div> </template>
父组件根据slot名称进行分发的
<div id="app"> <modal v-show="toggleModal" @click="closeModal"> <div class="modal-header" slot="header"> <div class="close rotate" @click="closeModal"> <i class="fa-times fa"></i> </div> <h3 class="modal-title">Modal Header</h3> </div> <div class="modal-body" slot="body"> <h3>Modal Body</h3> <p>Modal body conent...</p> </div> <div class="modal-footer" slot="footer"> <button class="btn" @click="closeModal">关闭</button> </div> </modal> <button class="btn btn-open" @click="showModal">Show Modal</button>
</div>
作用域插槽
作用域插槽是一种特殊类型的插槽,用作一个(能被传递数据的)可重用模板,来代替已经渲染好的元素。
在子组件中,只需将数据传递到插槽,就像你将prop
传递给组件一样:
在父级中,具有特殊特性 slot-scope
的 <template>
元素必须存在,表示它是作用域插槽的模板。slot-scope
的值将被用作一个临时变量名,此变量接收从子组件传递过来的 prop
对象:
在 2.5.0+,
slot-scope
能被用在任意元素或组件中而不再局限于<template>
。
作用域插槽更典型的用例是在列表组件中,允许使用者自定义如何渲染列表的每一项:
//父组件
<div id="app"> <!--Shapes--> <my-list :items="shapes" title="Shapes"> <template scope="shape"> <div>{{ shape.name }} <small>({{ shape.sides }} sides)</small></div> </template> </my-list> <!--Colors--> <my-list :items="colors" title="Colors"> <template scope="color"> <div> <div class="swatch" :style="{ background: color.hex }"></div> {{ color.name }} </div> </template> </my-list> </div> //子组件 <script type="text/x-template" id="my-list"> <div class="my-list"> <div class="title">{{ title }}</div> <div class="list"> <div class="list-item" v-for="item in items"> <slot v-bind="item"></slot> </div> </div> </div> </script>
//全局子组件
Vue.component('my-list', { template: '#my-list', props: [ 'title', 'items' ] }); //实例化的数据初始化 new Vue({ el: '#app', data: { shapes: [ { name: 'Square', sides: 4 }, { name: 'Hexagon', sides: 6 }, { name: 'Triangle', sides: 3 } ], colors: [ { name: 'Yellow', hex: '#F4D03F', }, { name: 'Green', hex: '#229954' }, { name: 'Purple', hex: '#9B59B6' } ] } });
如果想进一步的了解slot
中的作用域插槽,可以阅读《Vue的作用域插槽》一文。著作权归作者所有。
总结:
这篇文章主要学习和了解了Vue中的插槽<slot>
。是一个空壳子,它显示与否以及怎么显示完全是由父组件来控制。不过,插槽显示的位置由子组件自身决定,slot
写在组件template
的哪块,父组件传过来的模板将来就显示在哪块。在写一些组件的时候,slot
能帮助我们做很多事情,也能让组件可复用性变得更为灵活。