Vue數(shù)據(jù)響應(yīng)式

Vue 最獨特的特性之一蛉鹿,是其非侵入性的響應(yīng)式系統(tǒng)妖异。數(shù)據(jù)模型僅僅是普通的 JavaScript 對象日川。而當你修改它們時龄句,視圖會進行更新散罕。

前置知識

Vue對Data做了什么
getter 和 setter
let obj0 = {
    姓: "高",
    名: "圓圓",
    age: 18
};

// 需求一欧漱,得到姓名

let obj1 = {
    姓: "高",
    名: "圓圓",
    姓名() {
        return this.姓 + this.名;
    },
    age: 18
};

console.log("需求一:" + obj1.姓名());
// 姓名后面的括號能刪掉嗎误甚?不能窑邦,因為它是函數(shù)
// 怎么去掉括號擅威?

// 需求二,姓名不要括號也能得出值

let obj2 = {
    姓: "高",
    名: "圓圓",
    get 姓名() {
        return this.姓 + this.名;
    },
    age: 18
};

console.log("需求二:" + obj2.姓名);

// 總結(jié):getter 就是這樣用的冈钦。不加括號的函數(shù)郊丛,僅此而已。

// 需求三:姓名可以被寫

let obj3 = {
    姓: "高",
    名: "圓圓",
    get 姓名() {
        return this.姓 + this.名;
    },
    set 姓名(xxx) {
        this.姓 = xxx[0]
        this.名 = xxx.slice(1)
    },
    age: 18
};

obj3.姓名 = '高媛媛'

console.log(`需求三:姓 ${obj3.姓}瞧筛,名 ${obj3.名}`)

// 總結(jié):setter 就是這樣用的厉熟。用 = xxx 觸發(fā) set 函數(shù)
Object.defineProperty()

之前在使用getter、setter時较幌,是在定義這個對象時直接使用的揍瑟。在定義完一個對象之后,要想再添加新的get set時只能用Object.defineProperty()

// 需求:n不能小于0
let data2 = {}
data2._n = 0 //用_n存儲n的值
Object.defineProperty(data2, 'n', {
  get(){
    return this._n
  },
  set(value){ 
  //set可以添加判斷:小于0直接return,否則將n值置為最新value
    if(value < 0) return 
    this._n = value 
  }
})

代理和監(jiān)聽

let myData5 = { n: 0 };
let data5 = proxy2({ data: myData5 }); // 括號里是匿名對象乍炉,無法訪問

function proxy2({ data } ) {
let value = data.n;
Object.defineProperty(data, "n", {
get() {
return value;
},
set(newValue) {
if (newValue < 0) return;
value = newValue;
}
});
// 就加了上面幾句月培,這幾句話會監(jiān)聽 data

const obj = {};
Object.defineProperty(obj, "n", {
get() {
return data.n;
},
set(value) {
if (value < 0) return; //這句話多余了
data.n = value;
}
});

return obj; // obj 就是代理
}

Object.defineProperty

  • 可以給對象添加屬性value
  • 可以給對象添加getter/setter
  • getter/setter用于對屬性的讀寫進行監(jiān)控
什么是代理(設(shè)計模式)
  • 對myData對象的屬性讀寫,全權(quán)由另一個對象vm負責
  • 那么vm就是myData的代理
  • 比如myData.n不用此叠,偏要用vm.n來操作myData.n

vm = new Vue({data: myData})
一窗看、會讓 vm 成為 myData 的代理(proxy)
二软瞎、會對 myData 的所有屬性進行監(jiān)控 為什么要監(jiān)控,為了防止 myData 的屬性變了只锭, vm 不知道
vm 知道屬性變了就可以調(diào)用 render(data) UI = render(data)
總之對data做了任何修改纵顾,Vue必須知道才能做到響應(yīng)刷新


回到最初的問題,Vue對Data做了什么
1.Vue會對data后面的{n:0}進行竄改,給它加監(jiān)聽闷愤。
2.會新生成一個對象遭居,這個對象會代理篡改后的對象告丢。

圖片1.png

Vue數(shù)據(jù)響應(yīng)式

響應(yīng)式:若一個物體對外界刺激有所反應(yīng)颅湘,那就是響應(yīng)式

Vue的data是響應(yīng)式
const vm=new Vue({data:{n:0}})
我如果修改vm.n,那么UI中的n就會響應(yīng)我
Vue 2通過Object.defineProperty來實現(xiàn)數(shù)據(jù)響應(yīng)式

data.png

Vue的data的bug

new Vue({
  data: {
    obj: {
      a: 0 //obj.a會被Vue監(jiān)聽 & 代理
    //b:undefined  
    }
  },
  template: `
    <div>
      {{obj.b}}
      <button @click="setB">set b</button>
    </div>
  `,
  methods: {
    setB() {
      this.obj.b = 1; //頁面中不會顯示1
    //Vue.set(this.obj,'b'乙漓,1)
    //this.$set(this.obj,'b',1) 
    }
  }
}).$mount("#app");

