API
全局配置
Vue.config 是一個對象,包含 Vue 的全局配置。
- 源碼位置:util/config.js
- 搜索config 可以找到其源碼地址,其中聲明了config的類型和默認參數
下面僅僅留下官方的幾個配置項
export type Config = {
// user
optionMergeStrategies: { [key: string]: Function }; //自定義合並策略的選項。
silent: boolean; //關於日志和警告
productionTip: boolean; //設置為 false 以阻止 vue 在啟動時生成生產提示。
performance: boolean;//設置為 true 以在瀏覽器開發工具的性能/時間線面板中啟用對組件初始化、編譯、渲染和打補丁的性能追蹤。只適用於開發模式和支持 performance.mark API 的瀏覽器上。
devtools: boolean; //配置是否允許 vue-devtools 檢查代碼。
errorHandler: ?(err: Error, vm: Component, info: string) => void; //指定組件的渲染和觀察期間未捕獲錯誤的處理函數。這個處理函數被調用時,可獲取錯誤信息和 Vue 實例。
warnHandler: ?(msg: string, vm: Component, trace: string) => void; //為 Vue 的運行時警告賦予一個自定義處理函數。注意這只會在開發者環境下生效,在生產環境下它會被忽略。
ignoredElements: Array<string | RegExp>; //使 Vue 忽略在 Vue 之外的自定義元素
keyCodes: { [key: string]: number | Array<number> };//給 v-on 自定義鍵位別名
// platform
..... 平台相關
......
};
export default ({默認項}: Config))
- 分析: 可以看出來整個config是進行了單獨的整體的舉例,然后配置完默認項后暴露出去,那么我們又是如何能夠使用vue.confige.XXX 使用呢。
- 源碼地址 core/global-api/index.js
import config from '../config'
....
export function initGlobalAPI (Vue: GlobalAPI) {
// config
const configDef = {}
configDef.get = () => config
if (process.env.NODE_ENV !== 'production') {
configDef.set = () => {
warn(
'Do not replace the Vue.config object, set individual fields instead.'
)
}
}
Object.defineProperty(Vue, 'config', configDef)
....
}
-- 分析:,我們在這個文件中可以中看到,Vue在全局注入API 的時候將config注入.依然是用了Object.defineProperty()方法將其放在了Vue實例中。
綜上我能感受到作為大框架對於各種功能的分散和聚合(用詞不當,水平過低),是十分精煉的,組織結構清晰,明了。
那么接下來,看看vue提供的config暴露api大致都是如何工作的吧。
#silent
- 源碼地址:core/util/debug.js
...
warn = (msg, vm) => {
const trace = vm ? generateComponentTrace(vm) : ''
if (config.warnHandler) {
config.warnHandler.call(null, msg, vm, trace)
} else if (hasConsole && (!config.silent)) { //判斷slinet
console.error(`[Vue warn]: ${msg}${trace}`)
}
}
tip = (msg, vm) => {
if (hasConsole && (!config.silent)) { // 判斷slient
console.warn(`[Vue tip]: ${msg}` + (
vm ? generateComponentTrace(vm) : ''
))
}
}
...
- 分析:我們可以看到再debug.js中vue對slient的使用,就是非常常規的判斷,無需多說。
# optionMergeStrategies
- 源碼地址:core/util/option.js
...
/**
* Option overwriting strategies are functions that handle
* how to merge a parent option value and a child option
* value into the final value.
*/
const strats = config.optionMergeStrategies
... 做了老多事情
合並各種數據,數據,方法,watch等等
...
- 分析: optionMergeStrategies主要用於 mixin 以及 Vue.extend() 方法時對於子組件和父組件如果有相同的屬性(option),我們可以看到optionMergeStrategies的使用是在potion中,里面進行了各種合並,因為其中各種類型的合並策略都能拿出來細說,次此梳理,近是淺嘗即止,顧不深究,以后有機會再去討論,Vue方面更深刻的源碼分析,還是先以數據驅動和響應式部分為主。
# devtools
- 源碼地址:core/observer/scheduler.js & core/util/env.js
/**
* Flush both queues and run the watchers.
*/
function flushSchedulerQueue () {
...
// devtool hook
/* istanbul ignore if */
if (devtools && config.devtools) {
devtools.emit('flush')
}
....
}
// detect devtools
export const devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__
- 分析,可以看到devtools是聲明或者定義是在env.js中其實就是window.VUE_DEVTOOLS_GLOBAL_HOOK 這個對象,如果你安裝了這個工具,再控制台打印可以看到
{_buffer: Array(0), Vue: ƒ, _replayBuffer: ƒ, on: ƒ, once: ƒ, …}。那么其中你就可以看到再scheduler.js中是用的emit的方法, 我們只看對於vue的支持,這個工具的具體實現不考慮;,可以看到他的使用是在flushSchedulerQueue()這個方法中使用,這個方法在注釋中就很清晰,而且這個方法也是vue響應式中很關鍵的方法,這里大致說一下, 再數據派發更新過程中Vue會遍歷我們引入一個隊列概念,這也是 Vue 在做派發更新的時候的⼀個優化的點,它並不會每次數據改
變都觸發 watcher 的回調,⽽是把這些 watcher 先添加到⼀個隊列⾥,然后在 nextTick 后執⾏flushSchedulerQueue 。其中先后進行了
- 隊列排序,queue.sort((a, b) => a.id - b.id)
- 隊列遍歷在對 queue 排序后,接着就是要對它做遍歷,拿到對應的 watcher ,執⾏ watcher.run()
- 狀態恢復 執⾏ resetSchedulerState 函數,
大致如此,具體細節,又是很冗長繁瑣,如有興趣,可以看我的關於響應式的處理。
# errorHandler
- 源碼位置 core/util/error.js
function globalHandleError (err, vm, info) {
if (config.errorHandler) {
try {
return config.errorHandler.call(null, err, vm, info) //
} catch (e) {
// if the user intentionally throws the original error in the handler,
// do not log it twice
if (e !== err) {
logError(e, null, 'config.errorHandler')
}
}
}
logError(err, vm, info)
}
- 這個API其實看官方的文檔就很好理解。
指定組件的渲染和觀察期間未捕獲錯誤的處理函數。這個處理函數被調用時,可獲取錯誤信息和 Vue 實例。
此處感覺沒啥說的,,,,網上看到有分析的很多的,我就不細究了有興趣可以
點擊這里
# warnHandler
- 源碼位置 core/util/error.js
warn = (msg, vm) => {
const trace = vm ? generateComponentTrace(vm) : ''
if (config.warnHandler) {
config.warnHandler.call(null, msg, vm, trace)
} else if (hasConsole && (!config.silent)) {
console.error(`[Vue warn]: ${msg}${trace}`)
}
}
- 分析?感覺自己水平有限,實際使用幾乎為零,沒啥分析的。有興趣看看這個文章,作者算是再Vue異常處理方面進行研究,這里
# ignoredElements
- 源碼位置 core/dom/patch.js
function isUnknownElement (vnode, inVPre) {
return (
!inVPre &&
!vnode.ns &&
!(
config.ignoredElements.length &&
config.ignoredElements.some(ignore => {
return isRegExp(ignore)
? ignore.test(vnode.tag)
: ignore === vnode.tag
})
) &&
config.isUnknownElement(vnode.tag)
)
}
- 分析?官方文檔提供的很好,
須使 Vue 忽略在 Vue 之外的自定義元素 (e.g. 使用了 Web Components APIs)。否則,它會假設你忘記注冊全局組件或者拼錯了組件名稱,從而拋出一個關於 Unknown custom element 的警告。
代碼也很清晰。可以看到報錯點會出現在Vue進行數據驅動的核心方法creatElm中。
# keyCodes
- 源碼位置 core/instance/render-helpers/check-keycodes.js
function isKeyNotMatch<T> (expect: T | Array<T>, actual: T): boolean {
if (Array.isArray(expect)) {
return expect.indexOf(actual) === -1
} else {
return expect !== actual
}
}
/**
* Runtime helper for checking keyCodes from config.
* exposed as Vue.prototype._k
* passing in eventKeyName as last argument separately for backwards compat
*/
export function checkKeyCodes (
eventKeyCode: number,
key: string,
builtInKeyCode?: number | Array<number>,
eventKeyName?: string,
builtInKeyName?: string | Array<string>
): ?boolean {
const mappedKeyCode = config.keyCodes[key] || builtInKeyCode
if (builtInKeyName && eventKeyName && !config.keyCodes[key]) {
return isKeyNotMatch(builtInKeyName, eventKeyName)
} else if (mappedKeyCode) {
return isKeyNotMatch(mappedKeyCode, eventKeyCode)
} else if (eventKeyName) {
return hyphenate(eventKeyName) !== key
}
}
- 分析: 這個玩意,我專門實踐了一下,其實就是自定義別名,看文檔我當時有點懵逼,我改成了 如下
Vue.config.keyCodes = {
v: 86,
// 取而代之的是 kebab-case 且用雙引號括起來
"media-play-pause": 86,
}
<input type="text" @keyup.media-play-pause="method($event)">
這里,你就會發現他就是定義自己的別名去對應專屬的,keyCode個人感覺沒啥用,
實現的話,就是源碼方面的處理。隨后又走了proxy,完成代理。不多贅述
# prformance
直接飲用官方說明
用法:
設置為 true 以在瀏覽器開發工具的性能/時間線面板中啟用對組件初始化、編譯、渲染和打補丁的性能追蹤。只適用於開發模式和支持 performance.mark API 的瀏覽器上。
使用的話,需要安裝一個插件,我一直安裝不成功,不知道為啥,有一篇文章寫得很好這里,可以查看。
# productionTip
- 源碼地址:platforms/web/runtime/index.js
...
if (process.env.NODE_ENV !== 'production' &&
process.env.NODE_ENV !== 'test' &&
config.productionTip !== false &&
typeof console !== 'undefined'
) {
console[console.info ? 'info' : 'log'](
`You are running Vue in development mode.\n` +
`Make sure to turn on production mode when deploying for production.\n` +
`See more tips at https://vuejs.org/guide/deployment.html`
)
...
如官方說明
用法:
設置為 false 以阻止 vue 在啟動時生成生產提示。
- 關於全局配置部分總結:
- 個人將全局配置部分算是淺顯的走了一遍,說實話,其中部分內容我幾乎都沒有用過,而且確實這個梳理,更多像是,CV一下文檔和源碼代碼。其中細節沒有去深究,
- 整個Vue api 梳理的想法就是讓我重新對Vue進行了解一下,畢竟Vue是個很大的項目,對於每個API不可能都去研究源碼的細節,但求,有個概念,實操有個印象,也算事我對Vue,進一步了解。
- 關於源碼部分,我也在同時學習,主要還是准備針對性的對他數據驅動和響應式的核心 處理部分進行學習了解,當然這個Api系列,也是在個人有精力同時研究有意義的情況下,回去深入了解的,如果精力不夠或是從未涉及,我會找相對應我覺得不錯的博客放出鏈接。
- 本文全是個人向內容,希望對看到的你,有所幫助,也是我對Vue學習的一個梳理吧。