2016-01-18 69 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