对于大多数数据的 id
都是唯一的,这无疑的一个 key
的优选答案。对于任何大多数情况使用 id
作为 key
都不会出现上面 bug
。但是如果你需要考虑性能问题,那就就要思考是否应该使用原地复用了。
同样是上面的分页数据展示,如果使用 id
作为 key
,可想而知每一页的每一条数据 id
都是不一样的,所以当换页时两颗 虚拟DOM树
的节点的 key
完全不一致,vue
就会移除原来的节点然后创建新的节点。可想而知效率会更加低下。但是他也有它的优点。唯一的 key
可以帮助 diff
更加精确的为我们绑定状态,这尤其适合数据有独立的状态的场景,例如带输入框或者单选框的列表数据。
所以何时使用 id
作为 key
?只有一点:
- 无法使用
index
作为key
的时候
v-if/v-else-if/v-else 中使用 key
可能很多人都会忽略这个点
原因:默认情况下,Vue 会尽可能高效的更新 DOM。这意味着其在相同类型的元素之间切换时,会修补已存在的元素,而不是将旧的元素移除然后在同一位置添加一个新元素。如果本不相同的元素被识别为相同,则会出现意料之外的副作用。
如果只有一个 v-if ,没有 v-else 或者 v-if-else的话,就没有必要加 key 了
相对于 v-for 的 key, v-if/v-else-if/v-else 中的 key 相对简单,我们可以直接写入固定的字符串或者数组即可
<button
v-if=“isEditing”
v-on:click=“isEditing = false”
Save
<button
v-else
v-on:click=“isEditing = true”
Edit
.v-enter-active, .v-leave-active {
transition: all 1s;
}
.v-enter, .v-leave-to {
opacity: 0;
transform: translateY(30px);
}
.v-leave-active {
position: absolute;
}
例如对于上面的代码, 你会发现虽然对 button 添加了 过渡效果, 但是如果不添加 key 切换时是无法触发过渡的
v-for 和 v-if 不要一起使用(Vue2)
此优化技巧仅限于Vue2,Vue3 中对 v-for 和 v-if 的优先级做了调整
这个大家都知道
永远不要把
v-if
和v-for
同时用在同一个元素上。 引至 Vue2.x风格指南[1]
原因是 v-for
的 优先级高于 v-if
,所以当它们使用再同一个标签上是,每一个渲染都会先循环再进行条件判断
注意: Vue3 中
v-if
优先级高于v-for
,所以当v-for
和v-if
一起使用时效果类似于Vue2
中把v-if
上提的效果
例如下面这段代码在 Vue2
中是不被推荐的,Vue
也会给出对应的警告
{{ user.name }}
我们应该尽量将
v-if
移动到上级 或者 使用 计算属性来处理数据{{ user.name }}
如果你不想让循环的内容多出一个无需有的上级容器,那么你可以选择使用
template
来作为其父元素,template
不会被浏览器渲染为DOM
节点如果我想要判断遍历对象里面每一项的内容来选择渲染的数据的话,可以使用
computed
来对遍历对象进行过滤// js
let usersActive = computed(()=>users.filter(user => user.active))
// template
{{ user.name }}
合理的选择 v-if 和 v-show
v-if
和v-show
的区别相比大家都非常熟悉了;v-if
通过直接操作 DOM 的删除和添加来控制元素的显示和隐藏;v-show
是通过控制 DOM 的display
CSS熟悉来控制元素的显示和隐藏由于对 DOM 的 添加/删除 操作性能远远低于操作 DOM 的 CSS 属性
所以当元素需要频繁的 显示/隐藏 变化时,我们使用
v-show
来提高性能。当元素不需要频繁的 显示/隐藏 变化时,我们通过
v-if
来移除 DOM 可以节约掉浏览器渲染这个的一部分DOM需要的资源使用简单的 计算属性
应该把复杂计算属性分割为尽可能多的更简单的 property。
- 易于测试
当每个计算属性都包含一个非常简单且很少依赖的表达式时,撰写测试以确保其正确工作就会更加容易。
- 易于阅读
简化计算属性要求你为每一个值都起一个描述性的名称,即便它不可复用。这使得其他开发者 (以及未来的你) 更容易专注在他们关心的代码上并搞清楚发生了什么。
- 更好的“拥抱变化”
任何能够命名的值都可能用在视图上。举个例子,我们可能打算展示一个信息,告诉用户他们存了多少钱;也可能打算计算税费,但是可能会分开展现,而不是作为总价的一部分。
小的、专注的计算属性减少了信息使用时的假设性限制,所以需求变更时也用不着那么多重构了。
引至 Vue2风格指南[2]
computed 大家后很熟悉, 它会在其表达式中依赖的响应式数据发送变化时重新计算。如果我们在一个计算属性中书写了比较复杂的表达式,那么其依赖的响应式数据也任意变得更多。当其中任何一个依赖项变化时整个表达式都需要重新计算
let price = computed(()=>{
let basePrice = manufactureCost / (1 - profitMargin)
return (
basePrice -
basePrice * (discountPercent || 0)
)
})
当 manufactureCost、profitMargin、discountPercent 中任何一个变化时都会重新计算整个 price。
但是如果我们改成下面这样
let basePrice = computed(() => manufactureCost / (1 - profitMargin))
let discount = computed(() => basePrice * (discountPercent || 0))
let finalPrice = computed(() => basePrice - discount)
如果当 discountPercent 变化时,只会 重新计算 discount 和 finalPrice,由于
computed
的缓存特性
,不会重新计算 basePricefunctional 函数式组件(Vue2)
注意,这仅仅在 Vue2 中被作为一种优化手段,在 3.x 中,有状态组件和函数式组件之间的性能差异已经大大减少,并且在大多数用例中是微不足道的。因此,在 SFCs 上使用
functional
的开发人员的迁移路径是删除该 attribute,并将props
的所有引用重命名为$props
,将attrs
重命名为$attrs
。优化前
优化后
-
没有this(没有实例)
-
没有响应式数据
拆分组件
什么?你写的一个vue文件有一千多行代码?🤔
合理的拆分组件不仅仅可以优化性能,还能够让代码更清晰可读。单一功能原则嘛
源自 slides.com/akryum/vuec…[3]
优化前
{{ heavy() }}优化后
由于 Vue 的更新是组件粒度的,虽然每一帧都通过数据修改导致了父组件的重新渲染,但是
ChildComp
却不会重新渲染,因为它的内部也没有任何响应式数据的变化。所以优化后的组件不会在每次渲染都执行耗时任务使用局部变量
优化前
{{ result }}优化后
{{ result }}
这里主要是优化前后的组件的计算属性
result
的实现差异,优化前的组件多次在计算过程中访问this.base
,而优化后的组件会在计算前先用局部变量base
,缓存this.base
,后面直接访问base
。那么为啥这个差异会造成性能上的差异呢,原因是你每次访问
this.base
的时候,由于this.base
是一个响应式对象,所以会触发它的getter
,进而会执行依赖收集相关逻辑代码。类似的逻辑执行多了,像示例这样,几百次循环更新几百个组件,每个组件触发computed
重新计算,然后又多次执行依赖收集相关逻辑,性能自然就下降了。从需求上来说,
this.base
执行一次依赖收集就够了,把它的getter
求值结果返回给局部变量base
,后续再次访问base
的时候就不会触发getter
,也不会走依赖收集的逻辑了,性能自然就得到了提升。引至 揭秘 Vue.js 九个性能优化技巧[4]
使用 KeepAlive
在一些渲染成本比较高的组件需要被经常切换时,可以使用
keep-alive
来缓存这个组件而在使用
keep-alive
后,被keep-alive
包裹的组件在经过第一次渲染后,的vnode
以及 DOM 都会被缓存起来,然后再下一次再次渲染该组件的时候,直接从缓存中拿到对应的vnode
和 DOM,然后渲染,并不需要再走一次组件初始化,render
和patch
等一系列流程,减少了script
的执行时间,性能更好。注意: 滥用 keep-alive 只会让你的应用变得更加卡顿,因为他会长期占用较大的内存
事件的销毁
当一个组件被销毁时,我们应该清除组件中添加的 全局事件 和 定时器 等来防止内存泄漏
Vue3 的 HOOK 可以让我们将事件的声明和销毁写在一起,更加可读
function scrollFun(){ /* … */}
document.addEventListener(“scroll”, scrollFun)
onBeforeUnmount(()=>{
document.removeEventListener(“scroll”, scrollFun)
})
Vue2 依然可以通过
$once
来做到这样的效果,当然你也可以在optionsAPI
beforeDestroy 中销毁事件,但是我更加推荐前者的写法,因为后者会让相同功能的代码更分散ES6
-
列举常用的ES6特性:
-
箭头函数需要注意哪些地方?
-
let、const、var
-
拓展:var方式定义的变量有什么样的bug?
-
Set数据结构
-
拓展:数组去重的方法
-
箭头函数this的指向。
-
手写ES6 class继承。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
微信小程序
-
简单描述一下微信小程序的相关文件类型?
-
你是怎么封装微信小程序的数据请求?
-
有哪些参数传值的方法?
-
你使用过哪些方法,来提高微信小程序的应用速度?
-
小程序和原生App哪个好?
-
简述微信小程序原理?
-
分析微信小程序的优劣势
-
怎么解决小程序的异步请求问题?
其他知识点面试
-
webpack的原理
-
webpack的loader和plugin的区别?
-
怎么使用webpack对项目进行优化?
-
防抖、节流
-
浏览器的缓存机制
-
描述一下二叉树, 并说明二叉树的几种遍历方式?
-
项目类问题
-
笔试编程题:
最后
技术栈比较搭,基本用过的东西都是一模一样的。快手终面喜欢问智力题,校招也是终面问智力题,大家要准备一下一些经典智力题。如果排列组合、概率论这些基础忘了,建议回去补一下。