什么是插槽?
插槽就是子组件中提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。
插槽又分为匿名插槽、具名插槽以及作用域插槽。
1、匿名插槽
匿名插槽,又可以叫它单个插槽或者默认插槽。与具名插槽相对,它不需要设置name属性。(它隐藏的name属性为default。)
<!-- 子组件 --> <template> <div class="hello"> <div class="slotText"> <slot></slot> </div> </div> </template>
<!-- 父组件 --> <template> <div class="home"> <child> <h1>我是子组件中的插槽啊</h1> </child> </div> </template>
2、具名插槽
插槽有一个name属性。与匿名插槽相对,加了name属性的匿名插槽就是具名插槽。
<!-- 子组件 --> <template> <div class="hello"> <div class = 'slotLeft'> <slot name='left'></slot> </div> <div class = 'slotRight'> <slot name='right'></slot> </div> </div> </template>
<!-- 父组件 --> <!-- 父组件中通过在template上写v-slot:name来使用具名插槽 --> <template> <div class="home"> <child> <template v-slot:left> <h1>name属性为left</h1> </template> <template v-slot:right> <h1>name属性为right</h1> </template> </child> </div> </template>
注意:
- v-slot 只能添加在template标签上 (只有一种例外情况)。
- 例外情况(被废弃的slot=‘name’)
- 带slot属性的具名插槽自 2.6.0 起被废弃,vue3.x被完全废弃。只有vue3之前的cli可以使用。
<!-- 父组件 --> <template> <div class="home"> <child> <h1 slot='left'>name属性为left</h1> <h1 slot='right'>name属性为right</h1> </child> </div> </template>
具名插槽的小知识点
- 跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header。
3、作用域插槽
作用域插槽其实就是可以传递数据的插槽。子组件中的一些数据想在父组件中使用,必须通过规定的方法来传递。
在官方文档中提出了一条规则,父级模板里的所有内容都是在父级作用域中编译的。子模板里的所有内容都是在子作用域中编译的。如果你在父组件直接使用子组件中的值,是会报错的。
① 匿名插槽的作用域插槽
<!-- 子组件 --> <template> <div class="hello"> <div class='slotLeft'> <slot name='helloWorld' v-bind:users="user"></slot> </div> </div> </template> <script> export default { data(){ return{ user:{ name:'hello world', age:18 } } } } </script>
<!-- 父组件 --> <template> <div class="home"> <child> <template v-slot:helloWorld="slotProps"> <h1>{{slotProps.users.name}}</h1> </template> </child> </div> </template> <script> import child from '@/components/child.vue' export default { name: 'home', components: { child } } </script>
-------------------------------------------------------------------------------------
注意:
- 默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确。
上面的写法是不是觉得有些麻烦?别着急,我们来看一看解构插槽 Prop。
② 解构插槽 Prop
作用域插槽的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里:
function (slotProps) { // 插槽内容 }
这意味着 v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。所以在支持的环境下 (单文件组件或现代浏览器),你也可以使用 ES2015 解构来传入具体的插槽 prop。
语法:v-slot="{ users }"
子组件:
<!-- 子组件 --> <template> <div class="hello"> <div class='slotLeft'> <slot v-bind:users="user"></slot> </div> </div> </template> <script> export default { data(){ return{ user:{ name:'hello world', age:18 } } } } </script>父组件:
<!-- 父组件 --> <template> <div class="home"> <child> <template v-slot="{ users }"> <h1>{{users.name}}</h1> </template> </child> </div> </template> <script> import child from '@/components/child.vue' export default { name: 'home', components: { child } } </script>
重命名----更改users这个名字:
<template> <div class="home"> <child> <template v-slot="{ users:person }"> <h1>{{person.name}}</h1> </template> </child> </div> </template> <script> import child from '@/components/child.vue' export default { name: 'home', components: { child } } </script>