目录
在实际应用在slot(插槽)使用的也是很广的,是要求掌握的内容。尤其到后面章节使用第三方组件(比如饿了么的pc vue插件element)实现 修改 保存 删除 功能时,很多很广。
项目例子也是基于《vue 2.1:vue cli默认项目结构及其vue编写规则》的所创建的工程基础上进行修改的
一、为什么要用slot插槽
我们前面所学的父子组件中,子组件中的模板一般是固定的,如果要像html那样,可以在标签之间填写内容,如下面形式
<组件标签>内容<组件标签>
上面的形式内容是不会被显示的,项目例子也是基于《vue 2.1:vue cli默认项目结构及其vue编写规则》的所创建的工程基础上进行修改的,我把HelloWorld.vue改为t1.vue,如下图所示:
src/components/T1.vue代码如下:
<template>
<div>
<h3>this is t1 componment</h3>
</div>
</template>
<script>
export default {
name: 't1',
}
</script>
src/App.vue 代码如下:
<template>
<div id="app">
<mycom>这是父组件内容</mycom>
</div>
</template>
<script>
import T1 from "@/components/T1";
export default {
name: 'App',
components: {
'mycom':T1
}
}
</script>
<style>
/* 没有样式*/
</style>
运行结果为:hello vue
并没有“这是父组件内容”字样,因为你突然在标签中添加了内容,vue不知道你具体放哪个位置,你得告诉它放哪里。如果我要显示这个字样怎办?
我们知道在开发中有一个名称叫“占位符”,占位符就是先占住一个固定的位置,等着你再往里面添加内容的符号。占位符其实就告诉你,这个位置我占了,等下我的内容就在放在这个位置。vue也有这样相似的,叫插槽。
二、插槽介绍
2.1 介绍
我这里所说的插槽solt,主要是2.6的。在 2.6.0 中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot
指令)。它取代了 slot
和 slot-scope
作用域插槽slot-scope主要应用让插槽内容能够访问子组件中才有的数据
官方准则:父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译
简单来说:你不能在子组件直接使用父级组件中的数据
插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示,默认情况下组件内部包裹的内容是不会显示的,如果需要进行显示则需要通过插槽来进行显示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。
作用域插槽简单来说就是父组件只管显示样式,数据由子组件来提供.
个人简单理解就是:父组件中的数据,在子组件的“占位符”标签<solt>中显示
2.2 v-slot命令介绍
2.2.1 使用方法
我这里直接使用最新的,不再讲slot
和 slot-scope
有兴趣可以去vue中看相关内容。
- 缩写:
#
- 预期:可放置在函数参数位置的 JavaScript 表达式 (在支持的环境下可使用解构)。可选,即只需要在为插槽传入 prop 的时候使用。
- 参数:插槽名 (可选,默认值是
default
) - 限用于
<template>
- 组件 (对于一个单独的带 prop 的默认插槽)
- 用法:
提供具名插槽或需要接收 prop 的插槽。
2.2.2 相关说明
插槽的名字现在通过 v-slot:slotName
这种形式来使用
没有名字的 <slot>
隐含有一个 "default"
名称
v-slot:default="slotProps" 可以简写成 v-slot="slotProps" 可以看vue官方说明
请注意, v-slot
只能添加到 <template>
或自定义组件上,这点与弃用的 slot 属性不同
例子请看“Vue.js 你需要知道的 v-slot (译)”,此例子要学了后面的npm编写vue才能看懂,这里可以跳过。
三、例子
3.1 没有指定插槽名字
我在上面的例子T1.uve的基础上进行修改,把模板部分修改成如下这样
<template>
<div>
<slot></slot>
<h3>this is t1 componment</h3>
</div>
</template>
<script>
export default {
name: 't1',
}
</script>
运行效果:
我把<slot>标签和<h3>标签互换一下
<template>
<div>
<h3>this is t1 componment</h3>
<slot></slot>
</div>
</template>
运行后效果如下:
这样理解什么是“占位符”了吧,就是在那里先占着“位置”,内容就放在那个“位置”里
3.2 指定插槽名
3.2.1 指定插槽名
这个也简单,在<slot>标签添加name属性,如上面例子,我把t1.vue的slot修改一下
<template>
<div>
<slot name="s1"></slot>
<h3>this is t1 componment</h3>
</div>
</template>
再修改一下App.vue内容如下:
在父组件中,要使用v-slot:<slot名>来指定你要使用哪个点位符
<template>
<div id="app">
<mycom v-slot:s1>这是父组件内容</mycom>
</div>
</template>
运行后效果与上面代码一样:
PS:如果在父组件中你指定的名字不存在,那么内容将不会显示,vue调试会 “连接中断”
3.3 修改值(不错)
这个功能很有用,可以直接修改子组件的值,比如默认值,显示效果。
上面t1.vue代码修改如下:
为了让 stu
在父级的插槽内容中可用,我们可以将 stu
作为 <slot>
元素的一个 attribute 绑定上去,
我这里定义为student
<template>
<div>
<slot name="s1" :student="stu">{{stu.name}}</slot>
<h3>this is t1 componment</h3>
</div>
</template>
<script>
export default {
name: 't1',
data() {
return{
stu: {
name: 'liLei',
id: '1',
yuWen: 90,
shuXue: 99
}
}
}
}
</script>
App.vue修改为:
<template>
<div id="app">
<mycom>
<!-- 要为此插槽起一个名字,这个名字随便起,一般推荐按项目规范起,
如没有规范,可以起一个方便别人阅读和理解的名字
-->
<template v-slot:s1="father">
<!-- 在父组件用的是student 属性,不能直接用 father.stu.yuWen 否则会报错:
TypeError: father.stu is undefined
-->
{{father.student.name}}:{{father.student.yuWen}}
</template>
</mycom>
</div>
</template>
<script>
import T1 from "@/components/T1";
export default {
name: 'App',
components: {
'mycom':T1
}
}
</script>
<style>
/* 没有样式*/
</style>
运行效果为: