如果由jquery更新,则Vuejs绑定不起作用

时间:2017-10-26 13:09:31

标签: javascript jquery html vue.js vuejs2

Jsfiddle

HTML:

<div id="testVue">

<input id="test" v-model="testModel"/>

<button @click="clickMe()">Click me</button>

<button @click="showValue()">Show value</button>

</div>

的Javascript

var testVue = new Vue({
  el: '#testVue',

  data: {
    testModel: 'Hello Vue!'
  },

  methods: {

    clickMe: function() {
        $("#test").val("testing");
        console.log(this.testModel);
    },

    showValue: function() {
        console.log(this.testModel);
    }
  }
});

我完全理解我不应该在Vuejs $("#test").val("testing");中这样做,我应该像this.testModel="testing";

那样做

但我无法理解为什么这个基本绑定在Vuejs中不起作用?我有很多HTML组件通过jquery更新输入框,例如Calendar,Autocomplete和Select2,所有都将通过非vuejs方式更新输入框。

任何简单的方法来处理这个问题?

5 个答案:

答案 0 :(得分:7)

现在回答还为时已晚,但是对于以后偶然发现此问题的任何人都可以使用我的建议进行处理。

我在某处读过This is a jQuery problem, trigger/val() doesn't dispatch native events in some cases. 因此,在使用jQuery val()

更改值后,我们将调度本机JS Event
$("#test").val("testing")[0].dispatchEvent(new Event('input'))

注意事项:-

  • 在Vue中,texttextarea元素使用input事件,而checkboxesradioselect使用change作为一个事件。因此,dispatchEvent相应;
  • 我假设使用id选择器$("#test")将此代码应用于单个dom元素,这就是为什么我选择了[0] th元素。如果您打算将其用于多个元素,则可以使用for循环对al进行dispatchEvent。

参考:-Vue Issues on Github

答案 1 :(得分:5)

最好的方法是让jQuery更改数据而不是输入值以保持所有内容同步。

像这样:

let mainState = { inputVal: 'testing' };

let app = new Vue({
  el: '#app',
  data: mainState,
  methods: {
    vueThing() {
      this.inputVal = 'Vue value';
    }
  }
}); 

$('#jqThing').on('click', function() {
  mainState.inputVal = 'jQuery Value';
});

https://jsfiddle.net/6evc921f/

或者将jQuery元素构造函数包装在Vue组件中,并在Vue增强页面中使用它们

答案 2 :(得分:3)

只需使用@change事件:

<input @change="$emit('update:testModel', $event.target.value)" id="test" v-model="testModel"/>

您还可以使用.lazy修饰符:

<input id="test" v-model.lazy="testModel"/>

如文档所述:By default, v-model syncs the input with the data after each input event (with the exception of IME composition as stated above). You can add the lazy modifier to instead sync after change events.

答案 3 :(得分:2)

它不起作用,因为默认情况下v-model使用input事件,当你这样做时不会被触发:

$("#test").val("testing");

除非您有特殊原因,否则您不应该直接向DOM注入任何内容的原因之一。

尝试在该框中输入并点击showValue,您会看到它已正确更新,因为输入事件已被触发。

如果你真的想走这条路(我建议你不要),那么你可以自己编写custom directive,例如:

Vue.directive('model-inject', {
    bind: function(el, binding, vnode) {
        el.value = vnode.context[binding.expression];

        // Create inject event and add it to Vue instance (available by this.injectEvent)
        vnode.context.injectEvent = new CustomEvent("inject");
        // Attach custom event to el
        el.addEventListener('inject', function() {
            vnode.context[binding.expression] = el.value;
        });

        // Also bind input
        el.addEventListener('input', function() {
            vnode.context[binding.expression] = el.value;
        });
    },
    update: function(el, binding, vnode) {
        el.value = vnode.context[binding.expression];
    }
});

将名为inject的自定义事件绑定到元素以及默认输入事件,因此您可以像这样使用它:

<input id="test" v-model-inject = "testModel" />

然后当你通过jQuery更新任何东西时,你可以这样做:

document.getElementById("test").dispatchEvent(this.injectEvent);

这里是JSFiddle:https://jsfiddle.net/q591gn01/

答案 4 :(得分:0)

您可以创建一个全局函数来更新测试模型,也可以查看Vuex https://vuex.vuejs.org/en/intro.html

,而不是使用jQuery。

使用Vue时,不应尝试使用jQuery更新DOM。