当v-model改变时如何触发事件?

137

我试图使用 @click 来触发 foo() 函数,但是正如您所看到的,需要按两次单选按钮才能正确触发事件。只有第二次按下时才会捕获值...

我想在没有 @click 的情况下触发事件,只有当 v-model(srStatus)更改时才触发事件。

这里是我的 Fiddle:

http://fiddle.jshell.net/wanxe/vsa46bw8/


3
Fiddle的链接已失效。 - FrenkyB
如果调用 foo() 的意图是进行非模板更改,请使用 watcher - Saksham
这是一个很好的例子,说明为什么需要代码“在问题中”。如果可能,请恢复它并在此处显示。 - isherwood
我希望我能够检索到那个问题的代码,但那已经是5年前的事了...幸运的是我们有好的答案。 - jnieto
5个回答

123

您可以通过删除v-on指令来简化此过程:

<input type="radio" name="optionsRadios" id="optionsRadios1" value="1" v-model="srStatus">

使用watch方法监听变化:

new Vue ({
    el: "#app",
    data: {
        cases: [
            { name: 'case A', status: '1' },
            { name: 'case B', status: '0' },
            { name: 'case C', status: '1' }
        ],
        activeCases: [],
        srStatus: ''
    },
    watch: {
        srStatus: function(val, oldVal) {
            for (var i = 0; i < this.cases.length; i++) {
                if (this.cases[i].status == val) {
                    this.activeCases.push(this.cases[i]);
                    alert("Fired! " + val);
                }
            }
        }
    }
});

2
你能自动监视任何模型变化吗?例如,对于一个具有多个输入的表单,所有输入都需要被监视? - Eric Burel
@EricBurel 我知道这是老问题,但答案是否定的。你不能观察到整个数据对象所有绑定的字段,你需要单独观察该对象的每一个属性,这种方法对于具有许多字段的表单上的大记录来说是有问题的。 - JohnC
8
@EricBurel ,实际上您可以将 'deep' 属性设置为 'true' 来观察嵌套对象--> https://vuejs.org/v2/api/#watch - SanBen

108

这是因为您的 click 事件处理程序在单选按钮的值更改之前就已经触发。您需要监听 change 事件:

<input 
  type="radio" 
  name="optionsRadios" 
  id="optionsRadios2" 
  value=""
  v-model="srStatus" 
  v-on:change="foo"> //here

另外,请确保您真的想在准备就绪时调用 foo()...似乎您实际上并不想这样做。

ready:function(){
    foo();
},

1
你会如何处理滑块? - Royi
文档中列出了哪些可用事件?我找不到它。 - toraman
这些只是标准的 JavaScript 事件,您可以在此处找到:https://developer.mozilla.org/zh-CN/docs/Web/Events#Standard_events - pherris
谢谢!但是 Ready:function 对我没用。相反,使用 methods:{ foo(){//do something} }。 - Vince Banzon
还要注意,如果您想在自定义Vue组件(单文件组件)上注册“v-on:change”事件,则应改用“v-on:input”。 - Andres Biarge

50

你应该使用@input

<input @input="handleInput" />

@input会在用户更改输入值时触发。

@change会在用户更改值并取消焦点输入时触发(例如点击外部某处)。

您可以在这里看到区别:https://jsfiddle.net/posva/oqe9e8pb/


对于文本输入框,最好使用“@input”事件,而对于其他类型的控件,如<select>和复选框,则最好使用“@change”事件。 - RajV

41

Vue2: 如果你只想在输入框模糊(比如按下回车键或点击其他地方后)时检测更改,请执行以下操作(更多信息这里

<input @change="foo" v-model... >

如果您想检测单个字符的更改(在用户键入时),请使用

<input @keydown="foo" v-model... >

您还可以使用@keyup@input事件。如果您想在模板中传递附加参数,请使用例如@keyDown="foo($event, param1, param2)"的方式。以下是比较结果(可在此处编辑可编辑版本

new Vue({
  el: "#app",
  data: { 
    keyDown: { key:null, val: null,  model: null, modelCopy: null },
    keyUp: { key:null, val: null,  model: null, modelCopy: null },
    change: { val: null,  model: null, modelCopy: null },
    input: { val: null,  model: null, modelCopy: null },
    
    
  },
  methods: {
  
    keyDownFun: function(event){                   // type of event: KeyboardEvent   
      console.log(event);  
      this.keyDown.key = event.key;                // or event.keyCode
      this.keyDown.val = event.target.value;       // html current input value
      this.keyDown.modelCopy = this.keyDown.model; // copy of model value at the moment on event handling
    },
    
    keyUpFun: function(event){                     // type of event: KeyboardEvent
      console.log(event);  
      this.keyUp.key = event.key;                  // or event.keyCode
      this.keyUp.val = event.target.value;         // html current input value
      this.keyUp.modelCopy = this.keyUp.model;     // copy of model value at the moment on event handling
    },
    
    changeFun: function(event) {                   // type of event: Event
      console.log(event);
      this.change.val = event.target.value;        // html current input value
      this.change.modelCopy = this.change.model;   // copy of model value at the moment on event handling
    },
    
    inputFun: function(event) {                    // type of event: Event
      console.log(event);
      this.input.val = event.target.value;         // html current input value
      this.input.modelCopy = this.input.model;     // copy of model value at the moment on event handling
    }
  }
})
div {
  margin-top: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

Type in fields below (to see events details open browser console)

<div id="app">
  <div><input type="text" @keyDown="keyDownFun" v-model="keyDown.model"><br> @keyDown (note: model is different than value and modelCopy)<br> key:{{keyDown.key}}<br> value: {{ keyDown.val }}<br> modelCopy: {{keyDown.modelCopy}}<br> model: {{keyDown.model}}</div>
  
  <div><input type="text" @keyUp="keyUpFun" v-model="keyUp.model"><br> @keyUp (note: model change value before event occure) <br> key:{{keyUp.key}}<br> value: {{ keyUp.val }}<br> modelCopy: {{keyUp.modelCopy}}<br> model: {{keyUp.model}}</div>
  
  <div><input type="text" @change="changeFun" v-model="change.model"><br> @change (occures on enter key or focus change (tab, outside mouse click) etc.)<br> value: {{ change.val }}<br> modelCopy: {{change.modelCopy}}<br> model: {{change.model}}</div>
  
  <div><input type="text" @input="inputFun" v-model="input.model"><br> @input<br> value: {{ input.val }}<br> modelCopy: {{input.modelCopy}}<br> model: {{input.model}}</div>
     
</div>


按键事件中的 keyDown 不起作用,而按下 'backspace' 键时会触发。因此最好使用 @input 事件。 - Peretz30
在这个代码片段中,我们可以看到退格键与 @keyDown 一起使用 https://jsfiddle.net/rLzm0f1q/ (然而我并不是说 @input 好或坏) - Kamil Kiełczewski
我想补充一下,使用 keyDown 时,模型似乎只会在事件触发后更新。而使用 input 时,它似乎会在之前更新。 - Axelle

10

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