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
Observer
對象結合在一塊兒的紐帶observe -> 觸發setter -> watcher -> 觸發update -> Directive -> 觸發update -> 指令(如上圖流程所示)函數
<span>Hello, this is {{name}}</span> <script> var app = new Vue({ el : '#app', data : { name: 'i3yuan' } }) </script>
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當中將用戶自定義的指令、過濾器、組件等統稱爲資源。一個組件能夠聲明本身的私有資源。私有資源只有該組件和它的子組件能夠調用。
注意事項
1.經過官方文檔的學習和總結,認識到了vue的框架和通信方式,以視圖組件和數據綁定爲核心構建完整的漸進式的框架。
2.從上述的兩大核心的描述,咱們大致理解了Vue的構建方式,經過基本的指令控制DOM,實現提升應用開發效率和可維護性。
3.下一節咱們將對Vue視圖組件的核心概念進行詳細說明。