学习Vue源码之前要先打基础--概念解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 在学习源码之前,我们需要了解这么几个东西的概念。什么是AST、什么是render函数、什么是模板等等

网络异常,图片无法展示
|


在学习源码之前,我们需要了解这么几个东西的概念。什么是AST、什么是render函数、什么是模板等等。。。


前提概念


AST语法树


Abstract Syntax Tree。抽象语法树,用js语言来描述html代码。将html代码筛选出我们需要的属性,转成js语言。


<div id="app" style="color: red">
    <p class="text">文本</p>
</div>
// ast语法树  描述html语法
<script>
let root = {
    tag: 'div',
    type: 1,
    attrs: [
    { name: "id", value: "app" },
    { name: "style",value: {color: " red"} }
    ],
    parent: null,
    children: [{
        tag: 'p',
        attrs: [{ name: 'class', value: 'text' }],
        parent: root,
        type: 1,
        children: [{
            text: '文本',
            type: 3
        }]
    }]
}
</script>


模板template


template:基于html的字符串模板。优先级高于原始html模板。


渲染函数render


render:模板的代替,相比较模板更接近编译器。在vue中,如果render存在,template模板字符串将不会挂载到元素中渲染。


html模板、字符串模板、render函数比较


大家可以先看一下vue最初的使用:


html

<div id="app">
   <ul>
      <li v-for="item in sex" v-if="item==='男'">{{item}}</li>
    </ul>
</div>
<script>
  let vm = new Vue({
    el: '#app',
    data: {
      sex: ["男", "男", "女", "男"]
    },
  })
 console.log(vm.$options.render);
</script>


template模板:


<div id="app"></div>
<script>
  let vm = new Vue({
    el: '#app',
    template:
        `<ul>
          <li v-for="item in sex" v-if="item==='男'">{{item}}</li>
        </ul>`,
    data: {
      sex: ["男", "男", "女", "男"]
    },
  })
 console.log(vm.$options.render);
</script>


运行浏览器,两者页面上出现的均是男字。但是在template模板中,在html中写入其他的东西是无法显示的。说明如果模板存在,那么优先渲染template中的内容。

而在控制台输出vm.$options.render,可以看到这么一串东西:


ƒ anonymous(
) {
with(this){return _c('div',{attrs:{"id":"app"}},[_c('ul',_l((sex),function(item){return (item==='男')?_c('li',[_v(_s(item))]):_e()}),0)])}
}


这一串的东西就是将我们html中的内容转成用js语言描述的模样。当然我们也可以将这一串东西转成vue中的render函数,试一试浏览器运行。


<div id="app">hhh</div>
<script>
  let vm = new Vue({
    el: '#app',
    data: {
      sex: ["男", "男", "女", "男"]
    },
    render(h) {
      with (this) {
        return _c('div', { attrs: { "id": "app" } }, [_c('ul', _l((sex), function (item) { return (item === '男') ? _c('li', [_v(_s(item))]) : _e() }), 0)])
      }
    },
  })
</script>

网络异常,图片无法展示
|


对于render函数里面的_l_e_v等这些函数可以参考源码中定义的作用。


target._o = markOnce // v-once
target._n = toNumber  // 转数字
target._s = toString  // 转字符串 JSON.stringify
target._l = renderList // 循环 v-for
target._t = renderSlot  // 插槽 slot
target._v = createTextVNode // 文本节点
target._e = createEmptyVNode // 空节点
...


此外还有一个_c函数是创建虚拟节点(createElement)。


事实证明:


render函数可以代替模板,并且render的优先级高于template模板,template模板优先级高于原始的html


jsx


相比较render内部一长串的东西,我们可能难于理解。相对应的模板会比较简单一些。 Vue中支持使用jsx就是因为vue中的Babel插件


let vm = new Vue({
  el: '#app',
  data: {
    sex: ["男", "男", "女", "男"]
  },
  render() {
    return <ul>
      <li v-for="item in sex" v-if="item==='男'">{{ item }}</li>
    </ul>
  }
})


