🎈来源:
村长的vue面试训练营
📖题目汇总
- v-if 和 v-for优先级
- Vue组件data选项为什么必须是个函数而Vue的根实力则没有此限制
- 你知道key的作用和工作远离吗?说说你
- 对它的理解
- 你怎么理解vue中的diff算法
- 谈一谈对vue组件化的理解
- 谈一谈对vue设计的原则的理解
- 谈谈你对MVC、MVP和MVVM的理解
- 你了解哪些vue性能优化的方法
- vue3新特性
- vuex使用及理解
- vue中组件之间的通信方式?
- vue-router中如何保护指定路由的安全?
- 你知道nextTick吗?他是干什么的?实现原理是什么?
- 谈一谈你对vue响应式原理的理解?
- 总结
🎯问点
这么多题,花里胡哨的,面试官到底是在问什么?
- v-if 和 v-for哪个优先级高
- vue组件data为什么要函数形式
- key的作用和原理
- 介绍一下diff算法,谈谈你的理解
- 介绍一下vue组件化的理解
- vue的设计理念是什么
- MVC、MVP和MVVM
- vue优化
- vue3新特性
- vuex使用及理解
- vue组件通信原理
- vueRouter原理
- nextTick原理
- vue响应式原理
📜正式开始了
1. v-if 和 v-for优先级
v-for 优先于 v-if被解析,因为当 v-for 和 v-if 同时出现在一个标签内时,在源码里会先进性for循环,当本次循环完成,返回数据时如果有 v-if 出现,那么就会判断是否为 true,true 就会返回循环生成的内容_l( ),false 会返回一个_el( ),所以v-for优先级更高。
如果同时出现,每次渲染都会先执行循环再判断条件,无论如何都不可避免,浪费了性能
解决方案:在v-for外层嵌套template,在这一次进行v-if判断,然后在内部进行v-for循环
2. Vue组件data选项为什么必须是个函数而Vue的根实例则没有此限制
Vue组件可能存在多个实例,如果使用对象形式定义data,则会导致他们公用一个data对象,那么状态变更将会影响所有组件实例,这是不合理的;采用函数形式定义,在initDta时会将其作为i给阐述返回新的data对象,有效规避多实例之间状态污染问题。而在Vue根实例创建过程中则不存在改限制,也是因为根实例只能有一个,不需要但现这种情况
3. 你知道key的作用和工作远离吗?说说你的理解
key的作用主要是为了高效更新虚拟DOM,其原理是vue在patch过程中通过key可以精准判断两个节点是否是同一个,从而避免频繁更新不同元素,使得整个patch过程更加高效,减少DOM操作量,提高性能。
如果不设置key还可能在列表更新时引发一些隐藏的BUG
vue中在使用相同标签名元素的过度切换时,也会使用key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果
4. 你怎么理解vue中的diff算法
diff算法是虚拟DOM技术的必然产物:通过新旧虚拟DOM作对比(即diff),将变化的地方更新在真是DOM上;另外,也需要diff高效的执行对比过程,从而降低时间复杂度O(n)。
vue 2.x 中为了降低Watcher粒度,每个组件只有一个Watcher与之对应,只有引入diff才能精确找到发生变化的地方。
vue中diff执行的时刻是组件实例执行其更新函数时,它会比对上一次渲染结果oldVnode和新的渲染结果newVnode,此过程称为patch(补丁)。
diff过程整体遵循深度有限、同层比较的策略;两个节点之间比较会根据他们是是否拥有子节点或者文本节点做不同操作;比较两组子节点是算法的重点,首先假设头尾节点可能校内沟通做4次比对尝试,如果没有找到相同节点才按照通用方式遍历查找,查找结果再按情况处理剩下的节点;借助可以通常可以非常精确扎到相同节点,因此整个patch过程非常高效。
5. 谈一谈对vue组件化的理解
回答思路
组件化定义、优点、使用场景和注意事项等方面展开陈述,同时要强调vue中组件化的一些特点
回答
组件是独立和可复用的代码阻止单元。组件系统是Vue核心特性之一,他使开发者是哦也能够小型,独立和通常可以复用的组件构建大型应用;
组件化开发能大幅提高应用开发效率、测试性、复用性的等;
组件使用按照分类有:页面组件、业务组件、通用组件;
vue的组件时基于配置的,我们通常编写的组件时组件配置而非组件,框架后续会生成其构造函数,他们基于Vuecomponent,扩展Vue;
vue中常见的组件化技术有:属性prop,自定义事件,插槽等;
合理的划分组件,有卒于提升应用性能;
组件应该是高内聚、低耦合的;
遵循单向数据流的原则;
6.谈一谈对vue设计的原则的理解
- Vue是一款渐进式JavaScript框架
- 易用、灵活、高效
渐进式框架
Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层,不仅易上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue也完全能够为复杂的单页应用提供驱动
易用
vue提供数据响应式、声明式模板语法和基于配置的组件系统等核心特性。这些使我们只需要关注应用的核心业务即可,只要会写js、html、css就能轻松编写vue应用。
灵活性
渐进式框架的最大优点就是灵活性,如果应用足够小,我们可能仅需要vue核心特性即可完成功能;随着应用规模不断扩大,我们才可能逐渐引入路由、状态管理、cli等库和工具,不管是应用提价还是学习难度都是一个逐渐增加的和平曲线
高效性
超快的虚拟DOM和diff算法是我们的应用拥有醉解的性能表现。
追求高效的过程还在继续,vue3中引入Proxy对数据响应式改进以及编译器对于静态内容编译的改进都会让vue更加高效。
7. 谈谈你对MVC、MVP和MVVM的理解
总结:
- 这三者都是框架模式,他们设计的目标都是为了解决Model和View的耦合问题。
- MVC模式出现较早主要应用再后端,如Spring MVC、ASP.NET MVC等,再前端领域早期也有应用,如Backbone.js。他的优点是分层清晰,缺点是数据流混乱,灵活性带来的维护性问题。
- MVP模式实在MVC的进化形式,Presenter作为中间层负责MV通信解决了两者耦合问题,但P层过于臃肿会导致维护问题。
- MVVM模式在前端领域有广泛应用,它不仅解决MV耦合问题,还同时解决了维护两者映射关系的大龄繁杂代码和DOM操作代码,在提高开发效率、可读性同时还保持了优越的性能表现。
8. 你了解哪些vue性能优化的方法
路由懒加载
const router = new VueRouter({
routes:[
{ path: '/foo', components: () => import('./Foo.vue') }
]
})
keep-alive缓存页面
<template>
<div id="app">
<keep-alive>
<router-view/>
</keep-alive>
</div>
</template>
使用v-show复用DOM
<template>
<div class="cell">
<div class="on" v-show="value">
<Heavy :n="10000"/>
</div>
<section class="off" v-show="!value">
<Heavy :n="10000"/>
</section>
</div>
</template>
v-for比哪里避免同时使用v-if
<template>
<ul>
<li v-for="user in activeUsers" :key="user.id">{{ user.name }} </li>
</ul>
</template>
<script>
export default {
computed: {
activeUsers: function () {
return this.users.filter(function(user){
return user.isActive
})
}
}
}
</script>
长列表性能优化
如果列表是存粹的诗句展示,不会有任何变化,就不需要做响应式
export default {
data: () => ({
users: []
}),
async created() {
cosnt users = await axios.get("/api/users")
this.users = object.freeze(users)
}
}
如果大数据长列表,可以采用虚拟滚动,之渲染少部分内容
<recycle-scroller
class="items"
:items="items"
:items-size="24">
<template v-slot="{ item }">
<FetchItenView :item="item" @vote="voteItem(item)"/>
</template>
</recycle-scroller>
事件的销毁
- Vue组件销毁时,会自动解绑他的全部指令及事件监听器,但是仅限于组件本身的事件
create(){
this.timer = setInterval(this.refresh, 2000)
},
beforeDestroy(){
clearInterval(this.timer)
}
图片懒加载
- 对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要讲页面内未出现在可视区域内的图片先不做加载,等滚动到可视区域后在加载
<img v-lazy="/static/img/2.jpg"/>
第三方插件按需引入
- 像element-UI这样的第三方组件库可以按需引入避免体积太大。
import Vue from 'vue'
import { Button, select } from 'element-ui'
Vue.use(Button)
Vue.use(Select)
无状态的组件标记为函数式组件
<template functional>
<div class="cell">
<div v-if="props.value" class="on"></div>
<section v-else class="off"></section>
</div>
</template>
<script>
export default {
props: ['value']
}
</script>
子组件分割
<template>
<div>
<childComp/>
</div>
</template>
<script>
export default {
components: {
childComp: {
methods: {
heavy () {/* 耗时任务 */}
},
render (h) {
return h('div', tihs.heavy())
}
}
}
}
</script>
变量本地化
<template>
<div :style="{ opacity:start / 300 }">
{{ result }}
</div>
</template>
<script>
import { heavy } from '@/utils
export default {
props: ['start'],
computed: {
base() { return 43 },
result () {
const base = this.base
let result = this.start
for(let i = 0;i < 1000; i++){
result += heavy(base)
}
return result
}
},
components: {
}
</script>
SSR
- 就是服务端渲染
9. vue3新特性
特性
更快
- 虚拟DOM重写
- 优化slots的生成
- 静态树的提升
- 静态属性提升
- 基于Proxy的响应式系统
更小
- 通过摇树优化核心库体积
更易维护
- TypeScript + 模块化
更加友好
- 跨平台:编译器核心和运行时核心与平台无关,是的Vue更容易与任何平台(Web,Android,ios)一起使用
更容易使用
- 改进的TypeScript支持,编译器能提供强有力的类型检查和错误警告
- 更好的调试支持
- 独立的响应化模块
- Composition API
虚拟DOM重写
期待更多的编译时提示来减少运行时开销,使用有效的代码来创建虚拟节点。
组件快速路径 + 单个调用 + 子节点类型检测
- 跳过不必要的条件分支
- JS引擎更容易优化
优化slots生成
vue3中可以单独重新渲染父级和子级
- 确保实例正确的跟中依赖关系
- 避免不必要的父子组件重新渲染
静态树提升
使用静态树提升,这意味着Vue3的编译器将能够检测到什么是静态的,然后提升,从而降低了渲染成本
- 跳过修补整棵树,从而降低渲染成本
- 即使多次出现也能正常工作
静态属性提升
使用静态属性提升,Vue3打补丁时将跳过这些属性不会改变的节点
基于Proxy的响应式系统
Vue2的响应式系统使用Object.defineProperty的getter和setter。Vue3将使用ES2015Proxy作为其观察机制,这将会带来如下变化
- 组件实例初始化速度提高100%
- 使用Proxy节省以前一半的内存开销,加快速度,但是存在低浏览器版本的不兼容
- 为了继续支持IE11,Vue3将发布一个支持旧观察者机制和新Proxy版本的构建
高可维护性
Vue3将带来更可维护的源代码。它不仅会使用TypeScript,而且许多包被解耦,更加模块化。
10. vuex使用及理解
策略
- 首先给Vuex下一个定义
- Vuex解决了哪些问题,解读理念
- 什么时候我们需要vuex
- 你的具体用法
- 简述原理,提升层级
回答
(官网)Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension(opens new window),提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能
11. vue中组件之间的通信方式?
- 父子组件之间通信
- props
- e m i t / emit/ emit/on
- p a r e n t / parent/ parent/children
- ref
- a t t r s / attrs/ attrs/listeners
- 兄弟组件
- $parent
- $root
- enevtbus
- vuex
- 跨层级关系
- eventbus
- vuex
- provide/inject
12. vue-router中如何保护指定路由的安全?
13. 你知道nextTick吗?他是干什么的?实现原理是什么?
定义
Vue.nextTick([callback,context])
在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM。
// 修改数据
vm.msg = 'Hello'
// DOM还没更新
Vue.nextTick(function (){
// DOM更新了
})
14. 谈一谈你对vue响应式原理的理解?
15. 跨域怎么解决
crossdomain放开就可以了,主要就是安全。我个人觉得不安全也不利于公司业务的规划,个人建议通过nodejs渲染服务(ssr)的方式解决跨域的问题,也可以通过web api和token的方式加强接口安全。