Vue 数据更新了但页面没有更新

10 篇文章 0 订阅

目录

1. vue 无法检测实例被创建时没存在于 data 对象中的属性

2. vue 无法检测对象属性的添加或删除

3. vue 不能检测通过数组索引值,直接修改一个数组项

4. vue 不能监测直接修改数组长度的变化

5. 使用 this.$forceUpdate() 强制更新

6. 使用 this.$nextTick(() => {  })

7. 修改组件的 key 值


在 vue 项目中,有时我们会遇到修改完数据,但是视图却没有更新的情况。具体的场景不一样,解决问题的方法也不一样,在此汇总一下。

1. vue 无法检测实例被创建时没存在于 data 对象中的属性

原因:由于 vue 会在初始化实例时,对 data 对象中的属性执行 getter/setter 转化,所以属性必须在 data 对象上存在才能让 vue 将它转化为响应式的。

场景

let vm = new Vue({
  data:{},
  // 页面不会变化
  template: '<div>{{message}}</div>'
})
vm.message = 'Hello!' // `vm.message` 不是响应式的

解决办法

var vm = new Vue({
  data: {
    // 声明 message 为一个空字符串
    message: '',
  },
  template: '<div>{{ message }}</div>'
})
vm.message = 'Hello!'

2. vue 无法检测对象属性的添加或删除

原因:官方–由于 JavaScript(ES5) 的限制,Vue.js 不能检测到对象属性的添加或删除。因为 vue.js 在初始化实例时将属性转为 getter/setter,所以属性必须在 data 对象上才能让 vue.js 转换它,才能让它是响应的。

场景

var vm = new Vue({
  data:{
    obj: {
      id: 001
    }
  },
  // 页面不会变化
  template: '<div>{{ obj.message }}</div>'
})
vm.obj.message = 'hello' // 不是响应式的
delete vm.obj.id       // 不是响应式的

解决办法

// 动态添加 -- vue.set
Vue.set(vm.obj, message, 'hello');
// 动态添加 -- vm.$set
vm.$set(vm.obj, message, 'hello');

// 动态添加多个
// 代替 Object.assign(this.obj, {a:1,b:2})
this.obj = Object.assign({}, this.obj, {a:1,b:2});

// 动态移除--vm.$delect
Vue.delete(vm. obj, id);
// 动态移除 --vm.$delete
vm.$delete(vm. obj, id);

3. vue 不能检测通过数组索引值,直接修改一个数组项

原因:官方–由于 JavaScript 的限制,Vue 不能检测数组和对象的变化;性能代价和获得用户体验不成正比。

场景

var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 不是响应性的

解决办法

// Vue.set
Vue.set(vm.items, 1, 'x');
// vm.$set
vm.$set(vm.items, 1, 'x');
// Array.prototype.splice
vm.items.splice(1, 1, 'x');

4. vue 不能监测直接修改数组长度的变化

原因:官方–由于 JavaScript 的限制,vue 不能检测数组和对象的变化;(性能代价和获得用户体验不成正比)。

场景

var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items.length = 2 // 不是响应性的

解决办法

vm.items.splice(2)

那么在修改数组数据的时候,我们应该使用 push()、pop()、shift()、unshift()、splice()、sort()、reverse() 等原生的方法去操作数据,因为 vue 可以直接检测这些方法所带来的数组数据变化。

5. 使用 this.$forceUpdate() 强制更新

比如:循环嵌套层级太深,视图不更新

6. 使用 this.$nextTick(() => {  })

  • 如果修改完数据之后想立刻操作 DOM 元素,就需要使用 nextTick
    methods:{
      testClick:function(){
        this.msg="修改后的值";
        this.$nextTick(() => {
          console.log(that.$refs.btn.innerText);  // 输出:修改后的值
        });
      }
    }
    
  • 如果想要在 created() 中操作 DOM,也需要使用 nextTick,因为在此阶段,DOM 还未被渲染
    created(){
      this.$nextTick(() => {  // 不使用this.$nextTick()方法会报错
          that.$refs.btn.innerHTML="created中更改了按钮内容";  // 写入到DOM元素
      });
    },
    

7. 修改组件的 key 值

原因:当某个组件的 key 变化后,组件都会被重新渲染一遍

<template>
	<el-table :data="data" :key="refresh">
	      ...
	</el-table>
</template>
<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator'
@Component({})
export default class extends Vue {
	refresh = true
	@Watch('data')
	watchData() {
	  this.refresh = !this.refresh
	}
}
</script>

  • 23
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘子味的冰淇淋~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值