国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

淺談mvvm-simple雙向綁定簡單實現

2019-11-19 14:00:34
字體:
來源:轉載
供稿:網友

mvvm模式解放DOM枷鎖

mvvm原理分析

JavaScript在瀏覽器中操作HTML經歷了幾個不同階段

第一階段 直接用瀏覽器提供的原生API操作DOM元素

var dom = document.getElementById('id');dom.innerHTML = 'hello mvvm';

第二階段 jQuery的出現解決了原生API的復雜性和瀏覽器間的兼容性等問題,提供了更加簡易方便的API

$('#id').text('hello mvvm')

第三階段 MVC模式使前端可以和后端配合,修改服務端渲染后的頁面內容

而隨著產品對于用戶體驗的重視,交互體驗越來越重要,僅用jQuery遠遠不夠。 MVVM模型解決了頻繁操作的痛點,Model-View-ViewModel模式將數據與視圖的同步交由ViewModel完成

jQuery修改節點內容:

<p>name: <span id="name">vist</span>!</p><p>age: <span id="age">25</span>.</p>var name = 'bestvist';var age = 26;$('#name').text(name);$('#age').text(age);

MVVM模式下只需要關注數據結構:

var me = {  name: 'vist',  age: 25}

修改相應屬性就好

me.name = 'bestvist';me.age = 26;

mvvm實現

mvvm實現數據綁定的幾種方式:

  1. 發布-訂閱模式
  2. 臟值檢查
  3. 數據劫持

比較流行的vue采用的就是數據劫持和發布-訂閱模式,通過劫持es5提供的Object.defineProperty()中各個屬性的get,set方法, 數據更新時觸發消息給訂閱者,實現數據綁定功能。

Object.defineProperty(obj, prop, descriptor)方法直接在一個對象上定義一個新屬性,或者修改一個已經存在的屬性,并返回這個對象。 該方法接受3個參數:

  • obj 定義屬性的對象。
  • prop 被定義或修改的屬性名。
  • descriptor 被定義或修改的屬性的描述符。

一般情況通過直接給對象屬性賦值來創建屬性或者修改對應屬性,而使用Object.defineProperty可以修改對象屬性的一些額外默認配置。 如:

const obj = {name: 'Tom'};Object.defineProperty(obj, 'name', { get: function(val) {   return 'Jerry';  }})console.log(obj.name);//輸出: Jerry

Object.defineProperty詳細解釋,請戳這里

mvvm實現的主要流程:

  • 數據代理,訪問實例上的屬性時直接返回對應data里的屬性
  • 數據監聽,對實例上的屬性監聽,如果數據改變通知訂閱者更新
  • 指令解析,對每個元素節點進行解析,替換數據并綁定更新函數
  • 鏈接數據監聽和指令解析,保證每個數據的更新,指令解析都可以獲取并更新視圖

實例化類:

new MVVM({  el: '#app',  data() {    return {      message: 'hello mvvm'    }  }})

數據代理:

class MVVM {  constructor(options) {    this.$options = options || {};    let data = this._data = this.$options.data();    // 數據代理 vm.xxx => vm._data.xxx    Object.keys(data).forEach(key => {      this._proxyData(key);    });    // observe(data, this);    // this.$compile = new Compile(options.el || document.body, this);  }  _proxyData(key) {    Object.defineProperty(this, key, {      configurable: true,      enumerable: true,      get: () => {        return this._data[key];      },      set: newVal => {        this._data[key] = newVal;      }    });  }}

數據監聽,劫持實例屬性更新

class Observer {  constructor(data) {    this.data = data;    Object.keys(this.data).forEach(key => {      this.defineReactive(key, this.data[key]);    })  }  // 定義反應  defineReactive(key, val) {    let dep = new Dep();    Object.defineProperty(this.data, key, {      enumerable: true,      configurable: false,      get: () => {        return val;      },      set: newVal => {        if (val === newVal) {          return;        }        val = newVal;        // 賦值對象再進行劫持        observe(val);        ... // 數據修改通知      }    })  }}function observe(val) {  if (!val || typeof val !== 'object') {    return;  }  return new Observer(val);}

指令解析部分代碼

class Compile {  constructor(el, vm) {    this.$vm = vm;    this.$el = this.isElementNode(el) ? el : document.querySelector(el);    if (this.$el) {      this.$fragment = this.node2Fragment(this.$el);      this.init();      this.$el.appendChild(this.$fragment);    }  }  init() {    this.compileElement(this.$fragment);  }  node2Fragment(el) {    let fragment = document.createDocumentFragment(), child;    // 原生節點拷貝到fragment    while (child = el.firstChild) {      // appendChild將元素從dom上移到fragment      fragment.appendChild(child);    }    return fragment;  }  compileElement(el) {    let childNodes = el.childNodes;    [].slice.call(childNodes).forEach(node => {      let text = node.textContent;      let reg = //{/{(.*)/}/}/;      if (this.isElementNode(node)) {        this.compile(node);      } else if (this.isTextNode(node) && reg.test(text)) {        this.compileText(node, RegExp.$1);      }      if (node.childNodes && node.childNodes.length) {        this.compileElement(node);      }    })  }}

其中

while (child = el.firstChild) {  // appendChild將元素從dom上移到fragment  fragment.appendChild(child);}

通過appendChild改變原dom結構特點,逐步把dom元素節點移到fragment中。

完整代碼 Vue源碼

總結

以數據流為導向的mvvm模式極大的簡化前端對于dom的操作,加快前端開發速度,同時也提高了用戶體驗。

參考:

剖析Vue原理&實現雙向綁定MVVM mvvm廖雪峰

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 临桂县| 临汾市| 博野县| 大理市| 永德县| 平昌县| 武汉市| 龙海市| 平塘县| 新余市| 鸡东县| 成武县| 贞丰县| 富锦市| 长汀县| 桦甸市| 淮安市| 南陵县| 嘉禾县| 叶城县| 蕲春县| 丹阳市| 武宁县| 清流县| 罗源县| 巢湖市| 宜君县| 辽宁省| 尉氏县| 临武县| 石屏县| 临西县| 凭祥市| 深圳市| 西和县| 揭东县| 阳朔县| 凯里市| 锡林郭勒盟| 辉县市| 宜丰县|