Vue的响应式及相关问题
目錄
1.概念
2.頁面何時渲染
3.vm.$nextTick 和?Vue.nextTick
4.不發生重新渲染的情況
5. 響應式更新數組和對象
1.概念
Vue響應式指當數據變化時,頁面會重新渲染,如下例
<body><div id="app">{{ sentence}}</div> </body> <script src="./vue.js"></script> <script>const vm = new Vue({el: '#app',data: {sentence: '自由就是不再尋求認可'}}) </script>【結果】改變 sentence 的值,頁面重新渲染
【注】當創建vue實例時,vue會將data中的成員代理給vue實例,目的是為了實現響應式,監控數據變化,執行某個監聽函數?
2.頁面何時渲染
Vue更新DOM的操作是異步執行的,只要偵聽到數據變化,將開啟一個異步隊列,如果一個數據被多次變更,那么只會被推入到隊列中一次,這樣可以避免不必要的計算和DOM操作
<div id="app">{{ bookList }} </div> const vm = new Vue({el: '#app',data: {bookList: ['被討厭的勇氣', '沒有兇手的殺人夜', '親密關系']} }) vm.bookList[1] = 'JavaScript高級程序設計'; console.log(vm.bookList[1]); // 此時數據已經更改 console.log(vm.$el.innerHTML); //但是頁面內容還沒有更改【結果】
3.vm.$nextTick 和?Vue.nextTick
1)在DOM更新后,會立刻執行 vm.$nextTick 和 Vue.nextTick,所以可以利用它們看到數據更改后,立刻看到渲染后頁面的值
<div id="app">{{ bookName }} </div> const vm = new Vue({el: '#app',data: {bookName: '被討厭的勇氣'} }) vm.bookName = 'JavaScript高級程序設計'; console.log(vm.bookName); // 此時數據已經更改 console.log(vm.$el.innerHTML); vm.$nextTick(()=>{console.log(vm.$el.innerHTML); })?【結果】
?2)vm.$nextTick 和 Vue.nextTick 可以當作Promise使用
const vm = new Vue({el: '#app',data: {bookName: '被討厭的勇氣'} }) vm.bookName = 'JavaScript高級程序設計'; console.log(vm.bookName); // 此時數據已經更改 vm.$nextTick().then(()=>{console.log(vm.$el.innerHTML); }) Vue.nextTick().then(()=>{console.log(vm.$el.innerHTML); })【結果】?
?3)vm.$nextTick 和 Vue.nextTick 的區別
vm.$nextTick 內部函數的 this 指向 Vue 實例對象,Vue.nextTick 內部函數的 this 指向 window
4)nextTick 的實現
異步任務分為宏任務(macro)和微任務(micro),微任務執行在前,宏任務執行在后,在 nextTick 的實現源碼中,會先判斷是否支持微任務,不支持后才會執行宏任務
if(typeof Promise !== 'undefined') {// 微任務// 首先看一下瀏覽器中有沒有promise// 因為IE瀏覽器中不能執行Promiseconst p = Promise.resolve();} else if(typeof MutationObserver !== 'undefined') {// 微任務// 突變觀察// 監聽文檔中文字的變化,如果文字有變化,就會執行回調// vue的具體做法是:創建一個假節點,然后讓這個假節點稍微改動一下,就會執行對應的函數} else if(typeof setImmediate !== 'undefined') {// 宏任務// 只在IE下有} else {// 宏任務// 如果上面都不能執行,那么則會調用setTimeout}4.不發生重新渲染的情況
1)更改的數據必須是存在的數據,否則不能重新渲染頁面【例1】;
【例1】不會報錯,但是也不會渲染頁面,因為監聽不到這個值
<div id="app">{{ book.sentence }} </div> const vm = new Vue({el: '#app',data: {book: {name: '被討厭的勇氣',writer: '岸見一朗',}} }) vm.book.setence="觸手可及但互不干擾"2)更改的數據必須是已渲染過的數據,否則從性能角度考慮,不會重新渲染【例2】;
【例2】
<div id="app">{{ book.writer }} </div> const vm = new Vue({el: '#app',data: {book: {name: '被討厭的勇氣',writer: '岸見一朗',}} }) vm.book.name="JavaScript高級程序設計"3)利用索引直接設置一個數組項時不會重新渲染【例3】;
【例3】
<div id="app">{{ bookList }} </div> const vm = new Vue({el: '#app',data: {bookList:['被討厭的勇氣','沒有兇手的殺人夜','親密關系']} }) vm.bookList[3]="JavaScript高級程序設計"4)修改數組長度時不會重新渲染【例4】;
【例4】
<div id="app">{{ bookList }} </div> const vm = new Vue({el: '#app',data: {bookList: ['被討厭的勇氣', '沒有兇手的殺人夜', '親密關系']} }) vm.bookList.length = 0;5)添加或刪除對象時不會重新渲染【例5】;
<div id="app">{{ bookList }} </div> const vm = new Vue({el: '#app',data: {bookList: ['被討厭的勇氣', '沒有兇手的殺人夜', '親密關系']} }) vm.bookList[3] = 'JavaScript高級程序設計'; delete vm.bookList[2];5. 響應式更新數組和對象
(1)數組
1)利用數組方法 pop、pop、shift、unshift、splice、sort、reverse
2)利用vm.$set 或 Vue.set 實例方法,vm.$set(object, propertyName, value)
3)利用vm.$delete或 Vue.delete刪除數組中的某一項
<div id="app">{{ bookList }} </div> const vm = new Vue({el: '#app',data: {bookList: ['被討厭的勇氣', '沒有兇手的殺人夜', '親密關系']} }) vm.bookList.push('為奴十二年'); vm.$delete(vm.bookList, 2) vm.$set(vm.bookList, 3, '小王子')【結果】
(2)對象
1)添加利用 vm.$set 或 Vue.set 實例方法
2) 刪除利用vm.$delete或 Vue.delete
總結
以上是生活随笔為你收集整理的Vue的响应式及相关问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原理_JS引擎对未声明变量的处理
- 下一篇: Vue属性篇_侦听器watch