選擇題
1衷敌、下面關(guān)于 Vue.js 的數(shù)據(jù)響應(yīng)式描述正確的是:
- A. 任何一個對象都可以被設(shè)置為響應(yīng)式對象,當(dāng)該對象的數(shù)據(jù)發(fā)生變化后可以通知視圖更新罐监。
- B. 只有 Vue.js 中的選項 data (如:new Vue({ data: { } }))才可以設(shè)置為響應(yīng)式對象瞒爬,當(dāng)該對象的數(shù)據(jù)發(fā)生變化后通知視圖更新弓柱。
- C. Dep 對象的作用是收集依賴侧但,每一個屬性都會對應(yīng)一個 Dep 對象,當(dāng)屬性變化時會調(diào)用 Dep 對象的 notify 方法發(fā)送通知更新視圖屁药。
- D. 1個 Dep 對象可能會對應(yīng)多個 Watcher 對象,當(dāng)數(shù)據(jù)變化觸發(fā)依賴 Dep 對象通知對應(yīng)的 Watcher 對象更新視圖酿箭。( √ )
2趾娃、下面關(guān)于響應(yīng)式原理描述錯誤的是:
- A. 給 data 對象的某個屬性設(shè)置為一個新的對象 (this.o = { name: 'xxx' })缭嫡,此對象是響應(yīng)式的抬闷。
- B. 點擊按鈕的時候給 data 對象上的 obj 新增一個 name 屬性 (this.obj.name = 'xxx'),該屬性是響應(yīng)式的笤成。( × )
- C. Vue.js 內(nèi)部當(dāng)數(shù)據(jù)變化后,直接更新真實 DOM纵诞。
- D. Vue.js 內(nèi)部當(dāng)數(shù)據(jù)變化后培遵,首先操作的是虛擬 DOM。
簡答題
1荤懂、當(dāng)我們點擊按鈕的時候動態(tài)給 data 增加的成員是否是響應(yīng)式數(shù)據(jù),如果不是的話节仿,如果把新增成員設(shè)置成響應(yīng)式數(shù)據(jù),它的內(nèi)部原理是什么。
let vm = new Vue({
el: '#el'
data: {
o: 'object',
dog: {}
},
method: {
clickHandler () {
// 該 name 屬性是否是響應(yīng)式的
this.dog.name = 'Trump'
}
}
})
答:不是響應(yīng)式數(shù)據(jù)女轿。響應(yīng)式對象和響應(yīng)式數(shù)組是指在vue初始化時期壕翩,利用Object.defineProperty()方法對其進(jìn)行監(jiān)聽,這樣在修改數(shù)據(jù)時會及時體現(xiàn)在頁面上放妈。
設(shè)置為響應(yīng)式數(shù)據(jù)有兩種方法:
1、給 dog 的屬性 name 設(shè)置一個初始值珍策,可以為空字符串或者 undefined 之類的宅倒,代碼和原因如下:
let vm = new Vue({
el: '#app',
data: {
msg: 'object',
dog: {
name: ''
}
},
method: {
clickHandler() {
// 該 name 屬性是否是響應(yīng)式的
this.dog.name = 'Trump'
}
}
})
- 原因:vm[key] setter 操作的時候會觸發(fā) data[key] 的 setter 操作,data[key] 的 setter 操作會 walk 這個新的值(walk方法是給data里的對象類型的值設(shè)置響應(yīng)式)拐迁,而題目中的 data 的 dog 是個空對象,沒有任何屬性线召,所以初始化 Vue 實例的時候,在給 dog 設(shè)置 proxy 的時候沒有任何屬性有 getter 和 setter 方法祟蚀,所以在點擊按鈕動態(tài)的給 dog 添加 name 屬性割卖,并設(shè)置值的時候是不會觸發(fā) dog 對象下的屬性 name 的 setter 方法,故不是響應(yīng)式數(shù)據(jù)鹏溯。而給 dog 對象添加了 name 的初始值后淹仑,dog 對象的 name 屬性就有了 getter 和 setter 方法,故可以實現(xiàn)響應(yīng)式匀借。
2、使用 Vue.set(target, key, value) 時吓肋,target 為需要添加屬性的對象,key 是要添加的屬性名肤舞,value 為屬性 key 對應(yīng)的值.源碼(參考鏈接:https://www.cnblogs.com/heavenYJJ/p/9559439.html)
1. 如果是在開發(fā)環(huán)境,且 target 未定義(為 null李剖、undefined )或 target 為基礎(chǔ)數(shù)據(jù)類型(string、boolean篙顺、number、symbol)時腋寨,拋出告警;
2. 如果 target 為數(shù)組且 key 為有效的數(shù)組 key 時萄窜,將數(shù)組的長度設(shè)置為 target.length 和 key 中的最大的那一個撒桨,然后調(diào)用數(shù)組的 splice 方法( vue 中重寫的 splice 方法)添加元素;
3. 如果屬性 key 存在于 target 對象中且 key 不是 Object.prototype 上的屬性時凤类,表明這是在修改 target 對象屬性 key 的值(不管 target 對象是否是響應(yīng)式的,只要 key 存在于 target 對象中谜疤,就執(zhí)行這一步邏輯),此時就直接將 value 直接賦值給 target[key]履肃;
4. 判斷 target坐桩,當(dāng) target 為 vue 實例或根數(shù)據(jù) data 對象時尺棋,在開發(fā)環(huán)境下拋錯绵跷;
5. 當(dāng)一個數(shù)據(jù)為響應(yīng)式時,vue 會給該數(shù)據(jù)添加一個 ob 屬性荆残,因此可以通過判斷target對象是否存在 ob 屬性來判斷 target 是否是響應(yīng)式數(shù)據(jù)净当,當(dāng) target 是非響應(yīng)式數(shù)據(jù)時内斯,我們就按照普通對象添加屬性的方式來處理;當(dāng) target 對象是響應(yīng)式數(shù)據(jù)時品擎,我們將 target 的屬性 key 也設(shè)置為響應(yīng)式并手動觸發(fā)通知其屬性值的更新备徐;
- defineReactive(ob.value, key, val) ,將新增屬性設(shè)置為響應(yīng)式; ob.dep.notify() 手動觸發(fā)通知該屬性值的更新, 所以我們可以修改代碼如下:
let vm = new Vue({
el: '#app',
data: {
msg: 'object',
dog: {
name: undefined
}
},
method: {
clickHandler() {
// 該 name 屬性是否是響應(yīng)式的
this.$set(this.data.dog, name, 'Trump')
}
}
})