今天学了啥-23/03/28 vue提供slot机制让组件可以接收模板片段,来渲染模板片段。比如最常见的button组件,基本是如下这样使用。
<FancyButton>
Click me! <!-- 插槽内容 -->
</FancyButton>
FancyButton
组件则是这样:
<button class="fancy-btn">
<slot></slot> <!-- 插槽出口 -->
</button>
不过我的重点不是这个基本的slot,我的重点是scope slot,首先安装vue中对slot的定义,slot是无法访问到子组件的状态。
因为插槽内容是在父组件渲染的,插槽内容的数据也是由父组件定义的。
<FancyButton>{{ message }}</FancyButton>
插槽内容无法访问子组件的数据。Vue 模板中的表达式只能访问其定义时所处的作用域,这和 JavaScript 的词法作用域规则是一致的。父组件模板中的表达式只能访问父组件的作用域;子组件模板中的表达式只能访问子组件的作用域。
比如上面代码中message它是在父组件定义,message的数据也是由父组件提供。它是在父组件渲染,虽然它插入了fancyButton组件中但是无法访问fancybutton组件定义的数据。
但是有时候在项目中会遇到这种问题,插槽内容需要访问子组件的数据。
比如已经写好的组件ComponentA和componentB组件,现在我们要扩展componentA组件功能,要在ComponentA中使用ComponentB功能,但是B组件只是在某个功能才需要渲染,如果把componentB直接引入ComponentA,必须时刻使用v-if来控制渲染,有点麻烦。
所以我想到使用scope slot功能,scope slot机制可以让插槽组件访问子组件数据。
用vue3的scope slots文档 的例子,
<!--MyComponent-->
<script>
export default {
data() {
return {
greetingMessage: 'hello'
}
}
}
</script>
<template>
<div>
<slot :text="greetingMessage" :count="1"></slot>
</div>
</template>
MyComponent组件内部定义了数据和插槽。
<script>
import MyComponent from './MyComponent.vue'
export default {
components: {
MyComponent
}
}
</script>
<template>
<MyComponent v-slot="slotProps">
{{ slotProps.text }} {{ slotProps.count }}
</MyComponent>
</template>
像对组件传递 props 那样,向插槽内容传递 attributes,定义slotProps变量。
此时MyComponent
v-slot的slotProps
可以接受到MyComponent组件定义的text和count数据,实际上此时slotProps={text:'hello',count:1}
。那么MyComponent
插槽模板就能接收到数据从而渲染。
你可以把MyComponent例子类别为如下函数:
MyComponent({
// 类比默认插槽,将其想成一个函数
default: (slotProps) => {
return `${slotProps.text} ${slotProps.count}`
}
})
function MyComponent(slots) {
const greetingMessage = 'hello'
return `<div>${
// 在插槽函数调用时传入 props
slots.default({ text: greetingMessage, count: 1 })
}</div>`
}
MyComponent
它的参数slots只接受函数(模板片段),函数内部有定义好的变量,一旦传入参数就会生成新的模板字符串。
slotProps
数据是MyComponent
组件内部提供,实际上这个例子基本不可能,最常见的是数据通过props传递过来的。所以我们要改造下MyComponent
让它更接近实际碰到的样子。
<!--MyComponent-->
<script lang="ts" setup>
import {ref} from 'vue'
const info = ref<any>()
const showInfo =(data:any)=>{
info.value = data
}
defineExpose({
showInfo
})
</script>
<template>
<div>
<slot v-bind="info"></slot>
</div>
</template>
Parent
<script setup>
import MyComponent from './MyComponent.vue'
import {ref} from 'vue'
const componentRef =ref()
componentRef.value.showInfo({text:'hello',count:1})
</script>
<template>
<MyComponent v-slot="slotProps" ref="componentRef">
{{ slotProps.text }} {{ slotProps.count }}
</MyComponent>
</template>
在parent组件中使用showInfo将数据传入,Component就能绑定传入的数据。从而进行渲染。
标签:slot,插槽,slotProps,MyComponent,vue3,组件,Scope,模板
From: https://www.cnblogs.com/aliceKurapika/p/17338459.html