插槽的详细解读
编译作用域
什么是编译作用域呢?编译作用域简单来说,子组件有子组件的作用域,父组件有父组件的作用域,在父组件中,你只能访问到父组件的数据。官方文档是这么说的,父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
插槽(slot)
需要插槽的原因
插槽的简单理解就是Usb,他使得我们的程序更有扩展性,让使用者决定到底写入什么内容,比如说,你写的一个组件,他的大体框架可以使用于很多不同的样式,你就可以在里面定义插槽,写入不同的内容。
slot的基本使用
直接看代码
<div id="app">
<my-cpn></my-cpn>
<my-cpn>
<h2>我是插槽修改的内容</h2>
</my-cpn>
</div>
<template id="mycpn">
<div>
<slot>我是默认的内容</slot>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
Vue.component('my-cpn',{
template:'#mycpn'
})
let app = new Vue({
el:'#app'
})
</script>
运行结果如下
我们可以看到使用插槽的逻辑代码其实非常简单,你只需要定义一个slot标签在模板里面,如果你不想改变里边的内容,就什么都不写,显示是默认的内容
具名插槽
具名插槽便是,在slot里边加入一个name属性,这样子我们就得到了一个自定义插槽,而没有显式的写入name属性的插槽,就是一个默认插槽,它的name属性值为default
那我们该如何使用具名插槽呢?
简单来说,就是在父组件中使用v-slot指令,指令后面跟上的就是对应的插槽的名字
代码如下
<div id="app">
<my-cpn></my-cpn>
<my-cpn v-slot:myslot>
<h1>我是具名插槽的内容</h1>
</my-cpn>
</div>
<template id="mycpn">
<div>
<slot name="myslot">我是默认的内容</slot>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
Vue.component('my-cpn',{
template:'#mycpn'
})
let app = new Vue({
el:'#app'
})
</script>
运行结果如下
具名插槽的缩写
v-slot 写为#,例如插槽名字为myslot
正常来说我们是这么写的,v-slot:myslot
缩写可以这么写#myslot
作用域插槽
作用域插槽是插槽这里比较难理解的点,简单来说作用域插槽,就是父组件想要替换子组件的插槽标签,而内容则由子组件来提供。这里有的人会想,为什么我们不能直接将数据从子组件传给父组件呢?当然这是可以的,但在开发中往往你要写的模板是独立的,不能跟内容有太大的联系,这样子复用性就会变低,而且Vue并不建议你从子组件传数据给父组件,所以我们就需要一个作用域插槽。
代码如下
<div id="app">
<my-cpn>
<template v-slot:default="slotprop">
<div>
{{slotprop.data}}
</div>
</template>
</my-cpn>
</div>
<template id="mycpn">
<div>
<slot :data="data">我是默认的内容</slot>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
Vue.component('my-cpn',{
template:'#mycpn',
data() {
return {
data:'我是子组件的数据'
}
},
})
let app = new Vue({
el:'#app'
})
</script>
在子组件中我们将想要传出去的值用v-bind绑定在slot里面,这个值我们称为插槽Prop,它将作为一个对象传入到父组件中,我们在父组件中使用v-slot指令加上default,然后再在后边加上一个名字,我们这里写的名字就是slotprop 这个名字是可以随便起的,这就是插槽对象,然后就可以在父组件中使用了。