Vue插槽的使用

前言

上面两篇文章介绍了组件注册和父子组件之间通信的基本方式,当然父子组件通信不光只有常用的props属性,还有另外几种方式,不先介绍。这里主要介绍插槽。什么是插槽?在定义组件之后我想在html中另外新加入几个内容,这种情况肯定不可能再重新从组件模板中添加。插槽可以解决这个问题。

基础实例

<div id="app">
    <father title="这里是标签">
        插槽的使用
    </father>
</div>

<template id="father">
    <slot>father {{title}}</slot>
</template>

在这个实例中直接把一个<slot></slot>作为一个元素,默认是father,但是在<father></father>标签中我插入了一条语句,那么这条语句会直接渲染进<slot></slot>标签中。可以注意到,在<slot></slot>标签中有一个{{title}},如果打开控制台可以发现是有报错的,也就是说我们不可以使用这个值。作为一条规则要记住:

父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

具名插槽

有的时候,我们需要多个插槽,这种情况可以为插槽命名,使用的时候指明名字。
这是时候需要认识一个新的指令v-slot
使用: 可放置在函数参数位置的 JavaScript 表达式 (在支持的环境下可使用解构)。可选,即只需要在为插槽传入 prop 的时候使用。
参数: 插槽名 (可选,默认值是 default)
限用于: <template>、组件 (对于一个单独的带 prop 的默认插槽)

<body>
<div id="app">
    <child>
    	<!--    name=child插槽    -->
        <template v-slot:child>
        	...
        </template>
       
       <!--    默认插槽    -->
        <template v-slot>
        	...
        </template>
        
        <!--    name=otherr插槽的缩写    -->
        <template #otherr>
        	...
        </template>

    </child>
</div>

<template id = "child">
    <div>
        <h1>I am a child</h1>
        <slot name="child" >child</slot>
        <slot>default</slot>
        <slot name="otherr">other</slot>
    </div>
</template>


<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    new Vue({
        el: '#app',
        components: {
            child:{
                template: "#child"
            }
        }
    })
</script>
</body>

通过v-slot指令,我们可以绑定命名的插槽,和v-onv-bind指令一样,这条指令也有缩写#。如果指令后面什么都没有,那么就是使用默认插槽。

作用域插槽

作用域插槽就是让插槽内容能够访问子组件中才有的数据。例如,设想一个带有如下模板的 <current-user> 组件:

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

我们可能想换掉备用内容,用名而非姓来显示。如下:

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

然而上述代码不会正常工作,因为只有 <current-user> 组件可以访问到 user 而我们提供的内容是在父级渲染的。
为了让 user 在父级的插槽内容中可用,我们可以将 user 作为 <slot> 元素的一个 attribute 绑定上去:

<span>
  <slot v-bind:user="user">
    {{ user.lastName }}
  </slot>
</span>

绑定在 <slot> 元素上的 attribute 被称为插槽 prop。现在在父级作用域中,我们可以使用带值的 v-slot 来定义我们提供的插槽 prop 的名字:

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>
</current-user>

在这个例子中,我们选择将包含所有插槽 prop 的对象命名为 slotProps,但也可以使用任意名。
接着上个具名插槽的案例,进行拓展实现:

<body>
<div id="app">
    <child>
		<!--    name=child插槽    -->
        <template  #child="value">
            <p>value.cname: {{value.cname}}</p>
        </template>
        <!--    默认插槽    -->
        <template v-slot="slotProps">
            <p> slotProps.obj:{{slotProps.obj}}</p>
        </template>
        <!--    name=otherr插槽的缩写    -->
        <template #otherr="slotValue">
            <p>slotValue.age:{{slotValue.age}}</p>
        </template>

    </child>
</div>

<template id="child">
    <div>
        <h1>I am a child</h1>
        <slot name="child" :cname="name">kid</slot>
        <slot :obj="obj">sdfgdf</slot>
        <slot name="otherr" :age="age">other</slot>
    </div>
</template>


<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    new Vue({
        el: '#app',
        components: {
            child:{
                data(){
                    return{
                        name:"Jock",
                        age:18,
                        obj:[{id:1,title:"aaaaa"},
                            {id:2,title:"bbbbb"},
                            {id:3,title:"ccccc"}]
                    }
                },
                template: "#child"
            }
        }
    })
</script>
</body>
<!--
渲染效果
value.cname: Jock
slotProps.obj:[ { "id": 1, "title": "aaaaa" }, { "id": 2, "title": "bbbbb" }, { "id": 3, "title": "ccccc" } ]
slotValue.age:18
-->

总结

  1. 和组件中的属性template不同,这种情况下使用<template>,可以不用一个根元素包裹
  2. 可以通过v-slot:name 或者 #name进行插槽的绑定
  3. v-slot:default="slotProps"作用域传值,因为default 可以进行省略成v-slot="slotProps"
  4. 对不同插槽实行作用域的时候可以写成 v-slot:name="value" 或者简写成#name=“value”
  5. name已经被作为<slot>属性使用,不可在作用域插槽作为属性绑定
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值