20_Vue如何監測數組類型數據發生改變的?
通過上一節,我們知道了vue檢測對象數據發生改變的原理
但是還有個api我們沒有講解,Vue.set();
這個API比較適合在理解了對象檢測的原理後進行講解
案例準備
html
<!-- 創建一個容器 -->
<div class="app">
<h1>姓名:{{student.name}}</h1>
<h1>年齡:{{student.age}}</h1><br>
<h2>朋友們</h2>
<ul>
<!-- 列表渲染 == friends -->
<li v-for="(item,index) in friends">
{{item.name}}-{{item.rage}}-{{item.mage}}
</li>
</ul>
</div>
data配置項
<script>
const vm = new Vue({
el: '.app',
data: {
student: {
name: 'wavesbright',
age: 21,
},
friends: [ // 真實年齡,內心年齡
{name: "Jack",rage: 32,mage: 40},
{name: "Jony",rage: 24,mage: 45},
{name: "Jone",rage: 28,mage: 50},
]
},
methods: {
},
});
</script>
頁面效果
需求
- 我的數據都是寫在data當中的,通過vue的數據代理
- 在頁面當中實現了響應式開發
- 那麼現在有一個問題
- 我想給,student 添加一個屬性,這個屬性是後來添加的,不是之前就添加的
- 想讓 這個屬性能夠實現響應式,應該如何實現?
錯誤示範
- 直接在vm後面加個屬性不就完了?
- 修改 _data,然後給它添加一個屬性?
- 上述兩個操作的問題,添加的屬性沒有進行數據代理
- 無法完成響應式
- 仔細看的話,在student這個對象當中,sex這個屬性是沒有get和set函數的
添加測試
我們在這裡添加一個渲染項,然後我們添加屬性試試,現在我data當中是沒有這個屬性的
並不能被vue所識別到
那麼我們後面想要自己添加屬性就沒有辦法完成響應式了嗎,誒,這就是我們接下來要引入的API
Vue.set()
- 該API需要三個參數
- target: 目標
- key: 添加的屬性名
- val: 添加的屬性值
我現在算是明白了,小程序的 this.setData() 就是從這裡變來的
這裡其實應該是 .student的;因為操作的都是同一個對象的地址
set的局限性
我現在要在data當中,添加一個屬性,這個屬性是leader == 校長
我們使用.set添加試試
- 這裡報錯的意思就是,不允許直接在vue實例身上添加一個屬性
- 解讀一下這段話哈
- 我現在是在_data當中添加屬性
- 但是這個添加的屬性,最後會掛載在vue實例身上
- 所以,這裡使用.set是不允許的,不能直接添加
- .set()不能在data當中直接添加屬性
- 只能給data當中的某個對象(student)添加屬性
vm是不能作為target的,vm當中的data,也不能作為target
監測數組
準備工作
- 新建一個demo,重新配置了數據項data
- 在data當中有兩個屬性,一個numbers的數組,一個student的對象
- 我們查看vue實例對象,在查看之前可以很明確的說,numbers 和 student 都掛載在了vue實例身上,並且,有專門為他倆服務的get和set
數據代理
現在我們點擊去看看二者有什麼不同,或者說,vue當中對數組和對象類型的數據是如何代理的
數組和對象的不同
數組
對象
區別,目前而言
- 數組當中的數據,是沒有進行數據代理的,沒有專門為 元素 服務 的 get和set
- 而對象當中,每個屬性都是有get和set的,哪怕這個屬性是對象也有
- 也就是說,如果我們直接在vue當中直接修改numbers對應索引的值,vue是觀測不到的
直接修改numbers
我們寫一串DOM元素進行測試
<div class="app">
<ul>
<li v-for="item in numbers">{{item}}</li>
</ul>
</div>
現在,我直接在控制台中對數組當中的元素進行修改
我們將最後一項 從5改為6
數據的確修改成功了,但是vue檢測不到,頁面無法響應
之前的錯誤解釋
現在,我們來回顧一下之前遇到的bug,我們添加一個persons對象數組
從控制台我們來觀察一下這個persons
- 這是一個對象數組,這個數組當中的每一項數據,都沒有被進行數據代理
- 但是因為每一項 數據 都是對象類型,所以 在對象類型當中 數據是進行了代理(get和set)的
- 這裡很重要,請仔細看
所以為什麼下面的修改不起作用,因為根本沒代理,沒有代理無法完成響應式數據
這個問題解決了順勢拋出下一個問題,vue怎麼就知道數組內部的屬性發生改變了呢,它是如何監測到的?
vue如何監測?
- 藍色框當中的都是可以對數組進行修改的,會改變原有數組結構
- 但是filter不會,他會返回一個新數組,不修改原數組
- arr 調用了藍色框框當中的數組API,自身才會發生改變
- vue當中規定,你只有使用了上述的7個方法,我才承認你修改數組了
那它咋知道我調用了上面的7個API呢?
包裝技術
原形
使用 Array這個原形對象身上的 push 舉例子
這個push,是給數組調用的
我們在控制台上來個數組
這個push是哪裡來的?==> 其實是一層一層嵌套的,從原形對象身上來的
二者身上的push是相等的
vue
vue身上的數組,使用的並不是 原形數組Array身上的 API函數
如何測試?
很簡單,回到我們剛剛的案例
這下您能明白了嗎
流程
當你對一個被vue所管理的數組進行了api的調用(push,shift,unshift…..)
你調用的這個API,就不是原型對象Array身上的API了;而是vue的api
在這個api當中,會做兩個步驟
- 調用原形身上的API(push…..)
- 重新解析模板,生成虛擬dom…….那一套流程
是這麼一回事嗎,我們看下官網是如何解答的
官網尋找答案
- 點擊 列表渲染
- 點擊 數組更新檢測
我們來看這句話
enmmmm,後面沒講了,基本其實到這裡就差不多了,後面的都需要在實際開發當中去慢慢琢磨了
尚硅谷yyds,黑馬也是
你們都是我的天使