1. Vue 实例的 data 属性,可以在哪些生命周期中获取到?
A. beforeCreate B. created C. beforeMount D. mounted
(b,c,d)
2. 下列对 Vue 原理的叙述,哪些是正确的?
A. Vue 中的数组变更通知,通过拦截数组操作方法而实现
B. 编译器目标是创建渲染函数,渲染函数执行后将得到 VNode 树
C. 组件内 data 发生变化时会通知其对应 watcher,执行异步更新
D. patching 算法首先进行同层级比较,可能执行的操作是节点的增加、删除和更新
(A,B,C,D)
3. 对于 Vue 中响应式数据原理的说法,下列哪项是不正确的?
A. 采用数据劫持方式,即 Object.defineProperty() 劫持 data 中各属性,实现响应式数据
B. 视图中的变化会通过 watcher 更新 data 中的数据
C. 若 data 中某属性多次发生变化,watcher 仅会进入更新队列一次
D. 通过编译过程进行依赖收集
(B D)
4. 下列说法不正确的是哪项?
A. key 的作用主要是为了高效地更新虚拟 DOM
B. 若指定了组件的 template 选项,render 函数不会执行
C. 使用 vm.$nextTick 可以确保获得 DOM 异步更新的结果
D. 若没有 el 选项,vm.$mount(dom) 可将 Vue 实例挂载于指定元素上
(B)
5. 下列关于 Vuex 的描述,不正确的是哪项?
A. Vuex 通过 Vue 实现响应式状态,因此只能用于 Vue
B. Vuex 是一个状态管理模式
C. Vuex 主要用于多视图间状态全局共享与管理
D. 在 Vuex 中改变状态,可以通过 mutations 和 actions
(C)
6. 关于 Vue 组件间的参数传递,下列哪项是不正确的?
A. 若子组件给父组件传值,可使用 $emit 方法
B. 祖孙组件之间可以使用 provide 和 inject 方式跨层级相互传值
C. 若子组件使用 $emit('say') 派发事件,父组件可使用 @say 监听
D. 若父组件给子组件传值,子组件可通过 props 接受数据
(B)
7. 下列关于 vue-router 的描述,不正确的是哪项?
A. vue-router 的常用模式有 hash 和 history 两种
B. 可通过 addRoutes 方法动态添加路由
C. 可通过 beforeEnter 对单个组件进行路由守卫
D. vue-router 借助 Vue 实现响应式的路由,因此只能用于 Vue
(C)
8. 下列说法不正确的是哪项?
A. 可通过 this.$parent 查找当前组件的父组件
B. 可使用 this.$refs 查找命名子组件
C. 可使用 this.$children 按顺序查找当前组件的直接子组件
D. 可使用 $root 查找根组件,并可配合 children 遍历全部组件
(C)
9. 下列关于 v-model 的说法,哪项是不正确的?
A. v-model 能实现双向绑定
B. v-model 本质上是语法糖,它负责监听用户的输入事件以更新数据
C. v-model 是内置指令,不能用在自定义组件上
D. 对 input 使用 v-model,实际上是指定其 :value 和 :input
(C)
10. 关于 Vue 的生命周期,下列哪项是不正确的?
A. DOM 渲染在 mounted 中就已经完成了
B. Vue 实例从创建到销毁的过程,就是生命周期
C. created 表示完成数据观测、属性和方法的运算和初始化事件,此时 $el 属性还未显示出来
D. 页面首次加载过程中,会依次触发 beforeCreate,created,beforeMount,mounted,beforeUpdate,updated
(D)
10,vue2.0和vue3.0渲染器的Diff算法分别说一下
简单来说,diff算法有以下过程
1、 同级比较,再比较子节点
2、 先判断一方有子节点一方没有子节点的情况(如果新的children没有子节点,将旧的子节点移除)
3、 比较都有子节点的情况(核心diff)
4、 递归比较子节点
正常Diff两个树的时间复杂度是O(n^3)
,但实际情况下我们很少会进行跨层级的移动DOM
,所以Vue将Diff进行了优化,从O(n^3) -> O(n)
,只有当新旧children都为多个子节点时才需要用核心的Diff算法进行同层级比较。
Vue2的核心Diff算法采用了双端比较
的算法,同时从新旧children的两端开始进行比较,借助key值找到可复用的节点,再进行相关操作。相比React的Diff算法,同样情况下可以减少移动节点次数,减少不必要的性能损耗,更加的优雅。
在创建VNode时就确定其类型,以及在mount/patch
的过程中采用位运算
来判断一个VNode的类型,在这个基础之上再配合核心的Diff算法,使得性能上较Vue2.x有了提升。(实际的实现可以结合Vue3.x源码看。)
该算法中还运用了动态规划
的思想求解最长递归子序列。
(看到这你还会发现,框架内无处不蕴藏着数据结构和算法的魅力)
2.解释一下:响应式原理?
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data
选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty把这些 property 全部转为 getter/setter这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更,每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
3.vue有哪些缺点
- Vue 不能检测数组和对象的变化
4.为什么vue不能检测对象的变化
对于对象, Vue 无法检测 property 的添加或移除,由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的.
- 追问:那如何解决上述问题?
使用this.$set
(this.someObject,'b',2) 添加新的属性
使用this.$delete
(this.someObject,'b') 删除旧属性
5.讲一下 $set 的实现原理
1、如果目标是数组,使用 vue 实现的变异方法 splice 实现响应式
2、如果目标是对象,判断属性存在,即为响应式,直接赋值
3、如果 target 本身就不是响应式,直接赋值
4、如果属性不是响应式,则调用 defineReactive 方法进行响应式处理
6.new Vue()实例中,data 可以直接是一个对象,为什么在 vue 组件中,data 必须是一个函数呢?
关键词:复用
+污染
+ 函数返回
+ 数据拷贝
因为组件是可以复用的,JS 里对象是引用关系,如果组件 data 是一个对象,那么子组件中的 data 属性值会互相污染,产生副作用。所以一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝。new Vue 的实例是不会被复用的,因此不存在以上问题。
7.computed 和 watch 有什么区别?
computed 计算属性 :
依赖其它属性值,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值,如果和上次计算结果不一致,重新渲染页面。
watch 侦听器 : 更多的是「观察」的作用,无缓存性,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作。
追问:computed 和 watch 应用场景?
关键词 computed
+缓存
computed :当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算。
watch: 当我们需要在数据变化时执行的操作时使用(如调用其它函数)
追问 :能使用箭头函数定义computed和watch吗?
不应该使用箭头函数来定义 watcher 函数,理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,为undefined
8.vue数据绑定是双向还是单向的
Vue 在不同组件间强制使用单向数据流。这使应用中的数据流更加清晰易懂。
9.v-model双向绑定的原理?
v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据.
Object.defineproperty()重新定义(set方法)对象设置属性值和(get方法)获取属性值的操纵来实现的.
1.实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。
2.实现一个订阅者Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图。
3.实现一个解析器Compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。
10.全局导航钩子函数应用场景?
vue router.beforeEach(全局前置守卫)router.beforeEach 是页面加载之前(before each)意思是在 每次每一个路由改变的时候都得执行一遍.
vue router.afterEach(全局后置守卫),相反router.afterEach是页面加载之后.
应用场景:
- 可进行一些页面跳转前处理,例如判断需要登录的页面进行拦截,做登录跳转!
2.进入页面登录判断、管理员权限判断、浏览器判断
11.vue-loader是什么?它有什么作用?
解析和转换 .vue 文件,提取出其中的逻辑代码 script、样式代 码 style、以及 HTML 模版 template,再分别把它们交给对应的 Loader 去处理。
12.怎样动态加载路由?
通过router.addRoutes方法可以动态加载路由.
let router=new VueRouter({
routes:[
{path:'/product',component:a,name:'product'}
]
});
router.addRoutes([
{path:'/user',component:c,name:'user'},
{path:'/address',component:address,name:'address'}
]);
22.说说active-class是哪个组件的属性?
active-class是vue-router模块的router-link组件中的属性,用来设置选中连接的样式.
23.为什么vue使用异步更新组件?
收集当前的改动一次性批量更新,为了节省diff开销.
24.vuex中actions和mutations有什么区别?
1.mutations可以直接修改state,但只能包含同步操作,同时,只能通过提交commit调用.
2.actions可以包含异步操作,通过store.dispatch触发,不能直接修改数据,需要调用commit去修改数据.
25. 怎么监听vuex数据的变化?
通过watch监听数据的变化
watch:{
'$store.state.test':function(value){
console.log('数据修改了',value)
}}
28.开启vuex中的严格模式有什么好处?
主要用户防止不合理的改变状态值如:this.$.store.state.list = [],这样就会抛出异常
A.在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。
B. 不要在发布环境下启用严格模式!严格模式会深度监测状态树来检测不合规的状态变更——请确保在发布环境下关闭严格模式,以避免性能损失。
29.vue组件会在什么时候下被销毁?
1.页面关闭、
2.路由跳转、
3.v-if为false
4.改变key值