實(shí)例講解vue源碼架構(gòu)
下載
去github上下載Vue https://github.com/vuejs/vue
npm install npm run dev
運(yùn)行起來(lái)
rollup + flow
vue使用使用rollup打包,flow規(guī)范數(shù)據(jù)類(lèi)型
rollup可以先用webpack套用,讀起來(lái)差不多,時(shí)間有限,畢竟只有5分鐘,這個(gè)就不用去看rollup文檔了
入口
打開(kāi)package.json
我們看scripts配置
"dev": "rollup -w -c scripts/config.js --environment TARGET:web-full-dev", "dev:cjs": "rollup -w -c scripts/config.js --environment TARGET:web-runtime-cjs-dev",
找到scripts/config.js
打開(kāi)
根據(jù)配置TARGET的不同會(huì)選擇不同的config
同時(shí)在這里配置了process.env.NODE_ENV 環(huán)境
TARGET有CommonJS,ES Modules,UMD關(guān)于js引入類(lèi)型的
還有weex,ssr
'web-runtime-cjs-dev': {
entry: resolve('web/entry-runtime.js'),
dest: resolve('dist/vue.runtime.common.dev.js'),
format: 'cjs',
env: 'development',
banner
}
在alias.js下設(shè)置了別名路徑
我們先介紹src/platforms
里面有web和weex 分別的web和weex入口
在web文件下是CommonJS,ES Modules,UMD關(guān)于js引入類(lèi)型,server的打包入口
打開(kāi)web/entry-runtime.js
引入
import Vue from './runtime/index' export default Vue
打開(kāi)./runtime/index
import Vue from 'core/index'
Vue.prototype.$mount = function (
el?: string | Element,
hydrating?: boolean
): Component {
el = el && inBrowser ? query(el) : undefined
return mountComponent(this, el, hydrating)
}
export default Vue
在vue原型上添加了mount方法
處理了devtools,沒(méi)有安裝提醒安裝devtools
給了這句提示dev環(huán)境提示
You are running Vue in development mode. Make sure to turn on production mode when deploying for production. See more tips at https://vuejs.org/guide/deployment.html
platforms目錄夾講解完畢
core目錄
打開(kāi)core/instance/index
映入眼前的是
function Vue (options) {
if (process.env.NODE_ENV !== 'production' &&
!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword')
}
this._init(options)
}
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
export default Vue
先執(zhí)行的是initMixin(Vue)
打開(kāi)init
export function initMixin (Vue) {
Vue.prototype._init = function (options?: Object) {
const vm = this
// a uid
vm._uid = uid++
let startTag, endTag
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
startTag = `vue-perf-start:${vm._uid}`
endTag = `vue-perf-end:${vm._uid}`
mark(startTag)
}
// a flag to avoid this being observed
vm._isVue = true
// 處理傳入的options
// merge options
if (options && options._isComponent) {
// optimize internal component instantiation
// since dynamic options merging is pretty slow, and none of the
// internal component options needs special treatment.
initInternalComponent(vm, options)
} else {
// 傳入的options,默認(rèn)的options一起合并掛載到vm.$options上
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
)
}
/* istanbul ignore else */
if (process.env.NODE_ENV !== 'production') {
// 代理
initProxy(vm)
} else {
vm._renderProxy = vm
}
// 生命周期
initLifecycle(vm)
// emit on 事件
initEvents(vm)
// 處理render vdom
initRender(vm)
callHook(vm, 'beforeCreate')
// 處理Injections
initInjections(vm) // resolve injections before data/props
// 雙向數(shù)據(jù)綁定,監(jiān)聽(tīng)訂閱
initState(vm)
initProvide(vm) // resolve provide after data/props
callHook(vm, 'created')
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
vm._name = formatComponentName(vm, false)
mark(endTag)
measure(`vue ${vm._name} init`, startTag, endTag)
}
// 渲染到dom
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
}
}
lifecycle
打開(kāi) lifecycle
export function callHook (vm: Component, hook: string) {
// disable dep collection when invoking lifecycle hooks
pushTarget()
//執(zhí)行對(duì)象的周期函數(shù),周期函數(shù)最后被處理成數(shù)組
const handlers = vm.$options[hook]
const info = `${hook} hook`
if (handlers) {
for (let i = 0, j = handlers.length; i < j; i++) {
invokeWithErrorHandling(handlers[i], vm, null, vm, info)
}
}
if (vm._hasHookEvent) {
vm.$emit('hook:' + hook)
}
popTarget()
callHook 的時(shí)候,是執(zhí)行相應(yīng)周期,開(kāi)發(fā)者在周期函數(shù)里所寫(xiě)的
Events
initEvents實(shí)現(xiàn)了 emit on 等方法,請(qǐng)參考監(jiān)聽(tīng)者訂閱者模式,這里不詳解
render
renderMixin函數(shù)
添加了 $nextTick _render 原型對(duì)象
$nextTick會(huì)在dom跟新后立即調(diào)用
nextTick(fn, this)是一個(gè)自執(zhí)行函數(shù)
_render返回的是node的js數(shù)據(jù),還不是dom
做了Vdom
initRender函數(shù)
給vm添加了_c和 $createElement用來(lái)渲染的方法
state
if (!(key in vm)) {
proxy(vm, `_props`, key)
}
給vue屬性做代理,訪問(wèn)this.a可以得到this.data.a 的值
export function initState (vm: Component) {
vm._watchers = []
const opts = vm.$options
if (opts.props) initProps(vm, opts.props)
if (opts.methods) initMethods(vm, opts.methods)
if (opts.data) {
initData(vm)
} else {
observe(vm._data = {}, true /* asRootData */)
}
if (opts.computed) initComputed(vm, opts.computed)
if (opts.watch && opts.watch !== nativeWatch) {
initWatch(vm, opts.watch)
}
}
給數(shù)據(jù)做監(jiān)聽(tīng)
stateMixin函數(shù)
添加原型對(duì)象
Vue.prototype.$set = set Vue.prototype.$delete = del
其他
src/compiler 做了編譯處理
core/componetd 做了keep-alive
core/util 封裝了通用方法
core/vdom vdom算法
以上整體架構(gòu)分析完畢

相關(guān)文章
Vue?socket.io模塊實(shí)現(xiàn)聊天室流程詳解
vue-socket.io其實(shí)是在socket.io-client(在瀏覽器和服務(wù)器之間實(shí)現(xiàn)實(shí)時(shí)、雙向和基于事件的通信)基礎(chǔ)上做了一層封裝,將socket掛載到vue實(shí)例上,同時(shí)可使用sockets對(duì)象輕松實(shí)現(xiàn)組件化的事件監(jiān)聽(tīng),在vue項(xiàng)目中使用起來(lái)更方便2022-12-12
誤引用vuex-persistedstate導(dǎo)致用戶(hù)信息無(wú)法清除問(wèn)題及解決
這篇文章主要介紹了誤引用vuex-persistedstate導(dǎo)致用戶(hù)信息無(wú)法清除問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
Vue實(shí)現(xiàn)動(dòng)態(tài)樣式的多種方法匯總
本文要給大家介紹Vue實(shí)現(xiàn)動(dòng)態(tài)樣式的多種方法,下面給大家?guī)?lái)幾個(gè)案列,需要的朋友可以借鑒研究一下。2021-06-06
Vue.js實(shí)現(xiàn)圖片的隨意拖動(dòng)方法
下面小編就為大家分享一篇Vue.js實(shí)現(xiàn)圖片的隨意拖動(dòng)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
VUE使用router.push實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)和傳參方式
這篇文章主要介紹了VUE使用router.push實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)和傳參方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
如何在vue項(xiàng)目中嵌入jsp頁(yè)面的方法(2種)
這篇文章主要介紹了如何在vue項(xiàng)目中嵌入jsp頁(yè)面的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02
vue之?dāng)?shù)據(jù)交互實(shí)例代碼
本篇文章主要介紹了vue之?dāng)?shù)據(jù)交互實(shí)例代碼,vue中也存在像ajax和jsonp的數(shù)據(jù)交互,實(shí)現(xiàn)向服務(wù)器獲取數(shù)據(jù),有興趣的可以了解一下2017-06-06
vue中echarts的用法及與elementui-select的協(xié)同綁定操作
這篇文章主要介紹了vue中echarts的用法及與elementui-select的協(xié)同綁定操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11

