Vue3 + Directive input元素绑定指令后,在指令中更新input value,v-model未生效

问题背景:

在表格翻页组件中,有一个跳页输入框,当输入不合法字符时,利用绑定的指令去除不合法字符。

但是v-model不生效,在此记录一下,给前端的小伙伴们踩踩坑。

 问题描述:

输入不合法字符时,期望输入框内的值和绑定的变量都回填之前的数字。例如输入‘?’,期望输入框和变量都显示‘1’;实际输入框显示‘1,变量显示‘1?’,v-model未生效。

<input
      type="text"
      v-pager-formatter="{
          pagerFormatterMax: totalPage || 1
      }"
                    v-model="index"
      @blur="setPage()"
      @keyup.enter="$event.target.blur()"
      />

 v-pager-formatter就是输入框校验指令,当输入内容时,在指令中校验输入是否合法。

export default {
    updated(el: HTMLInputElement, binding: DirectiveBinding): void {
        const Service: InputValidator = new InputValidator();
        // 最大页数
        const totalPageNumber: number = binding.value.pagerFormatterMax;
        // 输入框值
        let targetValue: string;
        const inputChange = (elRef): boolean => {
            // 校验是否合法,不合法替换不合法字符,返回合法字符
            const limitNumber: string = Service.limitNumber(targetValue, 'int', 1, totalPageNumber);
            if (limitNumber !== targetValue) {
                // 如果有不合法字符,则回填合法字符
                if (limitNumber) {
                    elRef.value = limitNumber;
                } else {
                    elRef.value = '';
                }
            }
            return true;
        };
        el.oninput = (event: Event): void => {
            targetValue = event.target['value'];
            inputChange(el);
        };
    },
};

在指令中,elRef.value = limitNumber后,v-model绑定的变量并不会更新。

问题原因:

v-model双向绑定原理实际上就是 "@input" 事件与 ":value" 属性的结合体。v-model未生效其实(:value绑定的变量未更新)其实就是在指令中改变输入框value时未触发“@input”事件,导致v-moel未生效。

解决方法:

手动触发input事件,使绑定的变量更新。EventTarget.dispatchEvent()方法会向一个指定的事件目标派发一个Event,并以合适的顺序(同步地)调用所有受影响的EventListener。

代码中加入elRef.dispatchEvent(new Event('input'))触发input事件,使v-model更新。这样就能解决这个问题。

export default {
    updated(el: HTMLInputElement, binding: DirectiveBinding): void {
        const Service: InputValidator = new InputValidator();
        // 最大页数
        const totalPageNumber: number = binding.value.pagerFormatterMax;
        // 输入框值
        let targetValue: string;
        const inputChange = (elRef): boolean => {
            // 校验是否合法,不合法替换不合法字符,返回合法字符
            const limitNumber: string = Service.limitNumber(targetValue, 'int', 1, totalPageNumber);
            if (limitNumber !== targetValue) {
                // 如果有不合法字符,则回填合法字符
                if (limitNumber) {
                    elRef.value = limitNumber;
                } else {
                    elRef.value = '';
                }
                elRef.dispatchEvent(new Event('input'));
            }
            return true;
        };
        el.oninput = (event: Event): void => {
            targetValue = event.target['value'];
            inputChange(el);
        };
    },
};

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值