答案: 1:this.$forceUpdate() ;2:v-if 指令 ;3:key;
三种方法的使用取舍
三种方法的使用场景在上面已经做了明确的说明。这里做一下汇总:
$forceUpdate 适用于那些无法被 vue 监听到了 data 属性操作,比如对对象、数组的修改;或者你可能依赖了一个未被 Vue 的响应式系统追踪的状态,比如 某个 data 属性被 Object.freeze() 冻结了等等情况。
v-if 和key方法适用于$forceUpdate 无法满足的强制刷新,需要触发完整的生命周期钩子。由于v-if会有闪动的现象,基本弃用。
TIPS:
一、$forceUpdate
执行机制:
$forceUpdate
会使组件重新渲染,但是并不会触发完整的生命周期,它只会触发组件的beforUpate、updated这两个钩子;并不会让组件先注销再重建,不会重置data、computed等数据,created和mounted钩子也不会被触发,只是依据数据变化强制更新页面,重新渲染,不等于组件重载,所以被称为“伪组件强制刷新”;$forceUpdate
会使自身以及插入插槽内容的子组件重新渲染。但是如果子组件声明了插槽而父组件不插入内容,$forceUpdate
是不会使子组件重新渲染的;
二、$forceUpdate的开销比较大
:
$forceUpdate
方法会使 Vue 对整个组件视图进行一次完全的重新渲染。相比于单个data
属性或者computed
属性的变更触发的视图重新渲染,$forceUpdate
引发的重新渲染的范围更大,故而开销较大三、应用场景
1.在vue2中:$forceUpdate
适用于那些无法被 vue 监听到了data
属性操作,比如对对象、数组的修改;或者你可能依赖了一个未被 Vue 的响应式系统追踪的状态,比如某个data
属性被Object.freeze()
冻结了等等情况。2.在vue3中数据劫持通过proxy代理处理了数组、对象内的属性变化不触发响应式的问题,所以应用也比较少了;
1.v-if 是真正的条件渲染,是通过条件判断的布尔值,采用创建和销毁dom来实现dom的隐藏与展现;如果值为false,不会在页面加载之处就加载v-if指令,只有当取值变为true时才会加载;
(1)优点:对于一些隐秘性要求比较高的页面结构,比如电话号码的隐藏,可以通过v-if来实现;
(2)缺点:开销比较大,在隐藏与展示操作频繁的页面来说,会频繁的创建与销毁DOM结构,在切换比较频繁时,使用v-show会比较好,因为v-show是通过css的display:none|block来切换的;
2.通过
v-if
强制刷新子组件会使子组件触发beforeDestroy
、destroyed
、created
和mounted
s 生命周期钩子。证明了v-if
确实会销毁/重建子组件。所以,v-if
完全满足了我们的需求,是真正的强制刷新。因为该指令的执行是在创建和销毁DOM;3.通过
v-if
实现强制刷新的开销远远大于$forceUpdate;(操作DOM的开销比较大)
4.弊端:
闪动现象!!!
v-if
有个弊端。仔细观察页面动图,可以看到使用v-if页面会闪动。受限于帧率,表现不是很明显。如果在本地执行上面的代码,你就可以清楚的看到了。这个闪动是无法消除的。这是因为v-if
需要先注销子组件后再创建子组件。这个过程是线性的。
机制:
我们能通过 key 来实现组件的强制刷新,正是借助 diff 算法原理。只要将子组件的 key 修改了,Vue 就会认为子组件不能再使用了。会把旧 key 对应的子组件注销卸载,然后创建基于新 key 的子组件。因此,会触发完整的生命周期钩子。如果你为组件设置了过渡效果,过渡效果同时也会触发。
开销:同
v-if
一样,开销远远大于$forceUpdate
,与v-if
开销等同。触发
beforeDestroy
、destroyed
、created
和mounted
s 生命周期钩子。新子组件的创建和旧子组件的卸载是同时进行的。也正是这个原因,通过key
进行的强制刷新并不会存在闪动的现象
key:vue官方描述:
预期:number | string | boolean (2.4.2 新增) | symbol (2.5.12 新增)key 的特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。
最常见的用例是结合 v-for:
<li v-for="item in items" :key="item.id">...li>它也可以用于强制替换元素/组件而不是重复使用它。当你遇到如下场景时它可能会很有用:
完整地触发组件的生命周期钩子
触发过渡
例如:
<span :key="text">{{ text }}span>当 text 发生改变时, 总是会被替换而不是被修改,因此会触发过渡。
答案:
(1) Server side render 我们称为SSR,服务端渲染,指由服务端完成页面的HTML结构的搭建处理技术,发送到浏览器,然后在为其绑定事件状态;
(2) 主要解决了以下两个问题:
seo:搜索引擎爬取页面的HTML结构,使用SSR时,服务器已经生产了和业务相关的HTML标签和内容,有利于SEO,而CSR在vue构建时,页面的HTML标签尚不明确;
首屏呈现渲染:用户无需等待页面所以的js加载完成就可以看到页面;用户体验增强;
(3)缺点:开发速度慢,条件限制比较大;服务器端渲染只只支持beforCreate和created两个声明周期钩子;服务器端环境需要基于Node.js的运行环境;另外,服务器端的负载需求较大;
概念对比:
server side render 前端页面的产生是由服务器端生成的,我们就称之为服务端渲染;
client side render 服务端只提供json格式的数据,渲染成什么样子由客户端通过js控制;
运行对比:
CSR执行流程:浏览器加载html文件 -> 浏览器下载js文件 -> 浏览器运行vue代码 -> 渲染页面
SSR执行流程:浏览器加载html文件 -> 服务端装填好内容 -> 返回浏览器渲染
开发模式对比:
CSR:前后端通过接口JSON数据进行通信,各自开发互不影响
SSR:前后端分工搭配复杂,前端需要写好html模板交给后端,后端装填模板内容返给浏览器
优势对比:
| | 客户端渲染(CSR) | 服务端渲染(SSR) |
| ------------------ | ----------------- | ----------------- |
| 首次渲染时间 | 长 | 很短 |
| seo支持 | 差 | 良好 |
| 前后端分工开发效率 | 快 | 慢 |
答案:
1.加载速度慢的原因:
(1).网络延时问题;(2) 资源文件是否体积过大 (3) 资源是否重复发送请求去加载
(4) 在加载脚本文件时,渲染内容阻塞
2.解决方案:
(1)减小入口文件(采用懒加载方式,按需加载,先保证基本页面展示)
(2)静态资源本地缓存(使用localStorage)
(3)UI 框架 按需引入,不要全部默认引入,缩小文件体积;
(4)图片资源压缩处理,比如icon可以使用在线字体图标(阿里的iconfont),使用精灵图,较少图片对服务端的请求次数和压力;
(5)使用SSR
(6)开启Gzip压缩
(7)组件重复打包(在webpack的config文件中,修改CommonsChunkPlugin为minChunk:3)
那么为什么不能获取DOM节点呢?
因为:vue中数据变化渲染视图是异步渲染,当数据更新时,vue不会立即渲染视图,而是等到同一事件循环中的所有数据全部更新完成之后才会进行统一的视图更新渲染,这是vue为了提高性能;每个数据变化都去渲染DOM的话,那么性能将浪费很多;
可以使用this.$nextTick方法来等待最新的DOM 渲染成功立即进行DOM挂载或者操作,就不会出现获取不到DOM的情况;类似于async/await 或者说setTimeout;
应用场景:
在created钩子函数中DOM还没有渲染,此时如果去操作DOM那么肯定是不会有效果的,比如Echarts,swiper,等视图渲染是需要DOM节点来挂载的,如果DOM节点还没有渲染,那么是不会得到图的,这里就可以使用$nextTick(),意思是,挂载DOM动作是等到DOM更新完之后再立马进行后面的操作;
使用方法:
vm.$nextTick(callback),等到DOM跟新完成之后,执行他的回调函数;
答:vue2中,v-for的优先级高于v-if,如果一起使用,在操作数据时,都会先进行数据的循环,再进行条件判断,会很浪费性能,完全可以先进行条件判断,对符合的数据再进行循环操作;
vue3中v-if始终在v-for之前执行;但是还是不推荐一起使用,因为如果一起使用,v-if不能获取到v-for中的作用域中的变量;
解决方案:
(1)在v-for外层套一层template标签,在上面先进行v-if判断;
(2)使用计算属性,先对数据进行过滤;