码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-11-24 14:19:51      阅读:296      评论:0      收藏:0      [点我收藏+]

标签:update   ops   视图   dea   map   响应式   data   object   区别   

前言: 

数据变更之后,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之数据变更没有触发视图更新问题

标签:update   ops   视图   dea   map   响应式   data   object   区别   

原文地址:https://www.cnblogs.com/yy95/p/9872534.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!