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 ...
随机推荐
- 第8次Scrum会议(10/20)【欢迎来怼】
一.小组信息 队名:欢迎来怼 小组成员 队长:田继平 成员:李圆圆,葛美义,王伟东,姜珊,邵朔,冉华 小组照片 二.开会信息 时间:2017/10/20 17:20~17:45,总计25min. 地点 ...
- java错误:找不到或无法加载主类
问题: 在 windows cmd 中编译后,运行 java 文件时,出现此错误 分析: 源文件 ClientDemo.java: package netdemo; public class Clie ...
- this语句的第三、四点
接着上次的继续更新 up~` 第三点主体怎么找? 就在这个函数(方法)带不带“.”,如果函数和方法执行带“.”,那么this就指向“.”前面的对象,如果不带“.”就指向window. 第四点自执行函 ...
- gcd(1,n)+gcd(2,n)....gcd(n-1,n); Uva11426
#include<bits/stdc++.h> #define int long long using namespace std; ; int phi[maxn]; int prime[ ...
- hdu2886 Lou 1 Zhuang 数学/快速幂
All members of Hulafly love playing the famous network game called 'Lou 1 Zhuang' so much that Super ...
- python------Json与pickle数据序列化
一.json序列化 xml在被json取代,不同平台之间的语言转换,只能处理简单的.复杂的用pickle: pickle只能在python中用,而在Java中json也可以被识别. info = { ...
- day4 java消息中间件服务
PS: 讲个故事,老王要给他的两个女儿讲故事,他要一个一个讲很费劲,后来他使用了微信公众号,让订阅微信公众号的人关注就减轻了负担. PS: 传统的如果一个用户进行登录,会调用分多的服务,如果没有消息中 ...
- dc-vastinspector
https://developers.google.com/interactive-media-ads/docs/sdks/html5/vastinspector hosts: https://gis ...
- 文件I/0缓冲
设置stdio流缓冲模式 #include<stdio.h> int setvbuf(FILE *stream,char *buf,int mode,size_t size) int se ...
- goreleaser 方便的go 二进制包分发工具
goreleaser 可以帮助我们进行go 二进制包的快速,简单分发,我们可以用来创建一个github release 以及发布到homwbrew formula . 安装 mac 系统,实际根据自己 ...