Vue Slot 层级、作用域详解

本文详细探讨Vue中Slot的工作原理,包括层级关系和作用域。通过实例解析,阐述如何使用v-slot进行反向传参,解释了在不同层级组件间的数据交互。特别指出,尽管在HTML中组件可能呈现嵌套结构,但在JS中它们可能处于同一级别。文章还澄清了官方文档中关于后备内容和姓氏显示的误导,帮助读者理解如何正确地使用Slot传递和访问数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vue slot插槽的作用域在官方教程中有一条说明:
“父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。”
父级模版可以通过prop把参数传递给子级模版,但是反过来是不推荐的。
插槽v-slot就是用来反向传参的。

首先来看一下层级关系,一下是html页面中的dom元素实例

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Language" content="zh-cn">
        <title>Template</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
        <div id="components-demo" level="0">
            <im-level-11 title="how are you." level="1">
                {{ posts[2].title }}
                <im-level-12 :name="posts[1].title" level="1">
                        <template v-slot:default="slotProps">
                            {{ slotProps.user.firstName }} {{ posts[0].title }}
                        </template>
                </im-level-12>
            </im-level-11>
        </div>
        <script src="template.js"></script>
    </body>
</html>

同步对照js代码如下

Vue.component('im-level-11',{
    props:['title'],
    data(){
        return {count: 5,level:2}
    },
    template:`
        <div>
            <label> {{ title }} </label>
            <button @click='count++'>
                You clicked me {{ count }} times.
            </button>
            <slot></slot>
        </div>
    `
});

Vue.component('im-level-12',{
    props:['name'],
    data(){
        return {
            user:{
                lastName:"AJS",
                firstName:"Silvan"
            },
            level:2
        };
    },
    template:`
        <div>
            <label> {{ name }} </label>
            <slot v-bind:user="user"> {{ user.lastName }} </slot>
        </div>
    `
})

var vm = new Vue({
    el: "#components-demo",
    data: {
        posts: [
            { id: 1, title: 'My journey with Vue' },
            { id: 2, title: 'Blogging with Vue' },
            { id: 3, title: 'Why Vue is so fun' }
        ],
        level:1
    }
});

其中components-demo是根节点,在js中vue实例被绑定到了该节点上。
那么components-demo 作为level0
js代码中的vm Vue实例是level1
两个组件im-level-11 im-level-12 实际上是和vm实例同一级的。
在html中可以看到,im-level-11 和 im-level-12 可以直接调用vm实例中的posts数组对象,
虽然im-level-11 和 im-level-12 在html中是嵌套实现的,但是在js中是同级申明的。

在 im-level-11 和 im-level-12 组件内部,作为level2,他们各自的template模版只能直接调用组件内部的数据。

这个时候,子级给父级反向传参可以看im-level-12 的实现
im-level-12 内部有一个user对象,可以直接使用user.lastName值,
而父级level1要直接用同样的user对象则会报错。

在level2的插槽上即 im-level-12的 绑定user,把自己的user对象传去去。
在level1调用组件时直接使用 来接收传出的对象,该对象作为slotProps的属性存在,可以直接用过slotProps.user来访问。

"slotProps"只是一个自定义名称,可以随便改。

这里要吐槽官网的描述,也可能是我理解能力太差,之前一直搞混了。官网有这么一段说明:

<span>
  <slot>{{ user.lastName }}</slot>
</span>

我们想让它的后备内容显示用户的名,以取代正常情况下用户的姓,如下:

<current-user>
  {{ user.firstName }}
</current-user>

我一直没搞明白后备内容不是user.lastName 显示了用户的姓么,怎么又变成名了。还纠结了半天,官网指的lastName难道按照中国人的习惯是名字?

后来终于理解了,现在后备内容区域显示的是姓,要把他用组件改为名字显示。
这一下也终于搞明白,这个user是从子级组件里通过插槽slot传出来给父级组件渲染时调用的。

终于弄明白这个插槽的逻辑了,加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值