一、基础

1、使用 this.$forceUpdate(); 强制更新数据, computed里面的数据不会变化。
2、vue是单项数据流,不要在子组件里面更改父组件的数据,应该通过父组件的属性里面绑定一个函数,在子组件里面调用该函数,把数据传回父组件,然后在父组件里更改数据;
3、vue2.6版本的slot插槽使用和2.5的已经不一样了。但是还是兼容之前的使用方式。

  1. // 2.6版本的
  2. <template v-slot:item="props">
  3. <p>item slot-scope {{ props }}</p>
  4. </template>
  5. // 2.5版本的
  6. <p slot="item" slot-scope="props">item slot-scope {{ props }}</p>

4、vue2.4版本新增了inheritAttrs属性,当父组件传过来的数据,子组件没有在html中使用时,该变量会默认挂载到子组件的元素上,设置inheritAttrs为false时,就不会挂载了。应用场景?
5、子组件发射事件时,可以传递一个函数,在父组件接受到值后再回调。

  1. // 子组件
  2. this.$emit("change", e.target.value, val => {
  3. console.log(val);
  4. });
  5. 父组件
  6. handleEventChange(val, callback) {
  7. this.name = val;
  8. callback("hello");
  9. }

6、函数式组件:
functional:true
特征: 无状态、无实例、没有this上下文、无生命周期
7、指令的执行顺序:
创建时:beforeCreate
data
created
beforeMount
render
bind // 组件render后,开始执行指令的bind
mounted
inserted // 组件mounted后,开始执行指令的inserted
更新时:update // 执行指令的update方法
componentUpdated // 执行指令的componentUpdated 方法
beforeUpdate
render
updated
销毁时:beforeDestroy
destroyed
unbind // 执行指令的unbind方法
8、Vue.observable,创建一个响应对象。以前只有当实例被创建时 data 中存在的属性才是响应式
9、vue响应式原理和依赖收集

  1. function isObject (obj) {
  2. return typeof obj === 'object'
  3. && !Array.isArray(obj)
  4. && obj !== null
  5. && obj !== undefined
  6. }
  7. function observe (obj) {
  8. if (!isObject(obj)) {
  9. throw new TypeError()
  10. }
  11. Object.keys(obj).forEach(key => {
  12. let internalValue = obj[key]
  13. let dep = new Dep()
  14. Object.defineProperty(obj, key, {
  15. get () {
  16. dep.depend()
  17. return internalValue
  18. },
  19. set (newValue) {
  20. const isChanged = internalValue !== newValue
  21. if (isChanged) {
  22. internalValue = newValue
  23. dep.notify()
  24. }
  25. }
  26. })
  27. })
  28. }
  29. window.Dep = class Dep {
  30. constructor () {
  31. this.subscribers = new Set()
  32. }
  33. depend () {
  34. if (activeUpdate) {
  35. // register the current active update as a subscriber
  36. this.subscribers.add(activeUpdate)
  37. }
  38. }
  39. notify () {
  40. // run all subscriber functions
  41. this.subscribers.forEach(subscriber => subscriber())
  42. }
  43. }
  44. let activeUpdate
  45. function autorun (update) {
  46. function wrappedUpdate () {
  47. activeUpdate = wrappedUpdate
  48. update()
  49. activeUpdate = null
  50. }
  51. wrappedUpdate()
  52. }
  53. const state = {
  54. count: 0
  55. }
  56. observe(state)
  57. autorun(() => {
  58. console.log(state.count)
  59. })
  60. // should immediately log "count is: 0"
  61. state.count++

二、原理

new Vue 发生了什么

执行了初始化方法_init();
合并参数;

  1. // 各种初始化
  2. vm._self = vm
  3. initLifecycle(vm) // $parent/$root
  4. initEvents(vm) // 自定义事件监听
  5. initRender(vm) // $slots/$createElement
  6. callHook(vm, 'beforeCreate')
  7. // 获取祖辈注入的数据
  8. initInjections(vm) // resolve injections before data/props
  9. initState(vm) // 数据状态初始化:data/props/methods/computed/watch
  10. // 给后代提供数据
  11. initProvide(vm) // resolve provide after data/props
  12. callHook(vm, 'created')
  13. // 选项如果有el,自动执行$mount
  14. if (vm.$options.el) {
  15. vm.$mount(vm.$options.el)
  16. }

说一下数据响应式

在new Vue 中执行 initState(vm)的时候,遍历data并做响应式处理,
通过Object.defineProperty添加属性拦截,每一个属性会创建一个Dep,
在get的时候通过闭包的方式把依赖添加到之前创建的dep里面,从而对依赖进行收集,
在set的时候通知会通知各个watcher去更新视图;

keep-alive原理

根据组件id和tag 设置缓存的key值, value值用组件的vnode, 用 activeted deactived 钩子 , 如果组件已经缓存到队列里面了,会先删除缓存里面那个缓存的值,然后再把新的值更新到队列最后面, 有最大的缓存值

$nextTick 原理

vue里面set了一个数据后,不会马上更新视图,而是放到一个watcher里面,nextTick里面的方法也会放到watcher里面,用于created的时候操作dom元素,里面的实现主要有三个promise.then mutationObsive, setTimeout

Vue中的diff原理

Vue的diff算法是平级比较,不考虑跨级别比较的情况。内部采用深度递归的方式+双指针的方式进行比较;
1、先比较是否是相同的节点
2、相同节点比较属性,并复用老节点
3、比较儿子节点,考虑老节点和儿子节点的情况
4、优化比较:头头、尾尾、头尾、尾头
5、比对查找进行复用

三种类型的Watcher对象

Watcher分为三种,按创建的先后顺序为:计算属性的Watcher、用户Watcher(监听器)、渲染Watcher,执行的顺序也是一样的。

三、vue周边

vuex

state: 提供一个响应式数据
getter: 借助vue的计算属性computed来实现缓存
mutation: 更改state方法
action: 触发mutation
module: vue.set动态添加state到响应式数据中

微信图片_20190424184932.png
如上图所示:vue-devtool会监测mutation里面的数据改变并做记录,因此只能在mutation里面更改state的数据。
boforeCreate中混入$store的获取方式
问:为什么需要action?
用于异步操作,异步代码放在一个地方,便于复用

vue-router

  • hash模式 丑,无法使用锚点定位
  • history 需要后端配合,ie9不兼容(可使用强制刷新处理)

    原理:

image.png

vue.util.defineReactive为响应式数据

SPA 缺点
1、不利于seo
2、首屏渲染时间长

nuxt 优点
1、静态站点
2、动态渲染
3、简化配置

ssr 核心原理
无头浏览器渲染

四、vue2.x实现hoc功能