VUE3.0自定义指令使用详细教程(全局指令封装,使用自定义指令,动态传参,举例:input框聚焦、文本高亮、元素平滑上升)
VUE3.0自定义指令使用详细教程(全局指令封装,使用自定义指令,动态传参,举例:input框聚焦、文本高亮、元素平滑上升)
·
##自定义指令的使用 参考官方文档:https://cn.vuejs.org/guide/reusability/custom-directives.html
1. 在utils文件夹下新建directive文件夹
用来存放需要自定义的指令文件,该文件用于创建指令以及编写操作逻辑代码,目录结构
```
directive
├── index.js //导入需要的指令,并汇总导出,
└── highlight //文本高亮指令
| └── index.js
└── Focus //聚焦指令
| └── index.js
└── SlideIn //元素平滑上升指令
| └── index.js
└── ···
└── ···
```
2. 编写自定义指令文件
下面会列举三个自定义指令的例子(文本高亮、聚焦、元素平滑上升)
3. 在directive文件夹下新建index.js文件,
在该文件中导入需要的指令,然后调用directive()方法,将自定义的指令挂载到app.directive()方法中,
import SildeIn from './SlideIn'
import Focus from './Focus'
import Highlight from './highlight' //导入自定义指令
const directives = { //汇总自定义指令
SildeIn//元素平滑上升指令 这里就是指令名 在文本中使用方法就是 v-指令名
Focus,//聚焦指令
Highlight//文本高亮指令
}
export default { //导出自定义指令
install(app) {// 以安装的方式插到app中
Object.keys(directives).forEach((key) => { // 遍历directives对象的key
app.directive(key, directives[key]) // 将每个directive注册到app中
})
}
}
4. 在main.js中导入自定义指令,并全局注册,
import Directives from '@/utils/directive/index.js'
function initApp() {
const app = createApp(App)
// app.use(pinia)
// app.use(elementIcon)
// app.use(router)
app.use(Directives) //全局注册
app.mount('#app')
}
initApp()
5. 指令的使用方式
:v-指令名="指令方法",指令方法可以是函数也可以是对象,例如
<div v-SildeIn class="w-3/4 h-96 bg-slate-700 mt-14">{{ item }}</div>
<p v-highlight:color="color">这段文本会高亮显示,用来演示动态传参</p>
<input v-Focus type="text" placeholder="这个input会自动聚焦" />
### 例子1:自动聚焦
页面中
<input v-Focus type="text" placeholder="这个input会自动聚焦" />
/Focus/index.js 指令js
export default {
mounted(el) {
console.log(el)
el.focus() //DOM操作输入框聚焦
}
}
### 例子2:文本高亮 这里演示说明动态传参
页面中
<templete>
<p v-highlight>这段文本会高亮显示,不传参</p>
<p v-highlight:color="color">
这段文本会高亮显示,用来演示动态传参,第一个color是参,第二个color是值
</p>
<input v-model="color" placeholder="这是一个输入框,输入颜色值可以动态更新文本高亮颜色" />
</templete>
<script>
const color = ref('#f00') //定义响应式变量
</script>
//highlight/index.js 指令js
export default {
beforeMount(el, binding) {
// 获取传递的参数
const arg = binding.arg //从这里获取参数名,也就是第一个color
const value = binding.value //从这里获取参数值,也就是第二个color
// 将参数保存在指令上下文中
el._directiveContext = { arg, value }
el.style.backgroundColor = value || '#f00' //DOM操作,设置背景颜色
},
updated(el, binding) {
// 获取更新后的参数
const value = binding.value //更新后的参数值
el.style.backgroundColor = value //更新DOM
// 从指令上下文中获取之前保存的参数
// const { arg } = el._directiveContext
// console.log('参数:', arg, '值:', value)
}
}
### 例子3:元素平滑上升
页面中使用:
<div v-SildeIn class="w-3/4 h-96 bg-slate-700 mt-14">{{ item }}</div>
/SildeIn/index.js 指令JS
const DISTANCE = 100 //定义动画的距离
const duration = 500 //定义动画的持续时间 //也可以接收用户的一些配置
const animationMap = new WeakMap() // 记录元素和动画的对应关系 WeakMap房防止内存泄漏
const ob = new IntersectionObserver((entries) => {
//创建一个监听者,监听元素啊是否进入可视区域
for (const entry of entries) {
//遍历监听者
if (entry.isIntersecting) {
//如果元素进入可视区域
const animation = animationMap.get(entry.target)
if (animation) {
// console.log(animation)
animation.play()
ob.unobserve(entry.target) //动画播放完毕后取消监听
}
// console.log(entry.target)
}
}
})
/**
* 判断元素是否在可视区域之下
* @param {Element} el - 要判断的元素
* @returns {boolean} - 若元素在可视区域之上则返回true,否则返回false
*/
function isBelowViewport(el) {
const rect = el.getBoundingClientRect()
return rect.top - DISTANCE > window.innerHeight
}
export default {
mounted(el) {
if (!isBelowViewport(el)) {
//判断元素是否在可视区域之下
return //如果不在可视区域之下则直接返回 // 因为动画只需要在元素进入可视区域时才播放,所以只需要在元素进入可视区域时调用mounted方法即可 视口内容和视口之上的元素都不需要播放动画
}
const animation = el.animate(
[
{
transform: `translateY(${DISTANCE}px)`,
opacity: 0.3
},
{
transform: `translateY(0)`,
opacity: 1
}
],
{
duration: duration,
easing: 'ease-in'
}
)
//创建动画用 animate(keyframes, options),animate方法返回一个Animation实例,可以调用play()方法来播放动画,调用pause()方法来暂停动画
animation.pause() //创建动画后先将所有动画暂停
ob.observe(el) //监听元素是否进入可视区域,如果进入就播放动画,如果不进入就暂停动画
animationMap.set(el, animation) //将元素和动画的对应关系记录在WeakMap中
},
unmounted(el) {
console.log('unmounted')
ob.unobserve(el)
}
}
更多推荐
已为社区贡献1条内容
所有评论(0)