vue中 $forceUpdate的使用解析
作者:yerikyu 发布时间:2024-06-05 09:15:18
在vue的开发过程中,数据的绑定通常来说都不用我们操心,例如在data
中有一个msg
的变量,只要修改它,那么在页面上,msg
的内容就会自动发生变化。但是如果对于一个复杂的对象,例如一个对象数组,直接去给数组上某一个元素增加属性,或者直接把数组的length
变成0,vue可能就无法知道发生了改变。这个其实就是考验对于双向绑定的更进一步的理解应用了。
在Vue中,双向绑定属于自动档,然而在特定的情况下,需要手动触发“刷新”操作,目前有四种方案可以选择:
刷新整个页面
使用v-if标记
使用内置的forceUpdate方法
使用key-changing优化组件
方案分析
本次文章主要重点在于分析forceUpdate
这个方法,后续有机会再来分析key-changing
。
forceUpdate
该方案是比较好的一种方式,比如说我们尝试直接给某个object
增加一个属性,发现页面上没有效果;直接将length变成0来清空数组,也没有效果,
关键代码如下:
change: function(index) {
// 增加性格属性
this.girls[idx].character = 'lovely';
},
clear: function() {
// 清空数组
this.girls.length = 0;
}
按照上面的写法没有产生想要的效果,是因为没有按照vue的规范去写,因为文档里面写了,对于深层的,最好用$set方法,这样vue就可以知道发生了变化,同时vue也不建议直接修改length,而是给一个空数组来置空。
如果我们按照vue的规范去写的,是可以实现变化的,
关键代码如下:
change: function(index) {
// 增加性格属性
this.$set(this.girls[idx],'character','lovely')
},
clear: function() {
// 清空数组
this.girls = [];
}
如果我们不想利用$set
去设置,非要按照我们第一种方式去写,可以实现么?可以的,就是利用$forceUpdate
,此时修改了数据,然而页面层没有变动,之后通过日志打印的方式确认数据是否有修改过,之后再确认有没有监听到,用$forceUpdate
就相当于按照最新数据给渲染一下。
关键代码如下:
change: function(index) {
this.girls[idx].character = '男';
this.$forceUpdate();
},
clear: function() {
this.girls.length = 0;
this.$forceUpdate();
}
这种做法实际上并不推荐,官方说如果你现在的场景需要用forceUpdate
方法 ,那么99%是你的操作有问题,如上data里不显示声明对象的属性,之后添加属性时正确的做法时用 $set()
方法,所以forceUpdate
请慎用。
该同等效果的:window.location.reload()
本质
在vue的官方文档中有说明到这个是一个强制刷新的api,但很少用到,除非是遇到了需要实时响应组件状态的时候
Force the component instance to re-render.
This should be rarely needed given Vue's fully automatic reactivity system. The only cases where you may need it is when you have explicitly created non-reactive component state using advanced reactivity APIs.
实现原理
Vue.prototype.$forceUpdate = function () {
const vm: Component = this
if (vm._watcher) {
vm._watcher.update()
}
}
实例需要重新渲染是在依赖发生变化的时候会通知watcher
,然后通知watcher
来调用update
方法,就是这么简单。
分析
forceUpdate
就是重新render
有些变量不在
state
上,但是你又想达到这个变量更新的时候,重新(render),从而渲染虚拟DOM。
注意到这个时候并不是重新加载组件。
结合vue的生命周期,调用
$forceUpdate
后只会触发beforeUpdate
和updated
这两个钩子函数,不会触发其他的钩子函数。它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件,即强制更新因某些原因并未渲染到页面的,已经改变的,应该被渲染到页面的数据
state
里的某个变量层次太深,更新的时候没有自动触发render
。
这些时候都可以手动调用 forceUpdate 自动触发 render 。所以建议使用 immutable
来操作 state
,redux
等 flux
架构来管理 state
。
刷新页面
这个方案是挺low的,本质上是刷新页面
this.$router.go(0)
使用v-if标记
如果是刷新某个子组件,则可以通过v-if
指令实现。我们知道,当v-if
的值发生变化时,组件都会被重新渲染一遍。因此,利用v-if
指令的特性,可以达到强制刷新组件的目的。
<template>
<compare v-if="refresh"></compare>
<el-button @click="refreshComp()">刷新comp组件</el-button>
</template>
<script>
import compare from '@/views/compare.vue'
export default {
name: 'parentComp',
data() {
return {
refresh: true
}
},
methods: {
refreshComp() {
// 移除组件
this.refresh = false
// 在组件移除后,重新渲染组件
// this.$nextTick可实现在DOM 状态更新后,执行传入的方法。
this.$nextTick(() => {
this.refresh = true
})
}
}
}
</script>
key-changing
原理很简单,vue使用key标记组件身份,当key改变时就是释放原始组件,重新加载新的组件。
<template>
<div>
<span :key="key"></span>
</div>
</template>
<script>
export default {
data() {
return {
key: 0
}
},
methods: {
handleUpdateClick() {
this.key += 1 // 或者 this.key = new Date();
}
}
}
</script>
来源:https://blog.51cto.com/nu1l/5174021


