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()
problem:vue之数据变更没有触发视图更新问题的更多相关文章
- Vue.set() this.$set()引发的视图更新思考
引文 vue文档列表渲染中有条注意事项: 这里提到的两种情况实际改变了数据但是没有触发视图更新. 由此引出Vue.set(),先上文档API: this.$set()和Vue.set()本质方法一样, ...
- Vue.set 向响应式对象中添加响应式属性,及设置数组元素触发视图更新
一.为什么需要使用Vue.set? vue中不能检测到数组和对象的两种变化: 1.数组长度的变化 vm.arr.length = 4 2.数组通过索引值修改内容 vm.arr[1] = ‘aa’ Vu ...
- VUE 动态给对象增加属性,并触发视图更新。
在开发过程中,我们时常会遇到这样一种情况:当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,是不会更新视图的. 根据官方文档定义 ...
- vue数组对象修改触发视图更新
直接修改数组元素是无法触发视图更新的,如 this.array[0] = { name: 'meng', age: 22 } 修改array的length也无法触发视图更新,如 this.array. ...
- Vue 动态修改data 值 并触发视图更新
Vue 动态修改data 值 并触发视图更新 this.$set(obj, key, '') // Vue 动态修改或者添加data key 并触发视图更新
- Vue 改变数组触发视图更新
最近给table做了一个点击排序的功能,数组更改以后发现data数据变了,但是视图不更新 写惯了js的我们随手一串代码 this.items[2]={message:"Change Test ...
- problem: vue之数组元素中的数组类型值数据改变却无法在子组件视图更新问题
问题:给父组件上的一个数组中的某个元素中的数组类型值,添加值后,数据没有在子组件上更新. 对元素添加值之后,vue的数据其实已经更新了并传给了子组件,子组件中没有立即更新. 那么这里有个问题,在子组件 ...
- vue的data里面的值是数组时,在更改其某一项的时候,怎么触发视图的重新渲染?
1. 设置对象或数组的值:Vue.set(target,key,value) :2.删除对象或数组中元素: Vue.delete ( target,key) ;3. 数组对象直接修改属性,可以触发视图 ...
- vue实现数据双向绑定的原理
一.知识准备Object.defineProperty( )方法可以直接在一个对象上定义一个新属性,或者修改一个已经存在的属性,并返回这个对象.Object.defineProperty(obj,pr ...
随机推荐
- opencv中mat类介绍
The class Mat represents an n-dimensional dense numerical single-channel or multi-channel array. It ...
- 06 面向对象:多态&抽象类&接口&权限修饰符&内部类
多态: /* 多态(polymorphic)概述 * 事物存在的多种形态 多态前提 * a:要有继承关系. * b:要有方法重写. * c:要有父类引用指向子类对象. * 成员变量 * 编译看左边(父 ...
- ACM-ICPC 2018 北京赛区网络预赛(9.22)
#include<bits/stdc++.h> using namespace std; ; *maxn]; *maxn]; *maxn]; int main() { int T; sca ...
- Mybatis二(高级部分)
1.输入映射和输出映射 a) 输入参数映射 b) 返回值映射 2.动态sql a) If标签 b) Where标签 c) Sql片 ...
- A* 寻路学习
启发式搜索:启发式搜索就是在状态空间中的搜索.对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标.这样可以省略大量无谓的搜索路径,提高了效率.在启发式搜索中,对位置的估价是十分重 ...
- python 高阶函数学习, map、reduce
一个函数可以接收另一个函数作为参数,这样的函数叫做高阶函数. 函数map(): map()函数接收两个参数,一个是函数,一个是Iterable, map把函数作用于序列的每一个元素,并把结果作为Ite ...
- Java参数验证Bean Validation 框架
1.为什么要做参数校验? 参数校验和业务逻辑代码分离,参数校验代码复用,统一参数校验方式.校验不太通过时统一异常描述. 2.bean validation规范 JSR303 规范(Bean Valid ...
- VARCHAR(N)类型,utf8编码,则N最大值为多少,n表示什么?
4.0版本以下,varchar(20),指的是20字节,如果存放UTF8汉字时,只能存6个(每个汉字3字节) 5.0版本以上,varchar(20),指的是20字符,无论存放的是数字.字母还是UTF8 ...
- linux应用之gcc环境的安装
使用如下两个命令就可把gcc,gcc-c++统统安装 yum -y install gcc yum -y install gcc-c++ 但是用yum install gcc安装gcc编译环境,关于 ...
- RedHat6.5系统LVM增加新硬盘实现根文件系统扩容
一.新增物理空间 二.linux中创建新分区 1.首先查看硬盘信息,用fdisk -l命令,如果有硬盘有剩余空间就可以对其进行分区. [root@master 桌面]# fdisk -l Disk / ...