自定义指令
内置指令:
自定义指令:
v-focus
v-loading
v-lazy
- …
每个指令都有各自独立的功能
自定义指令:自己定义的指令,可以封装一些 dom 操作,扩展额外功能
实例:元素获得焦点
需求:当页面加载时,让元素获得焦点(autofocus
在 safari 浏览器有兼容性问题)
操作 dom:dom 元素.focus()方式比较麻烦
1 2 3
| mounted(){ this.$refs.inp.focus() }
|
注册自定义指令语法
- 全局注册(main.js 中注册)
1 2 3 4 5 6 7
| Vue.directive('指令名', { inserted(el) { el.focus(); }, });
|
- 局部注册(组件内注册)
1 2 3 4 5 6 7 8
| directives:{ 指令名:{ inserted(el){ el.focus() } } }
|
- 使用
1
| <input v-指令名 type="text" />
|
指令的值
需求:实现一个 color 指令,传入不同的颜色,给标签设置文字颜色
- 语法:在绑定指令时,可以通过“等号”的形式为指令绑定具体的参数值
1
| <div v-color="color">content</div>
|
- 通过
binding.value
可以拿到指令值,指令值修改会触发 update 函数
1 2 3 4 5 6 7 8 9 10
| directives:{ color:{ inserted(el,binding){ el.style.color=binding.value }, update(el,binding){ el.style.color=binding.value } } }
|
实例:v-loading 指令封装
场景:实际开发过程中,发送请求需要时间,在请求数据未回来时,页面会处于空白状态,用户体验不好
需求:封装一个 v-loading
指令,实现加载中的效果
分析:
- 本质
loading
效果就是一个蒙层,盖在了盒子上
- 数据请求中,开启
loading
状态,添加蒙层
- 数据请求完毕,关闭
loading
状态,移除蒙层
实现:
- 准备一个
loading
类,通过伪元素定位,设置宽高,实现蒙层
- 开启关闭
loading
状态,本质只需要添加移除类即可
- 结合自定义指令的语法进行封装复用
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
| <template> <div class="box" v-loading="isLoading"> <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> </template>
<script> import axios from 'axios';
export default { data() { return { list: [], isLoading: true, }; }, async created() { const res = await axios.get('http://hmajax.itheima.net/api/news');
setTimeout(() => { this.list = res.data.data; this.isLoading = false; }, 2000); }, 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(./assets/loading.gif) no-repeat center; } .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>
|