problem:vue之数据变更没有触发视图更新问题

Posted yy95

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了problem:vue之数据变更没有触发视图更新问题相关的知识,希望对你有一定的参考价值。

前言: 

数据变更之后,vue如何渲染dom?

  实际场景:

   更新数据之后,再设置滚动条的位置为什么设置无效?

   为什么将隐藏的元素设置为显示状态之后,读取元素状态读取不到?

   改变了对象/数组中的值,页面没有更新最新的值?

 

关于vue中的数据改变没有触发视图更新的现象:

    需要知道的一些细节

    vue中data中定义的变量,vue才能监听到其的变化。

    vue中无法监听到对象的属性的添加、修改和删除。

    vue中对数组,通过下标修改的属性值无法响应(不能触发视图更新)。

   

   一些解决方案

    1、给对象添加属性,通过$set(obj, propname, propvalue)或Object.assign({},obj,{...})添加

    2、对数组中的对象属性做修改,比如要给一个定义在data中的数组(响应式变量)中的值(一个对象类型的值)添加一个属性,

    直接通过点或[]的方式添加这个属性,这个属性值修改之后也可以触发视图更新。

    3、对于数组,在给数组通过push、shift、splice等方法给数组添加/删除值,可以触发视图更新,但是通过下标方式去给数组添加值,是不能触发视图更新的。

     

    组件中之间传递值时数据不触发视图更新问题:

     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()方法来修改值和读取值

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()

  

 

 

以上是关于problem:vue之数据变更没有触发视图更新问题的主要内容,如果未能解决你的问题,请参考以下文章

解决vue中修改了数据但视图无法更新的情况

实现一个最小版本vue之watcher

表维护视图 中变更日志写入自定义日志表

vue数组对象修改触发视图更新

vue的数据双向绑定的实现

Vue.set 向响应式对象中添加响应式属性,及设置数组元素触发视图更新