插槽<slot>
一、插槽与透传\props引用父DOM的区别
1、透传\props引用父DOM
- 子组件不能完整引用DOM,只能引用DOM属性。
引用方法是: 将DOM变量赋给父标签属性。在子组件中引用DOM变量的属性。
如下:是使用DOM的outerHTML属性生成的类似标签,这个标签只重现了outerHTM能包含的原DOM标签上的属性,并不能重现原DOM标签上的事件等其它内容。
父组件:<template> <button ref="wow" @click="ed" >草</button> <HelloWor :oj="wow" /> </template> <script setup> import HelloWor from './Hello.vue' import {ref} from 'vue' function ed(){console.log('能成功打印吗')} const wow=ref({})//我是DOM </script>
子组件:
<template> <div >{{'oj DOM:'+$attrs.oj}}</div> <div v-html="$attrs.oj.outerHTML"></div> </template> <script setup></script>
2、插槽引用父DOM
- 子组件能完整引用DOM,但不能单独引用DOM属性。
引用方法是: 借助
<template>
标签,要传的DOM对象放置在<template>
标签里。在子组件中用<slot>
接收<template>
标签,连同接收<template>
里的DOM对象。
如下:接收<template>
,连同接收<template>
里的DOM对象。子组件接收的DOM对象是完整的,属性和事件、指令都是完整复刻。
父组件:<template> <HelloWor :oj="wow"> <template v-slot:dg><button ref="wow" @click="ed" >草</button></template> </HelloWor> </template> <script setup> import HelloWor from './Hello.vue' import {ref}from 'vue' const wow=ref({}) function ed(){console.log('能成功打印吗')} </script>
子组件:
<template> <slot name="dg"></slot> {{$attrs.oj.outerHTML}} </template>
v-slot:dg给
<template>
具名,<slot name="dg">
接收此具名<template>
。
3、插槽与透传\props的区别
a、DOM本体
透传\props不需在父标签下放置DOM本体,只需在父标签的属性上赋值DOM变量;
插槽要把DOM本体放在父标签下的<template>
标签内。
b、引用内容
透传\props只能引用DOM对象的属性,不能引用完整的DOM对象;
插槽是接收完整的DOM对象,并不能单独引用DOM对象的属性。
二、<template>
标签
1、<template>
标签规范
a、必须顶级
<template>
标签在父标签下必须是顶级标签,不可放在其它标签内。
b、隐式<template>
系统会强行把父标签内所有非<template>
标签打包进一个隐式的<template>
标签内,并自动为其添加v-slot:指令绑定default具名。
c、<template>
内容
<template>
身处父组件内,可以直接访问父组件的所有数据(变量与函数),所以不需额外向子组件传递参数。<template>
的内容可以是任意合法的模板内容,不局限于文本。例如我们可以传入多个标签,甚至是组件。<template>
标签上的属性不会生效,如下style="color:red"并不会使字体变红
<template #rt style="color:red">
我会变红吗?
</template>
2、v-slot指令规范
v-slot:具名="子参合集对象"
v-slot:指令可简写成#
a、具名
props是通过父标签的属性名来引用DOM的。插槽则是通过<template>
标签的具名来引用DOM。
- 注意具名是指令参数,应以参数形式书写,指令值是子参合集对象。即v-slot:具名=“子参合集对象”。通常不需要子参,因此指令多是无值形式出现,如下:
<template v-slot:具名></template>
简写<template #具名></template>
- 特殊具名default
隐式<template>
会自动绑定default具名。
当父标签内没有隐式<template>
时,可以给非隐式的<template>
标签手动绑定default具名。
手动具名default的简写形式v-slot:或#
。
default具名的<template>
在子组件里引用时有略写形式(见后文“<slot>
标签规范--default略写”)。 <template>
子标签不可再具名<template>
子标签不可再具名。父标签下的非<template>
标签已是隐式<template>
标签的子标签,不可再具名,否则系统会报错。- 具名唯一性
具名唯一,不可与其它<template>
标签的具名相同。父标签下的非<template>
标签会生成具名为“default”的隐式<template>
,其它<template>
标签不可再具名为“default”,这会违反具名唯一性。 - 动态具名
具名可以是动态值,具名变量要放在[]中括号里,如下:<template #[de]>我具名可变</template>
。
b、子参合集对象
- v-slot指令值是子参合集对象
v-slot指令值是子参合集对象,子组件传递过来的参数是此对象的子属性。v-slot指令无值则无法接收子传过来参数。 - 子参合集对象解构
可以直接在v-slot指令值上原地解构,获得子参合集对象内的一个子参,如:<template #="{bb}">
- 子参作用域
子参只能在本v-slot指令标签及下级标签上使用,不能在本v-slot指令标签外使用。 - 事件、自定义事件子参的书写
事件子参要注意事件名前要加on,首写字母要大写。 隐式具名插槽的弊端
隐式具名插槽无法给v-slot指令赋值,所以尽量不要使用隐式具名插槽,而是把非<template>
标签放到<template>
里并手动具名default。
接收子参如下:
父组件<template> <HelloWor :oj="wow"> <template #de="zican"><button ref="wow" @click="ed" >{{zican.oo}}</button></template> </HelloWor> </template> <script setup> import HelloWor from './Hello.vue' import {ref}from 'vue' const wow=ref({}) function ed(){console.log('能成功打印吗')} </script>
子组件
<template> <slot name="de" oo="广州市"></slot> {{$attrs.oj.outerHTML}} </template>
三、<slot>
规范
1、name配对
子组件通过<slot>
标签的name属性值与父标签内的<template>
标签的v-slot:指令具名配对接收<template>
。
2、<slot>
name同名
子组件多个<slot>
标签可以引入同一个<template>
,name值为同一<template>
具名
3、default略写
name="default"时,可以略写,即<slot name="default"></slot>
可以略写成<slot></slot>
略写的<slot>
标签会与父标签内具名为default的<template>
标签配对。
4、<template>
缺省
可设置无<template>
配对时<slot>
的缺省内容,缺省内容书写在<slot>
标签下。
缺省内容只在没有配对到<template>
时才会渲显示。
5、<slot>
传参
<slot>
标签内的属性与事件并不会作用引入的<template>
及缺省<template>
时的内容。只单纯的传递参数的作用。
可传递的内容:子组件的所有数据(变量、函数)及<slot>
标签事件。
实例如下:
父组件
<template>
<HelloWor >
<template v-slot:rtr="hhh" >
<button @click="hhh.onClick" >测试事件子传父</button>
</template>
<template v-slot:default="tt">
{{ tt.oo}}
</template>
<template #rt style="color:red">
我会变红吗?
</template>
</HelloWor>
</template>
<script setup>
import HelloWor from './Hello.vue'
</script>
子组件
<template>
<slot oo="我引入具名default的<lttemplate >"></slot><br>
<slot oo="我也是引入具名default的<lttemplate >"></slot><br>
<slot name="rt"></slot><br>
<slot name="rtr" @click="()=>{console.log('事件子传父')}"></slot><br>
<slot name="rrrtr"><button>我是<template >缺省内容</button></slot>
</template>
<script></script>
四、无逻辑父组件与无渲染子组件
插槽子传父可以导致父组件不需要逻辑部来处理数据,只专注于显示DOM,而子组件不需要模板部来显示DOM,只专注于处理数据。这种父组件可称为无逻辑组件,子组件可称为无渲染组件。
虽然这个模式很简便,但大部分能用无渲染组件实现的功能都可以通过组合式 API 以另一种更高效的方式实现,并且还不会带来额外组件嵌套的开销。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。