程序员

7天深入Vue-vue源码浏览,初始化流程(四)

2021-02-15  本文已影响0人  申_9a33

术语解释:

初始化流程

  // Runtime+compiler CommonJS build (CommonJS)
  'web-full-cjs-dev': {
    entry: resolve('web/entry-runtime-with-compiler.js'),
    dest: resolve('dist/vue.common.dev.js'),
    format: 'cjs',
    env: 'development',
    alias: { he: './entity-decoder' },
    banner
  },

web/entry-runtime-with-compiler.js 为浏览器版本的入口文件 ,解析到的路径为 src/platforms/web/entry-runtime-with-compiler.js

const mount = Vue.prototype.$mount
Vue.prototype.$mount = function (

此处根据浏览器扩展$mount方法

import { mountComponent } from 'core/instance/lifecycle'
// public mount method
Vue.prototype.$mount = function (
  el?: string | Element,
  hydrating?: boolean
): Component {
  el = el && inBrowser ? query(el) : undefined
  return mountComponent(this, el, hydrating)
}

此处为Vue原本的挂在方法,实现在core/instance/lifecycle

callHook(vm, 'beforeMount')

    updateComponent = () => {
      vm._update(vm._render(), hydrating)
    }

  new Watcher(vm, updateComponent, noop, {
    before () {
      if (vm._isMounted && !vm._isDestroyed) {
        callHook(vm, 'beforeUpdate')
      }
    }
  }, true /* isRenderWatcher */)

callHook(vm, 'mounted')
function Vue (options) {
  if (process.env.NODE_ENV !== 'production' &&
    !(this instanceof Vue)
  ) {
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  this._init(options)
}
import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'

initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
import { initLifecycle, callHook } from './lifecycle'

    vm._self = vm
    initLifecycle(vm) /
    initEvents(vm)
    initRender(vm)
    callHook(vm, 'beforeCreate')
    initInjections(vm) // resolve injections before data/props
    initState(vm)
    initProvide(vm) // resolve provide after data/props
    callHook(vm, 'created')

    /* istanbul ignore if */
    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
      vm._name = formatComponentName(vm, false)
      mark(endTag)
      measure(`vue ${vm._name} init`, startTag, endTag)
    }

    if (vm.$options.el) {
      vm.$mount(vm.$options.el)
    }
  const options = vm.$options

  // locate first non-abstract parent
  let parent = options.parent
  if (parent && !options.abstract) {
    while (parent.$options.abstract && parent.$parent) {
      parent = parent.$parent
    }
    parent.$children.push(vm)
  }

  vm.$parent = parent
  vm.$root = parent ? parent.$root : vm

  vm.$children = []
  vm.$refs = {}

  vm._watcher = null
  vm._inactive = null
  vm._directInactive = false
  vm._isMounted = false
  vm._isDestroyed = false
  vm._isBeingDestroyed = false

vm.$parent = parentvm.$root = parent ? parent.$root : vm;找到根节点和父节点,其他则是将Vue的属性置为空数据

看示例

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue.js"></script>
</head>

<body>
    <div id="app">
        {{foo.bar}}
    </div>


    <script>
        const vm = new Vue({
            data: {
                foo: {
                    bar: "123"
                }
            },
            el: "#app"
        })
    </script>
</body>

</html>

观察上述代码,什么时候会渲染到真实Dom之上的

1.断点打到src\core\instance\index.js Vue的构造器

捕获.PNG

2.第二个断点打在src\core\instance\init.js

捕获.PNG

3.src\platforms\web\entry-runtime-with-compiler.js

捕获.PNG

4.src\platforms\web\runtime\index.js

捕获.PNG

5.src\core\instance\lifecycle.js

捕获.PNG
代码会先执行197行,然后内部调用``updateComponent`执行190行,就会看到界面渲染完成,整个Vue初始化完成
上一篇 下一篇

猜你喜欢

热点阅读