vue源碼分析系列之響應式數據(一)

概述

在使用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中渲染部分的內容。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章