vue渲染機制和如何解決數據修改頁面不刷新問題的多種方法

vue渲染機制和如何解決數據修改頁面不刷新問題的多種方法

本文不講原理,只講乾貨易懂易學,(感覺能學到知識,麻煩給小編來個贊!)

首先 第一點,vue底層是 將data對象傳人,使用Object.definePropety,轉換爲getter和setter,所以,vue不支持IE8.

1.簡單介紹一下Object.definePropety,

Object.defineProperty(obj, prop, descriptor)
//參數
obj
要在其上定義屬性的對象。
prop
要定義或修改的屬性的名稱。
descriptor
將被定義或修改的屬性描述符
  var obj = {}
  Object.defineProperty(obj, 'name', {
    get: function() {
      console.log('我的名字叫'+name);
      return name;
    },
    set: function(value) {
      console.log('你叫'+value)
      name = value;
    }
  });
    obj.name ='張三';//你叫張三
    obj.name//我的名字叫張三

從上述我們可以簡單發現。當我們對這個對象的name屬性賦值的時候,就會觸發set方法,獲取name屬性的時候就會觸發get方法;

  1. 因此在vue中寫在data中的屬性是是可以轉換成getter和setter,換一句話就是響應式的,其他定義在data之外的數據,是無法響應的渲染,意思就是改變數據頁面也不會刷新,所以一切要渲染到頁面上的數據,必須寫在data中,

    不需要的,可以定義在this上,

    var vm = new Vue({
      data:{
        a:1
      }
    })
    
    // `vm.a` 是響應式的
    
    vm.b = 2
    // `vm.b` 是非響應式的
    

    3.簡單介紹完了,我們來列舉幾個不刷新的實例當然上述也是一種

    第一種:修改對象的某一屬性

    vue只會將已經在data中聲明的屬性變爲響應,沒有聲明的是不響應的

    <template>
      <div>
          <div v-for='item in list'>{{item}}</div>
          <button @click='click'>改變</button>
          <button @click='hadelClick'>解決方法</button>
      </div>
    </template>
    <script>
      export default({
        data(){
          return{
            list:{a:'a',b:'b'},
          }
        },
        methods: {
              click() {
              //  未聲明不觸發渲染
               this.list.c='c'
    
              },
              hadelClick(){
                // 解決方法,使用vue提供的$set方法來觸發渲染
                this.$set(this.list,'d','d')
              }
            }
      })
       
    </script>
    

    當然如果我們要添加多個屬性,可以使用 Object.assign() 用於將所有可枚舉屬性的值從一個或多個源對象複製到目標對象,並返回目標對象。(簡單說就是合併到第一個參數中)

    this.list = Object.assign({},this.list,{c:'c',d:'d'})
    

    第二種:修改數組對象的某一屬性

    <template>
      <div>
          <div v-for='item in list'>{{item.a}}</div>
          <button @click='click'>改變</button>
          <button @click='hadelClick'>解決方法</button>
      </div>
    </template>
    <script>
      export default({
        data(){
          return{
            list:[{a:'vue'},{a:'react'},{a:'js'}],
          }
        },
        methods: {
              click() {
                //想這樣直接給數組中的某一個對象直接賦值,是無法動態渲染的(即改變了數據,頁面不渲染)
                this.list[0] = {a:'css'} //頁面不渲染
                console.log(this.list)  //[{a:'css'},{a:'react'},{a:'js'}]
              },
              hadelClick(){
                // 解決方法,使用vue提供的$set方法來觸發渲染
                this.$set(this.list[1],'a','css')
                console.log(this.list)//[{a:'css'},{a:'css'},{a:'js'}]
              }
            }
      })
       
    </script>
    

    當然前文講過,vue會遍歷data中的數據,將對象轉換成setter和getter。所以數組中的也不例外,所以上述操作

    改成:
    click(){
    	this.list[0].a = css //依舊能夠觸發setter。實現數據重新渲染
        }
    }
    

    在vue中更多的是數組的操作不刷新,一種是通過索引賦值,一種是修改數組長度,如何解決呢?

    vue官方也給了方法

    數組的API,中能夠改變原始數組的都能觸發更新;

    • push()
    • pop()
    • shift()
    • unshift()
    • splice()
    • sort()
    • reverse()

    第二種是返回一個新數組的,這種數組在引用地址上已經發生根本改變,這樣的賦值操作是能觸發更新的(這是處理不刷新的思路,就是改變引用地址,重新賦值觸發更新)

    簡單說,用數組的API就是直接用原數組接收改變的數組,

      <template>
      <div>
          <div v-for='item in list'>{{item.a}}</div>
          <button @click='click'>改變原數組</button>
          <button @click='hadelClick'>不改變原數組</button>
      </div>
    </template>
    <script>
      export default({
        data(){
          return{
           list:[{a:'vue'},{a:'react'},{a:'js'}],
          }
        },
        methods: {
              click() {
               //改變數組刷新頁面
                  this.list.push({a:'css'})
              },
              hadelClick(){
            //重新賦值刷新頁面      
                this.list =  this.list.map(item=>{
                      item.a = 'css'
                      return item
                    })
            }
      })
       
    </script>
    

    最後提供解決思路(以上都搞不定的話)

    對象和數組都是引用傳遞,要變成新數組,來接受,就需要改變源,

    第一種

    let arr = []//新數組
    this.list.forEach(item=>{  //需要渲染的數組
        //執行你的操作,最後用放到arr中
        arr.push(item)
    })
    this.list = arr //相當於返回一個新數組可以觸發渲染
    

    第二種

    //想要直接改變渲染數組中的數據,但沒有渲染
    //解決方法:
    let arr = this.list.slice(0);//深拷貝,(等價一個新的數組)
    arr.forEach(item=>{
        //執行你的操作
    })
    //賦值操作
    this.list =  arr
    

    上述如果都無法執行,但你的數據缺實修改了,可以使用this.$forceUpdate()方法 (強制刷新)

    //this.$forceUpdate();//強制刷新
    
    
    <template>
      <div>
          <div v-for='item in list'>{{item.a}}</div>
          <button @click='click'>改變</button>
          <button @click='hadelClick'>解決方法</button>
      </div>
    </template>
    <script>
      export default({
        data(){
          return{
            list:[{a:'vue'},{a:'react'},{a:'js'}],
          }
        },
        methods: {
              click() {
                this.list[0] = {a:'css'} //頁面不渲染
                console.log(this.list)  //[{a:'css'},{a:'react'},{a:'js'}]
              },
              hadelClick(){
                this.list[0] = {a:'css'} //頁面不渲染
                console.log(this.list)  //[{a:'css'},{a:'react'},{a:'js'}]
                  this.$forceUpdate();//強制刷新
              }
            }
      })
       
    </script>
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章