目录
常见笔试面试题:
对于MVVM的理解?
Vue的生命周期
Vue实现数据双向绑定的原理
Vue组件间通信
Vue Router的路由守卫
Vue Router的hash和history模式
Vuex有五个核心概念
keep-alive的作用是什么?
react和vue的异同
Q:vue几种常用的指令
A:v-for 、 v-if 、v-show、v-bind、v-on
Q:v-if 和 v-show 区别
A:v-if按照条件是否渲染,v-show是display的block或none
Q:css只在当前组件起作用
A:在style标签中写入scoped即可 例如:
Q:vue常用的修饰符?
A:
Q:v-for和v-if 可以在同一个标签内使用吗?有什么问题?
A:可以,v-for的优先级比v-if高,会先循环,再判断,造成性能浪费。
Q:vue中 key 值的作用?
A:当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM。
Q:什么是vue的计算属性?
A:在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。好处:①使得数据处理结构清晰;②依赖于数据,数据更新,处理结果自动更新;③计算属性内部this指向vm实例;④在template调用时,直接写计算属性名即可;⑤常用的是getter方法,获取数据,也可以使用set方法改变数据;⑥相较于methods,不管依赖的数据变不变,methods都会重新计算,但是依赖数据不变的时候computed从缓存中获取,不会重新计算。
Q:$route和$router的区别
A:$route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。而$router是“路由实例”对象包括了路由的跳转方法,钩子函数等。
Q:怎么定义 vue-router 的动态路由? 怎么获取传过来的值
A:在 router 目录下的 index.js 文件中,对 path 属性加上 /:id,使用 router 对象的 params.id 获取。
Q:vue.js的两个核心是什么?
A:数据驱动、组件系统
Q:vue等单页面应用及其优缺点
A:优点:Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统。MVVM、数据驱动、组件化、轻量、简洁、高效、快速、模块友好。
缺点:不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退。
MVVM 是 Model-View-ViewModel 的缩写。
Model:数据模型,可以在Model中定义数据修改和操作的业务逻辑。
View:视图,它负责将数据模型转化成UI 展现出来。
ViewModel: 视图模型,监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个连接View 和 Model的中转站。
在MVVM架构下,View 和 Model 之间并没有直接的联系,ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
beforeCreate(创建前)此阶段为实例初始化之后,此时的数据观察和事件机制都未形成,不能获得DOM节点。
created(创建后) 在这个阶段vue实例已经创建,已完成数据监测、属性和方法的运算、data和事件的初始化,但$el属性还没有显示出来,所以仍然不能获取DOM元素。
beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成编译模板,把data里面的数据和模板生成html,但此时还没有挂载html到页面上,所以在这一阶段,我们依然得不到具体的DOM元素。
mounted(载入后) 在这个阶段,el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用,数据和DOM都已被渲染出来。一般的异步请求都写在这里。
beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。
destroyed(销毁后) 在实例销毁之后调用。此时所有的事件监听器、子实例都被移除销毁。
vue的生命周期的思想贯穿在组件开发的始终,通过熟悉其生命周期调用不同的钩子函数,可以准确地控制数据流和其对DOM的影响;vue生命周期的思想是Vnode和MVVM的生动体现和继承。
Question:
Q:什么是Vue生命周期?
A: Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。
Q:Vue生命周期的作用是什么?
A:Vue生命周期提供了多个钩子函数,让开发者准确地控制数据流和其对DOM的影响。
Q:第一次页面加载会触发哪几个钩子?
A:会触发 下面这几个beforeCreate, created, beforeMount, mounted 。
Q:DOM 渲染在 哪个周期中就已经完成?
A:DOM 渲染在 mounted 中就已经完成了。
vue2.x使用Object.defineProperty()
vue3.x使用Proxy对象实现观察者模式
简单来说:Vue实现双向数据绑定的原理就是利用 Object.defineProperty() 重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。
Object.defineProperty() 接收三个参数,要操作的对象,要定义或修改的对象属性名,属性描述符。重点就是最后的属性描述符。属性描述符是一个对象,主要有两种形式:数据描述符和存取描述符。这两种对象只能选择一种使用,不能混合两种描述符的属性同时使用。上面说的get和set就是属于存取描述符对象的属性。
详细的讲:Vue实现数据双向绑定原理是:数据劫持+发布者-订阅者模式。
Vue的数据双向绑定利用Object.defineProperty() 把内部解耦为三部分
Observer: 递归的监听对象上的所有属性,当属性改变时触发对应的watcher
watcher(观察者):当监听的数据值修改时,执行相应的回调函数,更新模板内容
dep:链接observer和watcher,每一个observer对应一个dep,内部维护一个数组,保存与该observer相关的watcher
数据劫持:指的是在访问或者修改对象的某个属性时,通过一段代码拦截这个行为,进行额外的操作或者修改返回结果
订阅发布模式:对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。订阅发布模式中事件统一由处理中心处理,订阅者发布者互不干扰。
优点:实现更多的控制,做权限处理,节流控制之类,例如:发布了很多消息,但是不是所有订阅者都要接收。
关于Object.defineProperty() 的详细介绍可看这两篇文章:《JavaScript中的Object.defineProperty()》《深入浅出Object.defineProperty()》
使用Proxy实现观察者模式
观察者模式(Observer mode)指的是函数自动观察数据对象,一旦对象有变化,函数就会自动执行
Proxy实现数据劫持
observe(data) {
const that = this;
let handler = {
get(target, property) {
return target[property];
},
set(target, key, value) {
let res = Reflect.set(target, key, value);
that.subscribe[key].map(item => {
item.update();
});
return res;
}
}
this.$data = new Proxy(data, handler);
}
父子组件:props和$emit、$parent和$children/$refs
兄弟组件、非父子组件间:$emit和$on、Vuex
想了解全部详细的组件通信,请点这里《Vue组件通信》
router.beforeEach、router.beforeResolve、router.afterEach......
路由守卫接受三个参数:
对于vue这类渐进式前端开发框架,为了构建 SPA(单页面应用),需要引入前端路由系统,这也就是 Vue-Router 存在的意义。前端路由的核心,就在于 —— 改变视图的同时不会向后端发出请求。
为了达到这一目的,浏览器当前提供了以下两种支持:
hash —— 即地址栏 URL 中的 # 符号(此 hash 不是密码学里的散列运算)。比如这个 URL:http://www.abc.com/#/hello hash 的值为 #/hello。它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
history —— 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定浏览器支持)这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。
state
, getters
, mutations
, actions
, modules
。
1. state:vuex的基本数据,用来存储变量
2. geeter:从基本数据(state)派生的数据,相当于state的计算属性
3. mutation:提交更新数据的方法,必须是同步的(如果需要异步使用action)。每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。
4. action:和mutation的功能大致相同,不同之处在于:1. Action 提交的是 mutation,而不是直接变更状态。 2. Action 可以包含任意异步操作。
5. modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件缓存下来保留状态,避免重新渲染。两个钩子:activated 和 deactivated,钩子会在
常用应用场景有:
有关keep-alive->《利用Vue中keep-alive,快速实现页面缓存》
详解->《vue和react的区别及各自优点》