概念: 指令(Directives)是 Vue 提供的带有 v- 前缀 的 特殊 标签属性。
-
内容渲染指令(v-html、v-text)
-
条件渲染指令(v-show、v-if、v-else、v-else-if)
-
事件绑定指令(v-on)
-
属性绑定指令 (v-bind)
-
双向绑定指令(v-model)
-
列表渲染指令(v-for)
### 自定义指令:
1. 自定义指令
同时Vue也支持让开发者,自己注册一些指令。这些指令被称为自定义指令 每个指令都有自己各自独立的功能
2.注册指令
使用 Vue.directive 方法或 directive 函数来注册指令。这些方法接受两个参数:指令名称和指令配置对象。
inserted:被绑定元素插入父节点时调用的钩子函数
el:使用指令的那个DOM元素
//在main.js中
Vue.directive('指令名', {
"inserted" (el) {
// 可以对 el 标签,扩展额外功能
el.focus()
}
})
//在Vue组件的配置项中
directives: {
"指令名": {
inserted () {
// 可以对 el 标签,扩展额外功能
el.focus()
}
}
}
使用指令:- 使用指令 在使用指令的时候,一定要先注册,再使用,否则会报错 使用指令语法: v-指令名。如: **** ```
**注册**指令时**不用**加**v-前缀**,但**使用时**一定要**加v-前缀**
3. 钩子函数:
指令配置对象中的钩子函数定义了指令的生命周期。常用的钩子函数包括 bind、mounted、update、componentUpdated 和 unbind。这些钩子函数在指令的不同生命周期阶段被调用,允许开发者在相应的时机执行自定义的逻辑。
4.**钩子函数参数
指令的钩子函数可以接受一些参数,用于传递信息给指令的行为逻辑。常用的参数包括 el(指令所绑定的元素)、binding(一个对象,包含指令的绑定值、参数、修饰符等信息)、vnode(Vue 编译生成的虚拟节点)和 oldVnode(上一个虚拟节点)等。
常见自定义指令应用场景
封装 v-loading ,实现加载中的效果
分析
1.loading效果就是一个蒙层,盖在了盒子上
2.数据请求中,开启loading状态,添加蒙层
3.数据请求完毕,关闭loading状态,移除蒙层
代码实现
<template>
<div>
<!-- 数据来了之后 -->
<div class="box" v-loading="isShow">
<ul>
<li v-for="item in list" :key="item.id" class="news">
<div class="left">
<div class="title">{{ item.title }}</div>
<div class="info">
<span>{{ item.source }}</span>
<span>{{ item.time }}</span>
</div>
</div>
<div class="right">
<img :src="item.img" alt="" />
</div>
</li>
</ul>
</div>
<!-- 数据没来之前 loading -->
<div class="box1" v-loading="isShow"></div>
</div>
</template>
<script>
// 安装axios => yarn add axios
import axios from "axios";
// 请求方式:get
export default {
data() {
return {
list: [],
isShow: true,
};
},
async created() {
// 1. 发送请求获取数据
const res = await axios.get("http://xxxx/api/news");
setTimeout(() => {
// 2. 更新到 list 中,用于页面渲染 v-for
this.list = res.data.data;
// 3. 改变isShow的值
this.isShow = false;
}, 3000);
},
// loading 加载状态
directives: {
loading: {
inserted(el, binding) {
binding.value
? el.classList.add("loading")
: el.classList.remove("loading");
},
update(el, binding) {
binding.value
? el.classList.add("loading")
: el.classList.remove("loading");
},
},
},
};
</script>
<style>
.loading:before {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: #fff url("./loading.gif") no-repeat center;
}
.box1 {
width: 300px;
height: 300px;
border: 10px solid pink;
position: relative;
margin-top: 30px;
}
.box {
width: 800px;
min-height: 500px;
border: 3px solid orange;
border-radius: 5px;
position: relative;
}
.news {
display: flex;
height: 120px;
width: 600px;
margin: 0 auto;
padding: 20px 0;
cursor: pointer;
}
.news .left {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
padding-right: 10px;
}
.news .left .title {
font-size: 20px;
}
.news .left .info {
color: #999999;
}
.news .left .info span {
margin-right: 20px;
}
.news .right {
width: 160px;
height: 120px;
}
.news .right img {
width: 100%;
height: 100%;
object-fit: cover;
}
</style>