.vue文件编译成浏览器可执行文件的流程详解

 更新时间:2023年09月01日 09:36:20   作者:九殇  
这篇文章主要给大家介绍了.vue 文件是如何编译成浏览器可执行的文件,文中通过代码示例将编译流程介绍的非常详细,对我们的学习或工作有一定的价值,感兴趣的同学可以参考阅读下

vue2官网 其中”安装”介绍了关于Vue的各种版本。

  • 编译器:用来将模板字符串编译成为 JavaScript 渲染函数的代码。
<div id="app">
    <div>{{ a }}</div> 
</div> 
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script> <script> 
const vm = new Vue({ el: '#app', data: { a: 'hello world', }, }) 
</script>

以上是一段简单的Vue2代码, 打开浏览器可以正确显示出 “hello world”,- 可以发现 <div>{{ a }}</div> 不是浏览器支持的语法. 所以实际上能显示 hello world, 并不是由以上模板代码直接在浏览器执行的结果, 而是通过”编译器”编译, 再由浏览器执行

  • 接下来用代码为大家演示Vue2是如何将上面代码编译的
  • 首先必须引入”完整版”,
  • 打开页面, 在控制台可以发现方法: Vue.compile

  • 将刚才的 template 代码放到编译方法里执行, 结果如下

  • 可以看到 template 被编译成 JavaScript,_c,_v,_s,是vue实例vm上一些方法的简称

  • 编译结果可以翻译成
<script>
    const vm = new Vue({
      el: '#app',
      name: 'App',
      data: () => ({
        a: 'hello world!!!',
      }),
      render() {
        const {_c, _v, _s, a} = this
        //return createElement('div', [createTextNode(toString(a))])
        return  _c('div',[_v(_s(a))])
      }
  })
  </script>

这样 模板template就被编译为了 render函数

  • 以上便是在 .html 文件中使用template 开发, 由 Vue2完整版 进行编译的过程

.vue文件是如何进行编译的?

通常项目中是使用Webpack打包, 再由浏览器引入这些js, css等文件, 那么Webpack是如何对.vue文件进行编译的?

1. .vue文件

.vue文件.vue 文件是一个自定义的文件类型,用类 HTML 语法描述一个 Vue 组件。每个 .vue 文件包含三种类型的顶级语言块 <template><script> 和 <style>,还允许添加可选的自定义块.

2. vue-loader

vue-loader 会解析文件,提取每个语言块,如有必要会通过其它 loader 处理,最后将他们组装成一个 ES Module,它的默认导出是一个 Vue.js 组件选项的对象。

接下来通过vue-loader的源码来了解是如何实现编译的

vue-loader/src/index.ts

vue文件分为 template, script, style 三个部分, 而实际必须通过编译才能在浏览器执行的部分只有template, 所以我们在看 vue-loader 源码时可以重点关注 “template” 关键词

descriptor.template 如上图所示, 在源码搜索 template 关键字可以找到这段处理 script, template, style 的代码, 仔细观察发现这三段都在用 descriptor 对象, 接下来搜索 descriptor, 找到这个变量在哪里生成的 descriptor

再来找 parse 方法

compiler.ts compiler.ts

parse 方法从 vue/compiler-sfc 中引用

至此, 了解到 vue-loader 是通过 @vue/compiler-sfc 的 parse 方法解析 .vue 文件, 从中解析出script, template, style

@vue/compiler-sfc

用一段nodejs代码进行验证

// App.vue
<template>
  <div id="app">
    <div>{{ a }}</div>
    <input type="text" v-model="a">
  </div>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    a: 'hello world'
  }),
}
</script>
// build.js
const { parse } = require('@vue/compiler-sfc')
const fs = require('fs')
const data = fs.readFileSync('./App.vue')
const { descriptor } = parse(data.toString())
// 结果包含很多项, 本文档中只展示重点字段
console.log(Object.keys(descriptor))

运行 build.js

[
  'styles',
	'template',
  'script',
  // ...
]

通过以上代码可以解析出 .vue 文件的三部分, 接下来开始解析 template vue-template-compiler vue-template-compiler 可以将 template 编译成 Javascript

  • 继续修改 build.js, 根据文档加上 compile 的部分
