【Vue】vue2.6插槽slot使用详解(更新v-slot用法总结)
vue2.6插槽slot使用详解(更新v-slot用法总结)0、 插槽简介1、匿名插槽(默认插槽default)2、具名插槽(name)2.1 对 v-slot:todo 做操作:3、作用域插槽3.2 解构插槽Prop3.3 独占默认插槽(当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用)总结todo-list实例在 2.6.0 中,具名插槽和作用域插槽引入了一个新的统一的语法
vue2.6插槽slot使用详解(更新v-slot用法总结)
在 2.6.0 中,具名插槽和作用域插槽引入了一个新的统一的语法 (即
v-slot
指令)。
它取代了slot
和slot-scope
这两个目前已被废弃但未被移除且仍在文档中的attribute
。
一、 插槽简介
Vue
实现了一套内容分发的 API
,即:将<slot></slot>
元素作为承载分发内容的出口。
插槽作用: 父页面在组件标签内插入任意内容,子组件内插槽slot控制摆放位置(匿名插槽,具名插槽)。
插槽分类(共三类):
- 匿名插槽(也叫默认插槽): 没有命名,有且只有一个
- 具名插槽: 相对匿名插槽组件slot标签带name命名的
- 作用域插槽: 子组件内数据可以被父页面拿到(解决了数据只能从父页面传递给子组件的问题)
二、插槽的使用
2.1 匿名插槽
规则:
- 匿名插槽只有一个
- 一个不带
name
的<slot>
出口会带有隐含的名字default
- 父组件调用带有插槽的子组件,并传入值给子组件,替代子组件的默认值
<slot>默认值</slot>
2.2 具名插槽
规则:
slot
有name
属性,可以有多个具名插槽- 任何没有被包裹在带有
v-slot
中的内容都会被视为默认插槽的内容
2.3 匿名与具名插槽的使用
注意 v-slot
只能添加在<template>
上 (只有一种例外情况),这一点和已经废弃的 attribute
不同。
定义插槽 base-layout.vue
有时我们需要多个插槽。例如对于一个带有如下模板的 <base-layout>
组件:
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
使用插槽:
在向具名插槽提供内容的时候,我们可以在一个 <template>
元素上使用 v-slot
指令,并以v-slot
的参数的形式提供其名称:
<base-layout>
<template v-slot:header>
<h1>我是头部header</h1>
</template>
<p>未指定的内容默认归结为匿名插槽内容1</p>
未指定的内容默认归结为匿名插槽内容2
<template v-slot:footer>
<p>我是尾部footer</p>
</template>
</base-layout>
//v-slot:default写上感觉和具名写法比较统一,容易理解,也可以不用写
现在<template>
元素中的所有内容都将会被传入相应的插槽。
任何没有被包裹在带有 v-slot
的 <template>
中的内容都会被视为默认插槽的内容。
最后页面显示如下
我是头部header
未指定的内容默认归结为匿名插槽内容1
未指定的内容默认归结为匿名插槽内容2
我是尾部footer
2.4. 作用域插槽
自 2.6.0 起有所更新。已废弃的使用
slot-scope
attribute 的语法在这里。
规则:
- 父级模板里的所有内容都是在父级作用域中编译的;
- 子模板里的所有内容都是在子作用域中编译的。
作用域插槽
让插槽内容能够访问子组件中才有的数据
子组件
<slot name="todo" :user="user" :test="test">
{{ user.lastName }}
</slot>
data() {
return {
user:{
lastName:"张",
firstName:"三"
},
test:[1,2,3,4]
}
},
// {{ user.lastName }}是默认数据 v-slot:todo 当父页面没有(="slotProps")时显示: 张
父页面
重点是slotProps接取子组件里:user="user" :test="test"
类似属性的数据
<todo-list>
<template v-slot:todo="slotProps" >
{{slotProps.user.firstName}}
</template>
</todo-list>
//slotProps 可以随意命名
//slotProps 接取的是子组件标签slot上属性数据的集合所有v-bind:user="user"
最后显示
三
2.4.1 解构插槽Prop
这样可以使模板更简洁,尤其是在该插槽提供了多个 prop
的时候。
父组件:
// 相当于
function (slotProps) {
// 插槽内容
}
(slotProps)=>参数可以用slot标签上现有的值({user,test})替换
<todo-list>
<template v-slot:todo="{user,test}" >
{{user.firstName}} //此处原来需要写为{{slotProps.user.firstName}}
</template>
</todo-list>
## 显示 ##
## // yue
子组件:
<slot name="todo" :user="user" :test="test">
{{ user.lastName }}
</slot>
data() {
return {
user:{
lastName:"Zhang",
firstName:"yue"
},
test:[1,2,3,4]
}
},
## 显示 ##
// yue
参数值替换名字
<todo-list>
<template v-slot:todo="{user:person,test}" >
{{person.firstName}}
</template>
</todo-list>
// v-slot:[dynamicSlotName]="{user:person,test}
## 显示 ##
## // yue
注意v-slot
只能添加在<template>
上,只有一种例外情况,如下:独占默认插槽(当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用)
2.4.2 独占默认插槽
当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用
父组件:
//原本是需要写template
<todo-list>
<template v-slot:default="slotProps" >
{{slotProps.user.firstName}}
</template>
</todo-list>
<!--当被提供的内容只有默认插槽时 v-slot等属性可以直接写在组件标签上-->
<todo-list v-slot:default="slotProps" >
{{slotProps.user.firstName}}
</todo-list>
//或者简写
<todo-list #default="slotProps">
{{slotProps.user.firstName}}
</todo-list>
子组件:
<slot :user="user" :test="test">
{{ user.lastName }}
</slot>
data() {
return {
user:{
lastName:"Zhang",
firstName:"yue"
},
test:[1,2,3,4]
}
},
## 显示 ##
// yue
2.5 缩写形式
跟v-on
和v-bind
一样,v-slot
也有缩写,即把参数之前的所有内容 (v-slot:
) 替换为字符 #
。
例如: v-slot:header
可以被重写为#header
使用插槽 <base-layout>
组件:
<base-layout>
<template #header>
<h1>我是头部header</h1>
</template>
<p>未指定的内容默认归结为匿名插槽内容1</p>
未指定的内容默认归结为匿名插槽内容2
<template #footer>
<p>我是尾部footer</p>
</template>
</base-layout>
三、插槽示例
3.1 todo-list实例
父页面
<template>
<div>
新插槽 v-slot 代替具名插槽 作用于插槽
<todo-list>
<template #todo="{todos:list}">
<div @click = type(todos.id)>
{{list.text}}
</div>
</template>
</todo-list>
</div >
</template>
<script>
import todoList from "@/components/component/slotTodoChildren";
export default {
name:"vSlot",
components:{
todoList
},
data() {
return {
}
},
methods: {
type(data){
console.log(data)
}
},
}
</script>
子组件
<template>
<ul class="slotTodoChildren">
<li class="list"
v-for="todo in todoList"
v-bind:key="todo.id"
>
<!--
我们为每个 todo 准备了一个插槽,
将 `todo(todoList里的)` 对象作为一个插槽的 prop 传入。
-->
<slot name="todo" :todos="todo">
<!-- 后备内容 -->
{{ todo.text }}
</slot>
</li>
</ul>
</template>
<script>
export default {
name:"slotChildren",
data() {
return {
todoList:[
{
id:1,
text:"扫地"
},
{
id:2,
text:"做饭"
},
{
id:3,
text:"擦桌子"
}
]
}
},
created(){
console.log(this.filteredTodos)
}
}
</script>
<style scoped>
.slotTodoChildren .list{
display: block;
background: #434534;
line-height:40px;
margin-top: 10px;
color: #fff;
font-size: 24px;
height: 40px;
}
</style>
3.2 实际使用示例
title是插槽名,插入的内容是node
老写法
<app-tree
class="border-spe-right"
:treeConfig="treeConfig"
:expandedKeys.sync="treeConfig.defaultExpandedKeys"
:selectedKeys="treeConfig.defaultSelectedKeys"
:tree-data="treeData"
:handle="handle"
style="width: 20%"
:onSearch="onSearch"
:onSelect="onSelect"
:onLoadData="onLoadData"
@selectNode="onSelectNode"
>
<div slot="title" class="system-role-title" slot-scope="{ node }">
<div class="title-icon" :class="node.icon"></div>
<div class="title-label">{{ node.label }}</div>
</div>
</app-tree>
新写法
<app-tree
class="half"
:treeConfig="treeConfig"
:expandedKeys.sync="treeConfig.defaultExpandedKeys"
:selectedKeys="treeConfig.defaultSelectedKeys"
:checkedKeys.sync="treeConfig.defaultCheckedKeys"
:tree-data="treeData"
:onSearch="onSearch"
:onSelect="onSelect"
:onLoadData="onLoadData"
>
<template #title="{ node }">
<div class="title-icon" :class="node.icon"></div>
<div class="title-label">{{ node.label }}</div>
</template>
</app-tree>
四、总结
在用上v-slot之后 只需要考虑好
- 是否需要命名(匿名插槽,具名插槽)
- 父页面是否需要取存在子页面的数据(作用域插槽)
更多推荐
所有评论(0)