個人部落格首發部落格園: www.cnblogs.com/zhangrunhao…
參考
感謝作者
- 從一個奇怪的錯誤出發理解 Vue 基本概念
- 安裝 - Vue.js
- 渲染函式 - Vue.js
- Vue2 dist 目錄下各個檔案的區別
- 聊聊 package.json 檔案中的 module 欄位
- ES6模組 和 CommonJS 的區別
問題背景
- 在除錯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$ 的時候, 就會解析到指定的目錄下面.