problem:vue之數據變更沒有觸發視圖更新問題


前言: 

數據變更之后,vue如何渲染dom?

  實際場景:

   更新數據之后,再設置滾動條的位置為什么設置無效?

   為什么將隱藏的元素設置為顯示狀態之后,讀取元素狀態讀取不到?

   改變了對象/數組中的值,頁面沒有更新最新的值?

 

關於vue中的數據改變沒有觸發視圖更新的現象:

    需要知道的一些細節

    vue中data中定義的變量,vue才能監聽到其的變化。

    vue中無法監聽到對象的屬性的添加、修改和刪除。

    vue中對數組,通過下標修改的屬性值無法響應(不能觸發視圖更新)。

   ˙針對上面的一些解決方案

    1、給對象添加屬性,通過$set(obj, propname, propvalue)或Object.assign({},obj,{...})添加

    2、對數組中的對象屬性做修改,比如要給一個定義在data中的數組(響應式變量)中的值(一個對象類型的值)添加一個屬性,

    直接通過點或[]的方式添加這個屬性,這個屬性值修改之后也可以觸發視圖更新。

    3、對於數組,在給數組通過push、shift、splice等方法給數組添加/刪除值,可以觸發視圖更新,但是通過下標方式去給數組添加值,是不能觸發視圖更新的。

     

    還有一種情況:變量是響應式的卻還是沒有觸發視圖更新。因為vue中數據的更新是異步的,如果希望數據變化之后及時更新dom可以放在this.$nextTick()中。

    這里舉個數據變化但不觸發視圖更新的一個例子:

    組件中之間傳遞值時數據不觸發視圖更新問題

     1、限制輸入框字符數的功能,通過:value給表單框初始化值,     

                <input 
	        class="remark-modify" 
		maxlength="32"  
		type="text" 
		:value="username"
		@blur="saveRemark" 
		@keypress.enter="saveRemark" 
		@keyup="limitLength"
		autofocus v-else>

 2、keyup監聽輸入,當字符串達到32時,將32后的字符串裁剪掉,因為不能直接修改組件中props中的變量,所以只能通過向父組件拋事件或通過sync標識符來修改父組件中變量的值然后再傳到子組件中。子組件中接受了父組件中的變量的值但是卻沒有渲染。

  limitLength(e) {
        const input = e.target;
        const value = input.value
        const split = value.split('');
        const map = split.map((s, i) => {
            return (value.charCodeAt(i) >= 0 && value.charCodeAt(i) <= 128) ? 1 : 2;
        });
        let n = 0;
        const charLength = map.length > 0 && map.reduce((accumulator, currentValue, index) => {    
            const count = accumulator + currentValue;
            if (count === 31 || count === 32) {
                n = index;
            }
            if (count > 32) {        this.$emit('update:username',split.slice(0, n+1).join('') )
                this.$emit("setUserName",split.slice(0, n+1).join(''));
            }    
            return count
        });
    
    },

這里的沒有渲染和vue中的值修改是異步渲染的有關。

解決方案:

1、input的值通過v-model來綁定值,v-model相當於:value賦值和oninput事件的集合

        <input 
        class="remark-modify" 
        maxlength="32"  
        type="text" 
        v-model="name"
        @blur="saveRemark" 
        @keypress.enter="saveRemark" 
        @keyup="limitLength"
        autofocus v-else>

2、computed定義name變量,用於在輸入框中顯示內容,通過定義set()和get()方法來修改值和讀取值(props中定義username)

computed: {
	  name: {
		set(value) {	    
		  this.$emit("setUserName", value);
		},
		get(value) {
			
                    return this.username
		}
	  }
  },

 

3、限制字符數的方法里面裁剪內容之后直接將新值賦值給name變量,會觸發name中的set方法

limitLength(e) {
        const input = e.target;
        const value = input.value
        const split = value.split('');
        const map = split.map((s, i) => {
            return (value.charCodeAt(i) >= 0 && value.charCodeAt(i) <= 128) ? 1 : 2;
        });
        let n = 0;
        const charLength = map.length > 0 && map.reduce((accumulator, currentValue, index) => {    
            const count = accumulator + currentValue;
            if (count === 31 || count === 32) {
                n = index;
            }
            if (count > 32) {        
                this.name = split.slice(0, n+1).join('')    
                // this.$emit('update:username',split.slice(0, n+1).join('') )
                // this.$emit("setUserName",split.slice(0, n+1).join(''));
            }    
            return count
        });

 

vue系列日志中我會總結如下內容:

1、vue中異步渲染數據問題

2、computed定義變量,變量中定義set/get方法和沒有定義的區別

3、vue中的響應式數據機制

4、javascript中的定義對象屬性的Object.definedProperty()

  

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM