概述
在使用vue的時候,data,computed,watch是一些經常用到的概念,那麼他們是怎麼實現的呢,讓我們從一個小demo開始分析一下它的流程。
demo演示代碼片段
html代碼
<!DOCTYPE html>
<html>
<head>
<title>demo</title>
<script src="../../dist/vue.js"></script>
</head>
<body>
<div id="demo">
<div>
<p>a:{{a}}</p>
<p>b: {{b}}</p>
<p>a+b: {{total}}</p>
<button @click="addA">a+1</button>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
js代碼
var demo = new Vue({
el: '#demo',
data: {
a: 1,
b: 2,
},
computed:{
total() {
return this.a + this.b;
}
},
methods: {
addA() {
this.a += 1;
}
}
})
簡單說明
這是一段簡單的代碼。頁面中引用了data中的a,b屬性,計算屬性total則是求a與b的和。頁面中提供一個button按鈕,每點擊一次會對屬性a+1。total屬性則會根據依賴變化,判斷total值是否需要更新,並在合適的時機更新。
代碼初始化部分
new一個Vue的時候做了什麼
當我們new一個vue時,實際上執行了vue的構造函數,這個構造函數內部掛載了很多方法,可以在我的上一篇文章中看到。構造函數內部調用了_init方法,那我們看看init裏做了什麼即可。
function Vue (options) {
this._init(options)
}
init函數
Vue.prototype._init = function (options?: Object) {
const vm: Component = this
// a uid
vm._uid = uid++
// 通過_isVue標識該對象不需要被做響應式處理。
vm._isVue = true
// 合併構造函數上掛載的options與當前傳入的options.
if (options && options._isComponent) {
initInternalComponent(vm, options)
} else {
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
)
}
// 非生產環境,包裝實例本身,在後期渲染時候,做一些校驗提示輸出。
if (process.env.NODE_ENV !== 'production') {
initProxy(vm)
} else {
vm._renderProxy = vm
}
// expose real self
vm._self = vm
// 初始化生命週期相關
initLifecycle(vm)
// 初始化事件相關
initEvents(vm)
// 初始化渲染相關
initRender(vm)
// 這裏調用beforeCreate鉤子
callHook(vm, 'beforeCreate')
// inject/provide相關處理
initInjections(vm) // resolve injections before data/props
// 初始化data、props以及computed,watch等。
initState(vm)
initProvide(vm) // resolve provide after data/props
// 調用created鉤子
callHook(vm, 'created')
if (vm.$options.el) {
// 掛載組件到頁面上的
vm.$mount(vm.$options.el)
}
}
這篇文章講述的內容,需要我們着重關注一下initState
函數與vm.$mount
中渲染部分的內容。