頁面中不會顯示1涩蜘,因為Vue沒法監(jiān)聽一開始不存在的obj.b
解決辦法
1.把k都聲明好,后面不再加屬性 比如b:undefined
2.使用Vue.set或者this.$set
是為了防止重名 比如`Vue.set(this.obj,'b')`或者`this.set(this.obj,'b'秩贰,1)`
Vue.set和this.$set作用:

  • 新增key
  • 自動創(chuàng)建代理和監(jiān)聽(如果沒有創(chuàng)建過)
  • 觸發(fā)UI更新(但不會立刻更新)

數(shù)組變異

如果data中有數(shù)組,沒法提前聲明key的情況

  data: {
    array: ["a", "b", "c"]
  },
  template: `
    <div>
      {{array}}
      <button @click="setD">set d</button>
    </div>
  `,
  methods: {
    setD() {
    //this.array[3] = "d"; 頁面中不會顯示'd'
    //this.$set(this.array,3,'d') 增加下標的方式實現(xiàn)添加
    this.array.push('d')//尤雨溪的做法
    console.log(this.array)
    }
  }
}).$mount("#app");

變更方法

Vue 將被偵聽的數(shù)組的變更方法進行了包裹培漏,所以它們也將會觸發(fā)視圖更新友鼻。這些被包裹過的方法包括:

  • push()

  • pop()

  • shift()

  • unshift()

  • splice()

  • sort()

  • reverse()

Vue在這個對象僻爽,你以為這個是數(shù)組對象须板,你傳給Vue之后,Vue就會篡改這個數(shù)組柠横。它會在中間加一層原型搬俊。這個原型有7個方法扩淀,這7個方法跟以前是同名的但是代碼被尤雨溪改了,會幫你set(監(jiān)聽,每次push都會通知Vue)庆聘。也就是說push會做2件事情:調(diào)以前的push,調(diào)完后通知Vue添加監(jiān)聽和代理宴抚。

總結(jié)

1.對象中新增的key

Vue無法事先監(jiān)聽和代理

要使用set來新增key,創(chuàng)建監(jiān)聽和代理,更新UI

最好提前把屬性都寫出來常潮,不要新增key

但數(shù)組做不到「不新增key」

2.數(shù)組中新增的key

也可用set來新增key,更新UI

不過尤雨溪篡改了7個API方便你對數(shù)組進行增刪

這7個API會自動處理監(jiān)聽和代理岔留,并更新UI

結(jié)論:數(shù)組新增key最后通過7個API


對數(shù)據(jù)響應(yīng)式的理解

簡單說就是用戶更改數(shù)據(jù)時厕吉,視圖可以自動刷新班眯,頁面UI能夠響應(yīng)數(shù)據(jù)變化磁餐。Object.defineProperty()給數(shù)據(jù)對象添加value屬性伴箩,設(shè)置getter和setter監(jiān)控屬性的讀寫,這些 getter/setter 對用戶來說是不可見的,但是在內(nèi)部它們讓 Vue 能夠追蹤依賴芒炼,在屬性被訪問和修改時通知變更。并使用vm對象負責數(shù)據(jù)對象的代理,當屬性更新時鲜屏,調(diào)用render()更新也殖。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末响谓,一起剝皮案震驚了整個濱河市赖晶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖密浑,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件颤介,死亡現(xiàn)場離奇詭異韵吨,居然都是意外死亡,警方通過查閱死者的電腦和手機靖苇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來运吓,“玉大人瓮床,你說我怎么就攤上這事。” “怎么了琐谤?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我乾忱,道長纲酗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任帕翻,我火速辦了婚禮,結(jié)果婚禮上诅愚,老公的妹妹穿的比我還像新娘劫映。我一直安慰自己雌桑,他們只是感情好,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布泵三。 她就那樣靜靜地躺著,像睡著了一般萍歉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上斗幼,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天澎蛛,我揣著相機與錄音,去河邊找鬼蜕窿。 笑死谋逻,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的桐经。 我是一名探鬼主播毁兆,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼阴挣!你這毒婦竟也來了气堕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤畔咧,失蹤者是張志新(化名)和其女友劉穎茎芭,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體誓沸,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡梅桩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拜隧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宿百。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡趁仙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出垦页,到底是詐尸還是另有隱情雀费,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布外臂,位于F島的核電站坐儿,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏宋光。R本人自食惡果不足惜貌矿,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望罪佳。 院中可真熱鬧逛漫,春花似錦、人聲如沸赘艳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蕾管。三九已至枷踏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間掰曾,已是汗流浹背旭蠕。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留旷坦,地道東北人掏熬。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像秒梅,于是被迫代替她去往敵國和親旗芬。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容