• home > webfront > ECMAS > vue >

    vue源码 源码解读

    Author:zhoulujun Date:

    通过查看vue源码的目录结构解,解说Vue源码每个文件的作用。然后逐步解读每个文件的源码。这是一项浩大的工程。本篇立项在这里,希望逐步完成这个工作

    vue源码目录结构解读

    ├── build --------------------------------- 构建相关的文件
    ├── dist ---------------------------------- 构建后文件的输出目录
    ├── examples ------------------------------ 存放使用Vue开发的的例子
    ├── flow ---------------------------------- 类型声明,使用开源项目 [Flow](https://flowtype.org/)
    ├── package.json -------------------------- 项目依赖
    ├── test ---------------------------------- 包含所有测试文件
    ├── src ----------------------------------- 这个是我们最应该关注的目录,包含了源码
    │   ├── compiler -------------------------- 编译器代码的存放目录,将 template 编译为 render 函数
    │   │   ├── parser ------------------------ 存放将模板字符串转换成元素抽象语法树的代码
    │   │   ├── codegen ----------------------- 存放从抽象语法树(AST)生成render函数的代码
    │   │   ├── optimizer.js ------------------ 分析静态树,优化vdom渲染
    │   ├── core ------------------------------ 存放通用的,平台无关的代码
    │   │   ├── observer ---------------------- 反应系统,包含数据观测的核心代码
    │   │   ├── vdom -------------------------- 包含虚拟DOM创建(creation)和打补丁(patching)的代码
    │   │   ├── instance ---------------------- 包含Vue构造函数设计相关的代码
    │   │   ├── global-api -------------------- 包含给Vue构造函数挂载全局方法(静态方法)或属性的代码
    │   │   ├── components -------------------- 包含抽象出来的通用组件
    │   ├── platforms ------------------------- 包含平台相关的代码
    │   │   ├──web ---------------------------- 包含了不同构建的包的入口文件
    │   │   |   ├──entry-runtime.js ----------- 运行时构建的入口,输出 dist/vue.common.js 文件,不包含模板(template)到render函数的编译器,所以不支持 `template` 选项,我们使用vue默认导出的就是这个运行时的版本。大家使用的时候要注意
    │   │   |   ├── entry-runtime-with-compiler.js -- 独立构建版本的入口,输出 dist/vue.js,它包含模板(template)到render函数的编译器
    │   ├── server ---------------------------- 包含服务端渲染(server-side rendering)的相关代码
    │   ├── sfc ------------------------------- 包含单文件组件(.vue文件)的解析逻辑,用于vue-template-compiler包
    │   ├── shared ---------------------------- 包含整个代码库通用的代码



    vue初始化

    核心 vue/src/core/util/index.js

    export * from 'shared/util' // src/shared/util.js 基础方法   src/shared/constants.js vue常量
    export * from './lang' //html标签、组件名称、文件路径锁使用的  unicode字符串
    export * from './env' // 运行环境检测
    export * from './options' // 参数合并
    export * from './debug'
    export * from './props'
    export * from './error'
    export * from './next-tick'
    export { defineReactive } from '../observer/index'

    对上面的内容看一下

    通用函数

    vue中定义了大量通用函数,如下只是一部分,平常需要找一些通用函数也可以在这里找到例子

    如 node_modules/vue/src/shared/util.js   node_modules/vue-template-compiler/build.js 

    // These helpers produce better VM code in JS engines due to their
    // explicitness and function inlining.
    function isUndef (v) {
      return v === undefined || v === null
    }
    
    /**
     * Check if value is primitive.
     */
    function isPrimitive (value) {
      return (
        typeof value === 'string' ||
        typeof value === 'number' ||
        // $flow-disable-line
        typeof value === 'symbol' ||
        typeof value === 'boolean'
      )
    }
     
    function isTrue (v) {
      return v === true
    }
     
    function isFalse (v) {
      return v === false
    }

    消除浏览器差异

    为了抹平浏览器之间的差异,做了大量polyfill操作,例如ES6中的Set

    node_modules/vue-template-compiler/build.js 142行

    if (typeof Set !== 'undefined' && isNative(Set)) {
      // use native Set when available.
      _Set = Set;
    } else {
      // a non-standard Set polyfill that only works with primitive keys.
      _Set = /*@__PURE__*/(function () {
        function Set () {
          this.set = Object.create(null);
        }
        Set.prototype.has = function has (key) {
          return this.set[key] === true
        };
        Set.prototype.add = function add (key) {
          this.set[key] = true;
        };
        Set.prototype.clear = function clear () {
          this.set = Object.create(null);
        };
     
        return Set;
      }());
    }



    浏览器嗅探

    var inBrowser = typeof window !== 'undefined';
    var inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform;
    var weexPlatform = inWeex && WXEnvironment.platform.toLowerCase();
    var UA = inBrowser && window.navigator.userAgent.toLowerCase();
    var isIE = UA && /msie|trident/.test(UA);
    var isIE9 = UA && UA.indexOf('msie 9.0') > 0;
    var isEdge = UA && UA.indexOf('edge/') > 0;
    var isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android');
    var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios');
    var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;
    var isPhantomJS = UA && /phantomjs/.test(UA);
    var isFF = UA && UA.match(/firefox\/(\d+)/);


    常量

    定义常量,资源类型,生命周期钩子等:

    node_modules/vue/src/shared/constants.js

    var SSR_ATTR = 'data-server-rendered';
     
    var ASSET_TYPES = [
      'component',
      'directive',
      'filter'
    ];
     
    var LIFECYCLE_HOOKS = [
      'beforeCreate',
      'created',
      'beforeMount',
      'mounted',
      'beforeUpdate',
      'updated',
      'beforeDestroy',
      'destroyed',
      'activated',
      'deactivated',
      'errorCaptured',
      'serverPrefetch'
    ];



    服务器渲染

    vue加载模式分为是否服务端渲染,从process.env.VUE_ENV区分


    Vue构造函数


    转载本站文章《vue源码 源码解读》,
    请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/vue/8416.html