插槽
更新:2.6.0 中,具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)
废弃:slot 和 slot-scope特性
插槽目的
个人理解:子组件提供插槽位置(相当于占位),父组件任意提供插槽内容(相当于如何使用这个位置)
插槽内容
官方:Vue 实现了一套内容分发的 API,将 <slot>元素作为承载分发内容的出口。
自己:子组件通过<slot></slot>实现插槽,
父组件通过<template></template>并结合v-slot向某个插槽提供内容
***父组件不提供插槽内容时,则使用插槽的后备内容【默认值】
编译作用域
规则:父级模板里的所有内容都是在父级作用域中编译的;
子模板里的所有内容都是在子作用域中编译的。
后备内容
插槽的后备内容:指默认值
具名插槽
(1)总结:
1.父组件<template> 元素v-slot指令分发插槽内容,子组件<slot>元素定义插槽;
2.<slot>元素name 特性指定插槽名;
3.<slot>元素不带name特性时,为默认插槽,默认name为default;
4.任何没有被包裹在带有 v-slot的 <template> 元素中的内容都会被视为默认插槽的内容;
5.默认插槽也可用 <template>元素包裹默认插槽内容;
6.若没有默认插槽,找不到匹配的内容将会被抛弃
//父组件中: 为header插槽添加内容 <template v-slot:header> 我的博客 </template> //对应: //子组件中 定义header插槽 <slot name="header">默认头部</slot>
默认slot分发插槽内容
<template v-slot:default>
<p>博客内容</p>
</template>
(2)详细例子
//子组件s_slot.vue <template> <div class="container"> <header> <h1>Slot</h1> <slot name="header">默认头部</slot> </header> //不带name特性的插槽是默认插槽,默认插槽的name="default" <main> <slot></slot> </main> <footer> <slot name="footer">默认底部</slot> </footer> </div> </template> <style> footer ul{ display: flex; align-items: center; background:lightblue; } footer ul li{ flex: 1; text-align: center; list-style: none; height: 30px; line-height: 30px; } </style>
//父组件Slot.vue <template> <!-- 具名插槽的使用 --> <template v-slot:header> 我的博客 </template> <!--默认插槽的使用1,用template包裹--> <template v-slot:default> <p>博客内容</p> </template> 或者 <!--默认插槽的使用2,不用template包裹--> <!--<p>博客内容</p>--> <!--具名插槽的缩写--> <template #footer> <ul> <li>首页</li> <li>我的</li> </ul> </template> </template> <script> import sSlot from '@/components/s_slot'; export default { components:{ sSlot }, } </script>
效果如果:
作用域插槽
理解:1.父组件分发插槽内容时,可访问子组件中的数据
2.父组件分发插槽内容时,父组件可向子组件传递数据(参数)
如何实现:
第一种:实现父组件分发插槽内容时,可访问子组件中的数据
1.将子组件的数据A作为一个特性(属性)绑定到<slot>元素上,绑定在<slot>元素的特性称为“插槽prop”
2.在父级作用域中,v-slot带一个值B定义插槽prop的名字
3.详细例子 (为比较,父组件使用情况分2种,默认和访问数据)
//子组件中 <template> <div class="container"> <aside> <!-- 绑定在 <slot> 元素上的特性被称为插槽 prop --> <!-- 为了让user在父级的插槽内容上可用,需将user绑定在slot元素上 --> <slot name="aside" :user="user"> 名字:{{user.name}} 电视剧:{{user.TV}} </slot> </aside> </div> </template> <script> export default { data:function(){ return{ user:{ 'name':'李冰冰', 'TV':'再生缘' } } } } </script>
//父组件中使用子组件,默认时 <template v-slot:aside></template>
结果:
//父组件中使用子组件,访问子组件数据时 <!-- v-slot 定义【插槽 prop】 的名字 为star--> <template v-slot:aside="star"> 我喜欢{{star.user.name}} </template>
结果:
第二种:父组件分发插槽内容时,父组件可向子组件传递数据(参数)
就是普通的父子组件传参
1.父组件将数据A绑定
2.子组件通过props接收
3.详细例子 (为比较,父组件使用情况分2种,默认和传值)
//子组件中 <template> <header> <h1>作用域插槽</h1> <slot name="header">{{header}}</slot> </header> <div> <slot name="footer">{{footer}}</slot> </div> </template> <script> export default { props:{ header:{ type:String, default:'这是默认头部' }, footer:{ type:String, default:'这是默认底部' } }, } </script>
//父组件中:不传值时 <template> <sSlotScope> <template v-slot:header></template> <template #footer></template> </sSlotScope> </template> <script> import sSlotScope from '@/components/s_slotScope'; export default { components:{ sSlotScope }, data:function(){ return{ } } } </script>
结果:
//父组件中:传值 <template> <sSlotScope :header="header" :footer="footer"> <template v-slot:header></template> <template #footer></template> </sSlotScope> </template> <script> import sSlotScope from '@/components/s_slotScope'; export default { components:{ sSlotScope }, data:function(){ return{ header:'我的爱好', footer:'快乐每一天', } } } </script>
结果:
具名插槽的缩写
1.v-slot 缩写:把参数之前的所有内容 v-slot: 替换为字符 #
如:v-slot:header 缩写为 #header
2.缩写只在其有参数的时候才可用。若为变量时,使用缩写的话,必须明确插槽名