# vue相关面试题

# Vue响应式？
1. Vue响应式指的是：组件的data发生变化，立刻触发试图的更新 
2. 实现原理： 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？
1. 每个路由组件都有自己的$route属性，里面存储着自己的路由信息。
2. 整个应用只有一个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的单向数据流？
1. Vue 的单向数据流：指数据⼀般从⽗组件传到⼦组件，⼦组件没有权利直接修改⽗组件传来的数据，即⼦组件从 props 中直接获取的数据，只能请求⽗组件修改数据再传给⼦组件。⽗级属性值的更新会下⾏流动到⼦组件中。
2. 为什么不能⼦组件直接修改⽗组件传来的值呢？
⽗组件的值可能会不断发⽣变化，那么如果我们⼦组件对⽗组件传来的值⽐如说 props 有⼀个 number，⼦组件收到了 number=1，在收到后，⼦组件直接改变number 的值为 5，去做些事情，但还未做时⽗组件数据更新了，传过
来⼀个值 3，也就是说⼦组件刚将其变为 5，⽗组件⼜把它变成了 3，可能影响⼦组件的使⽤。说的官⽅⼀些，就是⽗组件的值更新时，⼦组件中 props 的值也会发⽣更新。
3. 在⼦组件中直接⽤ 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算法？
同级比较，深度优先。 
1. 两两交叉比较，首尾相比是sameVnode,则patchVnode(也有可能首尾相同，则还需要移动到对应DOM队首或尾)。
2. 首尾没有相同，则在OldVnode 中查找与newStar 相同的sameVnode： 
> 2.1 存在执行patchVnode,同时将VnodeToMove 移动到对应的OLdVnodeStar 前面。                                                                                                   
> 2.2 若不存在这时候调用CreateElm 创建一个新的DOM 节点。

3. 循坏结束： 

> - oldStar > oldEnd 说明旧的Vnode 遍历完，新的有剩余，将剩下的VNode对应的DOM插入到真实DOM中，此时调用addVnodes（批量调用createElm接口）；
> - 当结束时newStartIdx > newEndIdx时，说明新的VNode节点已经遍历完了，但是老的节点还有 剩余，需要从文档中删 的节点删除。
