VueJS:如何阻止textarea的默认行为

23

我正在尝试实现类似 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堆栈非常陌生,希望我的问题不是显而易见的

编辑:这个问题类似,但提出的解决方案不起作用。


在这种情况下,IMO的keyup事件是不合适的。Keypress、keydown和keyup都有副作用,比如你的'\n'字符。等我喝完咖啡,我会写一个例子来回答。 - user6748331
看起来是重复的 https://dev59.com/5aLia4cB1Zd3GeqPocnj - Nikolai Borisik
可能是重复的问题:如何防止 textarea 换行 - Nikolai Borisik
3个回答

56

问题

<textarea
  type="text"
  v-model="message"
  @keyup.enter.exact="sendMessage($event)"
>
</textarea>
代码在 Enter 键的 keyup 事件上调用了 sendMessage 方法。 keyup 事件会在松开按键后触发,因此代码会在按下按键、默认行为(换行)和松开按键之后才调用该方法。使用 preventDefault 将无法防止这个问题,因为需要被防止的行为已经在 keyup 事件之前发生了。

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

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

  <textarea
    v-model="value"
    @keydown.enter.exact.prevent
    @keyup.enter.exact="send"
    @keydown.enter.shift.exact="newline"
  >
  </textarea>
一个将换行符追加到文本区域值的方法可以在按下 Enter+Shift 组合键时被调用。
下面是一个演示解决方案中描述的所有行为的代码片段。
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>

更多阅读资料


请注意,如果您正在处理组件而不是原生的文本区域元素,则应使用@keydown.native.enter.exact.prevent - Titan
即使在Quasar框架中没有使用native修饰符,也能正常工作。 - Vahid Amiri

10

您的问题可以像这样简单地解决:

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>


1
尝试使用 Vue 内置的 prevent
<textarea type="text" v-model="message" @keyup.enter.exact.prevent="sendMessage($event)"></textarea>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接