猜你喜欢
- 在一篇文章 理解Python异步编程的基本原理 这篇文章中,我们讲到,如果在异步代码里面又包含了一段非常耗时的同步代码,异步代码就会被卡住。
- 在写ASP网页时常用的检测代码:服务器现在时间:<% =now %>服务器CPU型号:<%=Request.ServerV
- table.rows集合中是cell对象 cell.innerHTML = "<td>123</td>&q
- 1、PHP 中如何正确统计中文字数?这个是困扰我很久的问题,PHP 中有很多函数可以计算字符串的长度,比如下面的例子,分别使用了
- A.截取从字符串左边开始N个字符 Declare @S1 varchar(100) Select @S1='http://www.x
- 废话不多说了,具体代码如下所示:<html><head>< >function selectAll(){
- 笛卡尔坐标系对于平面坐标系,任一射线OP与x轴夹角θ的范围,可以取[0,2π)或者(-π,&
- Date对象即日期时间对象,它的主要功能是实现对日期时间的处理1、创建Date对象var myDate = new Date();或var
- 一、split()函数的简单应用1.join()函数Python join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串。j
- (一)问题遗传算法求解正方形拼图游戏(二)代码#!/usr/bin/env python# -*- coding: utf-8 -*-fro
- 问题怎样实现一个按优先级排序的队列? 并且在这个队列上面每次 pop 操作总是返回优先级最高的那个元素解决方案下面的类利用 heapq 模块
- 1.概述"""基础知识:1.多任务:操作系统可以同时运行多个任务;2.单核CPU执行多任务:操作系统轮流让各个
- decode()方法使用注册编码的编解码器的字符串进行解码。它默认为默认的字符串编码。语法以下是decode()方法的语法:st
- 前言 在我们学习C语言时,我们学了
- eval(“1+2”),-> 3 动态判断源代码中的字符串是一种很强大的语
- 视频加密流程图:后端获取保利威的视频播放授权token,提供接口api给前端参考文档:http://dev.polyv.net/2019/v
- 1. 列表使用sum, 如下代码,对1维列表和二维列表,numpy.sum(a)都能将列表a中的所有元素求和并返回,a.sum()用法是非法
- 1 常规错误的yum安装方法:在前文中记述了CentOS 6.5系统中通过yum方式快速地搭建了LNMP环境,那么是否也能在CentOS 7
- 1. 安装vim:# apt-get install -y vim-gnome2. 安装ctags,ctags用于支持tagli
- 最近花些时间学习了一下Python,并写了一个多线程的爬虫程序来获取电影天堂上资源的迅雷下载地址,代码已经上传到GitHub上了,需要的同学