【问题标题】:VueJS: How to prevent textarea default behaviorVueJS:如何防止 textarea 默认行为
【发布时间】:2024-04-28 16:00:02
【问题描述】:

我正在尝试实现类似 slack 的功能,以便仅在按确切输入时发送消息(不按 shift)

考虑这个 vue 模板 <textarea type="text" v-model="message" @keyup.enter.exact="sendMessage($event)"></textarea> 用这个组件

export default {
  name: 'Typing',
  data() {
      return {
          message: null
      }
  },
  methods: {
      sendMessage(e) {
        // e.stopPropagation() and e.preventDefault() have no impact
        this.$socket.emit('message', { text: this.message });
        console.log(this.message); // Print the message with another '\n' at the end due to textarea default behavior
      }
  }
}

有没有人知道如何避免在不使用正则表达式将其发送到后端之前删除最后一个 '\n'(我认为这会很脏)?

谢谢

PS:我对 VueJS 堆栈还很陌生,希望我的问题不明显

编辑:This question 类似,但建议的解决方案不起作用

【问题讨论】:

标签: javascript vue.js vuejs2 vue-component


【解决方案1】:

您的问题有这样简单的解决方案:

new Vue({
  el: '#app',
  data: {
    message: ''
  },
  methods: {
    sendMessage () {   
      console.log(this.message, this.message.length)
      // this.$socket.emit('message', {text: this.message});
      // clear textarea: this.message = ''
    }
  }
})
<div id="app">
  <textarea v-model="message" @keydown.enter.exact.prevent="sendMessage"></textarea>
</div>

<script src="https://unpkg.com/vue"></script>

【讨论】:

    【解决方案2】:

    问题

    <textarea
      type="text"
      v-model="message"
      @keyup.enter.exact="sendMessage($event)"
    >
    </textarea>
    

    代码在 Enter 键的keyup 事件上调用sendMessage 方法。 keyup 事件在密钥释放后触发。因此,代码在按键被按下、按键运行的默认行为(输入换行符)和按键被释放之后调用该方法。 preventDefault 不会阻止问题,因为试图阻止的行为在 keyup 事件之前已经发生。

    解决方案

    我们已经确定了以下内容:

    • 我们希望阻止按 Enter 键的默认行为。
    • keyup 事件在默认行为已经发生后触发。

    解决方法是阻止keydown事件上的默认行为,并在keyup事件上调用方法。

    注意:重要的是只在keyup事件上调用该方法,以避免用户按住键时多次调用。

      <textarea
        v-model="value"
        @keydown.enter.exact.prevent
        @keyup.enter.exact="send"
        @keydown.enter.shift.exact="newline"
      >
      </textarea>
    

    当按下 Enter+Shift 组合时,可以调用将换行符附加到 textarea 值的方法。

    下面是一个演示解决方案中描述的所有行为的 sn-p。

    new Vue({
      template: `
        <div>
          <textarea
            v-model="value"
            @keydown.enter.exact.prevent
            @keyup.enter.exact="send"
            @keydown.enter.shift.exact="newline"
          >
          </textarea>
        </div>
      `,
      
      data: {
        value: '',
      },
      
      methods: {
        newline() {
          this.value = `${this.value}\n`;
        },
    
        send() {
          console.log('========');
          console.log(this.value);
          console.log('========');
        },
      },
    }).$mount('#root');
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
    </head>
    <body>
      <div id="root"></div>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js"></script>
    </body>
    </html>

    进一步阅读

    【讨论】:

    • 注意,如果你是在一个组件上而不是在原生 textarea 元素上这样做,那么它是@keydown.native.enter.exact.prevent
    • 即使在 Quasar 框架中不使用 native 修饰符也能正常工作。
    【解决方案3】:

    尝试使用Vue内置prevent

    <textarea type="text" v-model="message" @keyup.enter.exact.prevent="sendMessage($event)"></textarea>
    

    【讨论】: