Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue2.0原理-模板解析 #12

Open
some-code opened this issue Jun 13, 2018 · 0 comments
Open

Vue2.0原理-模板解析 #12

some-code opened this issue Jun 13, 2018 · 0 comments
Labels

Comments

@some-code
Copy link
Owner

下面这段代码,vue内部做了什么操作?我去源码里面找找看

new Vue({
    el: '#app'
})

入口

vue 的入口文件在 src/core/instance/index.js, 里面一进来就执行了很多初始化的操作。

import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/index'

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

initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)

export default Vue

进入 initMixin 方法看看,这个方法内部只做了一件事,定义 Vue.prototype._init , 这个 _init 方法又做了什么呢?

...
// 各种初始化开始
initProxy(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')
// 各种初始化完毕
...
// 解析模板
if (vm.$options.el) {
  vm.$mount(vm.$options.el)
}

解析

进入 src/platforms/web/entry-runtime-with-compiler.js 文件,看看 $mount 方法是怎么处理模板的。

  • 判断 el 是否为body或者html根节点,是的话,提示错误。
  if (el === document.body || el === document.documentElement) {
    process.env.NODE_ENV !== 'production' && warn(
      `Do not mount Vue to <html> or <body> - mount to normal elements instead.`
    )
    return this
  }
  • 如果没有render函数,则开始解析模板
// 模板也分为多种
1,当使用 template 属性时,支持:
    1.1, 字符串模板
    1.2,一个script模板的id
    1.3,一个dom对象

2,当使用 el 属性时,获取对应dom的outerHTML 作为template

  • 调用 src/compiler/index.js 对模板进行AST解析和静态优化,并重建render方法

对于模板解析,这篇文章分析的很详细 Vue 模板编译原理

  • 在解析完模板之后,调用的是 runtime/index.js 中的 $mount 方法。

$mount 方法调用 src/core/instance/lifecycle.js 中的 mountComponent 方法

mountComponent() {
    // 1,经过上面的一系列初始化动作,render肯定已经有了,如果没有,返回一个节点并警告。
    callHook(vm, 'beforeMount')
    // 2,通过vm._render()方法把模板转化成vNode
    // 3,通过vm._update()更新dom节点
    callHook(vm, 'mounted')
}

和VUE1的区别

在vue1.0种,模板的解析是通过 createDocumentFragment 对dom进行代理实现的,到了2.0时代,考虑到服务端渲染,采用了jquery作者开发的 html-parse 库进行字符串模板解析。

@some-code some-code added the vue label Jun 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant