尋找專案中頂級Vue物件 (一)

張潤昊發表於2018-07-28

個人部落格首發部落格園: www.cnblogs.com/zhangrunhao…

參考

感謝作者

問題背景

  • 在除錯Chrome的時候, 發現不能找到vm這個物件.
  • window下面也沒有看到這個物件.
  • 產生了好奇心.

過程分析

  • 在dev環境下面:
    • 在控制檯看的時候放到了 window__VUE_DEVTOOLS_GLOBAL_HOOK__
  • 找到了new Vue的執行棧.
  • 但是沒能確定在Vue中具體的執行過程.
  • 應該是在import的時候, webpack就把引入的Vue物件放到了某個地方, 儲存起來了.

執行時構建的Vue庫/獨立構建的Vue庫

  • 使用import/require引入的是 執行時構建的Vue庫 dist/vue.runtime.common.js
  • 使用<script>引入的是獨立構建的Vue庫
  • 區別就是是否包含一個template功能, 因為在執行時構建的Vue庫中, 我們通過打包工具webpack等解決了這一問題.

選擇掛載優先順序

  • render渲染函式 > template編譯模板 > 掛載到el屬性上的指定DOM

render函式

  • 掛載在Vue的頂級函式上面. 渲染的最優先選擇
  • render: function(cb / createElement) {} // 所有的的核心都在這個回撥函式中
  • 這個回撥函式就是createElement函式, 也就是我們用來建立VNode的函式, render返回的就是 回撥函式的執行結果
  • return createElement(tag, data, array) // 這個就是我們的返回結果
  • 引數第一個表示, 我們的標籤名稱, 或者是一個例項元件. data就是我們這個元件的描述資訊了. 什麼都有.
  • 最後一個引數, 我們用來遞迴形成的子標籤, 或者子元件, 陣列表示平行關係
  • 第二個引數, 如果是一個字串的話, 就是我們想要往裡面插入的子元件陳列
  • render: h => h(App) / render(h) {return h('div', this.hi)}

vue不渲染Dom, 實現場景直接通訊

  • 新建檔案 import Vue from 'vue; export EventBus = new Vue()
  • 通過$on新增監聽事件
    • import EventBus from './event-bus.js; EventBus.$on('customerEvent', function() {}).
    • 此處儘量不要使用箭頭函式, 裡面的指標不易改變
    • 回頭自己試試.
  • 其他檔案引入, 通過$emit觸發
    • import EventBus from './event-bus.js; EventBus.$emit('customerEvent', ...params)

查詢vue.runtime.common.js

應該從打包工具開始查詢

/dist資料夾下八個檔案的區別

  • 按照執行環境區分: 完整構建/執行時構建, 也就是是否可以使用template選項
  • 按照模組化規範: UMD/CommonJS/ESModule
    • AMD: requireJS實現. 主要是非同步載入模組. (偏向瀏覽器)
    • COMMONJS: Node, 同步載入, 模組無需包裝. (偏向伺服器)
    • UMD: AMD和COMMON的結合, (先判斷是否執行export/Node), 再判斷是否支援(define/AMD).
  • vue.common.js: 基於common的完整構建. 使用webpack打包時, 需要配置別名.(這就不太理解了)
    • 我又預感, 問題應該就出在webpack的配置中
// webpack-1
{
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.common.js'
    }
  }
}
複製程式碼
  • vue.esm.js: 基於ESModule的完整構建. 使用webpack打包時, 也是需要配置
  • vue.js: 基於UMD的完整構建
  • vue.runtime.common.js: 基於common的執行時構建. 不支援template, .vue被解析成了render函式
  • vue.runtime.esm.js: 基於ESModule的執行時構建.
  • vue.runtime.js: 基於UMD的執行時構建.

專案直接引用的vue, 引用的是vue.runtime.common.js嗎. 為何可以使用ESModle

  • 先貼出vue的package.json
{
  // ...
  "main": "dist/vue.runtime.common.js",
  "module": "dist/vue.runtime.esm.js",
  "unpkg": "dist/vue.js",
  "jsdelivr": "dist/vue.js",
  // ...
}
複製程式碼
  • main: 是基於COMMONJS的. module: 是基於ES6的.
  • 因為使用ES6的話, 可以配置uglifyjs-webpack-plugin外掛, 可以去除沒有用到的函式.
  • 但是因為有些npm包不支援ES6, 比如有些node環境.
  • 這個時候, 會判斷當前支援哪種環境, 然後選擇不同的包.
  • 引入的時候, 不論包怎麼匯出都可用import引入. 但是匯出的時候, 就會區分出來. 使用export/export default關鍵字, 還是module.exports/exports匯出

結論, 我們的專案, 應該是引用了run.runtime.esm.js

webpack中配置別名

  • baseConf.resolve.alias.vue = 'vue/dist/vue.common.js';
  • 當我們解析vue / vue$ 的時候, 就會解析到指定的目錄下面.

相關文章