Vue|数据更新,视图未更新的几种解决方案

前言:

本文主要介绍在vue项目中,遇到数据更新但视图不更新的情况时,无法使用watch监听、无法使用this.$set方法,同时使用this.$forceUpdate()无效时,所使用的解决方案。

一、问题描述

在Vue项目中,有时我们会遇到数据更新了,但是视图没有更新的情况,这是因为Vue使用的是异步更新的方式,如果数据变化时视图没有立即响应,则一般都会考虑使用以下几种解决方案:

  1. 方案一:使用watch监听对象属性变化
xml 复制代码
<template>
    <div>
        <h3>{{userInfo.name}}</h3>
        <button @click="changeUserName">点击我改变用户名</button>
    </div>
</template>

<script>
export default {
    data(){
        return {
            userInfo: {
                name: '张三',
                age: 16
            }
        }
    },
    watch:{
        'userInfo.name': {
            handler(newValue, oldValue) {
              console.log('用户名变化了,新值:' + newValue + ',旧值:' + oldValue);
            },
            immediate: true,
            deep: true
        }
    },
    methods:{
        changeUserName(){
            // 假设异步请求修改用户名
            const newUserName = '李四';
            this.userInfo.name = newUserName;
        }
    }
}
</script>
  1. 方案二:使用this.$set()强制更新响应式变量
js 复制代码
// 定义数据对象:
obj: { name: "小明", age: 18, },       

// 基本语法:
this.$set(需要改变的对象,"需要改变的对象属性","新值")

示例如下:

xml 复制代码
<template>
    <div>
        <h3>{{initList.message}}</h3>
        <button @click="changeMessage">点击我改变message值</button>
    </div>
</template>

<script>
export default {
    data(){
        return {
            initList: {
                message: 'hello'
            },
        }
    },
    methods:{
        changeMessage(){
            // 假设是异步调用获取到了新的message值
            const newMessage='world';
            this.$set(this.initList, 'message', newMessage);
        }
    }
}
</script>
  1. 方案三:使用this.$forceUpdate()强制性重新渲染
js 复制代码
methods: {
    // 在某些情况下需要强制重新渲染组件
    forceRerender() {
        // 调用 $forceUpdate()方法
        this.$forceUpdate();
    }
}

但是,在项目中,如果以上方案均无效,比如由于无法使用watch或this.$set()实现所需功能,或者使用后会使代码变得更复杂、冗余;同时层级太多或其他原因导致this.$forceUpdate()也不起作用,那么还有什么方案可以解决视图不更新的问题呢?

二、解决方案

为确保视图更新,可以先将数据赋值后再清空,最后在this.$nextTick()中处理数据,并重新赋值。代码示例如下:

js 复制代码
// 为确保视图更新,先将数据重新赋值给一个变量,然后再清空
const details = this.detailsList;
this.detailsList = [];

// 处理数据,并重新赋值
this.$nextTick(() => {
    // 处理数据
    const detailsList = this.formatList(details, data.playCourseChapterId);
    // 重新赋值
    this.detailsList = Object.assign([], detailsList);
})

这时,数据更新的同时,视图也会同步更新。

备注:

我这边的项目中,是因为层级循环太多,导致以上三种方案均不起作用。只有最后这种方案可以解决视图不更新的问题。

以上,希望对大家有帮助!

相关推荐
_菜鸟果果1 小时前
高德地图 JS API 2.0 在国产 Linux/ARM 电脑上渲染失败 的排查与解决
linux·开发语言·javascript
Java后端的Ai之路2 小时前
前端技术Vue-09-webpack-vuejs-实战
前端·vue.js·webpack
迷途小羔羊2 小时前
项目概述
java·javascript·后端
迷迭绿2 小时前
Cesium 轨迹回放播放器
前端·javascript·cesium
tryCbest4 小时前
Vue3——第 7 篇:组件基础——从注册到使用的完整流程
前端·javascript·vue.js
weixin_BYSJ19874 小时前
【计算机毕设】房屋租赁系统02647
java·vue.js·spring boot·python·django·课程设计
时间的情敌4 小时前
Electron 设置-webkit-app-region: drag;实现拖拽后, 无法响应鼠标划过事件及点击事件的解决方式
前端·vue.js
专业程序开发源5 小时前
springboot校企合作双选会一站式预约与面试系统16010-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·面试·php·课程设计
Eastmount6 小时前
[论文阅读] (54)NDSS26 JSIMPLIFIER:动静态与LLM如何协同完成JavaScript解混淆?
javascript·论文阅读·恶意代码分析·智能体安全·ndss