Vue.js 一个核心思想是数据驱动。所谓数据驱动,是指视图是由数据驱动生成的,我们对视图的修改,不会直接操作 DOM,而是通过修改数据。他相比我们传统的前端开发,如使用 jQuery 等前端库直接修改 DOM,大大简化了代码量。特别是当交互复杂的时候,只关心数据的修改会让代码逻辑变得非常清晰,因为 DOM 变成了数据的映射,我们所有的逻辑都是对数据的修改

new vue 发生了什么

src/core/instance/index.js

initMixin 注册_init 方法

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')

挂载
vm.$mount(vm.$options.el)

mounted 里如何访问 data 里的数据
initState() -> initData()
data 也会赋值给 _data

proxy((target: Object), (sourceKey: string), (key: string)) {}

//initData方法里调 proxy()
initData(vm: Component) {
  data = vm._data = typeof data === 'function'
    ? getData(data, vm)
    : data || {}

  const keys = Object.keys(data)
  // ...
  proxy(vm, `_data`, key)

  // 数据响应式处理
  observe(data ,true)
}

vue 实例挂载的实现

Vue 中我们是通过 $mount 实例方法去挂载 vm 的,$mount 方法在多个文件中都有定义src/platforms/web/entry-runtime-with-compiler.jssrc/platform/web /runtime/index.jssrc/platfrom/weex/runtime/index.js。因为 $mount这个方法是和平台、构建方式都相关的。接下来重点分析 compiler 版本的$mount 实现,因为抛开 webpack 的 vue-loader,我们在纯前端环境分 Vue 的工作原理,有助于我们对原理理解的深入。

complier 版本的 $mount 实现非常有意思,先来看下
src/platforms/web/entry-runtime-with-compiler.js 文件中的定义

new Watcher() 渲染 watcher
定义 src/core/observer/watcher.js

调用 updateComponent

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

render

vm._render 返回的是 VNode

vm.renderProxy 在生产环境就是 vm

createElement