一文搞懂vue编译器(DSL)原理

yizhihongxing

一、Vue编译器(DSL)的原理

在讲解Vue编译器(DSL)原理前,我们先来了解一下什么是DSL。

DSL(Domain Specific Language),中文名为领域特定语言。DSL是一个非常重要的概念,它是指针对某一领域的语言和工具,是一种非通用的语言,优点是极大地提高了效率,缺点是只有在特定的领域下才有用。

Vue编译器(DSL)原理,就是通过使用一种领域特定语言,在模板中的表达式、指令和属性等进行解析和编译,最终输出渲染函数(render函数),从而实现对组件的渲染。

在Vue.js中,模板被处理成了渲染函数(render函数),这个渲染函数返回的是虚拟DOM树,最终由Vue.js的核心层执行真实的DOM操作,更新页面。

而Vue编译器(DSL)就是实现了将模板解析成渲染函数的过程。Vue编译器(DSL)分为了三个阶段,分别是parse(解析)、optimize(优化)、generate(生成)。

二、Vue编译器(DSL)的实例

下面通过一个简单的实例来讲解Vue编译器(DSL)的应用。

<template>
  <div>
    <h1>{{title}}</h1>
    <p v-if="isShow">Vue.js is amazing.</p>
    <ul>
      <li v-for="item in list">{{item}}</li>
    </ul>
  </div>
</template>

上面是一个简单的Vue组件的模板,包括了表达式、指令和属性等。

解析:首先,Vue编译器(DSL)会将模板解析成AST(抽象语法树)。

{
  type: 1, // 元素节点
  tag: 'div',
  attrsList: [],
  attrsMap: {},
  parent: undefined,
  children: [
    {
      type: 1, // 元素节点
      tag: 'h1',
      attrsList: [],
      attrsMap: {},
      parent: [Circular],
      children: [
        {
          type: 2, // 表达式节点
          expression: '_s(title)',
          text: '{{title}}'
        }
      ]
    },
    {
      type: 1, // 元素节点
      tag: 'p',
      attrsList: [
        {
          name: 'v-if',
          value: 'isShow'
        }
      ],
      attrsMap: {
        'v-if': 'isShow'
      },
      parent: [Circular],
      children: [
        {
          type: 3, // 文本节点
          text: 'Vue.js is amazing.'
        }
      ]
    },
    {
      type: 1, // 元素节点
      tag: 'ul',
      attrsList: [],
      attrsMap: {},
      parent: [Circular],
      children: [
        {
          type: 1, // 元素节点
          tag: 'li',
          attrsList: [
            {
              name: 'v-for',
              value: 'item in list'
            }
          ],
          attrsMap: {
            'v-for': 'item in list'
          },
          parent: [Circular],
          children: [
            {
              type: 2, // 表达式节点
              expression: '_s(item)',
              text: '{{item}}'
            }
          ]
        }
      ]
    }
  ]
}

优化:接下来,Vue编译器(DSL)会执行优化阶段,比如静态节点的标记和缓存等。最终,会得到具有静态节点标记和缓存的优化后的AST:

{
  type: 1, // 元素节点
  tag: 'div',
  attrsList: [],
  attrsMap: {},
  parent: undefined,
  children: [
    {
      type: 1, // 元素节点
      tag: 'h1',
      attrsList: [],
      attrsMap: {},
      parent: [Circular],
      children: [
        {
          type: 2, // 表达式节点
          expression: '_s(title)',
          text: '{{title}}',
          isStatic: false,
          staticRoot: false
        }
      ],
      isStatic: false,
      staticRoot: false
    },
    {
      type: 1, // 元素节点
      tag: 'p',
      attrsList: [
        {
          name: 'v-if',
          value: 'isShow'
        }
      ],
      attrsMap: {
        'v-if': 'isShow'
      },
      parent: [Circular],
      children: [
        {
          type: 3, // 文本节点
          text: 'Vue.js is amazing.',
          isStatic: false,
          staticRoot: false
        }
      ],
      isStatic: false,
      staticRoot: false,
      ifConditions: [
        {
          exp: 'isShow',
          block: [Circular],
          key: undefined
        }
      ]
    },
    {
      type: 1, // 元素节点
      tag: 'ul',
      attrsList: [],
      attrsMap: {},
      parent: [Circular],
      children: [
        {
          type: 1, // 元素节点
          tag: 'li',
          attrsList: [
            {
              name: 'v-for',
              value: 'item in list'
            }
          ],
          attrsMap: {
            'v-for': 'item in list'
          },
          parent: [Circular],
          children: [
            {
              type: 2, // 表达式节点
              expression: '_s(item)',
              text: '{{item}}',
              isStatic: false,
              staticRoot: false
            }
          ],
          isStatic: false,
          staticRoot: false,
          for: 'list',
          alias: 'item',
          iterator1: 'i',
          key: 0
        }
      ],
      isStatic: false,
      staticRoot: false
    }
  ],
  isStatic: false,
  staticRoot: false
}

生成:最后,根据优化后的AST,Vue编译器(DSL)会生成最终的渲染函数:

function render() {
  with (this) {
    return _c('div', [
      _c('h1', [_v(_s(title))]),
      _c('p', { directives: [{ name: 'show', rawName: 'v-show', value: (isShow), expression: 'isShow' }] }, [_v('Vue.js is amazing.')]),
      _c(
        'ul',
        _l(list, function(item, i) {
          return _c('li', { key: i }, [_v(_s(item))])
        }),
        0
      )
    ])
  }
}

最终,根据该渲染函数,Vue.js的核心层就可以执行真实的DOM操作,更新页面。

三、另一个示例说明

下面再通过另一个示例来说明Vue编译器(DSL)的应用。

<template>
  <div>
    <h1>{{title}}</h1>
    <p v-bind:class="{ active: isActive }">Hello World!</p>
  </div>
</template>

上面的模板中,除了表达式之外,还包括了一个指令。

解析:同样,Vue编译器(DSL)会将模板解析成AST。

{
  type: 1, // 元素节点
  tag: 'div',
  attrsList: [],
  attrsMap: {},
  parent: undefined,
  children: [
    {
      type: 1, // 元素节点
      tag: 'h1',
      attrsList: [],
      attrsMap: {},
      parent: [Circular],
      children: [
        {
          type: 2, // 表达式节点
          expression: '_s(title)',
          text: '{{title}}'
        }
      ]
    },
    {
      type: 1, // 元素节点
      tag: 'p',
      attrsList: [
        {
          name: 'v-bind:class',
          value: '{ active: isActive }'
        }
      ],
      attrsMap: {
        ':class': '{ active: isActive }'
      },
      parent: [Circular],
      children: [
        {
          type: 3, // 文本节点
          text: 'Hello World!'
        }
      ]
    }
  ]
}

优化:接下来,Vue编译器(DSL)会执行优化阶段。

{
  type: 1, // 元素节点
  tag: 'div',
  attrsList: [],
  attrsMap: {},
  parent: undefined,
  children: [
    {
      type: 1, // 元素节点
      tag: 'h1',
      attrsList: [],
      attrsMap: {},
      parent: [Circular],
      children: [
        {
          type: 2, // 表达式节点
          expression: '_s(title)',
          text: '{{title}}',
          isStatic: false,
          staticRoot: false
        }
      ],
      isStatic: false,
      staticRoot: false
    },
    {
      type: 1, // 元素节点
      tag: 'p',
      attrsList: [
        {
          name: 'v-bind:class',
          value: '{ active: isActive }'
        }
      ],
      attrsMap: {
        ':class': '{ active: isActive }'
      },
      parent: [Circular],
      children: [
        {
          type: 3, // 文本节点
          text: 'Hello World!',
          isStatic: true,
          staticRoot: false
        }
      ],
      isStatic: false,
      staticRoot: false,
      classBinding: 'isActive ? "active" : ""'
    }
  ],
  isStatic: false,
  staticRoot: false
}

生成:最后,根据优化后的AST,生成对应的渲染函数。

function render() {
  with (this) {
    return _c('div', [
      _c('h1', [_v(_s(title))]),
      _c('p', { class: isActive ? 'active' : '' }, [_v('Hello World!')])
    ])
  }
}

