开发者社区> ClyingDeng> 正文

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

简介: 在学习源码之前,我们需要了解这么几个东西的概念。什么是AST、什么是render函数、什么是模板等等
+关注继续查看

image


在学习源码之前,我们需要了解这么几个东西的概念。什么是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>

image


对于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操作次数减到最少。

image


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


  • 两者出现的时机不同,AST出现在编译过程;虚拟DOM出现在运行时。
  • AST就相当于虚拟DOM的前身,经过一些列操作后变成虚拟DOM。
  • 可以对比两者结构,虽然相似,但是我们可以明显看到虚拟dom没有attrs属性,虚拟dom将ast中的attrs放到了相应节点中。比如,attr中的style属性,在虚拟dom中放到了相对应的元素data中,转化成了元素节点的style。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
ES6的新特性----Vue学习必备基础知识
学习Vue之前,ES6的基础常识是必须要了解的,下面列举了几种最重要的特性,学会了这些,Vue的学习就易如反掌了。 1.变量声明const和let 在ES6之前,我们都是用var关键字声明变量。
1082 0
解析Vue.js中的computed工作原理
我们通过实现一个简单版的和Vue中computed具有相同功能的函数来了解computed是如何工作的。写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下。
751 0
vue学习笔记1-基本知识
1.npm 安装node.js的时候会一起安装npm包管理器,能够解决nodejs代码部署问题,常见使用如下: 允许用户从npm服务器下载别人编写的第三方包到本地应用允许用户从npm服务器下载并安装别人编写的命令行程序到本地使用允许将自己编写的包或命令上传到npm服务器上供别人使用 新版的nodejs已经集成npm,安装好nodejs之后使用npm -v命令检查是否安装成功。
928 0
学习Vue源码之前要先打基础--概念解析
在学习源码之前,我们需要了解这么几个东西的概念。什么是AST、什么是render函数、什么是模板等等
23 0
学习VUE3总得知道Proxy怎么使用吧
学习VUE3总得知道Proxy怎么使用吧
33 0
vue observer 源码学习
一、版本:2.5.9 二、建议       vue最重要的应该就是响应式更新了,刚开始接触vue或多或少都能从官方文档或者其他地方知道vue响应式更新依赖于Object.defineProperty()方法,这个方法在MDN上有详细讲解,不过,如果是初学者的话,直接去看响应式更新源码还有点难度的,最好是先用项目练一遍,对vue有个相对熟悉的了解,然后可以去各大热门讲解的博客上看看人家的讲解,这样汇总一番有点底子了再去看源码实现相对轻松点。
1534 0
源码解析——VUE
源码解析——VUE
38 0
SPRING03_为什么要学习源码、基础的接口、SPRING工作流程详解
①. 为什么要学习源码? ②. Spring基础接口 ③. Spring的工作流程详解
30 0
+关注
ClyingDeng
前端开发
95
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载