一. 自定义指令:
自己定义的指令,可以封装一些 dom操作,扩展额外功能
全局自定义指令:
(1). 在 main.js 中注册指令
(2). 组件中绑定
局部自定义指令:
(1). 在组件内部注册指令(作用域:只能自己使用)
二. 自定义指令 - 指令的值
需求: 实现一个color 指令 - 传入不同的颜色,给标签设置文字颜色
语法: 在绑定指令时,可以通过 "等号" 的形式为指令 绑定 具体的参数值
<div v-color="color"> 我是内容 </div>
通过 binding.value 可以拿到指令值,指令值修改会 触发 update 函数
directives: {
color:{
inserted (el,binding){
el.style.color = binding.value
},
update (el,binding) {
el.style.color = binding.value
}
}
}
总结:
1. 通过指令的值相关语法,可以应对更复杂指令封装场景
2. 指令值的语法:
(1). v-指令名 ="指令值",通过 等号 可以绑定指令的值
(2). 通过 binding.value 可以拿到指令的值
(3). 通过 update 钩子,可以监听指令值的变化,进行dom更新操作
三. 自定义指令- v-loading 指令的封装
场景:实际开发过程中,发送请求需要时间,在请求的数据未回来时,页面会处于空白状态 =>用户体验不好
需求: 封装一个 v-loading 指令,实现加载中的效果
分析:
1. 本质loading 效果就是一个蒙层,盖在了盒子上
2. 数据请求中,开启loading状态,添加蒙层
3. 数据请求完毕,关闭loading状态,移除蒙层
实现:
1. 准备一个 loading 类,通过伪元素定位,设置宽高,实现蒙层
2. 开启关闭 loading 状态(添加移除蒙层),本质只需要添加移除类即可
3. 结合自定义指令的语法进行封装复用
.loading:before{
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: #fff url("./loading.gif") no-repeat center;
}
总结:
1. 通过指令相关语法,封装了指令 v-loading 实现了请求的loading效果
2. 核心思路:
(1)准备类名 loading,通过伪元素提供遮罩层
(2)添加或移除类名,实现loading蒙层的添加移除
(3)利用指令语法,封装 v-loading 通用指令
inserted 钩子中,binding.value 判断指令的值,设置默认状态
update 钩子中,binding.value 判断指令的值,更新类名状态
<template>
<!-- 3. 使用 自定义loading指令 -->
<div class="box" v-loading="isLoading">
<ul>
<li v-for="item in list" :key="item.id" class="news">
<div class="left">
<div>{{ item.title }}</div>
<div>
<span>{{ item.source }}</span>
<span>{{ item.time }}</span>
</div>
</div>
<div class="right">
<img :src="item.img" alt="">
</div>
</li>
</ul>
</div>
</template>
<script>
// npm i axios
import axios from 'axios'
// 接口地址: http://hmajax.itheima.net/api/news
// 请求方式: get
export default {
data() {
return {
list: [],
isLoading: true
}
},
async created() {
// 1. 发送请求获取数据
const res = await axios.get("http://hmajax.itheima.net/api/news")
// 延时 2秒
setTimeout(() => {
// 2. 更新到list中,用于页面渲染 v-for
this.list = res.data.data
// 页面渲染完成后,isLoading 为 false
this.isLoading = false
}, 2000)
},
// 2. 自定义loading指令
directives: {
loading: {
inserted(el, binding) {
// loading指令=的值 ? true标签class属性 增加 值 : false删除loading值
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>
/* 1. 准备一个 loading 类,使用伪元素进行添加 */
.loading:before {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: #fff url("./loading.gif") no-repeat center;
}
.box {
width: 800px;
min-height: 500px;
border: 3px solod 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-around;
padding-right: 10px;
}
</style>