最终,根据该渲染函数,Vue.js的核心层就可以执行真实的DOM操作,更新页面。

至此,我们完成了Vue编译器(DSL)原理的完整讲解。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一文搞懂vue编译器(DSL)原理 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • 从零开始实现Vue简单的Toast插件

    让我们开始讲解“从零开始实现Vue简单的Toast插件”的完整攻略。 1. 确定插件的功能和结构 在进行插件开发之前,我们需要确定Toast插件的基本功能以及它的结构。一般来说,Toast插件应该能够在页面上显示一条简短的提示信息,比如操作成功或者失败。根据这个要求,我们可以定义一个名为VueToast的插件,并且将它的HTML结构定义如下: <div…

    Vue 2023年5月28日
    00
  • vue3.0如何在全局挂载对象和方法

    在Vue 3.0中,我们可以使用 createApp 函数来创建一个应用实例,在该实例中可以挂载对象和方法,使其在全局范围内可用。 全局挂载对象 在应用实例中调用 provide 方法,然后将需要全局挂载的对象作为参数传递进去,即可实现全局挂载该对象。 // main.js import { createApp } from ‘vue’ import App…

    Vue 2023年5月28日
    00
  • vue使用directive限制表单输入整数、小数的方法

    下面是详细讲解“vue使用directive限制表单输入整数、小数的方法”的完整攻略: 一、什么是directive 在Vue中,Directive(指令)是一种特殊的标记,它可以在模板中添加行为。在Vue中,有很多自带的directive,例如v-model、v-if、v-show等。通过使用Directive,开发者可以自定义自己的指令。Vue中,Dir…

    Vue 2023年5月28日
    00
  • vue-cli 3如何使用vue-bootstrap-datetimepicker日期插件

    使用vue-cli 3来集成vue-bootstrap-datetimepicker日期插件,需要使用以下步骤: 步骤一:安装依赖 在命令行中进入项目根目录,然后运行以下命令来安装需要的依赖: npm install vue-bootstrap-datetimepicker –save 步骤二:引入CSS和JS文件 在你的Vue组件之前,需要引入CSS和J…

    Vue 2023年5月29日
    00
  • Vue select 绑定动态变量的实例讲解

    下面我将详细讲解如何在Vue中使用select绑定动态变量的实例攻略。 首先,我们需要导入Vue.js,然后创建Vue实例,并在该实例的data属性中定义我们需要绑定的动态变量(这里我们定义一个变量名为selectedValue)。然后我们需要在Vue实例中声明一个options对象,其中包含一个数组,该数组中包含我们需要绑定到select元素的选项。最后,…

    Vue 2023年5月29日
    00
  • vue2.0开发入门笔记之.vue文件的生成和使用

    当我们使用 Vue.js 进行开发的时候,最普遍的方式就是通过 .vue 文件进行组件化开发。本次攻略将详细讲解 .vue 文件的生成和使用。 什么是 .vue 文件? .vue 文件是一种组件化的文件格式,Vue.js 是通过 .vue 文件进行组件开发。.vue 文件将一个组件的 HTML、CSS 和 JavaScript 内容放在同一个文件中,便于管理…

    Vue 2023年5月28日
    00
  • ElementUI日期选择器时间选择范围限制的实现

    下面是ElementUI日期选择器时间选择范围限制的实现的完整攻略。 基本使用 首先,我们需要在项目中引入ElementUI的日期选择器组件,并使用它进行基本日期选择。使用步骤如下: 1.1 引入ElementUI组件 在项目中使用npm安装ElementUI,然后在使用日期选择器的页面中引入: import { DatePicker } from ‘ele…

    Vue 2023年5月29日
    00
  • Vue 内置指令梳理总结

    “Vue 内置指令梳理总结”是一篇介绍 Vue 框架内置指令的文章。在这篇文章中,我将会讲解 Vue 框架内置指令包括 v-model、v-show、v-if、v-for 等等的用法,以及每个指令的使用场景、注意事项等等。下面是本篇文章的详细攻略。 1. 指令的基本概念 指令是指 Vue 框架提供的一种特殊的 HTML 属性,通过以 v- 开头的命名来表示。…

    Vue 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部