简单来说,Slot是对组件的扩展,通过slot插槽向组件内部指定位置传递内容
入门示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <style type="text/css"> .bg-error { background-color: red; } </style> </head> <body> <div id="app"> <!-- <2> 使用组件时,传入值会替换模版中的slot --> <alert-box>dddddddddd</alert-box> </div>
<script type="text/javascript"> // <1> 组件模版中定义slot插槽 Vue.component("alert-box", { template: '<div class="bg-error"> <strong>Error!!!</strong> <slot></slot> </div>' }); var vm = new Vue({ el: "#app", data: { } }); </script>
</body> </html>
|
插槽显示的位置在定义模版时决定,显示的内容使用组件时决定。slot写在组件template的哪块,使用组件时传过来的模板内容将来就显示在哪块。
单个插槽
单个插槽是vue的官方叫法,但是其实也可以叫它默认插槽,或者与具名插槽相对,我们可以叫它匿名插槽。因为它不用设置name属性。
- ChildSlot.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <template> <section class="bg-child"> <div> <h2>这是子组件</h2> <slot>子组件-slot默认值</slot> </div> </section> </template>
<script> export default { } </script>
<style> .bg-child { background: #84ccc9 } </style>
|
- ParentSlot.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <template> <section class="bg-parent"> <div> <h2>这是父组件</h2> <ChildSlot> <div class="tmpl"> <span>菜单1</span> <span>菜单2</span> <span>菜单3</span> <span>菜单4</span> <span>菜单5</span> <span>菜单6</span> </div> </ChildSlot> </div> </section> </template>
<script> import ChildSlot from '@/components/ChildSlot.vue'
export default { components: {ChildSlot} } </script>
<style> .bg-parent { background: #999999; padding: 10px; } </style>
|
具名插槽
匿名插槽没有name属性,所以是匿名插槽,那么,插槽加了name属性,就变成了具名插槽。具名插槽可以在一个组件中出现N次。出现在不同的位置。下面的例子,就是一个有两个具名插槽和单个插槽的组件,这三个插槽被父组件用同一套css样式显示了出来,不同的是内容上略有区别。
- childSlotNamed.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| <template> <section class="bg-child"> <div> <!-- 具名插槽 --> <slot name="up">子组件slot, name=up的默认值</slot> <h2>这是子组件</h2> <!-- 具名插槽 --> <slot name="down">子组件slot, name=down的默认值</slot> <br> <!-- 匿名插槽 --> <slot>子组件-slot默认值</slot> </div> </section> </template>
<script> export default { } </script>
<style> .bg-child { background: #84ccc9 } </style>
|
- parentSlotNamed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| <template> <section class="bg-parent"> <div> <h2>这是父组件</h2> <ChildSlotNamed> <div slot="up"> <span>菜单1-up</span> <span>菜单2-up</span> <span>菜单3-up</span> <span>菜单4-up</span> <span>菜单5-up</span> <span>菜单6-up</span> </div> <div slot="down"> <span>菜单1-down</span> <span>菜单2-down</span> <span>菜单3-down</span> <span>菜单4-down</span> <span>菜单5-down</span> <span>菜单6-down</span> </div> <div> <span>菜单1</span> <span>菜单2</span> <span>菜单3</span> <span>菜单4</span> <span>菜单5</span> <span>菜单6</span> </div> </ChildSlotNamed> </div> </section> </template>
<script> import ChildSlotNamed from '@/components/ChildSlotNamed.vue'
export default { components: {ChildSlotNamed} } </script>
<style> .bg-parent { background: #999999; padding: 10px; } </style>
|
作用域插槽 | 带数据的插槽
父组件决定html+css,子组件决定数据。
下面的例子,你就能看到,父组件提供了三种样式(分别是flex、ul、直接显示),都没有提供数据,数据使用的都是子组件插槽自己绑定的那个人名数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <template> <section class="bg-child"> <div> <h2>这是子组件</h2> <slot :data="data"></slot> </div> </section> </template>
<script> export default { data: function() { return { data: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba'] } } } </script>
<style> .bg-child { background: #84ccc9 } </style>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| <template> <section class="bg-parent"> <div> <h2>这是父组件</h2> <ChildSlotScope> <template slot-scope="user"> <div> <span class="flex-border" v-for="item in user.data" :key="item">{{item}}</span> </div> </template> </ChildSlotScope>
<ChildSlotScope> <template slot-scope="user"> <ul> <li v-for="item in user.data" :key="item">{{item}}</li> </ul> </template> </ChildSlotScope>
<child-slot-scope> <template slot-scope="user"> {{user.data}} </template> </child-slot-scope>
<child-slot-scope>不使用其提供的数据, 作用域插槽退变成匿名插槽</child-slot-scope> </div> </section> </template>
<script> import ChildSlotScope from '@/components/ChildSlotScope.vue'
export default { components: {ChildSlotScope} } </script>
<style> .bg-parent { background: #999999; padding: 10px; }
.flex-border { padding: 10px; } </style>
|