js 动态改变Input/Textarea值,vue双向绑定数据没有改变

作者: tww844475003 分类: 前端开发 发布时间: 2021-12-16 21:07

给 input、textarea 组件设置快捷录入操作

  • vue 自带的修饰键+keydown 事件
  • js 原生事件委托 onkeydown 事件

一、vue 自带的修饰键+keydown 事件

<input @keydown.ctrl.81="setValue">

这个实现非常方便简单,但是每个 input、textarea 都得去绑定,非常的麻烦

二、js 原生事件委托 onkeydown 事件

<template>
  <div id="app">
    <div class="oper-c">
      <br /><br />
      <input type="text" v-model="inputStr" />
      <br /><br />
      <textarea v-model="textareaStr" />
    </div>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      inputStr: "input str",
      textareaStr: "textarea str",
    };
  },
  destroyed() {
    window.removeEventListener('resize', this.resizeWin)
  },
  mounted() {
    const operInput = document.querySelector(".oper-c input");
    const operTextarea = document.querySelector(".oper-c textarea");
    
    operInput.onkeydown = (e) => {
      if (e.altKey) {
        if (e.keyCode === 81) {
          // e.target.value = "快捷键插入";
          this.insertAtCaret(e.target, "快捷键插入")
          e.target.dispatchEvent(new Event("input"));
        }
      }
    };
    operInput.onselect = (e) => {
      this.setCaret(e)
    };
    operTextarea.onkeydown =  (e) => {
      if (e.altKey) {
        if (e.keyCode === 81) {
          // e.target.value = "快捷键插入";
          this.insertAtCaret(e.target, "快捷键插入")
          e.target.dispatchEvent(new Event("input"));
        }
      }
    };
    operTextarea.onselect = (e) => {
      this.setCaret(e)
    };
  },
  methods: {
    setCaret(obj) {
      if (obj.createTextRange) {
        obj.caretPos = document.selection.createRange().duplicate();
      }
    },
    insertAtCaret(obj, value) {
      if (document.all) {
        if (obj.createTextRange && obj.caretPos) {
          var caretPos = obj.caretPos;
          caretPos.text =
            caretPos.text.charAt(caretPos.text.length - 1) == " "
              ? value + " "
              : value;
        } else {
          obj.value = value;
        }
      } else {
        if (obj.setSelectionRange) {
          var rangeStart = obj.selectionStart;
          var rangeEnd = obj.selectionEnd;
          var tempStr1 = obj.value.substring(0, rangeStart);
          var tempStr2 = obj.value.substring(rangeEnd);
          obj.value = tempStr1 + value + tempStr2;
        } else {
          alert(
            "This version of Mozilla based browser does not support setSelectionRange"
          );
        }
      }
    }
  },
  watch: {
    inputStr: {
      handler(val) {
        console.log("input值变化:", val);
      },
    },
    textareaStr: {
      handler(val) {
        console.log("textarea值变化:", val);
      },
    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
  text-align: center;
}
</style>

是不是通过事件委托方法,比每个组件都去绑修饰符要简单、快捷很多。

注意:这里运用原生 js 插入 input 、textarea 值,并不会改变 vue 双向绑定数据,这里主动通知浏览器进行事件分发,让Vue监听到

e.target.dispatchEvent(new Event(“input”));

为什么会出现这种情况?

Vue只监听浏览器原生事件,而jQuery改变输入框的值属于jQuery定义的事件,这个Vue是无法监听到的。

还有这里是能用原生 js 实现,没有考滤多个 Input 、textarea 的情况, 可以通过 document.querySelectorAll 来处理

当然用 jquery 的方法也会更加方便,只是这个包有点大,具体可以根据自身项目选择最优方式

$(".oper-c").on("keydown", 'input, textarea', function(){});
$(".oper-c").on("select", 'input, textarea', function(){});

前端开发那点事
微信公众号搜索“前端开发那点事”

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注