面试题
3)谈谈对vue生命周期的理解
Vue实例从创建到销毁的过程,就是生命周期,生命周期总共分为三个阶段:初始化、更新、销毁
1)初始化和挂载阶段
* beforeCreate() 实例创建出来之后会调用这个生命周期回调,这个时候还只是一个空壳,无法访问到数据
* created() 数据初始化、绑定事件和解析组件模板完成后会调用这个生命周期回调,这个时候文档碎片已经插入到容器对象中,可以访问到数据
* beforeMount() 准备渲染前会调用这个生命周期回调,这个时候什么都没有做,也可以访问到数据
!! * mounted() 页面渲染完成之后会调用这个生命周期回调,在这里可以操作真实dom
1. 发送ajax请求
2. 设置定时器
3. 绑定原生DOM事件...
4. 监视浏览器全屏
2)更新状态
* beforeUpdate() 页面重新更新之前会调用这个生命周期回调(数据已经发生改变),然后vue的虚拟dom机制会重新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比之后重新渲染
* updated() 当更新完成后会调用这个生命周期回调,dom也重新render完成,可以操作更新后的虚拟dom
3)销毁vue实例: vm.$destory()
!! * beforeDestory() 当经过某种途径调用$destroy方法(删除组件)后,立即执行beforeDestroy,一般在这里做一些善后工作(消除内存泄漏的隐患)
1. 清除定时器
2. 取消ajax请求
3. 解绑事件
* destoryed() 组件的数据绑定、监听...去掉后只剩下dom空壳,这个时候,执行destroyed,在这里做善后工作也可以
4)其它3个
activated() keep-alive 组件激活时调用。
deactivated() keep-alive 组件停用时调用。
errorCaptured() 当任何一个来自后代组件的错误时被捕获时调用
3.vue组件间的通信方式?
1)props(父-->子)
接收属性是数组形式,直接接收属性,接收属性是对象形式,可以指定属性名、属性值得类型和必要性
2)自定义事件 (父-->子)
3)slot(父-->子)
1.默认插槽
2.具名插槽
3.作用域插槽
4)ref(子-->父)
5)事件总线(任意组件)
订阅消息与发布消息(任意组件间通信,开发中基本不用)
7)vuex(任意组件)
8)组件通信高级部分
1.v-model深入(父传给子传递属性和修改父级属性的方法)
2.属性修饰符sync(父传给子传递属性和修改父级属性的方法)
3.$attrs与$listeners(父传子)
4.$children与$parent(父修改子,子修改父)
4.路由
1)什么是路由?
一种映射关系:地址和组件的关系,当监测到URL地址发生改变会加载相应的组件,专门用来实现单页面应用(SPA)
2)路由分类
1.hash模式
前端需要根据路径hash值不同显示对应的内容,由于路径中多了#号比较不好看,所以上线时一般采用history模式
主要依赖hashchange事件监听hash值变化,然后执行回调函数加载对应页面
2.history模式
history模式是根据浏览器提供的history对象来实现的,根据对应的路径来显示对应的内容,由于实现时通过前端history对象来实现的,
所有刷新时访问的路径后端并不存在,所以会报错,真正上线时需要后端配合(路径不在直接进入首页)。
HTML5 History API包括2个方法:history.pushState()和history.replaceState(),和1个事件window.onpopstate
1)pushState:实现push方法
2)replaceState:实现replace方法
3)onpopstate:该事件会在调用浏览器的前进、后退以及执行history.forward、history.back、和history.go触发,因为这些操作有一个共性,即修改了历史堆栈的当前指针
一旦当前指针改变则会触发onpopstate事件,但是 pushState 和 replaceState 不会触发 popstate 事件,这时我们需要手动触发页面跳转(渲染)。
3)keep-alive 组件有什么作用?
如果你需要在组件切换的时候缓存组件,防止多次渲染,就可以使用 keep-alive 组件包裹需要保存的组件。
提供 include 和 exclude 属性设置缓存条件,include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高;
对应两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated。
4)谈谈对路由守卫的了解?
路由守卫可以监视路由地址的变化,一旦地址发送变化可以做一系列的事情
应用: 在跳转到某个界面之前,进行用户的权限的限制(是否登录),离开这个界面前,做相关的收尾的一些操作
1.全局路由守卫:全局中只要发生路由跳转就会拦截下来做判断进而做一系列事情,包含全局前置守卫和全局后置守卫
//afterEach
router.beforeEach((to, from, next) => {
to:目标的路由route对象
from:当前的路由route对象
next:用来控制路由跳转的函数 next()同意跳转 next(地址)跳转到指定的path的路由
}
2.路由独享守卫:只要跳转到指定路由就会拦截下来做判断进而做一系列事情,包含前置守卫和后置守卫
//路由配置文件中配置,afterEnter
{
path: '/addcartsuccess',
component: AddCartSuccess,
beforeEnter: (to, from, next) => {}
}
3.组件内守卫:只要跳转到指定路由就会拦截下来做判断进而做一系列事情(和路由独享守卫差不多,就是写的地方不一样而已,写在组件中),包含前置守卫和后置守卫
//写在组件中,afterRouteEnter
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
// vm为实例对象
next(vm => {})
}
5)外链样式页面刷新页面样式丢失问题?
原因是在子路由组件中刷新页面会出现加载css路径出错,解决办法是将相对路径改成绝对路径
6)$route和$router的区别
$route是路由信息对象,包括path,params,hash,query,fullPath,matched,name等路由信息参数。
而$router是路由实例对象包括了路由的跳转方法,钩子函数等。
6)vue-router 路由钩子函数是什么 执行顺序是什么
路由钩子的执行流程, 钩子函数种类有:全局守卫、路由守卫、组件守卫
全局前置守卫:beforeEach
路由独享函数:beforeEnter
组件独享函数 :beforeRouteEnter
全局解析守卫 :beforeResolve
完整的导航解析流程:
导航被触发。
在失活的组件里调用 beforeRouteLeave 守卫。
调用全局的 beforeEach 守卫。
在要进入的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
在路由配置里调用 beforeEnter。
在被激活的组件里调用 beforeRouteEnter。
调用全局的 beforeResolve 守卫 (2.5+)。
调用全局的 afterEach 钩子。
触发 DOM 更新。
调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
6)路由组件
1) <router-link>: 用来生成路由链接
<router-link to="/xxx"></router-link>
2) <router-view>: 用来显示当前路由组件界面
<router-view></router-view>
6)源码
1.install()方法的实现,Vue.mixin()方法在beforeCreate生命周期函数将router实例放在vm根实例上,然在再把vue根实例放到所有的组件上面
这个所有的组件就可以拿到router实例了
2.router-view和router-link的实现,使用Vue.component()方法注册router-view和router-link这两个组件,在link组件中给组件标签绑定点击事件,进行跳转和改变url的hash值
router-view组件所对应的组件渲染即可
5.vuex
1)vuex有什么用?
对 vue 应用中多个组件的共享状态进行集中式的管理
2)vuex核心对象store的五大配置对象有什么用
1. state:包含了共享状态数据的对象,state属性具有响应式效果是因为,state属性是经过vue实例的响应包装,所以直接改state可以重新渲染页面
2. getters:包含多个状态数据的计算属性的对象,getters属性具有缓存效果,是因为内部使用vue的computed来实现的
3. actions:包含多个间接改变状态数据的方法,一般放一些业务逻辑
4. mutations:包含多个直接改变状态数据的方法
5. modules:包含多个 module,一个 module是一个 store的配置对象
3)vuex的执行流程
组件中用户调用$store.dispatch()调用actions执行一些业务代码,actions中调用commit执行mutations更新状态
4)介绍一下 Vuex的 Action和Mutation的区别吗?
action一般用于存放业务逻辑的异步操作,内部通过commit调用Mutation方法间接修改状态数据
Mutation做同步操作,内部有直接修改状态数据的方法
5)ajax请求代码应该写在组件的methods中还是vuex的actions中
如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。
如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用。
5)Redux和vuex有什么区别?
1.vuex的异步数据不需要使用到中件间,redux需要
2.vuex可以直接commit,action不是必须的,redux是必须的
3.Redux使用的是不可变数据,而Vuex的数据是可变的。Redux每次都是用新的state替换旧的state,而Vuex是直接修改
5)源码
1.加载vuex,在install()方法将vue根实例store全部注入给子孙组件
2.模块收集,建立上下级模块树
3.模块加载,将所有模块上的actions、mutation、getters 都把他定义在根模块上面,将所有的子模块的状态安装到父模块的状态上
4.state/getter,将state属性经过vue实例响应式代理后在将vm实例挂载Store实例上,当去取Store实例上的state属性时就去vm实例上取,这样state属性就是响应式的
将getters属性的值全部放在vue实例的computed属性上,然后当去Store实例上getters属性值时就会去取computed属性上的值调用getters属性相应方法,这样就取到值并且做到缓存效果
5.命名空间,在安装模块actions、mutation、getters时获取到标有命名空间模块的前缀再去安装模块
6.源码
1)Vue响应式原理和数据双向绑定原理
Vue 数据双向绑定/响应式原理主要是指数据变化更新视图,视图变化更新数据,所以 Vue 的数据双向绑定的工作主要是如何根据 Data 变化更新 View。
Vue 主要通过以下 4 个步骤来实现数据双向绑定的:
1.实现一个监听器 Observer:对数据对象进行遍历,利用 Object.defineProperty() 对属性都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。
对象是通过递归遍历进行劫持的,数组是通过重写了一些能改变原数组的数组方法来实现响应式的,(补充:在Vue中修改数组的索引和长度是无法监控到的)
const methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
2.实现一个解析器 Compile:解析 Vue 模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新。
3.实现一个订阅者 Watcher:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁 ,主要的任务是订阅 Observer 中的属性值变化的消息,当收到属性值变化的消息时,触发解析器 Compile 中对应的更新函数。
4.实现一个订阅器 Dep:订阅器采用 发布-订阅 设计模式,用来收集订阅者 Watcher,对订阅者 Watcher 进行统一管理,来优化更新逻辑。
5.实现Vue异步批量更新之nextTick
数据变化时会将不同的watcher和用户调用$nextTick的回调放在一个数组里面,并且通过Promise.then异步处理更新
2)模板解析
简而言之,就是先转化成AST树,再得到的render函数返回dom
1.在模板编译过程中默认会先找render()方法的返回值作为模板进行解析,没有的话再找设置的template模板进行编译,最后实在没有找到才会找el属性指定的模板进行编译,
2.模板开始会被编译成ast语法树,ast语法树是用来描述js语言的,内部是通过正则匹配解析标签内容生成ast树的
3.ast树优化
Vue的数据是响应式的,但其实模板中并不是所有的数据都是响应式的。有一些数据首次渲染后就不会再变化,对应的DOM也不会变化。那么优化过程就是深度遍历AST树,按照相关条件对树节点进行标记。这些被标记的节点(静态节点)我们就可以跳过对它们的比对,对运行时的模板起到很大的优化作用。
静态节点的判断方法:
如果是表达式,就是非静态;如果是纯文本,就是静态;
没有使用 v-if、v-for没有使用其它指令等
4.将优化后的AST树可执行的render()函数,最后编译我们的render模板是通过new Function + with来进行实现的
3)diff的策略是什么?
1、Web UI 中 DOM 节点跨层级的移动操作特别少,可以忽略不计,因此仅进行同层比较。
2、如果父节点不同(标签名),放弃对子节点的比较,直接删除旧节点然后添加新的节点重新渲染;
3、如果子节点有变化(标签名),Virtual DOM不会计算变化的是什么,而是重新渲染。
4、同级多个节点可通过唯一的key对比异同;
4)diff算法
1.在更新页面前会做diff算法来复用老模板可以复用的节点
2.比较两个元素的标签 ,标签不一样直接拿新的节点替换掉老的dom节点即可,如果标签一样那么先复用标签上的属性再去对比孩子
3.对比子元素(双指针diff比较)
Vue2的核心Diff算法采用了双端比较的算法(头头/尾尾/头尾/尾头),同时从新旧children的两端开始进行比较,借助key值找到可复用的节点,再进行节点的移动、添加、删除三个操作操作。
5)watch的实现原理
初始化watch属性,最终调用vm.$watch()创建一个用户watcher,在批量更新时执行执行watch回调即可
6)Computed的实现原理
1.初始化Computed属性,把Computed上的属性重新定义在实例上,Computed属性如果是个函数那么这个函数就是取值时
的get()方法,如果是对象,那么对象的get()和set()方法就是取值和设置值时的get()和set()方法
2.在重新定义computed属性时给每个属性增加一个watcher实例,这个watcher实例上有个dirty属性专门用来缓存computed属性,计算属性的值没有改变不会重新调用get()方法
8)组件的解析
1.Vue内部是通过extend()方法创建一个Vue子类,子类拥有父类所以响应式和解析模版的能力。
2.在模板解析时,如果标签是组件,那么要返回组件的真实dom即可
9)生命周期的合并(ximin)
在初始化数据前会先将用户自定义的options 和全局的options做合并,生命周期放在一个数组中依次调用,其它组件中的属性替代ximin中的
10)$set()方法的实现
1.如果给数组增加元素,那么使用splice()方法添加,这样新增的元素就具备响应式
2. 如果给对象增加属性,通过调用 defineReactive 方法进行响应式处理( defineReactive 方法就是 Vue 在初始化对象时,给对象属性采用 Object.defineProperty 动态添加 getter 和 setter 的功能所调用的方法)
11)Vue.observable()方法的实现
通过调用 defineReactive 方法进行响应式处理,在返回对象
12)Vue.use()方法的实现
将Vue构造函数传给插件的install()方法,在方法中将插件的属性挂载vue实例上即可
13)Vue事件绑定原理说一下
原生事件绑定是通过 addEventListener 绑定给真实元素的,组件事件绑定是通过 Vue 自定义的$on 实现的。如果要在组件上使用原生事件,需要加.native 修饰符,这样就相当于在父组件中把子组件当做普通 html 标签,然后加上原生事件。
$on、$emit 是基于发布订阅模式的,维护一个事件中心,on 的时候将事件按名称存在事件中心里,称之为订阅者,然后 emit 将对应的事件进行发布,去执行事件中心里的对应的监听器
14)vue的$nextTick
在下次 DOM 更新循环结束之后执行延迟回调。vue内部会把更新逻辑和用户调用$nextTick()方法放在一个队列中,等批量更新时会先执行
更新逻辑在执行用户调用$nextTick()方法,这样$nextTick中就可以拿到下次 DOM 更新的真实dom了
15)v-modal实现原理
v-modal是个语法堂,把表达式的值给表单标签的value属性,同时给标签绑定input事件,当表单内容改变时去改变对应表达式的值即可。
7.其它
1)你对MVVM的理解?
1.什么是 MVVM?
MVVM是一个软件架构设计模式,View 是视图层,也就是用户界面。Model 是指数据模型,泛指后端进行的各种业务逻辑处理和数据操控,对于前端来说就是后端提供的 api 接口。
ViewModel层,它就像是一个View和Model的中转站,在这一层,前端开发者对从后端获取的 Model 数据进行转换处理,做二次封装,以生成符合 View 层使用预期的视图数据模型。需要注意的是
ViewModel 所封装出来的数据模型包括视图的状态和行为两部分,而 Model 层的数据模型是只包含状态的,比如页面的这一块展示什么,而页面加载进来时发生什么,点击这一块发生什么,这一块滚动
时发生什么这些都属于视图行为(交互),视图状态和行为都封装在了 ViewModel 里。数据会绑定到viewModel层并自动将数据渲染到页面中,视图变化的时候会通知viewModel层更新数据。
2)组件中的data为什么是一个函数?
一个组件被复用多次的话,也就会创建多个实例。本质上,这些实例用的都是同一个构造函数。如果data是对象的话,对象属于引用类型,
会影响到所有的实例。所以为了保证组件不同的实例之间data不冲突,data必须是一个函数。
3)vue的key
key的作用主要是为了高效的更新虚拟DOM,其原理是vue在patch过程中通过key可以精准判断两个节点是否是同一个,
从而避免频繁更新不同元素,使得整个patch过程更加高效,减少DOM操作量,提高性能
4)为什么V-for和v-if不 能连用
原因:v-for比v-if优先级高,所以嵌套使用的的话,每次v-for都会执行v-if,造成不必要的计算,影响性能,尤其是当之需要渲染很小一部分的时候。
必要情况下应该替换成computed属性。
5)自定义组件使用v-modal
在自定义组件中,v-model 默认会利用名为 value 的 prop 和名为 input 的事件,如下所示
父组件:
<ModelChild v-model="message"></ModelChild>
子组件:
<div>{{value}}</div>
props:{
value: String
},
methods: {
test1(){
this.$emit('input', '小红')
},
},
6)使用过 Vue SSR 吗?说说 SSR?(react+next框架的实现。vue+nuxt)
SSR也就是服务端渲染,也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回给客户端。
SSR有着更好的SEO、并且首屏加载速度更快等优点。不过它也有一些缺点,比如我们的开发条件会受到限制,服务器端渲染只支持beforeCreate和created两个钩子,当我们需要一些外部扩展库时需要特殊处理,服务端渲染应用程序也需要处于Node.js的运行环境。还有就是服务器会有更大的负载需求。
7)vue-loader是什么?使用它的用途有哪些?
vue文件的一个加载器,跟template/js/style转换成webpack可以识别的js模块。
8)请说下封装 vue 组件的过程
组件设计思路:降低组件和调用者之间的耦合度,组件设计好要接收的属性,属性变化的逻辑交给调用者去操作,通过插槽等方式增加组件的灵活性。
使用Vue.component方法注册组件。子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。
9)Vue中父子组件生命周期调用顺序说一下
组件的调用顺序都是先父后子,渲染完成的顺序是先子后父。
组件的销毁操作是先父后子,销毁完成的顺序是先子后父。
加载渲染过程
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount- >子mounted->父mounted
子组件更新过程
父beforeUpdate->子beforeUpdate->子updated->父updated
销毁过程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
10)虚拟 DOM 的优缺点?
提高性能: 比起直接操作真实dom性能消耗更少,虚拟dom可以做diff算法优化页面渲染
跨平台: 虚拟 DOM 本质上是 JavaScript 对象,而 DOM 与平台强相关,相比之下虚拟 DOM 可以进行更方便地跨平台操作,例如服务器渲染、weex 开发等等。
缺点:
无法进行极致优化: 虚拟 DOM可以满足绝大部分应用的性能需求,但在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化。
11)v-show 与 v-if 区别?
v-if是将元素删除来达到隐藏的效果
v-show是将元素display:none来达到隐藏的效果,频繁切换的使用v-show,不频繁切换的使用v-if
12)computed 和 watch 区别?
Computed:就是依赖其它值来计算出一个值,它根据依赖会自动缓存,依赖不变computed的值就不会重新计算
watch:监听属性,如果一个属性变化了,那么就执行一个函数(在函数中可以做一些复杂的逻辑),它不支持缓存,当我们需要深度监听对象中的属性时,可以打开deep:true选项,
当我们需要组件以挂载就调用一次watch方法,可以打开immediate:true选项
13)常用修饰符
@click.prevent="fun" : 阻止事件的默认行为 event.preventDefault()
@click.stop="fun" : 停止事件冒泡 event.stopPropagation()
@keyup.13="fun" :操作的是某个keycode值的健
@keyup.enter="fun" :操作的是enter键
<Event1 @click.native="showMsg3" /> //添加.native修饰符绑定原生事件
<Event1 @click="showMsg4"/> //绑定自定义事件
9.Vue与React的区别
1)相似处
1.都是构建用户界面的js框架
1.组件化: 都使用组件化编程思想编写项目
2.虚拟DOM: 内部都通过虚拟DOM提高效率
3.Props和ref: 组件间通信的基本方式
2)不同点
1.react是整体的思路的就是函数式,所以推崇纯组件,数据不可变,单向数据流。而vue声明式思想,所以数据是可变的,双向绑定,
2.vue多了指令系统,让模版可以实现更丰富的功能,而React需要使用JSX自己实现;
3.react整体的生态比起vue更完整点,对ts的支持更好
面试题
1.谈谈对vue生命周期的理解
2.vue组件间的通信方式?
3.路由
1)什么是路由?
2)路由分类
3)keep-alive 组件有什么作用?
4)谈谈对路由守卫的了解?!
5)外链样式页面刷新页面样式丢失问题?
6)$route和$router的区别
6)vue-router 路由钩子函数是什么 执行顺序是什么!
6)路由组件
6)源码
1.install()方法的实现
2.router-view和router-link的实现
4.vuex
1)vuex有什么用?
2)vuex核心对象store的五大配置对象有什么用
3)vuex的执行流程
4)介绍一下 Vuex的 Action和Mutation的区别吗?
5)ajax请求代码应该写在组件的methods中还是vuex的actions中
5)Redux和vuex有什么区别?
5)源码
state和getter实现原理
5.源码
1)Vue响应式原理和数据双向绑定原理!
2)模板解析
3)diff的策略是什么?
4)diff算法
5)watch的实现原理
6)computed实现原理
8)组件的解析!
9)生命周期的合并(ximin)
10)$set()方法的实现
11)Vue.observable()方法的实现
12)Vue.use()方法的实现
13)Vue事件绑定原理说一下
14)vue的$nextTick
15)v-modal实现原理
6.其它
1)你对MVVM的理解?
2)组件中的data为什么是一个函数?
3)vue的key
4)为什么V-for和v-if不 能连用
5)自定义组件使用v-modal
6)使用过 Vue SSR 吗?说说 SSR?
7)vue-loader是什么?使用它的用途有哪些?
8)请说下封装 vue 组件的过程!
9)Vue中父子组件生命周期调用顺序说一下
10)虚拟 DOM 的优缺点?!
11)v-show 与 v-if 区别?
12)computed 和 watch 区别?
13)常用修饰符!
7.Vue与React的区别!
1)相似处
2)不同点
标签:面试题,vue,调用,Vue,vue2,组件,路由,属性 From: https://www.cnblogs.com/lxxxxStar/p/16821366.html