1、MVVM的概念
MVVM是Model-View-ViewModel的缩写。MVVM是一种设计思想。Model 层代表数据模型;View 代表UI 组件;ViewModel 是连接View 和 Model的桥梁。
在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,因此View 和 Model 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
MVVM框架理解及其原理实现
2.生命周期的概念
Vue实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载DOM->渲染、更新->渲染、卸载等一系列过程,我们称这是Vue的生命周期。
详解vue生命周期
3.computed 和 watch 有什么区别及运用场景?
区别
computed 计算属性 : 依赖其它属性值,并且 computed 是惰性求值的,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值。
watch 侦听器 : 更多的是「观察」的作用,无缓存性,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作。
运用场景:
当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算。
当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
4.Vue 中的 key 到底有什么用?
key 是给每一个 vnode 的唯一 id,依靠 key,我们的 diff 操作可以更准确、更快速
Vue2.0 v-for 中 :key 到底有什么用?
5.谈一谈 nextTick 的原理
异步更新队列
可能你还没有注意到,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。
如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。
然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。
在 vue2.5 的源码中,macrotask 降级的方案依次是:setImmediate、MessageChannel、setTimeout
vue 的 nextTick 方法的实现原理:
vue 用异步队列的方式来控制 DOM 更新和 nextTick 回调先后执行
microtask 因为其高优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕
考虑兼容问题,vue 做了 microtask 向 macrotask 的降级方案
6.Vue 组件 data 为什么必须是函数 ?
因为组件是可以复用的,JS 里对象是引用关系,如果组件 data 是一个对象,那么子组件中的 data 属性值会互相污染,产生副作用。
所以一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝。new Vue 的实例是不会被复用的,因此不存在以上问题。
7.v-if 和 v-show 有什么区别?
v-show 仅仅控制元素的显示方式,将 display 属性在 block 和 none 来回切换;而v-if会控制这个 DOM 节点的存在与否。当我们需要经常切换某个元素的显示/隐藏时,使用v-show会更加节省性能上的开销;当只需要一次显示或隐藏时,使用v-if更加合理。
8.delete和Vue.delete删除数组的区别
delete只是被删除的元素变成了 empty/undefined 其他的元素的键值还是不变。
Vue.delete直接删除了数组 改变了数组的键值。
var a=[1,2,3,4]
var b=[1,2,3,4]
delete a[1]
console.log(a)
this.$delete(b,1)
console.log(b)
9.Vue中给data中的对象属性添加一个新的属性时会发生什么,如何解决?
<template>
<div>
<ul>
<li v-for="value in obj" :key="value">
{{value}}
</li>
</ul>
<button @click="addObjB">添加obj.b</button>
</div>
</template>
<script> export default {
data () {
return {
obj: {
a: 'obj.a'
}
}
},
methods: {
addObjB () {
this.obj.b = 'obj.b'
console.log(this.obj)
}
}
} </script>
<style></style>
点击button会发现,obj.b 已经成功添加,但是视图并未刷新:
原因在于在Vue实例创建时,obj.b并未声明,因此就没有被Vue转换为响应式的属性,自然就不会触发视图的更新,这时就需要使用Vue的全局api $set():
addObjB () {
// this.obj.b = 'obj.b'
this.$set(this.obj, 'b', 'obj.b')
console.log(this.obj)
}
$set()方法相当于手动的去把obj.b处理成一个响应式的属性,此时视图也会跟着改变了:
10.vue.js的两个核心是什么?
数据驱动、组件系统。
11.vue 是如何对数组方法进行变异的 ?
简单来说,Vue 通过原型拦截的方式重写了数组的 7 个方法,首先获取到这个数组的ob,也就是它的 Observer 对象,如果有新的值,就调用 observeArray 对新的值进行监听,然后手动调用 notify,通知 render watcher,执行 update
12.v-model
就是:value @input的语法糖
13.怎样理解单向数据流
这个概念出现在组件通信。父组件是通过 prop 把数据传递到子组件的,但是这个 prop 只能由父组件修改,子组件不能修改,否则会报错。子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改。
14.vue中v-if和v-for不建议同时使用的坑
v-for比v-if优先级高,所以使用的话,每次v-for都会执行v-if,造成不必要的计算,影响性能,所以我们可以选择使用computed过滤掉列表中不需要显示的项目。
15.@click="function" 和@click="function()"有什么区别
总结就是 带括号会被间接触发 所以不会有event的传递 而不带括号是直接触发 会有event的传递 所以如果带括号还想要event的话 需要手动在括号内添加$event
vue单个元素绑定多个事件 例如点击绑定多个事件方法
16.组件间通信
17.性能优化
尽量减少data中的数据,data中的数据都会增加getter和setter
v-if和v-for不能连用
如果需要使用v-for给每项元素绑定事件时使用事件代理
<ul @click="meths">
<li v-for="(item,key) in 10" :key="key" :data-index="key">{{item}}</li>
</ul>
// vue
meths(e) {
if (e.target.nodeName.toLowerCase() === 'li') {
console.log(e.target.dataset.index)
}
}
第 94 题:vue 在 v-for 时给每项元素绑定事件需要用事件代理吗?为什么?
SPA 页面采用keep-alive缓存组件
合理使用v-if和v-show
key保证唯一
使用路由懒加载、异步组件
防抖、节流
第三方模块按需导入
长列表滚动到可视区域动态加载
图片懒加载
揭秘 Vue.js 九个性能优化技巧
vue 性能优化
动态组件 & 异步组件
vue-lazy-component
vue-lazy-render
18.高阶组件
一个函数接受一个组件为参数,返回一个包装后的组件。
Vue 进阶必学之高阶组件 HOC
奇技淫巧 - Vue Mixins 高级组件 与 Vue HOC 高阶组件 实践
19.Vue的History模式和Hash模式的区别理解
hash锚点跳转
History浏览历史
Vue的History模式和Hash模式的区别理解
history和hash,vue-router
20.你的接口请求一般放在哪个生命周期中?
因为请求是异步的 所以就算放在created里也不会争取到多久的时间
所以我个人更倾向于放在mounted里 这样做更清晰
21.vue路由传参方式
query传参,刷新页面不会丢失参数。但是params会丢参的。
params 和path不能共存 所以只能用name
params传参 需要在 路由配置 path /:id 这样就不会丢参
最重要的一点,params刷新会消失。。。query则不会,params参数只要在路由中声明了就不会消失。
在路由声明了,跟query又有什么区别呢,干嘛不直接query呢,params不会出现在地址栏,更加美观。
路由声明path里加上参数(冒号加参数名称)比如 /article/:articleId/:articleType 这样你通过params传递的articleId和articleType就会在路由路径里。
$router是路由对象,是一个只写的对象
$route是当前路由的信息对象,是一个只读的对象
vue路由传参四种方式
vue路由传参的三种基本方式
22.Vue事件绑定原理说一下
原生事件绑定是通过addEventListener
绑定给真实元素的,组件事件绑定是通过Vue自定义的$on
实现的。
23.Vue中组件生命周期调用顺序说一下
组件的调用顺序都是先父后子
,渲染完成的顺序是先子后父
。
组件的销毁操作是先父后子
,销毁完成的顺序是先子后父
。
加载渲染过程父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount- >子mounted->父mounted
子组件更新过程父beforeUpdate->子beforeUpdate->子updated->父updated
销毁过程父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
以上是从别人的文章中收集的一些个人觉得还不错的面试题,后续还会持续的更新。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。