Vue.js | Manually triggered events breaking model

2019-09-05 08:04发布

问题:

I am having some issues with one of my modules.

Consider the following example:

Vue.config.async = false; // if I remove this, it stays at initial value

var vm = new Vue({
  el: '#test',
  data: {
  	value: 'initial value'
  },
  methods: {
    changeHandler: function () {
      console.log('changed!')
    }
  }
});

vm.value = 'value change 1';
vm.$el.dispatchEvent(new Event('change'));
vm.value = 'value change 2';
vm.$el.dispatchEvent(new Event('change'));

console.log(vm.value); // 'value change 1'
<textarea id='test' v-model='value' v-on:change="changeHandler"></textarea>

<script src="https://vuejs.org/js/vue.js"></script>

Why won't model (and view) update after dispatching a 'change' event right before I want to assign a new value?

Is this a problem with Vue or am I just doing something incorrectly?

回答1:

You're working with the DOM when you should be working with the viewmodel. You've bound value to your textarea, and then you want to notice changes, right? Since you're modeling the textarea this way, you should watch the bound variable rather than the DOM element.

If you want to signal an event within Vue to trigger a handler, you should use Vue events, not DOM Events. As a general rule, strongly prefer manipulating your Vue over touching the DOM.

Setting async to false allows you to see all the changes, which otherwise happen so fast that some get debounced.

Vue.config.async = false;

var vm = new Vue({
  el: '#test',
  data: {
    value: 'initial value'
  },
  watch: {
    value: function() {
      console.log('changed!')
    }
  }
});

vm.$on('valueChange', function() {
  console.log('value change!');
});

vm.value = 'value change 1';
vm.$dispatch('valueChange');
vm.value = 'value change 2';
vm.$dispatch('valueChange');

console.log(vm.value); // 'value change 2'
<textarea id='test' v-model='value'></textarea>

<script src="https://vuejs.org/js/vue.js"></script>



回答2:

Your use of the change event is interfering with normal event processing. If you give each event a little bit of time (see the nextTick calls in my snippet), things work out as expected.

var vm = new Vue({
  el: '#test',
  data: {
    value: 'initial value'
  },
  methods: {
    changeHandler: function() {
      console.log('changed!')
    }
  }
});

vm.value = 'value change 1';
Vue.nextTick(() => vm.$el.dispatchEvent(new Event('change')));
Vue.nextTick(() =>vm.value = 'value change 2');
Vue.nextTick(() => vm.$el.dispatchEvent(new Event('change')));

console.log(vm.value); // 'value change 1'
<textarea id='test' v-model='value' v-on:change="changeHandler"></textarea>

<script src="https://vuejs.org/js/vue.js"></script>