2016-01-18 29 views
1

我有一个JavaScript对象,我试图绑定到Vue视图。Javascript对象数据绑定Vue

我正在运行一个函数来使用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> 

回答

3

尝试了这一点:

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

它会将新对象追加到externalJSSystems并且视图将被更新。为什么你的例子不工作?因为您正在分配一个新的Array参考externalJSSystems但Vue仍在观看旧的。

要实现您想要的功能,请不要指定新的Array实例,而是清除它。例如:

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

可以确认 - [小提琴](https://jsfiddle.net/qfxpznor/) – ShadowScripter

+0

感谢您的回复。这只是一个简单的例子,我放在一起,我不知道这将如何在我的实际代码中工作...让我测试一下,看看它是否会工作... – vmitchell85

+0

这确实工作,但我必须循环通过每个条目来单独推送每个条目而不是仅使用全新的数据集更新对象 - 我也尝试设置整个对象,然后再推入一个条目,但它仍然不更新 - 如果我找不到更好的解决方案然后我将这个标记为答案(或者那是不好的做法?) – vmitchell85

0

而不是使系统数据属性,你可以把它计算性能。就像所说的其他答案一样,这个参考是针对旧对象的。但是,如果您使systems为计算属性,它将自动监视计算中使用的任何变量(如externalJSSystems)并重新计算计算出的属性。

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

无法得到这个工作...你可以创建一个小提琴吗? – vmitchell85

2

systable组件的该实例被实例化,Vue的增加了一个“观察者”级到初始externalJSSystems阵列 - 延伸的阵列的原型,加入吸气剂/ setter方法对于每个属性,并维持两组件的data与原始阵列之间的双向绑定。 changeTheData()方法覆盖Vue修改externalJSSystems阵列与一个全新的阵列(缺乏观察器),从而打破双向绑定。

通过这种方式,externalJSSystems.push(…)可以工作,因为默认的Array方法('push','pop','shift','unshift','splice','sort'和'reverse')已被突变,他们由观察员处理。

我认为你正在寻找的行为的关键在于Vue组件“道具” - http://vuejs.org/guide/components.html#Props。实际上,它看起来像组件标记 - <systable :systems="systems"></systable> - 已经设置为将动态数据传递到组件实例。现在,那:systems="systems"没有做任何事情。通过在Parent Vue范围中定义systems,并在组件注册中将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 od有权访问其systems数据。 这给你的外部changeTheData()方法提供了一个对你定义的system的Vue实例的引用 - 从而使它能够访问修改(不需要替换,或者迭代地添加/删除项目......)数据数组。

+0

感谢关于观察者的信息,现在它变得更有意义,但我不确定我将能够做我需要做的事情。我添加了按钮点击功能来模拟我的AJAX调用,以获取我不想放入Vue的数据。现在我想这样做可能会更好。 – vmitchell85