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 ...
随机推荐
- lesson5-图像检测-小象cv
R-CNN: 2014,cnn为Alexnet 训练流程: 1)在imagenet上对cnn模型pre-train 2)使用所有ss生成区域对1)进行fine-tune ~softmax改为21维度 ...
- plot 函数常用参数
- java构造代码块详解
一.简介 首先说一下,Java中有哪些代码块. 普通代码块 就是在方法后面使用"{}"括起来的代码片段,不能单独执行,必须调下其方法名才可以执行. 静态代码块 在类中使用stati ...
- 【TCP/IP】二、协议的概念
一.概念 1.tcp/ip是通信协议的统称. 2.协议就是计算机与计算机之间通过网络实现通信时,事先达成的一种约定.这种约定,使那些不同厂商的设备,不同的CPU以及不同的操作系统组成的计算机之间,只要 ...
- LG4213 【【模板】杜教筛(Sum)】
sum\(\mu\)求法 设 \[S(n)=\sum_{i=1}^n \mu(i)\] 回顾公式 \[\sum_{d|n}\mu(d)=[n=1]\] 对\(n\)求和 \[\sum_{i=1}^n\ ...
- docker下搭建fastfds集群版
搭建过程参考 作者 https://me.csdn.net/feng_qi_1984 的课程视频 声明:集群版是在我之前写的单机版基础之上进行搭建的,我将安装了fastfds单机版的docker打包成 ...
- seelog 文件输出格式
项目中用到seelog,希望每个小时的记录输入在当前小时命名的日志,配置如下: <seelog> <outputs formatid="leads"> &l ...
- 实现在同一界面打开putty终端连接工具
用过putty的人可能知道,每打开一次啊putty程序只能开启一个连接,这个在实际运用中很不方便,反正我开ssh一般都是同时开四个窗口 其实有一个程序可以实现打开多个putty,下面是下载地址 htt ...
- Modern Data Lake with Minio : Part 2
转自: https://blog.minio.io/modern-data-lake-with-minio-part-2-f24fb5f82424 In the first part of this ...
- C libraries in Linux
Copy from a book. There are several C libraries to choose from. The main options are as follows: gli ...