目录
自定义指令
是什么
作用
使用方法
定义
使用
自定义指令配合绑定数据
语法
自定义指令的简写
语法
使用时机
插槽
什么是插槽
默认(匿名)插槽
编辑插槽的默认值
具名插槽
使用方法
简写
使用示例
作用域插槽
自定义指令
是什么
- 内置指令:是vue3自带的,比如:v-model、v-for、v-if....我们可以直接使用。
- 自定义指令:相对内置指令而言,我们自己编写的指令,当内置指令无法满足需求的时候,就可以自己编写的指令。
作用
封装一段公共的DOM操作的代码。
与ref属性操作DOM的区别:
- ref是作用在单个标签上的,代码无法复用
- 自定义指令可以把一段公共的DOM操作代码封装起来,进行复用
使用方法
定义
main.js -> app.directive('指令名',{
mounted(el){
//el就是指令所在的DOM元素
}
})
示例:在main.js文件中
const app=createApp(App)
app.directive('jujiao',{
mounted(el){
el.focus()
}
})
app.mount('#app')
使用
<XXX v-指令名>
<template>
<input type="text" v-jujiao/>
</template>
自定义指令配合绑定数据
语法
1、在绑定指令时,可以通过“等号”的形式为指令绑定具体的参数值
<template>
<div v-color="colorStr">
Hello World
</div>
</template>
<script setup>
import { ref } from 'vue'
const colorStr = ref('blue')
</script>
2、通过binding.value可以拿到指令值,指令值修改会触发updated钩子
app.directive('color',{
//mouted钩子只负责初次渲染,后续指令所在表达式的值变了,该函数不会执行,因此需要引入updated钩子
mounted(el,binding){
//el就是指令所在的DOM元素
//binding:指令绑定的信息对象,通过binding.value获取表达式结果
el.style.color=binding.value
},
updated(el,binding){
el.style.color=binding.value
}
})
自定义指令的简写
将上面提到指令的mounted()和updated()两个钩子进行合写,用一个函数来代替,并且这个函数会在mounted()和updated()时机都会执行。
语法
app.directive('color',(el,binding)=>{
el.style.color=binding.value
})
使用时机
- 当自定义指令绑定数据,那么就可以简写(简写的本质=mounted()+updated())
- 当自定义指令没有绑定数据,那么就采用非简写的方式。
插槽
什么是插槽
本质就是一个占位符,今后可以给这个占位符传入想要的组件结构,从而大大提高组件的灵活性和可复用性。
默认(匿名)插槽
作用
让组件内部的一些结构支持自定义
语法
- 在使用组件的时候,把组件写成双标签
- 在双标签之间传入想展示的结构,从而替换占位的slot组件
子组件
<script setup></script>
<template>
<div class="dialog">
<div class="dialog-header">
<h3>友情提示</h3>
<span class="close">✖️</span>
</div>
<div class="dialog-content">
<!-- 1. 在组件内标签不确定位置用 slot 组件 -->
<slot></slot>
</div>
<div class="dialog-footer">
<button>取消</button>
<button>确认</button>
</div>
</div>
</template>
<style scoped>
* {
margin: 0;
padding: 0;
}
.dialog {
width: 470px;
height: 230px;
padding: 0 25px;
background-color: #ffffff;
margin: 40px auto;
border-radius: 5px;
}
.dialog-header {
height: 70px;
line-height: 70px;
font-size: 20px;
border-bottom: 1px solid #ccc;
position: relative;
}
.dialog-header .close {
position: absolute;
right: 0px;
top: 0px;
cursor: pointer;
}
.dialog-content {
height: 80px;
font-size: 18px;
padding: 15px 0;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
}
.dialog-footer button {
width: 65px;
height: 35px;
background-color: #ffffff;
border: 1px solid #e1e3e9;
cursor: pointer;
outline: none;
margin-left: 10px;
border-radius: 3px;
}
.dialog-footer button:last-child {
background-color: #007acc;
color: #fff;
}
</style>
App.vue
<template>
<!-- 在使用组件的时候,给组件传入想展示的结构,从而替换掉组件内的slot组件 -->
<MyDialog>
<span>你确定要进行删除操作吗?</span>
</MyDialog>
<MyDialog>
<span>你确定要退出本系统吗?</span>
</MyDialog>
</template>
<script setup>
import MyDialog from './components/MyDialog.vue';
</script>
插槽的默认值
如果未传入内容,则显示slot标签内的内容
<slot> 我是默认内容 </slot>
默认值的生效规则:
- 如果没传,就显示默认值,防止页面空白
- 如果传入了,就会用传入的,替换掉占位的slot,从而展示实际传入的标签结构
具名插槽
一个组件内有多处结构,需要外部传入标签,进行定制,默认插槽只能定制一处内容。这是给插槽添加name属性,进行区分,添加name属性的插槽就是具名插槽。
使用方法
<slot name="插槽名"> 默认的内容</slot>
<template v-slot:插槽名> 要展示的内容</template>
简写
<template #插槽名> 要展示的内容</template>
使用示例
根组件
<template>
<!-- 在使用组件的时候,给组件传入想展示的结构,从而替换掉组件内的slot组件 -->
<MyDialog>
<template v-slot:title>
<span>删除确认</span>
</template>
<template v-slot:content>
<span>你确定要进行删除操作吗?</span>
</template>
</MyDialog>
</template>
<script setup>
import MyDialog from './components/MyDialog.vue';
</script>
子组件(插槽)
<script setup></script>
<template>
<div class="dialog">
<div class="dialog-header">
<slot name="title"></slot>
<span class="close">✖️</span>
</div>
<div class="dialog-content">
<!-- 1. 在组件内标签不确定位置用 slot 组件 -->
<slot name="content"></slot>
</div>
<div class="dialog-footer">
<button>取消</button>
<button>确认</button>
</div>
</div>
</template>
<style scoped>
* {
margin: 0;
padding: 0;
}
.dialog {
width: 470px;
height: 230px;
padding: 0 25px;
background-color: #ffffff;
margin: 40px auto;
border-radius: 5px;
}
.dialog-header {
height: 70px;
line-height: 70px;
font-size: 20px;
border-bottom: 1px solid #ccc;
position: relative;
}
.dialog-header .close {
position: absolute;
right: 0px;
top: 0px;
cursor: pointer;
}
.dialog-content {
height: 80px;
font-size: 18px;
padding: 15px 0;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
}
.dialog-footer button {
width: 65px;
height: 35px;
background-color: #ffffff;
border: 1px solid #e1e3e9;
cursor: pointer;
outline: none;
margin-left: 10px;
border-radius: 3px;
}
.dialog-footer button:last-child {
background-color: #007acc;
color: #fff;
}
</style>
作用域插槽
带数据的插槽,用slot占位的同时,还可以给slot绑定数据,也就是说数据来源于插槽,但是怎么展示这些数据由自定义结构决定。
接收插槽数据
这里的obj就代表对应slot标签绑定的所有数据的对象
<template v-slot:content="obj">
<span>obj.a={{ obj.a }}</span>
</template>
上面是使用一个对象进行接收,我们也可以对接收的数据进行解构,直接获取指定的数据,如下:
<template v-slot:content="{a}">
<span> a={{ a }}</span>
</template>
slot绑定数据
<div class="dialog-content">
<slot name="content" a="123" b="456"></slot>
</div>