• 《Vue 编程房内考》


    古人有云:码农爱coding,则为之计深远。
    众人问:何为之?
    古人曰:底层、算法和架构。
    众木然。
    古人又曰:多看源码。

    以下内容是我在学习 Vue-2.5.2 源码时的一个总结。

    第一章 活捉Vue

    旁白:既然是学习Vue源码,首先要搞清楚的是——Vue是什么东西?不然,天知道你在学什么玩意儿。所以,找到Vue对象就是本次学习的一条主线。本次任务的目标就是——活捉Vue

    盖工欲善其事必先利其器。出发之前,应该要有一件趁手的武器,呐,这套祖传的vs code就送给你了。

    第一回 不入虎穴焉得虎子

    欲活捉Vue,最紧要的是找到它大概在哪里,然后根据线索顺藤摸瓜。那么,它到底在哪儿呢?

    看着眼前的武器,你灵光一闪:git clone https://github.com/vuejs/vue.git。恭喜,Vue的老巢已经被你发现,令人激动的是,入口package.json也被你找到了。但紧闭的大门阻碍了你的步伐,于是你运用所学姿势,很快找到破解开关的关键scripts属性:

      "scripts": {
        "dev": "rollup -w -c build/config.js --environment TARGET:web-full-dev",
        ...
        "build": "node build/build.js",
        ...
      }  
    

    P.S.package.json几乎是所有成熟库/框架必备的入口文件。

    你命令终端执行npm run dev,看到rollup构建工具正在自动执行build文件夹下的config.js,并在环境中注入参数TARGET:web-full-dev,你紧跟线索,找到了build/config.js。看着两百多行代码,你微微一笑,心想,这等雕虫小技也敢造次?径直走向exports,看它导出了什么?

    P.S.s 一般而言,导出对象在文件末尾。

    // build/config.js

    ...
    if (process.env.TARGET) {
      module.exports = genConfig(process.env.TARGET); // (1)
    } else {
      exports.getBuild = genConfig
      exports.getAllBuilds = () => Object.keys(builds).map(genConfig)
    }
    

    脑回路高速运行——因为执行npm run dev会植入环境变量TARGET:web-full-dev,上述代码会走(1),所以结合上下文,build/config.js实际导出的对象应该是这样的:

    module.exports = {
      input: resolve('web/entry-runtime-with-compiler.js'),
      plugins: [
        replace({__VERSION__: version}),
        {
          vue: resolve('src/platforms/web/entry-runtime-with-compiler'),
          compiler: resolve('src/compiler'),
          core: resolve('src/core'),
          shared: resolve('src/shared'),
          web: resolve('src/platforms/web'),
          weex: resolve('src/platforms/weex'),
          server: resolve('src/server'),
          entries: resolve('src/entries'),
          sfc: resolve('src/sfc'),
          he: './entity-decoder'
        }
      ],
      output: {
        file: resolve('dist/vue.js'),
        format: 'umd',
        banner: banner,
        name: 'Vue'
      }
    }         
    

    直到这里,Vue的庐山真面目依然没有揭开。“果然是狡兔三窟!”你不屑道,然而你明白,已经越来越接近了...

    此地唯一的入口就是input,小小的障眼法对你来讲不足挂齿,轻轻旋转机关,来到了src/platforms/web/entry-runtime-with-compiler.js。只一眼,你便看到了import Vue from './runtime/index'。"hehe,总算把你逮住了,老东西!"

    你小心翼翼的进入./runtime/index,以为终于抓到了Vue。突然,一支利箭飞来import Vue from 'core/index',险险的避过后,一群彪形大汉又蜂拥而至:

    ./runtime/index.js

    import Vue from 'core/index'
    ...
    Vue.config.mustUseProp = mustUseProp
    ...
    extend(Vue.options.directives, platformDirectives)
    ...
    Vue.prototype.$mount = function (
      el?: string | Element,
      hydrating?: boolean
    ): Component {
      el = el && inBrowser ? query(el) : undefined
      return mountComponent(this, el, hydrating)
    }
    ...
    

    第二回 降服Vue

    面对群魔乱舞,你开始受伤、流血,一波又一波的攻势逐渐让你体力不支,更糟糕的是,你,只是一个人。“就这样结束了么?”你喘着粗气暗问自己,恍惚间,往昔在脑海中一幕幕重现,从一无所知的小白到现在敢于挑战Vue,经历了重重历练,你不甘心,不甘心就这样失败。放手一搏吧,骚年!!!

    体内的能量在积累,终于,你用尽全力使出了终极必杀技:404 Page Not Found。一时间,大汉们应声而倒,就连./runtime/index也开始坍塌,电光火石间,一股大力将你震晕击飞,醒来之时,已经到了另一个世界:src/core/index.js

    这里就是Vue的核心了么?环顾四周,只见一间虚掩着房门的小屋./instance/index,推开门,Vue端坐在那里:

    ...
    function Vue (options) {
      if (process.env.NODE_ENV !== 'production' &&
        !(this instanceof Vue)
      ) {
        warn('Vue is a constructor and should be called with the `new` keyword')
      }
      
      this._init(options)
    }
    ...
    

    终于找到了,此刻,你可以轻松的把它杀死,成为万众瞩目的英雄,于是乎你挥起手中利刃,直直的刺向Vue。当刃尖离Vue只有0.0001公分的时候,你看着眼前的Vue,原来,鼎鼎大名的Vue只是一个普普通通的构造函数,好像看到了最初的自己,刹那间,你顿住了。

    Vue却开口到:“骚年,你终于来了!看你风流倜傥、天资聪颖,老夫这一身绝学总算是后继有人了。”说罢,万丈金光从Vue身上迸发而出,场面一度失控。待金光散去,Vue却不见了,只留下一本《Vue 编程房内考》...

  • 相关阅读:
    spring总结
    mybatis总结
    HttpClient,okhttp,Jodd-http 使用上的差异
    RPC序列化
    RPC是什么? (学习笔记)
    MySQL普通索引与唯一索引
    MySQL 存储引擎
    TCP的流量控制和拥塞控制
    【转载】Windows自带.NET Framework版本大全
    [知识点] 总目录
  • 原文地址:https://www.cnblogs.com/fayin/p/7798700.html
Copyright © 2020-2023  润新知