Vue自定义指令如何实现双向绑定?需求与问题咨询
问题描述
我想把鼠标移入移出切换布尔值的逻辑封装成自定义指令,变量toggle是Ref<boolean>类型。
当前实现:
<!-- 当前写法 --> <div @mouseenter="toggle = true" @mouseleave="toggle = false"></div>
目标写法:
<!-- 期望写法 --> <div v-hover="toggle"></div>
我注册了下面的指令,但绑定是单向的,指令内修改值无法同步到实际DOM和组件变量:
Vue.directive('hover', function(el, binding) { el.addEventListener('mouseenter', () => binding.value = true); el.addEventListener('mouseleave', () => binding.value = false); });
请问如何实现双向绑定?
解决方案
问题出在你直接修改了binding.value的引用——因为你绑定的是Ref对象,binding.value拿到的是这个Ref实例,直接给它赋值布尔值会把原有的Ref对象替换掉,自然无法同步。正确的做法是修改Ref对象的.value属性:
Vue.directive('hover', { mounted(el, binding) { // 校验绑定值是否为合法的Ref类型 if (!binding.value || typeof binding.value.value === 'undefined') { console.warn('v-hover指令需要绑定一个Ref<boolean>类型的变量'); return; } // 定义事件处理函数,修改Ref的value属性 const enterHandler = () => binding.value.value = true; const leaveHandler = () => binding.value.value = false; el.addEventListener('mouseenter', enterHandler); el.addEventListener('mouseleave', leaveHandler); // 把处理函数存到元素上,方便销毁时移除监听 el._hoverEnterHandler = enterHandler; el._hoverLeaveHandler = leaveHandler; }, unmounted(el) { // 移除事件监听,避免内存泄漏 el.removeEventListener('mouseenter', el._hoverEnterHandler); el.removeEventListener('mouseleave', el._hoverLeaveHandler); // 清理元素上的自定义属性 delete el._hoverEnterHandler; delete el._hoverLeaveHandler; } });
关键说明:
- 使用
mounted钩子而非函数式指令:函数式指令会在每次更新时重新执行,重复绑定事件,而mounted只在元素挂载时绑定一次。 - 修改
Ref的.value属性:因为Ref是响应式容器,修改它的.value会自动同步到组件变量和DOM。 - 移除事件监听:在
unmounted钩子中清理事件绑定,防止内存泄漏。
这样你就能直接用<div v-hover="toggle"></div>实现需求,鼠标移入时toggle.value变为true,移出时变为false,双向同步生效。
内容的提问来源于stack exchange,提问作者KorbenDose
相关产品推荐
相关产品推荐