// build.js
const { parse } = require('@vue/compiler-sfc')
const fs = require('fs')
const compiler = require('vue-template-compiler')
const data = fs.readFileSync('./App.vue')
const { descriptor } = parse(data.toString())
// console.log(Object.keys(descriptor))
console.log(compiler.compile(descriptor.template.content).render)
  • 运行结果如下
with(this){
  return _c(
    'div',
    {attrs:{"id":"app"}},
    [
      _c('div',[_v(_s(a))]),
      _v(" "),
      _c(
        'input',
        {
          directives:[{name:"model",rawName:"v-model",value:(a),expression:"a"}],
          attrs:{"type":"text"},
          domProps:{"value":(a)},
          on:{
            "input": function($event){
              if($event.target.composing) return;
              a=$event.target.value
            }
          }
        }
      )
    ]
  )
}

再将以上代码放到 .html 的 new Vue(...) 方法中进行验证

<div id="app"/>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
  const vm = new Vue({
    name: 'App',
    data: () => ({
      a: 'hello world!!!',
    }),
    render() {
      const {_c, _v, _s, a} = this
      return _c(
        'div',
        {attrs: {'id': 'app'}},
        [
          _c('div', [_v(_s(a))]),
          _v(' '),
          _c(
            'input',
            {
              directives: [{name: 'model', rawName: 'v-model', value: (a), expression: 'a'}],
              attrs: {'type': 'text'},
              domProps: {'value': (a)},
              on: {
								// 注意这里的 this, 需要改成箭头函数
                'input': ($event) => {
                  if ($event.target.composing) return
                  this.a = $event.target.value
                },
              },
            },
          ),
        ],
      )
    },
  }).$mount('#app')
</script>

以上便是 Webpack 如何将 .vue 文件编译成浏览器可执行文件的过程

到此这篇关于.vue文件编译成浏览器可执行文件的流程详解的文章就介绍到这了,更多相关.vue文件编译成可执行文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解vue-cli多页面工程实践

    详解vue-cli多页面工程实践

    本篇文章主要介绍了详解vue-cli多页面工程实践,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • Vue基础配置讲解

    Vue基础配置讲解

    在本篇文章里小编给大家整理的是关于Vue基础配置讲解内容,有兴趣的朋友们可以学习下。
    2019-11-11
  • Vue重要修饰符.sync对比v-model的区别及使用详解

    Vue重要修饰符.sync对比v-model的区别及使用详解

    这篇文章主要为大家介绍了Vue中重要修饰符.sync与v-model的区别对比及使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • vue + echarts实现中国省份地图点击联动

    vue + echarts实现中国省份地图点击联动

    这篇文章主要介绍了vue + echarts实现中国地图省份点击联动,需要的朋友可以参考下
    2022-04-04
  • Vue配置环境变量的正确打开方式

    Vue配置环境变量的正确打开方式

    这篇文章主要为大家介绍了Vue配置环境变量,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-01-01
  • vue实现视频全屏切换功能

    vue实现视频全屏切换功能

    这篇文章主要为大家详细介绍了如何使用vue实现视频全屏切换的功能,文中的示例代码讲解详细, 具有一定的借鉴价值,有需要的小伙伴可以参考一下
    2023-11-11
  • vue动态的 BreadCrumb 组件el-breadcrumb ElementUI详解

    vue动态的 BreadCrumb 组件el-breadcrumb ElementUI详解

    这篇文章主要介绍了vue如何做一个动态的 BreadCrumb 组件,el-breadcrumb ElementUI
    ,本文通过图文示例代码相结合给大家介绍的非常详细,需要的朋友可以参考下
    2024-07-07
  • vue中的数据绑定原理的实现

    vue中的数据绑定原理的实现

    本篇文章主要介绍了vue中的数据绑定原理的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • 深入探究Vue中探究组合式API的奥秘

    深入探究Vue中探究组合式API的奥秘

    Vue 3中引入了组合式API,它是一种新的代码组织方式,旨在让开发者更灵活地组织和重用Vue组件的逻辑,下面我们就来学习一下Vue中常见组合式API的使用吧
    2023-11-11
  • Vue使用Props实现组件数据交互的示例代码

    Vue使用Props实现组件数据交互的示例代码

    在Vue中,组件的props属性用于定义组件可以接收的外部数据,这些数据来自父组件并传递给子组件,本文给大家介绍了Vue使用Props实现组件数据交互,文中有详细的代码示例供大家参考,需要的朋友可以参考下
    2024-06-06

最新评论