Directives Vue3 自定义指令
目录
- 什么是自定义指令:
- 怎么识别自定义指令:
- 自定义指令分析
- 什么是自定义指令:
在 Vue.js 中,自定义指令的常用生命周期钩子函数通常是mounted、updated、unmounted
这些钩子函数接收参数 el 和 binding。
- 怎么识别自定义指令:
看到 el 和 binding 作为函数参数出现,特别是在 mounted 和 unmounted 钩子中,这是一个明确的标志,表明这是一个 Vue.js 的自定义指令。
- 自定义指令分析
const obj = {
name: "change",
createHandler: (el, binding, fn) => {
return function (...args) {
fn.apply(null, args);
};
},
alias: {
hover: "mouseenter",
},
pairs: {
mouseenter: "mouseleave",
mouseover: "mouseout",
},
mounted(el, binding) {
binding.arg = binding.arg || "mouseenter"; // 提供默认事件
binding.arg = obj.alias[binding.arg] || binding.arg; // 检查别名
binding.flag = true; // 初始状态
binding.originalStyles = {}; // 存储原始样式
const cs = window.getComputedStyle(el);
for (let key in binding.value) {
binding.originalStyles[key] = cs[key]; // 获取并存储原始样式
}
binding.eventHandler = obj.createHandler(el, binding, (e) => {
let styles = binding.value;
if (binding.modifiers.clear) {
styles = binding.flag ? binding.value : binding.originalStyles; // 根据 flag 决定应用哪种样式
}
for (let key in styles) {
el.style[key] = styles[key]; // 应用样式
}
binding.flag = !binding.flag; // 切换 flag 状态
});
el.addEventListener(binding.arg, binding.eventHandler); // 绑定事件处理函数
if (obj.pairs[binding.arg]) {
binding.clearHandler = obj.createHandler(el, binding, (e) => {
for (let key in binding.originalStyles) {
el.style[key] = binding.originalStyles[key]; // 清除样式
}
});
el.addEventListener(obj.pairs[binding.arg], binding.clearHandler); // 绑定配对事件处理函数
}
},
unmounted(el, binding) {
el.removeEventListener(binding.arg, binding.eventHandler); // 移除事件处理函数
binding.eventHandler = null;
if (binding.clearHandler) {
el.removeEventListener(obj.pairs[binding.arg], binding.clearHandler); // 移除配对事件处理函数
binding.clearHandler = null;
}
},
};
export default obj;
1. createHandler部分疑问:
createhandler是对象中的一个方法 用于创建事件处理函数,createhandler返回一个新函数 新函数接受任意数量的参数
问:作用是回调函数里返回一个新函数 该新函数将收到的args作用到原回调函数fn上?
作用是创建一个新的事件处理函数。这个新函数接收任意数量的参数(通过 ...args),并将这些参数传递给原始回调函数 fn。
当事件触发时,事件对象(event)会作为参数传递给这个新函数,它会调用 fn 并将参数应用到 fn 上
2. 成对的事件,在pair部分:为啥成对的事件才要绑定事件清除?
成对事件是为了确保在某些情况下能够恢复样式。例如,mouseenter 和 mouseleave 是成对的事件,当鼠标进入时应用样式,当鼠标离开时恢复样式。
这段代码检查是否存在配对事件(例如 mouseenter 的配对事件是 mouseleave)。
如果存在配对事件,创建 clearHandler,用于在配对事件触发时恢复原始样式,并将 clearHandler 绑定到配对事件上。
所以这里的pair的作用是什么?
pairs 对象定义成对的事件,比如mouseenter对应mouseleave
mouseover对应 mouseout
当某个事件被绑定时 比如mouseenter 为了
**确保 事件触发后样式能恢复原样** 会绑定一个配对的事件 mouseleave来清除应用 的样式
3. binding.arg = binding.arg || "mouseenter"
//第一遍 看 v-change后有无参数
binding.arg = obj.alias[binding.arg] || binding.arg
//第二遍 别名例如hover优先
4. binding.flag=true
//如果有flag则要是有修饰符如clear则立即调整样式?为何要切换flag状态 ?
切换 flag 状态是为了在每次事件触发时交替应用和恢复样式。
如果 flag 是 true,则应用 binding.value 中的样式;如果 flag 是 false,则恢复原始样式。这种切换确保了在事件反复触发时能够在两种样式状态之间切换。
如果有flag那么就更新当前binding.value状态不然就用originalStyles?
flag用于切换样式状态的标志 如果flag为true 应用binding.value里样式,否则恢复到originalstyles
半修饰符 clear存在时根据flag的值决定应用哪种样式
5 el.addEventListener(obj.pairs[binding.arg],binding.clearHandler)
//这是定义完毕回调事件直接应用到元素el上?
这行代码将 binding.eventHandler 绑定到指定的事件上(例如 mouseenter)。
当事件发生时,eventHandler 会被触发,执行样式更新逻辑。
- binding.arg的处理
mounted钩子里 binding.arg 就是指令绑定的参数 模板中使用指令
<div v-change:mouseenter></div>
这里mouseenter就是binding.arg
binding.arg = binding.arg ||"mouseenter"表示如果 binding.arg 没有定义默认为mouseenter
第一个是确保binding.arg有默认值
第二个赋值是处理可能的别名映射
mounted里两次赋值给binding.arg 应该是以别名为主?别名就覆盖了原本 的binding.arg?
第一次赋值是提供默认值 确保 binding.arg有值
第二次赋值 是为了检查是否有别名 如果存在别名 则将binding.arg
换为别名对应的值
确实别名优先级高于原本的 binding.arg
binding.value是指令的绑定值
<div v-change:mouseenter="{color:'red'}">
这里 {color:'red'}就是binding.value
binding:value 不包含flag和arg
window.getComputedStyle什么用
window.getComputedStyle(el)返回一个对象 该对象包含el所有css样式的当前值
使用他可以获取元素当前应用的所有样式
binding.value 与 binding.originalStyles
bingding.originalStyles 存储的是元素在应用 binding.value之前的原始样式
binding.value是指令绑定的值
可以包含多个css属性和值
{color:"red", backgroundColor:'blue'}
binding.originalStyles[key]=cs[key]
这个赋值语句在干嘛:这是把每一个 binding.value中的键对应的当前样式存储起来
这里的binding.modifiers.clear什么含义?
这是指令的修饰符 <div v-vhange:mouseenter.clear="{color:'red'}">
clear就是个修饰符 binding.modifiers.clear被解析为true或者false
存储的是元素在应用指令样式前的原始样式
事件触发后能恢复元素的原始样式
binding.arg = obj.alias["hover"] || "hover";
obj.alias["hover"] 是 "mouseenter",所以 binding.arg 最终变成 "mouseenter"。
obj.alias["mouseenter"] 是 undefined,所以 binding.arg 依然是 "mouseenter"。
所以这整个代码是 定义了一个自定义指令 v-change,它可以监听指定的事件(通过 binding.arg 或其别名),并在事件触发时应用或恢复样式。
在元素挂载时,初始化 binding.arg,存储原始样式,并创建和绑定事件处理函数。
在事件触发时,根据 flag 切换样式或恢复原始样式。
在元素卸载时,移除所有绑定的事件处理函数。