1. 程式人生 > >Vue渲染原理及其雙向資料繫結詳解

Vue渲染原理及其雙向資料繫結詳解

雙向資料繫結原理

1. 新建vue例項

var data = {
        text:'hello world!'
    };
    var vm = new Vue({
        el:'#app',
        data
    });

2. 將vue例項中的el HTML模板渲染進DOM

 function nodeToFragment(node,vm) {
        var frag = document.createDocumentFragment(),//建立DocumentFragment片段
            child;
        while
(child = node.firstChild){//依次取node的子節點將其新增到frag中, compile(child,vm);//新增到DOM之前需對child和Vue例項進行繫結以監聽彼此的變化 frag.appendChild(child);//此方法會同時刪除node中的child節點 } return frag; } var dom = nodeToFragment(document.getElementById(id),this); document.getElementById(id).appendChild(dom);//將上面返回的節點新增進DOM

3. 將vue例項中的el HTML模板渲染進DOM,compile詳解

function compile(node,vm) {//node為el的子節點
        var reg = /\{\{(.*)\}\}/,// .為匹配除\r\n之外的任意單個字元,*為匹配前面字元任意多次
            name;
        //元素節點
        if(node.nodeType == 1){
            var attr = node.attributes;
            for(var i = 0; i<attr.length; i++){//遍歷el的子節點的屬性,若其有v-model屬性,變從vm.data中取v-model屬性對應的值value,將value作為el的子節點的value|innerHTML值,因為v-model一般對應input元素
if(attr[i].nodeName == 'v-model'){ VModelEle.push(node); name = attr[i].nodeValue; node.value = vm.data[name]; node.innerHTML= vm.data[name]; node.addEventListener('input',function (e) { vm.data[name] = e.target.value; });//此處已假定node為input元素,監聽此input,若其value有變化則將其反映到vm.data的name中,name為'v-model'屬性對應的nodeValue。到這裡,已經實現了DOM到vm.data的繫結。 new Watcher(vm,node,name);//這一步實現vm.data到DOM的繫結 node.removeAttribute('v-model');//從node中刪除v-model屬性。 break; } } } //若node為文字節點,判斷文字節點的值是不是{{}}這種形式。 if(node.nodeType == 3){ if(reg.test(node.nodeValue)){ name = RegExp.$1;//RegExp為全域性物件,$1-$9為最新匹配到的9個正則表示式中帶括號的項,只能儲存最新9個 name = name.trim();//取reg = /\{\{(.*)\}\}/中括號內匹配到的值,name在vm.data中也有 new Watcher(vm,node,name);//為vm.name新增監聽器,實現從vm到DOM的繫結 } } }

4. 為vm.name新增監聽器,new Watcher(vm,node,name)

  • Dep方法詳情
 function Dep() {
        this.subs = [];
    }
    Dep.prototype = {
        addSub:function (sub) {
            this.subs.push(sub);//sub為Watcher例項
        },
        notify:function () {
            this.subs.forEach(function (sub) {
                sub.update();//通知所有Watcher更新DOM
            })
        }
    };
  • Watcher方法詳情
 function Watcher(vm,node,name) {
        Dep.target = this;
        this.name = name;
        this.node = node;
        this.vm = vm;
        this.update();//每次new Watcher時都要用vm.data[this.name]資料更新this.node.nodeValue,即實現vm.data到DOM的繫結。
        Dep.target = null;
    }
    Watcher.prototype = {
        update:function () {
            this.node.nodeValue = this.vm.data[this.name];
        }
    };
  • vm.data中的每個資料重寫其Object.defineProperty中的setget方法
 function observe(obj) {
        Object.keys(obj).forEach(function (key) {
            defineReactive(obj,key,obj[key]);
        })
    }
  function defineReactive(obj,key,val){
//defineReactive即為每個data屬性新增setter和getter,當在外部重新為data新增新屬性時,還會呼叫此方法,介面為Vue.$set(obj,kay,value);。
        var dep = new Dep();

        Object.defineProperty(obj,key,{

        //因為讀取vm.data的地方比較多,比如compile方法中的node.value =vm.data[name];node.innerHTML= vm.data[name];而只有第一次為vm.data[name]新增Watcher時才需將此Watcher新增進Dep的subs中,因為new Watcher會執行Watcher的update方法,其中會讀取this.vm.data[this.name]。

            get:function () {
                if(Dep.target){
                    dep.addSub(Dep.target);
                }
                return val;
            },
            //當重寫vm.data中的屬性時,就重置vModelEles中元素的value,vModelEles為所有有v-model屬性的元素
            set:function (value) {
                for(var ele in vModelEles){
                    vModelEles[ele].value = value;
                }
                if(value == val) return;
                //若兩次值不同,將呼叫dep.notify方法,啟動所有Watcher,更改nodeValue
                val = value;
                dep.notify();
                console.log(val);
            }
        });
    }

雙向資料繫結原理總結

  • 從DOM到vm.data很簡單,即addEventListener監聽DOM的變化,將其值寫到vm.data中即可。
  • 從vm.data到DOM:
    • 為出現在DOM中的vm.data中的每個元素新增Watcher,所有的Watcher都存放在Dep的subs中
    • 每當vm.data有變化就呼叫Dep的notify方法,即取出所有subs中的Watcher,呼叫Watcher的updata方法,更新DOM

相關推薦

Vue渲染原理及其雙向資料

雙向資料繫結原理 1. 新建vue例項 var data = { text:'hello world!' }; var vm = new Vue({

vue.js和angular雙向資料的實現原理

一、vue雙向資料繫結 1、原理 資料劫持: vue.js 是採用資料劫持結合釋出者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter,getter,在資料變動時釋出訊息給訂閱者,觸發相應的監聽回撥。 2、實現步驟 要實現mv

vue的思中雙向資料原理

我們在面試中經常會被問道什麼是mvc 什麼是 mvvm  還有雙向資料繫結的原理:MVC:對專案的整體把控,M代表的是資料庫中的資料,V代表的是前端的檢視層,C用於處理M和V之間進行互動的業務邏輯(業務

vue.js v-model雙向資料vue.js form表單資料

vue.js v-model雙向資料繫結, vue.js form表單資料繫結   ================================ ©Copyright 蕃薯耀 2018年11月29日 http://fanshuyao.iteye.com/   &l

vue指令v-model(雙向資料)自動收集資料

前言:表單提交資料在網站頁面中是十分常見的,而這個表單資料的獲取在原生寫法甚至於JQ都是比較麻煩的(首先需要獲取DOM,然後獲取值)。 但是,在vue的專案環境下,表單資料的收集又該怎麼辦呢?(這種自己寫input元素的方法在實際專案中是不常用的哈,因為一般我們都會用一個UI庫,方便而快捷!

Vue】原始碼分析--雙向資料的實現

總結 Vue的雙向資料繫結主要通過Object.defineProperty來實現,先為所有的屬性加上get/set的監控,這樣當屬性值改變時就會觸發對應的set方法,然後再在set方法中通過觀

SpringMVC型別轉換、資料[附帶原始碼分析]

目錄 前言 SpringMVC是目前主流的Web MVC框架之一。  public String method(Integer num, Date birth) { ... } Http請求傳遞的資料都是字串String型別的,上面這個方法在Contro

WPF 資料。。。

資料繫結 控制元件之間的繫結 繫結源 source  資料提供者 繫結物件 target  接受資料的物件,被繫結的物件 對 繫結物件 進行資料繫結,將其的屬性,和繫結源的某個屬性進行繫結 純 xaml 繫結 < Grid > < T

vue實現雙向資料原理及實現篇 vue雙向原理及實現

轉自:canfoo#! vue的雙向繫結原理及實現 前言 先上個成果圖來吸引各位: 程式碼:                          &nb

angular,vue,react的基本語法—雙向資料、條件渲染、列表渲染、angular小案例

基本語法: 1、雙向資料繫結 vue 指令:v-model="msg" react constructor(){ this.state{ msg:"雙向資料繫結" } render(){ <input type="text" value={this.state

vue中實現雙向資料原理,使用了Object.defineproperty()方法,方法簡單

在vue中雙向資料繫結原理,我們一般都是用v-model來實現的 ,但一般在面試話會問到其實現的原理, 方法比較簡單,就是利用了es5中的一個方法.Object.defineproperty(),它有三個引數, Object.defineproperty(obj,'val',attrObject), 引數

vue 雙向資料原理,並實現一組雙向資料

1:vue 雙向資料繫結的原理: Object.defineProperty是ES5新增的一個API,其作用是給物件的屬性增加更多的控制Object.defineProperty(obj, prop, descriptor)引數 obj: 需要定義屬性的物件(目標物件)prop: 需被定義或修改的屬性名(物

vue雙向資料原理

Vue應用的是mvvm框架,view和model分離,然後通過vm雙向資料繫結,` <code class="hljs handlebars has-numbering" style="display: block; padding: 0px; color: inh

Vue.js雙向資料原理

vue雙向繫結就是指model層與view層的同步,兩者之間任意一個發生變化都會同步更新到另一者。 View為檢視層,Model為資料層,ViewModel為邏輯控制層。 vue.js採用資料劫持結合釋出者-訂閱者模式的方法,通過Object.defin

vue雙向資料原理

有關雙向資料繫結的原理 最近兩次面試的時候,被問到了vue中雙向資料繫結的原理,因為初學不精,只是使用而沒有深入研究,所以答不出來。之後就在網上查找了別人寫的部落格,學習一下。 下面是部落格園一篇部落格,以及MDN上講解Object.defineProper

vue 雙向資料原理

Vue的雙向資料繫結原理是什麼?vue.js是採用資料劫持結合釋出者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter, getter,在資料變動時釋出訊息給訂閱者,出發相應的監聽回撥。具體步驟:首先Vue會使用document

單項資料雙向資料及其原理(髒檢查)

參考文章: https://segmentfault.com/q/1010000002511449/a-1020000002514653 單向資料繫結:指的是我們先把模板寫好,然後把模板和資料(資料可

Vue雙向資料原理解析

首先上原始碼,模擬vue的雙向資料繫結原理<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Two-way data-

深入vue原始碼,瞭解vue雙向資料原理

大家都知道vue是一種MVVM開發模式,資料驅動檢視的前端框架,並且內部已經實現了雙向資料繫結,那麼雙向資料繫結是怎麼實現的呢? 先手動擼一個最最最簡單的雙向資料繫結 1 <div> 2 <input type="text" name="" id="te

面試題:你能寫一個Vue雙向資料嗎?

在目前的前端面試中,vue的雙向資料繫結已經成為了一個非常容易考到的點,即使不能當場寫出來,至少也要能說出原理。本篇文章中我將會仿照vue寫一個雙向資料繫結的例項,名字就叫myVue吧。結合註釋,希望能讓大家有所收穫。 1、原理 Vue的雙向資料繫結的原理相信大家也都十分了解了,主要是通過 Obje