VueJS:如何防止 textarea 默认行为

Posted

技术标签:

【中文标题】VueJS:如何防止 textarea 默认行为【英文标题】:VueJS: How to prevent textarea default behavior 【发布时间】:2018-04-23 14:01:55 【问题描述】:

我正在尝试实现类似 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 类似,但建议的解决方案不起作用

【问题讨论】:

IMO keyup 事件不适合此目的。 Keypress、keydown 和 keyup 有副作用,比如你的 '\n' 字符。喝完咖啡,我会写一个例子来回答。 看起来像重复的***.com/questions/44680638/… Preventing new line in textarea的可能重复 【参考方案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>

进一步阅读

W3C Specification for Keyboard Events 特别是event order 和event types

【讨论】:

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

尝试使用Vue内置prevent

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

【讨论】:

以上是关于VueJS:如何防止 textarea 默认行为的主要内容,如果未能解决你的问题,请参考以下文章

VueJS - 防止默认链接点击但也捕获对象

使用 VueJS 和 Laravel 的 Textarea v-model 初始值

JQuery:Keyup,如何防止箭头(向上和向下)的默认行为并输入键?

如何在 Vs Code 中更改默认自动选择的用户片段行为

如何防止调整大小的TextArea溢出页面?

如何防止 textarea 内容溢出到填充中?