【Vue】自定义指令、插槽

目录

自定义指令

是什么

作用

使用方法

定义

使用

自定义指令配合绑定数据

语法

自定义指令的简写

语法

使用时机

插槽

什么是插槽

默认(匿名)插槽

​编辑插槽的默认值

具名插槽

使用方法

简写

使用示例

作用域插槽


自定义指令

是什么

  • 内置指令:是vue3自带的,比如:v-model、v-for、v-if....我们可以直接使用。
  • 自定义指令:相对内置指令而言,我们自己编写的指令,当内置指令无法满足需求的时候,就可以自己编写的指令。

作用

封装一段公共的DOM操作的代码。

与ref属性操作DOM的区别:

  1. ref是作用在单个标签上的,代码无法复用
  2. 自定义指令可以把一段公共的DOM操作代码封装起来,进行复用

使用方法

定义

main.js -> app.directive('指令名',{

mounted(el){

//el就是指令所在的DOM元素

}

})

示例:在main.js文件中

javascript 复制代码
const app=createApp(App)

app.directive('jujiao',{
    mounted(el){
        el.focus()
    }
})

app.mount('#app')

使用

<XXX v-指令名>

html 复制代码
<template>
    <input type="text" v-jujiao/>
</template>

自定义指令配合绑定数据

语法

1、在绑定指令时,可以通过"等号"的形式为指令绑定具体的参数值

html 复制代码
<template>
    <div v-color="colorStr">
        Hello World
    </div>
</template>

<script setup>
    import { ref } from 'vue'

    const colorStr = ref('blue')
</script>

2、通过binding.value可以拿到指令值,指令值修改会触发updated钩子

javascript 复制代码
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()时机都会执行。

语法

javascript 复制代码
app.directive('color',(el,binding)=>{
    el.style.color=binding.value
})

使用时机

  1. 当自定义指令绑定数据,那么就可以简写(简写的本质=mounted()+updated())
  2. 当自定义指令没有绑定数据,那么就采用非简写的方式。

插槽

什么是插槽

本质就是一个占位符,今后可以给这个占位符传入想要的组件结构,从而大大提高组件的灵活性和可复用性。

默认(匿名)插槽

作用

让组件内部的一些结构支持自定义

语法

  1. 在使用组件的时候,把组件写成双标签
  2. 在双标签之间传入想展示的结构,从而替换占位的slot组件

子组件

html 复制代码
<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

html 复制代码
<template>
    <!-- 在使用组件的时候,给组件传入想展示的结构,从而替换掉组件内的slot组件 -->
    <MyDialog>
        <span>你确定要进行删除操作吗?</span>
    </MyDialog>
    <MyDialog>
        <span>你确定要退出本系统吗?</span>
    </MyDialog>
</template>

<script setup>
    import MyDialog from './components/MyDialog.vue';
</script>

插槽的默认值

如果未传入内容,则显示slot标签内的内容

<slot> 我是默认内容 </slot>

默认值的生效规则:

  1. 如果没传,就显示默认值,防止页面空白
  2. 如果传入了,就会用传入的,替换掉占位的slot,从而展示实际传入的标签结构

具名插槽

一个组件内有多处结构,需要外部传入标签,进行定制,默认插槽只能定制一处内容。这是给插槽添加name属性,进行区分,添加name属性的插槽就是具名插槽。

使用方法

<slot name="插槽名"> 默认的内容</slot>

<template v-slot:插槽名> 要展示的内容</template>

简写

<template #插槽名> 要展示的内容</template>

使用示例

根组件

html 复制代码
<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>

子组件(插槽)

html 复制代码
<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标签绑定的所有数据的对象

html 复制代码
<template v-slot:content="obj">
    <span>obj.a={{ obj.a }}</span>
</template>

上面是使用一个对象进行接收,我们也可以对接收的数据进行解构,直接获取指定的数据,如下:

html 复制代码
<template v-slot:content="{a}">
    <span> a={{ a }}</span>
</template>

slot绑定数据

html 复制代码
<div class="dialog-content">
	<slot name="content" a="123" b="456"></slot>
</div>
相关推荐
SoaringHeart34 分钟前
Flutter进阶:基于 EasyRefresh 的下拉刷新封装 n_easy_refresh_mixin.dart
前端·flutter
IT_陈寒2 小时前
Vite的热更新突然不香了,排查三小时差点砸键盘
前端·人工智能·后端
子兮曰3 小时前
Agency-Agents 深度解析:400+ AI 专家的"梦之队"如何重塑开发工作流
前端·后端·vibecoding
山河木马3 小时前
渲染管线-计算得到gl_Position(顶点着色器)之后续GPU流程
javascript·webgl·图形学
竹林8184 小时前
用 The Graph 查询链上数据实战:从手搓 RPC 到 Subgraph,我的 NFT 项目数据加载快了 10 倍
前端·javascript
妙码生花4 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十九):点选验证码代码逐行目检
前端·后端·go
Awu12275 小时前
⚡从零开发 Agent CLI(五)实现一个可治理、可扩展的工具系统
前端·人工智能·claude
咪库咪库咪5 小时前
Vue3-生命周期
前端
莪_幻尘5 小时前
你的 AI Skill 越多越蠢?Token 上下文爆炸的求生指南
前端·ai编程
lichenyang4536 小时前
从 has.echo 到异步 API 注册表:一次 ASCF API 回调不触发的排查复盘
前端