问题背景:

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

但是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);
        };
    },
};

Logo

前往低代码交流专区

更多推荐