【问题标题】:Vuejs binding not working if update by jquery如果通过 jquery 更新,Vuejs 绑定不起作用
【发布时间】:2018-04-07 21:21:21
【问题描述】:

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 更新输入框,例如日历、自动完成和 Select2,都将通过非 vuejs 方式更新输入框。

有什么简单的方法来解决这个问题?

【问题讨论】:

  • 我不知道 VueJS,但我觉得它有点像 Angular?如果是这样的话,jQuery 就没有生意了。它只是干扰了 Vue。只需删除 jQuery 并以 Vue 的方式做事。
  • 我认为你的小提琴正在工作......我刚改成this.testModel= 'testing';
  • @SantoshKumar,我知道,但是我的 v-model 是由其他 3rd 方组件通过 jquery 更新的。我不能改变那些来做到这一点this.testModel='testing';

标签: javascript jquery html vue.js vuejs2


【解决方案1】:

现在回答为时已晚,但对于以后遇到此问题的任何人都可以使用我的建议。

我在某处读过This is a jQuery problem, trigger/val() doesn't dispatch native events in some cases. 所以我们会在用jQuery val()改变值后调度原生JS事件

$("#test").val("testing")[0].dispatchEvent(new Event('input'))

注意事项:-

  • 在 Vue 中,texttextarea 元素使用 input 事件,checkboxesradioselect 使用 change 作为事件。所以相应地 dispatchEvent;
  • 我假设使用 id 选择器 $("#test") 您将其应用于单个 dom 元素,这就是我选择 [0] th 元素的原因。如果您打算将它用于多个元素,那么您可以使用 for 循环在 al 上调度事件。

参考:-Vue Issues on Github

【讨论】:

  • 非常感谢。
【解决方案2】:

最好的方法是让 jQuery 更改数据而不是输入 val 以保持一切同步。

像这样:

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 增强页面中使用它们

【讨论】:

    【解决方案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.

    【讨论】:

    • v-model.lazy 将仅在输入失去焦点或按下enter 时更新数据,因为它将事件从@input 修改为@change
    【解决方案4】:

    它不起作用,因为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/

    【讨论】:

      【解决方案5】:

      您可以创建一个全局函数来更新您的测试模型,而不是使用 jQuery,或者您可以查看 Vuex https://vuex.vuejs.org/en/intro.html

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

      【讨论】:

        猜你喜欢
        • 2011-12-14
        • 2016-09-16
        • 2018-06-21
        • 1970-01-01
        • 1970-01-01
        • 2014-09-07
        • 2016-07-02
        • 2017-02-16
        • 1970-01-01
        相关资源
        最近更新 更多