真实DOM


页面上的每个元素都算一个节点。 例子:


<div id="app" style="color: red">
    <p class="text">文本</p>
</div>
复制代码


虚拟DOM


简化DOM节点的。通过渲染函数的_c_v 等函数实现用对象来描述dom的操作。虚拟DOM将真实DOM简化,包含tag,data,key,children,text等属性。


<div id="app" style="color: red">
    <p class="text">文本</p>
</div>
// 虚拟dom
<script>
let root = {
  tag: 'div',
  data: [{ id: 'app', style: { color: 'red' } }],
  key:undefined,
  text:undefined,
  children:[
    {
        tag: 'p',
        key:undefined,
        text:undefined,
        data:{class:'text'},
        children: []
  ]
}
</script>


编译


简要说明一下编译渲染过程:


  • 解析html字符 将html字符 => AST语法树
  • 需要将AST语法树生成最终的render函数
  • 拼接字符串
  • 增加with
  • new Function
  • 生成虚拟dom
  • 生成真实dom


在编译的过程中,我们需要将html转成AST语法树再转成render虚拟dom。其实普通的编译也可直接从render转虚拟dom


只是在vue的编译过程中,在转成AST时,需要根据模板处理插值、指令,进行一些优化标记,提取出最大静态树(固定不变),把DOM操作次数减到最少。

网络异常,图片无法展示
|


AST和虚拟DOM(VNode)两者都是js语言,不同:


  • 两者出现的时机不同,AST出现在编译过程;虚拟DOM出现在运行时。
  • AST就相当于虚拟DOM的前身,经过一些列操作后变成虚拟DOM。
  • 可以对比两者结构,虽然相似,但是我们可以明显看到虚拟dom没有attrs属性,虚拟dom将ast中的attrs放到了相应节点中。比如,attr中的style属性,在虚拟dom中放到了相对应的元素data中,转化成了元素节点的style。
目录
相关文章
|
13天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
13天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
13天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
2月前
|
缓存 监控 Java
Java线程池提交任务流程底层源码与源码解析
【11月更文挑战第30天】嘿,各位技术爱好者们,今天咱们来聊聊Java线程池提交任务的底层源码与源码解析。作为一个资深的Java开发者,我相信你一定对线程池并不陌生。线程池作为并发编程中的一大利器,其重要性不言而喻。今天,我将以对话的方式,带你一步步深入线程池的奥秘,从概述到功能点,再到背景和业务点,最后到底层原理和示例,让你对线程池有一个全新的认识。
57 12
|
1月前
|
PyTorch Shell API
Ascend Extension for PyTorch的源码解析
本文介绍了Ascend对PyTorch代码的适配过程,包括源码下载、编译步骤及常见问题,详细解析了torch-npu编译后的文件结构和三种实现昇腾NPU算子调用的方式:通过torch的register方式、定义算子方式和API重定向映射方式。这对于开发者理解和使用Ascend平台上的PyTorch具有重要指导意义。
|
1月前
|
调度 开发者
核心概念解析:进程与线程的对比分析
在操作系统和计算机编程领域,进程和线程是两个基本而核心的概念。它们是程序执行和资源管理的基础,但它们之间存在显著的差异。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
57 4
|
14天前
|
安全 搜索推荐 数据挖掘
陪玩系统源码开发流程解析,成品陪玩系统源码的优点
我们自主开发的多客陪玩系统源码,整合了市面上主流陪玩APP功能,支持二次开发。该系统适用于线上游戏陪玩、语音视频聊天、心理咨询等场景,提供用户注册管理、陪玩者资料库、预约匹配、实时通讯、支付结算、安全隐私保护、客户服务及数据分析等功能,打造综合性社交平台。随着互联网技术发展,陪玩系统正成为游戏爱好者的新宠,改变游戏体验并带来新的商业模式。
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
88 2
|
3月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
87 0
|
3月前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
69 0