Vue學習系列(一)——初識Vue.js核心

 前言

    vue.js是一套構建用戶界面的漸進式框架,vue.js的目標是經過儘量簡單的API實現響應的數據綁定和組合的視圖組件。vue

    vue經過DOM事件操做和指令來進行視圖層和模型層的相互通信,會爲每一處須要動態更新的DOM節點建立一個指令對象。每當一個指令對象觀測的數據變化時,它便會對所綁定的目標節點執行相應的DOM操做。基於指令的數據綁定使得具體的DOM操做都被合理地封裝在指令定義中,業務代碼只須要涉及模板和對數據狀態的操做便可,這使得應用的開發效率和可維護性都大大提高。node

    所以,數據綁定,組件是整個vue的核心。響應的數據綁定就是數據驅動視圖的概念。它讓你在寫 Web 應用介面時,只須要關注兩件事:數據如何展現和數據如何變化。一旦數據發生變化時,好比用戶輸入,或者 ajax 請求返回後數據發現修改,對應的視圖介面會自動的進行更新。ajax

 原理

    vue.js是MVVM的架構,如圖:數組

 

    從圖中能夠看出視圖層和模型層的相互傳遞,經過用戶操做來綁定一些DOM事件來從新渲染到視圖層。具體的內部架構以下圖:瀏覽器

 

 開始

1、 數據綁定架構

    實現方式:數據綁定便是視圖層和模型層的雙向綁定。即數據的改變驅動了視圖的自動更新。  app

    經過ViewModel控制,修改數據,從而控制View的展現,實現MVVM的思想。框架

 

    裏面的兩個屬性getter和setter,在這兩個函數內部實現依賴的收集和觸發,並且完美支持嵌套的對象結構。對於數組,則經過包裹數組的可變方法(好比push)來監聽數組的變化。這使得操做Vue.js的數據和操做原生對象幾乎沒有差異。dom

  • Obejct.defineProperty 【提供getter 和 setter】
  • Observer 【提供getter 和 setter】—— 訂閱者模式,一個目標對象管理全部相依於它的觀察者對象,而且在它自己的狀態改變時主動發出通知,用來實時事件處理系統。
  • watcher 【提供getter 和 setter】 —— 模板和 Observer 對象結合在一塊兒的紐帶
  • Dep 【負責收集watcher】
  • Directive 【處理Vue模板指令】

    observe -> 觸發setter -> watcher -> 觸發update -> Directive -> 觸發update -> 指令(如上圖流程所示)函數

<span>Hello, this is {{name}}</span>
<script>
var app = new Vue({
    el : '#app',
    data : {
        name: 'i3yuan'
    }
})

</script>

new Vue 執行時作了什麼

function Vue(option) {
  var data = option.data 
  this.data = data
  // 掛載 getter 和 setter
  observe(data, this)
  var id = option.el
  // 編譯 模板
  var dom = new Compile(document.querySelector(id), this)
  // 把編譯好的模板掛載到 #app 上
  document.querySelector(id).appendChild(dom)
}
//observe構造函數
function observe(obj, vm) {
  Object.keys(obj).forEach(key => {
    defineReactive(vm, key, obj[key])
  })
}
//defineReactive
function defineReactive(vm, key, val) {
  // 爲每一個變量分配一個 dep實例
  var dep = new Dep()
  // 配置getter和setter而且掛載到vm上
  Object.defineProperty(vm, key, {
    get() {
      if ( Dep.target ) {
        // JS的瀏覽器單線程特性, 保證整個全局變量在同一時間內, 只有一個監聽器使用
        dep.addSub(Dep.target)
      }
      return val
    },
    set(newVal) {
      if ( newVal == val ) return;
      val = newVal;
      // 做爲發佈者發出通知
      dep.notify()
    }
  })
}

//Dep構造函數
function Dep() {
  // 存放watcher
  this.subs = []
}

Dep.prototype = {
  // 添加watcher, 也就是添加訂閱
  addSub(sub) {
    this.subs.push(sub)
  },
  // 通知全部watcher
  notify() {
    this.subs.forEach(sub => {
      sub.update()
    })
  }
}



