Vue:觸發視圖更新的hack

前言

觸發視圖更新的hack,hack的是什麼?hack那些數據改變卻沒有被vue檢測到的更新!那麼vue有哪些狀況是檢測不到數據的變更的? 官方說明的有下面兩大類:javascript

  • 數組
  1. 使用下標更新數組元素;
  2. 使用賦值方式改變數組長度;
  3. 使用下標增刪數組元素;
  • 對象
  1. 對象的增刪
  • 其餘
  1. 好比props到子組件的原始屬性 …… 具體看另一篇文章: [傳送門: Vue:不能檢測到Object/Array更新的狀況]

正文

那麼要怎麼hack?!html

原理也很簡單~vue

既然vue檢測不到數據的變化,那麼就強制觸發vue去更新!可是vue並無提供這樣的接口(我是說統一的接口,不是官方提供的解決方案),若是有提供就不叫hack了對吧!java

是這樣的:對於每次vue能夠檢測到的數據變更,vue都會從新去渲染整個視圖上的變更,整個,注意是整個,並非說,data裏面那個對象或列表的數據變更了,就僅僅更新對應的視圖區域,不是這樣的,是整個,ok!因此能夠利用這一點!數組

具體的作法就是: 在修改vue檢測不到的數據後,再變更一下vue能夠檢測到的數據,好比更新一下一個隨機數app

實踐

<div id="app" v-cloak :data-counter="counter">
  <dl>
    <span v-for="(item, index) in arrs">{{ index === 0 ? '' : ', ' }}{{ item }}</span>
  </dl>
  <dl v-for="(item, key) in items">{{key}}: {{item}}</dl>
  <button @click="operate('add')">add</button>
  <button @click="operate('delete')">delete</button>
  <button @click="operate('update')">update</button>
  <button @click="operate('updateArrs')">update arrs</button>
</div>
複製代碼
new Vue({
  el: '#app',
  data: {
    useCounter: true,
    counter: 0,
    arrs: [0, 1, 2, 3, 4],
    items: {
      name: 'isaac',
      position: 'coder'
    }
  },
  watch: {
    items: {
      deep: true,
      handler(val, oldVal) {
      	console.log({ val, oldVal });
      }
    }
  },
  methods: {
    env(callback) {
      callback && callback();
      this.useCounter && this.counter++;
    },
    operate(order) {
      if(order === 'add') {
      	this.env(() => {
          this.items.goodAt = 'javascript';
        });
      } else if(order === 'delete') {
        this.env(() => {
          delete this.items.goodAt;
        });
      } else if(order === 'update'){
      	this.items.name = Math.random();
      } else if(order === 'updateArrs') {
      	this.env(() => {
          this.arrs[0] = Math.round(Math.random() * 100);
        });
      }
    }
  }
});
複製代碼

正如前言中說的幾種狀況,都會在以後更新一個data.counter,而data.counter則是能夠檢測被檢測到的!dom

缺點

雖然這樣hack確實出發了視圖的更新,可是有個缺點:post

  • 對應的watch是檢測不到數據的變更!

因此說,最好仍是使用官方提供的解決方案!測試

最後說一句

上面的hack是我在實踐中發現的,應該在說debug的時候!由於本身清洗知道數組和對象那些狀況下是觸發不到視圖更新的,可是某次卻神奇地更新了視圖!而後就開始慢慢地測試~ui

相關文章
相關標籤/搜索