github地址:https://github.com/lily1010/vue_learn/tree/master/lesson03 一 實例 每個 Vue 實例都會代理其 data 對象里所有的屬性,改變data,vue實例同時改變,當然改變vue實例,data也同時改變,即 vue實例<=>d ...
github地址:https://github.com/lily1010/vue_learn/tree/master/lesson03
一 實例
每個 Vue 實例都會代理其 data
對象里所有的屬性,改變data,vue實例同時改變,當然改變vue實例,data也同時改變,即 vue實例<=>data
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>vue實例與方法</title> <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> </head> <body> <div class="test"> {{a}} </div> <script type="text/javascript"> var data = { a: 1 } var myVue = new Vue({ el: ".test", data: data }) </script> </body> </html>
在console控制台操作是:(其中每種顏色框起來的代碼都是一組改變)
二 實例數據如何被追蹤變化
註意只有這些被代理的屬性是響應的。如果在實例創建之後添加新的屬性到實例上,它不會觸發視圖更新.那麼就要講下實例數據如何被追蹤變化
把一個普通對象傳給 Vue 實例作為它的 data
選項,Vue.js 將遍歷它的屬性,用Object.defineProperty 將它們轉為 getter/setter,在內部它們讓 Vue.js 追蹤依賴,在屬性被訪問和修改時通知變化,
舉個慄子:(我們訪問介面時返回的數據通常是get和set)
那麼來瞭解一下追蹤原理:
上圖描述的是:模板中每個指令/數據綁定都有一個對應的 watcher 對象,在計算過程中它把屬性記錄為依賴。之後當依賴的 setter 被調用時,會觸發 watcher 重新計算 ,也就會導致它的關聯指令更新 DOM。
那麼我們如果在實例化後給數據添加一個屬性,由於ES5的限制,Vue.js 不能檢測到對象屬性的添加或刪除,實際上vue的做法是初始化實例時將屬性轉為 getter/setter,這時已經開始了監控數據變化,所以數據是響應的,但是後來添加進去的屬性就沒辦法轉化為getter/setter.
舉個慄子,還是上面那段代碼:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>vue實例與方法</title> <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> </head> <body> <div class="test"> {{a}} </div> <script type="text/javascript"> var data = { a: 1 } var myVue = new Vue({ el: ".test", data: data }) </script> </body> </html>
在控制台新添加b和c兩個新屬性,如下:
但是vue的作者還是想辦法實現了在實例創建之後添加屬性並且讓它是響應的,但是不推薦,先來看一下做法:
(1)方式一:對於 Vue 實例,可以使用 $set(key, value)
實例方法
(2)方式二:對於普通數據對象,可以使用全局方法 Vue.set(object, key, value)
既然vue的作者已經提供了實例化後添加新屬性並讓它成為實時相應的,那為什麼還不推薦使用?
(1)data
對象就像組件狀態的模式(schema)。在它上面聲明所有的屬性讓組件代碼更易於理解。
(2)添加一個頂級響應屬性會強制所有的 watcher 重新計算,因為它之前不存在,沒有 watcher 追蹤它。這麼做性能通常是可以接受的,但是可以在初始化時避免。