组件插槽
用来实现组件内容的分发,通过slot标签,可以接收到写在组件标签内的内容
vue提供组件插槽的能力,允许开发者在封装组件时,把不确定的部分定义为插槽
基础使用–匿名插槽
- 组件内使用slot 占位
- 使用组件时 中间传入标签替换slot
Pannel.vue
<template>
<div>
<div class="title">
<h4>鹅鹅鹅</h4>
<span @click="isShow = !isShow">{{ isShow ? '收起' : '展开' }}</span>
</div>
<div class="container" v-show="isShow">
<!--1: 组件内使用slot 占位 -->
<slot></slot>
</div>
</div>
</template>
<script>
export default {
data() {
return {
isShow: false,
}
},
}
</script>
<style scoped>
h4 {
text-align: center;
}
.title {
display: flex;
justify-content: space-between;
align-items: center;
border: 1px solid #ccc;
padding: 0 10px;
}
.title h4 {
line-height: 2;
margin: 0;
}
.container {
border: 1px solid #ccc;
padding: 0 10px;
}
</style>
App.vue
<template>
<div>
<!-- 2 使用组件时 pannel
在组件中间 传入标签替换slot -->
<pannel>
<p>曲项向天歌</p>
<p>曲项向天歌</p>
<p>曲项向天歌</p>
<p>曲项向天歌</p>
<p>曲项向天歌</p>
</pannel>
<pannel>
<img src="./assets/logo.png" alt="" />
</pannel>
</div>
</template>
<script>
import Pannel from './components/Pannel.vue'
export default {
components: { Pannel },
}
</script>
默认内容
如果外面不给传,想给个默认显示内容
夹着内容默认显示内容,如果不给插槽slot传东西,就使用slot夹着的内容在原地显示
<slot>默认内容</slot>
具名插槽
当一个组件内有2处以上需要外部传入标签的地方
传入的标签可以分别派发给不同的slot位置
v-slot一般跟template标签使用(template是HTML5新出标签内容模板元素,不会渲染在页面上,一般被vue解析内部标签)
Pannel.vue
<template>
<div>
<div class="title">
<slot name="title"></slot>
<span @click="isShow = !isShow">{{ isShow ? '收起' : '展开' }}</span>
</div>
<div class="container" v-show="isShow">
<!--1: 组件内使用slot 占位 -->
<slot name="content"></slot>
</div>
</div>
</template>
<script>
export default {
data() {
return {
isShow: false,
}
},
}
</script>
App.vue
<template>
<div>
<!-- 2 使用组件时 pannel
在组件中间 传入标签替换slot -->
<pannel>
<template v-slot:title>
<h4>鹅鹅鹅</h4>
</template>
<template v-slot:content>
<span>我是内容</span>
</template>
</pannel>
<!-- v-slot: 简写为 # -->
<pannel>
<template #title>
<h2>hello</h2>
</template>
<template #content>
<p>123</p>
</template>
</div>
</template>
总结:
v-slot: 可以简写为 #
slot的name属性起插槽名,使用组件时,template配合#插槽名传入具体的标签
作用域插槽
子组件里的值,在给插槽赋值时在父组件环境下使用
步骤:
- 子组件:在slot上绑定属性和子组件内的值
- 使用组件时,传入自定义标签,用template和v-slot=“自定义变量名scope”
- scope变量名自动绑定slot上所有的属性和值
Pannel.vue
<template>
<div>
<div class="title">
<!-- 1:slot上绑定属性和子组件内的值 -->
<slot name="title" :msg="msg" tit="nihao"></slot>
<span @click="isShow = !isShow">{{ isShow ? '收起' : '展开' }}</span>
</div>
<div class="container" v-show="isShow">
<!--1: 组件内使用slot 占位 -->
<slot name="content"> </slot>
</div>
</div>
</template>
<script>
export default {
data() {
return {
isShow: false,
msg: 'hello world',
}
},
}
</script>
App.vue
<template>
<div>
<pannel>
<!--2 传入自定义标签 template和v-slot:插槽名="自定义变量名" -->
<template v-slot:title="scope">
<!--3 scope上自动绑定slot上所有属性和值 -->
<h4>{{ scope.tit }}</h4>
</template>
<template v-slot:content>
<span>我是内容</span>
</template>
</pannel>
<!-- v-slot: 简写为 # -->
<pannel>
<template #title>
<h2>hello</h2>
</template>
<template #content>
<p>123</p>
</template>
</pannel>
</div>
</template>
总结:
组件内变量绑定到slot上,使用组件v-slot:插槽名=“自定义变量”,变量上会自动绑定属性和值
使用场景
需求:封装一个表格组件,在表格组件内循环产生单元格
- 准备MyTable.vue组件—内置表格,传入数组循环铺设页面,把对象每个内容显示在单元格里
- App.vue组件里,准备数据传入给MyTable.vue使用
- 分析
- 想要给td内显示图片,传入自定义的img标签(td中准备slot占位符,但是外面需要把图片地址赋予给src属性,在slot上把item数据进行绑定)
MyTable.vue
<template>
<div>
<table>
<thead>
<tr>
<th>序号</th>
<th>姓名</th>
<th>年龄</th>
<th>头像</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in list" :key="index">
<td>{{ index + 1 }}</td>
<td>{{ item.name }}</td>
<td>{{ item.age }}</td>
<td>
<slot :row="item">
<!-- 默认值,使用组件不自定义标签显示默认文字 -->
{{ item.headImgUrl }}
</slot>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
props: ['list'],
}
</script>
App.vue
<template>
<div>
<my-table :list="list">
<template v-slot="scope">
<img :src="scope.row.headImgUrl" width="50" alt="" />
</template>
</my-table>
<my-table :list="list">
<template v-slot="{ row }">
<a :href="row.headImgUrl">
{{ row.headImgUrl }}
</a>
</template>
</my-table>
</div>
</template>
<script>
import MyTable from './components/MyTable.vue'
export default {
components: { MyTable },
data() {
return {
list: [
{
name: '张三',
age: 18,
headImgUrl: 'https://img01.yzcdn.cn/vant/ipad.jpeg',
},
{
name: '李四',
age: 23,
headImgUrl: 'https://img01.yzcdn.cn/vant/ipad.jpeg',
},
{
name: '王五',
age: 45,
headImgUrl: 'https://img01.yzcdn.cn/vant/ipad.jpeg',
},
],
}
},
}
</script>
自定义指令
除了核心功能默认内置的指令(v-model和v-show),vue允许我们注册自定义指令。 v-xxxx
html+css的复用的主要形式是组件
你需要对普通DOM元素进行底层操作,这时候就会用到自定义指令
目标:获取标签 扩展额外的功能
局部注册和使用
只能在当前组件中使用
<template>
<div>
<div class="main">
<input type="text" v-focus />
</div>
</div>
</template>
<script>
/*
局部指令
directives:{
'指令名':{
bind(el,binding,vnode){},
inserted(el,binding,vnode){}
}
}
在标签上使用自定义指令 v-指令名
inserted 指令所在标签 被插入到页面上触发(一次)
update 指令对应的数据/标签更新时 触发
*/
export default {
directives: {
// 页面加载时获取焦点
focus: {
inserted(el, binding, vnode) {
// console.log(el)
el.focus()
},
},
},
}
</script>
全局注册和使用
在任何的.vue文件中使用
main.js中用Vue.directive 全局注册指令
// 全局注册
Vue.directive('gfocus', {
inserted(el) {
el.focus()
},
})
自定义指令-传值
使用自定义指令,传入一个值
需求:定义color指令,传入一个颜色,给标签设置文字颜色
<template>
<div>
<div class="main">
<input type="text" v-focus />
<input type="text" v-gfocus />
</div>
<p v-color="theColor" @click="changeColor">修改文字颜色</p>
</div>
</template>
<script>
/*
局部指令
directives:{
'指令名':{
bind(el,binding,vnode){},
inserted(el,binding,vnode){}
}
}
在标签上使用自定义指令 v-指令名
inserted 指令所在标签 被插入到页面上触发(一次)
update 指令对应的数据/标签更新时 触发
*/
export default {
data() {
return {
theColor: 'blue',
}
},
methods: {
changeColor() {
this.theColor = 'yellow'
},
},
directives: {
// 页面加载时获取焦点
focus: {
inserted(el, binding, vnode) {
// console.log(el)
el.focus()
},
},
// 给标签设置文字颜色
color: {
inserted(el, binding) {
el.style.color = binding.value
},
update(el, binding) {
el.style.color = binding.value
},
},
},
}
</script>