资讯专栏INFORMATION COLUMN

Vue源码解析(1)-模版渲染

k00baa / 928人阅读

摘要:首先在里调用函数把获取相应传递过去里在原型上定义方法对浏览器的怪癖做兼容布尔值。对浏览器的怪癖做兼容布尔值。

首先在init.js里调用$mount函数
把el #app获取相应dom传递过去

Vue.prototype._init = function (options) {
   ...
   if (vm.$options.el) {
      vm.$mount(vm.$options.el)
    }   
}

entry-runtime-with-compiler.js里在Vue原型上定义$mount方法

Vue.prototype.$mount = function (
  el,
  hydrating
) { 
       let template = options.template
       template = idToTemplate(template)
       const { render, staticRenderFns } = compileToFunctions(template , {
        shouldDecodeNewlines, // 对浏览器的怪癖做兼容,布尔值。
        shouldDecodeNewlinesForHref, // 对浏览器的怪癖做兼容,布尔值。
        delimiters: options.delimiters, //vue透传
        comments: options.comments //vue透传
      }, this)
 } 

template(64)和 render(72), staticRenderFns(73) 对应图中所示

render是渲染函数,staticrenderfns是静态树的渲染函数

//render
function anonymous(
) {
with(this){return _c("div",[_c("h1",{staticStyle:{"color":"red"}},[_v("我是选项模板3")]),_v(" "),_c("p",[_v(_s(number))]),_v(" "),_c("p",[_v(_s(message))]),_v(" "),_m(0)])}
}  
//staticrenderfns
function anonymous(
) {
with(this){return _c("div",[_c("div",[_v("
          1
          "),_c("div",[_v("11")]),_v(" "),_c("div",[_v("12")])]),_v(" "),_c("div",[_v("2")]),_v(" "),_c("div",[_v("3")]),_v(" "),_c("div",[_v("4")]),_v(" "),_c("div",[_v("5")])])}
}
//template

children多的放进了staticrenderfns 其余的放进了render 至于为什么这么做,传送门
从ast到render过程

compileToFunctions来源
platform文件下 compiler文件 index.js文件

const { compile, compileToFunctions } = createCompiler(baseOptions)

createCompiler来源
core文件下 compiler文件 index.js文件

export const createCompiler = createCompilerCreator(function baseCompile (
  template,
  options
) {
  // 使用 parse 函数将模板解析为 AST
  const ast = parse(template.trim(), options)
 
  // ast对象进行优化,找出ast对象中所有静态子树
  if (options.optimize !== false) {
    optimize(ast, options)
  }
  // 根据给定的AST生成最终的目标平台的代码
  const code = generate(ast, options)
  return {
    ast,
    render: code.render,
    staticRenderFns: code.staticRenderFns
  }
})

createCompilerCreator来源
creact-compiler.js下

export function createCompilerCreator (baseCompile) {
  return function createCompiler (baseOptions) {
    function compile (
      template,
      options
    ) {
      const finalOptions = Object.create(baseOptions)
    // 执行createCompilerCreator里传来的函数 生生ast等
      const compiled = baseCompile(template, finalOptions)
      compiled.errors = errors
      compiled.tips = tips
      return compiled
    }

    return {
      compile,
      compileToFunctions: createCompileToFunctionFn(compile)
    }
  }
}

compiled如下即

 return {
    ast,
    render: code.render,
    staticRenderFns: code.staticRenderFns
  }
compiled.errors = errors
compiled.tips = tips

总之,在$mount原型函数里面$mount
给 vue.options 挂载了 render和staticRenderFns
options.render = render
options.staticRenderFns = staticRenderFns

打印 options

挂在后需要渲染

lifecycle.js

mountComponent(){
   callHook(vm, "beforeMount")
   updateComponent = () => {
      vm._update(vm._render(), hydrating)
   }
   // 把更新组件加入依赖
   new Watcher(vm, updateComponent, noop, {
    before () {
      if (vm._isMounted) {
        callHook(vm, "beforeUpdate")
      }
    }
  }, true /* isRenderWatcher */)
}

vm._render()生成传说中的VNode,即虚拟dom

vm._render()执行函数结果

vm._update方法的实现

 Vue.prototype._update = function (vnode, hydrating) {
   // 判断vnode是否初始化过
    if (!prevVnode) {
      // initial render
      vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */)
    } else {
      // updates
      vm.$el = vm.__patch__(prevVnode, vnode)
    }
  }

通过__patch__更新

在 platform/web/runtime/index.js文件里执行了mountComponent方法

import { mountComponent } from "core/instance/lifecycle"


Vue.prototype.$mount = function (
  el,
  hydrating
) {
  el = el && inBrowser ? query(el) : undefined
  // 调用mountComponent方法
  return mountComponent(this, el, hydrating)
}

最终效果图

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97347.html

相关文章

  • vue源码阅读之数据渲染过程

    摘要:图在中应用三数据渲染过程数据绑定实现逻辑本节正式分析从到数据渲染到页面的过程,在中定义了一个的构造函数。一、概述 vue已是目前国内前端web端三分天下之一,也是工作中主要技术栈之一。在日常使用中知其然也好奇着所以然,因此尝试阅读vue源码并进行总结。本文旨在梳理初始化页面时data中的数据是如何渲染到页面上的。本文将带着这个疑问一点点追究vue的思路。总体来说vue模版渲染大致流程如图1所...

    AlphaGooo 评论0 收藏0
  • Vue源码解析(一)-模版渲染

    摘要:接下来我们分析下是如何调用的,这就涉及到了经典的机制此处先简单介绍,下一篇会有较详细的分析。 Vue demo 先给出vue简单的使用demo,通过创建一个Vue的实例,将被替换成template模版中的内容,a,b的值也会被换成data属性的值 var vm = new Vue({ el: #app, template: ` {{a}} {{b}} ...

    KitorinZero 评论0 收藏0
  • Vue源码解析模版字符串转AST语法树

    摘要:通过对源码阅读,想写一写自己的理解,能力有限故从尤大佬第一次提交开始读,准备陆续写模版字符串转语法树语法树转函数双向绑定原理虚拟比较原理其中包含自己的理解和源码的分析,尽量通俗易懂由于是的最早提交,所以和最新版本有很多差异,后续将陆续补充, 通过对 Vue2.0 源码阅读,想写一写自己的理解,能力有限故从尤大佬2016.4.11第一次提交开始读,准备陆续写: 模版字符串转AST语法...

    chengjianhua 评论0 收藏0
  • Vue源码解析模版字符串转AST语法树

    摘要:通过对源码阅读,想写一写自己的理解,能力有限故从尤大佬第一次提交开始读,准备陆续写模版字符串转语法树语法树转函数双向绑定原理虚拟比较原理其中包含自己的理解和源码的分析,尽量通俗易懂由于是的最早提交,所以和最新版本有很多差异,后续将陆续补充, 通过对 Vue2.0 源码阅读,想写一写自己的理解,能力有限故从尤大佬2016.4.11第一次提交开始读,准备陆续写: 模版字符串转AST语法...

    王伟廷 评论0 收藏0

发表评论

0条评论

k00baa

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<