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之数据变更没有触发视图更新问题的主要内容,如果未能解决你的问题,请参考以下文章