Vue 實(shí)例的 data 屬性

基本認(rèn)識(shí)

  1. 作用:Vue 會(huì)遞歸將 data 的屬性轉(zhuǎn)換為 getter/setter 方法,從而使得 data 中屬性能夠響應(yīng)數(shù)據(jù)變化。
  2. 類型: Object | Function
// Object 類型 data 屬性
const vm = new Vue({
  data: { 
    name: 'IT白'
  }
}) 

// Function 類型 data 屬性
const component = Vue.extend({
  template: '<p>My name is {{ name }}</p>',
  data: function () {
    return {
      name: 'IT白',
    }
  }
})

創(chuàng)建 Object 類型與 Function 類型的data屬性的異同

  • 相同點(diǎn):Vue 都會(huì)為其生成相應(yīng)的 getter/setter 方法。
  • 不同點(diǎn):當(dāng)組件被同一時(shí)間多次實(shí)例化時(shí)
    ??Object 類型:組件的所有實(shí)例都會(huì)引用同一個(gè)數(shù)據(jù)對(duì)象。當(dāng)一個(gè)實(shí)例修改的自身的 data 屬性,由于引用統(tǒng)一個(gè)數(shù)據(jù)對(duì)象,導(dǎo)致修改也將會(huì)在其它實(shí)例中呈現(xiàn)。
    ??Function 類型:每次創(chuàng)建組件實(shí)例時(shí), Vue 都將通過(guò)調(diào)用該函數(shù),創(chuàng)建一個(gè)全新副本的數(shù)據(jù)對(duì)象。當(dāng)一個(gè)實(shí)例修改自身的 data 屬性,由于每個(gè)實(shí)例中的 data 屬性對(duì)象都是單獨(dú)的副本,所以不會(huì)影響其它實(shí)例。

:如果將組件的 data 屬性定義為 Object 類型,Vue 會(huì)拋出警告。


data 屬性響應(yīng)式原理

追蹤數(shù)據(jù)變化
  • 準(zhǔn)備:Vue 會(huì)遍歷 data 對(duì)象(如果是 Function 類型,Vue 會(huì)先調(diào)用函數(shù),創(chuàng)建對(duì)應(yīng)對(duì)象),并將所有屬性通過(guò) Object.defineProperty() 轉(zhuǎn)換成 getter/setter
  • collect as dependency:每個(gè)組件實(shí)例都對(duì)應(yīng)一個(gè) watcher 實(shí)例,它會(huì)在組件渲染的過(guò)程中把“接觸”過(guò)的數(shù)據(jù)屬性記錄為依賴。
  • notify:當(dāng) setter 被觸發(fā)時(shí),會(huì)通知 watcher。
  • trigger re-render:watcher 重新渲染關(guān)聯(lián)的組件。
  • touch:如果實(shí)例修改 data 屬性的值,將會(huì)觸發(fā) setter。
Vue 官方文檔插圖
檢測(cè)變化的注意事項(xiàng)

由于 JavaScript 的限制,Vue 無(wú)法檢測(cè)對(duì)象屬性的添加或刪除,所以直接動(dòng)態(tài)添加屬性到 data 對(duì)象中,該屬性為非響應(yīng)式。

var vm = new Vue({
  data:{
    a:1
  }
})
// `vm.a` 是響應(yīng)式的

vm.b = 2
// `vm.b` 是非響應(yīng)式的

但是可以通過(guò) Vue.set(object, propertyName, value) 方法向嵌套對(duì)象添加響應(yīng)式屬性,以及 Object.assign() 方法創(chuàng)建一個(gè)新的對(duì)象。

Vue.set(vm.someObject, 'b', 2)

// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
異步更新隊(duì)列
  • Vue 在更新 DOM 時(shí)是異步執(zhí)行的。
    ??只要偵聽(tīng)到數(shù)據(jù)變化,Vue 將開(kāi)啟一個(gè)隊(duì)列,并緩沖在同一事件循環(huán)中發(fā)生的所有數(shù)據(jù)變更。
    ??如果同一個(gè) watcher 被多次觸發(fā),只會(huì)被推入到隊(duì)列中一次。這種在緩沖時(shí)去除重復(fù)數(shù)據(jù)對(duì)于避免不必要的計(jì)算和 DOM 操作是非常重要的。然后,在下一個(gè)的事件循環(huán)“tick”中,Vue 刷新隊(duì)列并執(zhí)行實(shí)際 (已去重的) 工作。
    ??Vue 在內(nèi)部對(duì)異步隊(duì)列嘗試使用原生的 Promise.thenMutationObserversetImmediate,如果執(zhí)行環(huán)境不支持,則會(huì)采用 setTimeout(fn, 0) 代替。

  • 使用 .nextTick() 。
    ??為了在數(shù)據(jù)變化之后等待 Vue 完成更新 DOM,可以在數(shù)據(jù)變化之后立即使用 Vue.nextTick(callback)。這樣回調(diào)函數(shù)將在 DOM 更新完成后被調(diào)用。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 使用Vue在日常開(kāi)發(fā)中會(huì)頻繁接觸和使用生命周期,在官方文檔中是這么解釋生命周期的: 每個(gè) Vue 實(shí)例在被創(chuàng)...
    心_c2a2閱讀 2,388評(píng)論 1 8
  • 這方面的文章很多,但是我感覺(jué)很多寫的比較抽象,本文會(huì)通過(guò)舉例更詳細(xì)的解釋。(此文面向的Vue新手們,如果你是個(gè)大牛...
    Ivy_2016閱讀 15,579評(píng)論 8 63
  • 前言 Vue.js 的核心包括一套“響應(yīng)式系統(tǒng)”。 “響應(yīng)式”,是指當(dāng)數(shù)據(jù)改變后,Vue 會(huì)通知到使用該數(shù)據(jù)的代碼...
    NARUTO_86閱讀 37,772評(píng)論 8 86
  • 前言 Vue.js 的核心包括一套“響應(yīng)式系統(tǒng)”。 “響應(yīng)式”,是指當(dāng)數(shù)據(jù)改變后,Vue 會(huì)通知到使用該數(shù)據(jù)的代碼...
    world_7735閱讀 1,003評(píng)論 0 2
  • 每次看一會(huì)書,我就習(xí)慣性地拿起手機(jī)翻翻朋友圈,或是被其他事情所打擾,總是靜不下心來(lái)?,F(xiàn)在看書的時(shí)候,我會(huì)把手機(jī)放在...
    Linda003閱讀 1,520評(píng)論 0 0

友情鏈接更多精彩內(nèi)容