function Compile(node, vm) {
  if(node) {
    this.$frag = this.nodeToFragment(node, vm)
    return this.$frag
  }
}

//watcher構造函數
function Watcher(vm, node, name, type) {
  // 單例, 使用緣由未知
  Dep.target = this
  // 姓名
  this.name = name;
  // 呵呵噠 uid
  this.id = ++uid;
  // 與變量相關的Node節點
  this.node = node;
  // vm 實例
  this.vm = vm;
  // 變量類型  nodeValue  || value
  this.type = type;
  // 觸發本身原型上的update方法
  this.update()
  // Watcher 實例建立結束就把單例置空
  Dep.target = null
}


Watcher.prototype = {
  update() {
    this.get()
    if(!batcher) {
      // bastcher 單例
      batcher = new Batcher()
    }
    // 加入隊列
    batcher.push(this)
  },
  // 獲取新值掛到本身的實例上
  get() {
    this.value = this.vm[this.name]  // 觸發getter
  }
}

 整個流程:

new Vue –> Observe 掛載 setter 和 getter –> Compile 編譯模板 –> 爲每一個指令分配一個watcher –> 建立時會調用一次watcher.update 將本身加入到batcher的隊列 –>
而且此時會觸發 getter 將watcher加入dep –> batcher 統一來處理watcher後初始化本身 –> 當用戶修改某個變量時 –> dep通知watcher –> watcher又被加入batcher處理 –> watcher 更新dom 

2、視圖組件:

    組件,相信大部分開發人員在開發現代框架的時候都或多或少的遇到一些組件,可想而知,現代框架已經走向了組件化的道路,雖然不一樣的主流框架都有不一樣封裝組件的方式,可是核心思想都差很少同樣。經過分離頁面,使得整個頁面由不少個組件構成,給咱們的第一個印象就是,就像咱們平時使用到的MVC中的分視圖,或者子視圖,可是又不同,雖然組件是一部分,可是倒是本身的一個總體,和其餘組件相互獨立,高內聚低耦合,能夠經過自定義標籤的形式來使用。

    所以,在開發中, 把整一個網頁的拆分紅一個個區塊,每一個區塊咱們能夠看做成一個組件。網頁由多個組件拼接或者嵌套組成:

// 定義一個名爲 Mycomponent  的新組件
Vue.component('Mycomponent', {
    // 模板
    template: '<div>{{msg}} {{privateMsg}}</div>',
    // 接受參數
    props: {
        msg: String    
    },
    // 私有數據,須要在函數中返回以免多個實例共享一個對象
    data: function () {
        return {
            privateMsg: 'component!'

        }
    }
})
<Mycomponent msg="i3yuan"></Mycomponent>

組件的核心選項:

1 模板(template):模板聲明瞭數據和最終展示給用戶的DOM之間的映射關係。

2 初始數據(data):一個組件的初始數據狀態。對於可複用的組件來講,這一般是私有的狀態。

3 接受的外部參數(props):組件之間經過參數來進行數據的傳遞和共享。

4 方法(methods):對數據的改動操做通常都在組件的方法內進行。

5 生命週期鉤子函數(lifecycle hooks):一個組件會觸發多個生命週期鉤子函數,最新2.0版本對於生命週期函數名稱改動很大。

6 私有資源(assets):Vue.js當中將用戶自定義的指令、過濾器、組件等統稱爲資源。一個組件能夠聲明本身的私有資源。私有資源只有該組件和它的子組件能夠調用。

注意事項

  • 組件註冊必定要在實例化Vue對象以前,不然會報錯
  • 屬性名爲components,s千萬別忘了
  • 不論是全局組件仍是局部組件,data都必須是一個函數,且return不能換行
  • 由於this指向的問題,建議用es5的方式寫方法

 總結

1.經過官方文檔的學習和總結,認識到了vue的框架和通信方式,以視圖組件和數據綁定爲核心構建完整的漸進式的框架。

2.從上述的兩大核心的描述,咱們大致理解了Vue的構建方式,經過基本的指令控制DOM,實現提升應用開發效率和可維護性。

3.下一節咱們將對Vue視圖組件的核心概念進行詳細說明。

相關文章
相關標籤/搜索