個人博客首發博客園: http://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$ 的時候, 就會解析到指定的目錄下面.