【问题标题】:Javascript object data binding with Vue与 Vue 的 Javascript 对象数据绑定
【发布时间】:2016-04-23 17:40:31
【问题描述】:

我有一个试图绑定到 Vue 视图的 JavaScript 对象。

我正在运行一个函数来使用 AJAX 更新 JavaScript 对象,我希望 Vue 绑定到 JS 对象并在对象更新时更新视图,尽管这并没有发生。

研究建议在 Vue 声明中进行 AJAX 调用,但由于其他限制,我宁愿不这样做。

我创建了一个小提琴来说明问题所在,因为它可以在没有 AJAX 部分的情况下重现,并且粘贴了下面的代码。

https://jsfiddle.net/g6u2tph7/5/

提前感谢您的时间和智慧。

谢谢,

vmitchell85

JavaScript

window.changeTheData = function (){
    externalJSSystems =  [{description: 'Baz'}, {description: 'Car'}];
    document.getElementById("log").innerHTML = 'function has ran...';
    // This doesn't update the Vue data

}

var externalJSSystems = [{description: 'Foo'}, {description: 'Bar'}];

Vue.component('systable', {
    template: '#sysTable-template',
    data() {
        return {
            systems: externalJSSystems
        };
    }
});
new Vue({
   el: 'body'
});

HTML

<systable :systems="systems"></systable>

<button type="button" onclick="changeTheData()">Change</button>
<br><br>
<div id="log"></div>
<template id="sysTable-template">
    <table>
        <thead>
            <tr>
                <th>Description</th>
            </tr>
        </thead>
        <tbody>
            <tr v-for="sys in systems">
                <td>{{ sys.description }}</td>
            </tr>
        </tbody>
    </table>
</template>

【问题讨论】:

    标签: javascript ajax vue.js


    【解决方案1】:

    试试这个:

    externalJSSystems.push({description: 'Baz'}, {description: 'Car'});
    

    它将新对象附加到 externalJSSystems 并且视图将被更新。为什么你的例子不起作用?因为您正在为 externalJSSystems 分配一个新的 Array 引用,但 Vue 仍在关注旧的。

    要实现你想要的,不要分配新的Array 实例,而是清除它。例如:

    window.changeTheData = function (){
        externalJSSystems.length = 0
        externalJSSystems.push({description: 'Baz'}, {description: 'Car'});
    }
    

    【讨论】:

    • 感谢您的回复。这只是我放在一起的一个简单示例,我不确定这将如何在我的实际代码中工作......让我测试一下,看看它是否能工作......
    • 这确实有效,但是我必须遍历每个条目以单独推送每个条目,而不是仅使用整个新数据集更新对象 - 我还尝试设置整个对象,然后再推送一个条目并且它仍然没有更新 - 如果我找不到更好的解决方案,那么我会将此标记为答案(或者这是不好的做法?)
    • zxzak 或 @ShadowScripter - 是否有关于 JS 变量何时是对象而不是数组的建议?
    【解决方案2】:

    systable 组件的实例被实例化时,Vue 会在初始 externalJSSystems Array 中添加一个“Observer”类——扩展 Array 的原型,为每个属性添加 getter/setter,并维护两个-组件的data 和原始数组之间的方式绑定。 changeTheData() 方法用一个全新的数组(缺少观察者)覆盖了 Vue 修改的 externalJSSystems 数组,从而打破了双向绑定。

    通过这种方式,externalJSSystems.push( … ) 可以正常工作,因为默认的 Array 方法('push'、'pop'、'shift'、'unshift'、'splice'、'sort' 和 'reverse')已经发生了这样的变化它们由观察者处理。

    我认为你正在寻找的行为的关键在于 Vue 组件“props”——http://vuejs.org/guide/components.html#Props。事实上,看起来您的组件标记 - &lt;systable :systems="systems"&gt;&lt;/systable&gt; - 已经设置为将动态数据传递给组件实例。现在,:systems="systems" 没有做任何事情。通过在 Parent Vue 范围内定义 systems,并在 Component 注册中将 systems 定义为 prop(s),您可以将动态数据传递给该 Parent 范围内的组件。

    组件

    Vue.component('systable', {
      template: '#sysTable-template',
      props: {
        systems: Array
      }
    });
    

    Vue 实例

    var vm = new Vue({
      el: 'body',
      data: {
        systems: externalJSSystems
      }
    });
    

    您可以在这个小提琴中看到它的实际效果:https://jsfiddle.net/itopizarro/ycr12dgw/

    我缓存了 Vue 实例——var vm = new Vue({ … })——所以changeTheData 方法可以访问它的systems 数据。 这为您的外部 changeTheData() 方法提供了对您定义 system 的 Vue 实例的引用 - 从而使其能够修改(无需替换或迭代地添加/删除......)数据数组。 em>

    【讨论】:

    • 感谢有关观察者的信息,现在更有意义,但我不确定我是否能够做我需要做的事情。我添加了按钮单击功能来模拟我的 AJAX 调用,以获取我不想放入 Vue 的数据。现在我想这样做可能会更好。
    【解决方案3】:

    与其将系统设为数据属性,不如将其设为计算属性。就像另一个答案所说,引用是对旧对象的引用。但是如果您将systems 设为计算属性,它会自动监视计算中使用的任何变量(如externalJSSystems)并重新计算计算属性。

    Vue.component('systable', {
    template: '#sysTable-template',
    computed: {
        systems() {
            return externalJSSystems;
        }
    }
    });
    

    【讨论】:

    • 无法让它工作...你能创建一个小提琴吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-17
    • 2021-05-16
    • 2017-12-29
    • 2019-05-12
    • 2020-03-27
    相关资源
    最近更新 更多