官方学习网站 https://cn.vuejs.org/
1.Vue中插槽的使用和方法
定义一个名child子组件,为该子组件添加内容应该在子组件的template中定义,直接在父组件的<child>标签中定义的内容不会被渲染,如下例。
<div id="root">
<child>
需要插槽才能渲染的内容
<p>Dell</p>
<p>Lee</p>
</child>
</div>
<script>
Vue.component('child',{
template: `<div>
<p>这是子组件中正常渲染的内容</p>
</div>`
}
)
var vm=new Vue![在这里插入图片描述](https://img-blog.csdnimg.cn/20190322092601331.png)({
el:'#root'
})
</script>
运行结果如下图
使用插槽就能解决这个问题。在子组件template中加入元素占位,便能渲染父组件标签下的内容,对上例的子组件修改为:
Vue.component('child',{
template: `<div>
<p>这是子组件中正常渲染的内容</p>
<slot></slot>
</div>`
}
)
结果:
2、插槽默认内容
插槽可以提供一个默认内容,如果如果父组件没有为这个插槽提供了内容,会显示默认的内容。如果父组件为这个插槽提供了内容,则默认的内容会被替换掉
父组件没有提供插槽内容
<div id="root">
<child></child>
</div>
<script>
Vue.component('child',{
template:'<div><slot>defalut value</slot></div>
}
)
var vm=new Vue({
el:'#root'
})
</script>
如果父组件中提供了渲染了新的内容,那么默认部分就会被替代
3.具名插槽
当需要多个插槽时,可以使用的特性:name。这个特性可以用来定义额外的插槽
使用方法如下例
<div id="root">
<child>
<header slot="header">header</header>
<footer slot="footer">footer</footer>
</child>
</div>
<script>
Vue.component('child',{
template:`<div>
<slot name="header">default header</slot>
<div>content</div>
<slot name="footer">default footer</slot>
</div>`
}
)
var vm=new Vue({
el:'#root'
})
</script>
4.作用域插槽
有时让插槽内容能够访问子组件中才有的数据很有用的,
有时让插槽内容能够访问子组件中才有的数据是很有用的。例如,设想一个带有如下模板的 组件:
<span>
<slot>{{ user.lastName }}</slot>
</span>
我们想让它的后备内容显示用户的名,以取代正常情况下用户的姓,如下:
<current-user>
{{ user.firstName }}
</current-user>
然而上述代码不会正常工作,因为只有 组件可以访问到 user 而我们提供的内容是在父级渲染的。
为了让 user 在父级的插槽内容可用,我们可以将 user 作为一个 元素的特性绑定上去:
<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
绑定在 元素上的特性被称为插槽 prop。现在在父级作用域中,我们可以给 v-slot 带一个值来定义我们提供的插槽 prop 的名字:
绑定在 元素上的特性被称为插槽 prop。现在在父级作用域中,我们可以给 v-slot 带一个值来定义我们提供的插槽 prop 的名字:
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
在这个例子中,我们选择将包含所有插槽 prop 的对象命名为 slotProps,但你也可以使用任意你喜欢的名字。
具名插槽和作用域插槽
相同点:
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
{{ slotProps.user.firstName }} 相同点:(1)在组件中都会用到用到 不同点:(1)具名插槽子定义组件时使用,然后与父组件中template相对应 (2)作用域插槽在子组件定义时给slot绑定了一个变量,因为要在父组件的渲染元素中使用,
<slot 、name="header" v-bind:user1="user1">
<slot 、name="header" v-bind:user2="user1">
该语法的含义为我给slot绑定了一个user变量,这个user变量只想user对象,在父组件中的渲染调用方式为
<current-user>
<template v-slot:header="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
注1:在这里首先要用template接收一下子组件中绑定的变量,这里接收到的slotprops是一个对象,因为在子组件中可能会有多个slot给header传递数据,如上述代码,然后在父组件接收时,我们需要调用具体的值
注2:slotProps输出如下图
f猜测是一次性把所有绑定的变量以对象的形式接收过来,然后在渲染内容中使用。这里的“default”含义是该插槽为默认插槽,如果是其他名,就用对应的name
4.1独占默认插槽的缩写语法
在上述情况下,当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用。这样我们就可以把 v-slot 直接用在组件上:
<current-user v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</current-user>
这种写法还可以更简单。就像假定未指明的内容对应默认插槽一样,不带参数但 v-slot 被假定对应默认插槽:
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
</current-user>
总结:如果是默认插槽,那么在接收prop对象时,就可以省去template标签,如上面代码所示。
注意:默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确:
<!-- 无效,会导致警告 -->
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
<template v-slot:other="otherSlotProps">
slotProps is NOT available here
</template>
</current-user>
只要出现多个插槽,请始终为所有的插槽使用完整的基于 的语法:
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
<template v-slot:other="otherSlotProps">
...
</template>
</current-user>
总结:上面一段话的含义是,如果既有默认插槽好其他具名插槽,就不能使用默认插槽的缩写形式,应该使用完整的template语法
4.2解构插槽 Prop
作用域插槽的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里:
function (slotProps) {
// 插槽内容
}
这意味着 v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。所以在支持的环境下 (单文件组件或现代浏览器),你也可以使用 ES2015 解构来传入具体的插槽 prop,如下:
<current-user v-slot="{ user }">
{{ user.firstName }}
</current-user>
这样可以使模板更简洁,尤其是在该插槽提供了多个 prop 的时候。它同样开启了 prop 重命名等其它可能,例如将 user 重命名为 person:
<current-user v-slot="{ user: person }">
{{ person.firstName }}
</current-user>
你甚至可以定义后备内容,用于插槽 prop 是 undefined 的情形:
<current-user v-slot="{ user = { firstName: 'Guest' } }">
{{ user.firstName }}
</current-user>
解构插槽prop,让我们真正认识了-v-lot,可以给提供的prop重命名,当传过来的prop参数没有具体内容时,还可以自定义内容
注意:
(1)这里和前面部分提到的作用域插槽的区别,也就是说区分两种语法:
<current-user v-slot="{ user }"> 和 <template v-slot:other="otherSlotProps">
第一种方式直接传递过来了具体,如图,采用双引号加大括号,第二种方式传递过来了一个对象组
(2)可以自己重命名
<template v-slot:header="{user1:person}">
{{ person }}
</template>