Vue官方文档中,我们可以通过插槽分发内容。
<slot>元素作为承载分发内容的出口:即在一个组件模板中使用<solt>,在使用该组件时,开始与结束标签中包含的内容会替换掉<slot></slot>;
Vue.component(navigation-link,{
template: '
<a :href="url" class="nav-link">
<slot></slot> //此处将被替换 可以包含任何模板代码,html或者其他组件
</a>'
})
使用全局注册的组件时有:
<navigation-link url="/profile"> 我是使用组件时由插槽插入的内容 </navigation-link>
//当组件navigation-link的template中没有包含slot元素,则此处位于开始结束标签之内的内容会被抛弃
1.插槽的编译作用域(父级模板内的所有内容都是在父级作用域中编译的,子模板中的所有内容都是在子作用域中编译的),插槽跟模板其他地方一样可以访问相同的实例属性,不能访问上述<navigation-link>的作用域,例如url(非组件内部定义的).
2.插槽的默认内容
插槽的默认内容只会在没有提供内容的时候被渲染。默认内容写在<slot></slot>中:
Vue.component(navigation-link,{
template: '
<a :href="url" class="nav-link">
<slot>hello,我是默认内容!没有提供时我会被渲染!</slot>
</a>'
})
情况1(没有提供内容):
<navigation-link url="/profile"></navigation-link>
情况2(提供内容):
<navigation-link url="/profile"> 我会替换默认内容! </navigation-link>
- 具名插槽
<slot>有一个特殊属性:name,可以用来定义额外的插槽(一个模板可能使用多个插槽,需要准确定位不同内容插入到不同位置),使用方法:
<slot name="xxx"></slot>
给具名插槽提供内容时,在一个<template>元素上使用v-slot指令,以指令的参数形式提供名称:
Vue.component(navigation-link,{
template: '
<a :href="url" class="nav-link">
<slot name="one">我是插槽1的默认内容!</slot>
</a>
<p><slot name="two">我是插槽2的默认内容!</slot></p>
<slot>我是默认插槽!</slot>'
})
使用组件(利用template给具名插槽提供内容,默认插槽的内容可以用带有v-slot:default的<template>包含):
<navigation-link>
<template v-slot:one>
www.baidu.com
</template> //给插槽1提供内容
<template v-slot:two>
大家好,我给插槽2提供内容,我是一个正儿八经的段落!
</template> //给插槽2提供内容
我没有被包裹在带有v-slot的<template>中,我给默认插槽提供内容!
</navigation-link>
4.插槽prop
上面我们说过插槽是有编译作用域的。当一个变量定义在子组件模板中,当我们在父组件中替换插槽的默认内容时想访问子组件定义的变量,直接使用变量名访问是不可以的,因为提供的插槽内容是在父级渲染的。
解决方法: 想要在父组件插槽内容中访问子组件定义的变量,就在子组件中将该变量作为<slot>的一个属性绑定(插槽prop,绑在slot元素上的属性),举例
<slot v-bind: user="user"> //插槽prop
父组件中使用带值的v-slot来定义提供的插槽prop的名字
<XXX>
<template v-slot:default="slotProps"> //包含所有插槽prop的对象暂时命名为slotProps
{{slotProps.user.firstname}}
</template>
</XXX>
- 解构插槽prop
作用域插槽的内部原理:将插槽内容包括在一个传入单个参数的函数中:
function(slotProps){
插槽内容 }
- v-slot的缩写: #(只在有参数的时候使用)
v-slot: one 等价于 #one
网友评论