import config from '../config' import { noop } from 'shared/util' let warn = noop let tip = noop let formatComponentName
//如果是在開發環境 或者 在測試環境 if (process.env.NODE_ENV !== 'production') {
//如果 有 window.console, 這里用typeof判斷, 是因為如果用 if(window.console)
//在沒有console的瀏覽器中, window對象會增加一個屬性 console, 雖然它的值是undefined, 不太確定 const hasConsole = typeof console !== 'undefined'
//這個正則就是把連接符轉換成的駝峰寫法, 並且第一個字符大寫 ^|[-_] 的意思是 字符串的開頭, 或者 -_ 后面的一個字符
// str = 'ms-border' 經過 classify(str) => MsBorder
//這里 ?: 是希望在它的這個括號不用捕獲了, 也就是 (?:^|[-_])這個整體, 正則不會把它當成是一個子項, 所以 $1就是(\w)
//?: 非常常見, 是為了提高正則的性能
const classifyRE = /(?:^|[-_])(\w)/g const classify = str => str .replace(classifyRE, c => c.toUpperCase()) .replace(/[-_]/g, '')
//classifyRE = /(^|[-_])(\w)/g 如果寫成這樣 str.replace(classifyRE,function(a,b,c){ console.log( 'a:'+a +' b:' +b+ ' c:' +c ) })
//會輸出 a:a b: c:a a:-p b:- c:p
//可以看到 b第一次是開頭, 開頭的位置, 沒有值, 所以第一次b是空
//第二次是 - warn = (msg, vm) => {
//如果配置的console.silent, 就不會打印錯誤日志 if (hasConsole && (!config.silent)) { console.error(`[Vue warn]: ${msg} ` + (
//取得vm的名字 , 如果獲取不到, 提示用戶配置一個 vm ? formatLocation(formatComponentName(vm)) : '' )) } }
//這個函數功能和上面一樣, 但是上面的程度比較嚴重, 用了console.error, 這里是 console.warn tip = (msg, vm) => { if (hasConsole && (!config.silent)) { console.warn(`[Vue tip]: ${msg} ` + ( vm ? formatLocation(formatComponentName(vm)) : '' )) } } formatComponentName = (vm, includeFile) => {
//看來如果是根組件, 它會有一個屬性.$root 指向它自己 if (vm.$root === vm) { return '<Root>' }
//這三元寫的, 可讀性太差, 源碼這么寫是為了節省代碼, 簡單的來說就是先看option有沒自定義name,如果沒有就用vm.name, 這個name應該是vue自己配置的一個隨機數 let name = typeof vm === 'string' ? vm : typeof vm === 'function' && vm.options ? vm.options.name : vm._isVue ? vm.$options.name || vm.$options._componentTag : vm.name
const file = vm._isVue && vm.$options.__file
if (!name && file) {
// abc/dd.vue 獲取其中的dd , 也就是組件的名稱 const match = file.match(/([^/\\]+)\.vue$/)
//全匹配時 dd.vue, 第一個子項是 dd name = match && match[1] } return (
// 這里使用了es6的語法 ${變量名}, 最終返回駝峰 (name ? `<${classify(name)}>` : `<Anonymous>`) +
//提示文件路徑出錯 (file && includeFile !== false ? ` at ${file}` : '') ) }
// 就是返回那段 (found in component <...> ) const formatLocation = str => { if (str === `<Anonymous>`) {
// 如果是本地調試? 提示用戶配置名字, 跟容易跟蹤出錯信息 str += ` - use the "name" option for better debugging messages.` } return `\n(found in ${str})` } } export { warn, tip, formatComponentName }