vue相关面试题
Vue响应式?
- Vue响应式指的是:组件的data发生变化,立刻触发试图的更新
- 实现原理: Vue 采用数据劫持结合发布者-订阅者模式的方式来实现数据的响应式,通过Object.defineProperty来劫持数据的setter,getter,在数据变动时发布消息给订阅者,订阅者收到消息后进行相应的处理。
vue生命周期?
- beforeCreate:Vue实例创建之前会执行它,此时data和methods中的数据或方法还未初始化,无法调用,只能使用一些默认事件。
- created:Vue实例化之后执行的,此时data和methods已经初始化完成了,可以供我们调用,但是模板还没有编译,也就是我们还不能获取到DOM。
- beforeMount:模板渲染之前调用,也就是DOM节点挂载到真实DOM树之前调用。此模板进行编译,会调用render函数生成vDom,也就是虚拟DOM,此时我们同样无法获取DOM节点。
- mounted:模板编译好了,而且挂载到真实DOM树上面去了,也就是我们的页面可以显示了。
- beforeUpdate:data数据发生变化之后调用,此时data里面的数据已经是最新的了,但是页面上DOM还没有更新最新的数据。注意:不要在updated中修改data数据,很容易造成死循环。
- updated:data数据更新之后执行,而且此时页面也渲染更新完成了,显示的就是最新的数据。
- beforeDestroy:Vue组件实例销毁之前,此时组件实际上还没有被销毁,还可以正常使用。我们通常会在这个钩子函数里面解除一些全局或者自定义事件。
- destroyed:组件实例销毁之后执行,此时所有的组件包括子组件都被销毁了。
- activated和deactivated是路由组件所独有的两个钩子,用于捕获路由组件的激活状态
- activated:页面渲染的时候执行。
- deactivated:页面被隐藏或者页面即将被替换成新的页面时被执行。
组件通信?
- props:父子
- 插槽:父子
- 自定义事件($emit):子父
- 全局事件总线$bus:万能
- Vuex:万能
- $ref:父子通信
Vuex?
- Vuex其实就是一个为Vue.js设计的数据仓库,就是把各个组件公用的数据放到一个仓库里面进行统一的管理.
- state:存数据的地方。
- Actions:Actions不能直接更改数据,它的作用是提交Mutations。
- Mutations:唯一能够修改数据的方法就是提交mutation,简单来说mutations里面存的就是一些操作数据的方法。
- Getter:store的计算属性,就和computed差不多。
- mapState方法:用于帮助映射state中的数据为计算属性
- mapGetters方法:用于帮助映射getters中的数据为计算属性
- mapActions方法:用于帮助生成与actions对话的方法,即包含$store.dispatch(xxx)的函数
- mapMutations方法:用于帮助生成与mutations对话的方法,即包含$store.commit(xxx)的函数
router与route?
- 每个路由组件都有自己的$route属性,里面存储着自己的路由信息。
- 整个应用只有一个router,可以通过组件的$router属性获取到。
vue-router?
// 全局前置守卫:初始化时、每次路由切换前执行
router.beforeEach((to,from,next) => {})
// 全局后置守卫:初始化时、每次路由切换后执行
router.afterEach((to,from,next) => {})
// 独享守卫
beforeEnter(to,from,next){}
// 组件内守卫
//进入守卫:通过路由规则,进入该组件时被调用
beforeRouteEnter (to, from, next) {... next()},
//离开守卫:通过路由规则,离开该组件时被调用
beforeRouteLeave (to, from, next) {... next()},
Vue的单向数据流?
- Vue 的单向数据流:指数据⼀般从⽗组件传到⼦组件,⼦组件没有权利直接修改⽗组件传来的数据,即⼦组件从 props 中直接获取的数据,只能请求⽗组件修改数据再传给⼦组件。⽗级属性值的更新会下⾏流动到⼦组件中。
- 为什么不能⼦组件直接修改⽗组件传来的值呢? ⽗组件的值可能会不断发⽣变化,那么如果我们⼦组件对⽗组件传来的值⽐如说 props 有⼀个 number,⼦组件收到了 number=1,在收到后,⼦组件直接改变number 的值为 5,去做些事情,但还未做时⽗组件数据更新了,传过 来⼀个值 3,也就是说⼦组件刚将其变为 5,⽗组件⼜把它变成了 3,可能影响⼦组件的使⽤。说的官⽅⼀些,就是⽗组件的值更新时,⼦组件中 props 的值也会发⽣更新。
- 在⼦组件中直接⽤ v-model 绑定⽗组件传过来的数据是不合理的,如果希望修改⽗组件传给⼦组件的值:
(1)在⼦组件 data 中创建⼀个变量获取 props 中的值,再改变这个 data 中的值。
(2)⼦组件使⽤ $emit 发出⼀个事件,让⽗组件接收去修改这个值。
$listeners与$attrs
父组件中未被props(v-on)绑定的属性(事件) 可以在子组件中,通过 $attrs , $listeners 获取。
v-model?
v-model其实是一个语法糖,他背后的本质上是包含两个操作
- v-bind绑定一个value属性
- v-on指令给当前元素绑定input事件
事件修饰符
- .stop:阻止冒泡(阻止事件向上级dom元素传递)。
- .prevent:阻止默认事件的发生。
- .captrue:捕获冒泡。
- .self:将事件绑定到自身,只有自身才能触发。通常用于避免冒泡事件的影响。
- .once:设置事件只能触发一次。
- .passive:用于对dom的默认事件进行性能优化
- .native:在父组件中给子组件绑定一个原生事件,就将子组件变成普通的html标签。
Diff算法?
同级比较,深度优先。
- 两两交叉比较,首尾相比是sameVnode,则patchVnode(也有可能首尾相同,则还需要移动到对应DOM队首或尾)。
首尾没有相同,则在OldVnode 中查找与newStar 相同的sameVnode:
2.1 存在执行patchVnode,同时将VnodeToMove 移动到对应的OLdVnodeStar 前面。
2.2 若不存在这时候调用CreateElm 创建一个新的DOM 节点。循坏结束:
- oldStar > oldEnd 说明旧的Vnode 遍历完,新的有剩余,将剩下的VNode对应的DOM插入到真实DOM中,此时调用addVnodes(批量调用createElm接口);
- 当结束时newStartIdx > newEndIdx时,说明新的VNode节点已经遍历完了,但是老的节点还有 剩余,需要从文档中删 的节点删除。