引入Vue后進(jìn)行了global-api的初始化,那么現(xiàn)在就到了第二步的初始化,文件入口為:
src\entries\web-runtime.js
首先是4個(gè)方法綁定在Vue.config上
isUnknownElement --方法解釋看methods realizes目錄 源碼在platforms\web\util\element.js
isReservedTag --方法解釋看methods realizes目錄 源碼在platforms\web\util\element.js
getTagNamespace --這個(gè)方法就不做解釋了比較簡單 源碼在platforms\web\util\element.js
mustUseProp --方法解釋看methods realizes目錄 源碼在platforms\web\util\attrs.js
然后這里到了extend方法,這個(gè)和Vue.extend不一樣的,我們來看一下src\shared\util
export function extend (to: Object, _from: ?Object): Object {
for (const key in _from) {
to[key] = _from[key]
}
return to
}
好吧,這個(gè)就是object的繼承吧,把后者的屬性賦值給前者,最后返回前者,然后我們找到這兩個(gè)東西
platforms/web/runtime/directives/index
platforms/web/runtime/components/index
這兩個(gè)文件夾里面有6個(gè)js文件,很熟悉的東東,就是常用的v-model,v-show,transition組件了,在上
一篇有提到過的
// 還記得Vue.options這個(gè)值是這樣的
Vue.options = {
components: {
KeepAlive: {
},
// 這兩個(gè)是Vue自帶的,在另一個(gè)地方初始化的,這里暫時(shí)這樣理解就好,存在這兩個(gè)方法的
Transition: {
},
TransitionGroup: {
},
my-component: {
}
},
directives: {
// 這兩個(gè)是Vue自帶的,在另一個(gè)地方初始化的,這里暫時(shí)這樣理解就好,存在這兩個(gè)方法的
model: {
},
show: {
},
// 如果經(jīng)過了第一種方法注冊指令,那么就會添加下面一個(gè)了
demo: {
bind: function () {
// some methods
}
}
},
filters: {}
}
那么自帶的東東就是在這里初始化的了通過這兩個(gè)操作,這里水平有限,暫時(shí)擱著 - -#
extend(Vue.options.directives, platformDirectives)
extend(Vue.options.components, platformComponents)
然后到了Vue.prototype.patch
這個(gè)東西涉及太多,包括vdom和渲染rander等等,水平有限,暫時(shí)擱著 - -#
主要就是看這個(gè)Vue.prototype.$mount
這里有個(gè)query(el),這個(gè)源碼在platforms\web\util\index.js里面,主要就是獲取el這個(gè)dom元素
然后執(zhí)行this._mount(el, hydrating),這個(gè)方法后續(xù)再講,這個(gè)是Vue實(shí)例啟動了的方法,至于第二個(gè)
參數(shù)hydrating,<span style="font-weight: bold;margin-bottom: 10px;color: #FF0000">這個(gè)貌似是服務(wù)端渲染才要用到的,個(gè)人猜想</span>
然后再到了同目錄下的web-runtime-with-compiler.js文件,這個(gè)文件重寫了$mount方法,查了下資料以及
官方的說法大概就是,獨(dú)立構(gòu)建時(shí)帶有模板編譯功能的初始化方法,還是直接看代碼吧
首先const mount = Vue.prototype.$mount緩存了上面的$mount方法,然后重寫,query(el)獲取dom,
然后判斷dom不能是body標(biāo)簽或者h(yuǎn)tml標(biāo)簽,獲取this.$options,這個(gè)實(shí)際上就是new Vue傳入的參數(shù)
后面講數(shù)據(jù)綁定的時(shí)候會經(jīng)常用到,這里舉個(gè)栗子說明一下吧:
var options = {
el: '#app',
data () {
return {
msg: 'hello world'
}
}
}
new Vue(options)
// 這個(gè)就是這個(gè)options,一個(gè)對象字面量,然后有if (!options.render)這樣的一個(gè)判斷,這里要
// 說下Vue的三種寫法:Render函數(shù),template模板,el綁定
第一種:Render函數(shù)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Render函數(shù)</title>
</head>
<body>
<div id="app">
</div>
</body>
<script type="text/javascript" src="vue.js"></script>
<script>
var options = {
el: '#app',
data () {
return {
msg: 'hello world'
}
},
render: function (createElement) {
return createElement('h1', this.msg)
}
}
new Vue(options)
</script>
</html>
// 這種寫法就是最底層的寫法,性能最好,但是難以理解,這里方法還有更復(fù)雜的方式,后面的兩種寫法
// 最后會經(jīng)過一些列的算法,比如AST解析再轉(zhuǎn)換成render函數(shù),最后還是得出這樣的形式,這里這種方
// 法不討論了
第二種:template模板,這里又有三種情況
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>template模板</title>
</head>
<body>
<div id="app">
</div>
</body>
<script type="text/javascript" src="vue.js"></script>
<script>
var options = {
el: '#app',
data () {
return {
msg: 'hello world'
}
},
template: '<h1 style="color: red;">{{msg}}</h1>'
}
new Vue(options)
</script>
</html>
// 這是第一種情況
// 這種寫法因?yàn)闆]有render函數(shù),則會進(jìn)入if語句里面,然后這里let template = options.template獲取
// 字符串模板后就直接進(jìn)入compileToFunctions這個(gè)方法了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>template模板</title>
</head>
<body>
<div id="app">
</div>
</body>
<script type="text/javascript" src="vue.js"></script>
<script id="my-tel">
`<h1 style="color: blue;">{{msg}}</h1>`
</script>
<script>
var options = {
el: '#app',
data () {
return {
msg: 'hello world'
}
},
template: '#my-tel'
}
new Vue(options)
</script>
</html>
// 這是第二種情況
// 這種寫法因?yàn)闆]有render函數(shù),則會進(jìn)入if語句里面,然后進(jìn)入if (template.charAt(0) === '#')
// idToTemplate方法執(zhí)行,方法解釋見methods realizes目錄
// 之后就直接進(jìn)入compileToFunctions這個(gè)方法了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>template模板</title>
</head>
<body>
<div id="app">
</div>
<template id="typeByMe">
<div>
<p style="color: red">{{msg}} No.1</p>
<p style="color: blue">{{msg}} No.2</p>
</div>
</template>
</body>
<script type="text/javascript" src="vue.js"></script>
<script>
var options = {
el: '#app',
data () {
return {
msg: 'hello world'
}
},
template: document.getElementById('typeByMe')
}
new Vue(options)
</script>
</html>
// 第三種則走if (template.nodeType)這里,這個(gè)就很好理解了,因?yàn)檫@里的template是dom節(jié)點(diǎn)
// 所以里面直接就獲取innerHTML了,和第二種差不多,只是這里自己手動獲取了dom節(jié)點(diǎn)
// 之后就直接進(jìn)入compileToFunctions這個(gè)方法了
第三種:el綁定方法,這種便是我們最常用的了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>el綁定</title>
</head>
<body>
<div id="app">
<p style="color: blue">{{msg}}</p>
</div>
</body>
<script type="text/javascript" src="vue.js"></script>
<script>
var options = {
el: '#app',
data () {
return {
msg: 'hello world'
}
}
}
new Vue(options)
</script>
</html>
// 這種則走template = getOuterHTML(el)這個(gè)方法,這里el就是dom節(jié)點(diǎn),通過query(el)方法獲取的
// getOuterHTML方法就在下面,獲取元素的el元素的html片段,最后template也是一段字符串模板了
// 之后就直接進(jìn)入compileToFunctions這個(gè)方法了,這個(gè)方法先不看了,很復(fù)雜
// 這個(gè)方法返回對象{ render, staticRenderFns },然后綁定在options上面
// options.render = render 也就是下面這個(gè)方法
function anonymous() {
with(this){return _c('div',{attrs:{"id":"app"}},[_c('p',{staticStyle:{"color":"blue"}},[_v(_s(msg))])])}
}
這個(gè)并不是一個(gè)自定義的方法名字,它的創(chuàng)建其實(shí)是這樣子的,算是一種比較特殊的創(chuàng)建函數(shù)方式
var code = 'var co = 12;co = co + 1;return co'
var a = new Function(code)
console.log(a)
輸出 =>
function anonymous() {
var co = 12;co = co + 1;return co
}
console.log(a())
輸出 => 13
最后還是調(diào)用先前緩存下來的mount方法,這個(gè)下一節(jié)再說
關(guān)于這個(gè)可以參考這位大神的文章
【Vue源碼探究二】從 $mount 講起,一起探究Vue的渲染機(jī)制
<p style="font-weight: bold;margin-bottom: 10px;color: #FF0000">剩下的幾個(gè)問題</p>
Vue.set = set // 涉及到Vue的數(shù)據(jù)響應(yīng)式系統(tǒng),先保留
Vue.delete = del // 涉及到Vue的數(shù)據(jù)響應(yīng)式系統(tǒng),先保留
Vue.nextTick = util.nextTick // 水平有限,看不懂 - -#
initMixin(Vue) // 這個(gè)后面再講
initExtend(Vue) // 水平有限,看不懂 - -#
extend(Vue.options.directives, platformDirectives) // 水平有限,看不懂 - -#
extend(Vue.options.components, platformComponents) // 水平有限,看不懂 - -#
Vue.prototype.__patch__ // 水平有限,看不懂 - -#
compileToFunctions // 水平有限,看不懂 - -#