欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

如何使用proxy實(shí)現(xiàn)一個(gè)MVVM庫(kù)的方法-創(chuàng)新互聯(lián)

這篇文章主要介紹如何使用proxy實(shí)現(xiàn)一個(gè)MVVM庫(kù)的方法,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

成都創(chuàng)新互聯(lián)專注于臨澤企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,商城網(wǎng)站開發(fā)。臨澤網(wǎng)站建設(shè)公司,為臨澤等地區(qū)提供建站服務(wù)。全流程專業(yè)公司,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

前言

MVVM 是當(dāng)前時(shí)代前端日常業(yè)務(wù)開發(fā)中的必備模式(相關(guān)框架如react,vueangular 等), 使用 MVVM 可以將開發(fā)者的精力更專注于業(yè)務(wù)上的邏輯,而不需要關(guān)心如何操作 dom。雖然現(xiàn)在都 9012 年了,mvvm 相關(guān)原理的介紹已經(jīng)爛大街了,但出于學(xué)習(xí)基礎(chǔ)知識(shí)的目的(使用 proxy 實(shí)現(xiàn)的 vue3.0 還在開發(fā)中), 在參考了之前 vue.js 的整體思路之后,自己動(dòng)手實(shí)現(xiàn)了一個(gè)簡(jiǎn)易的通過 proxy 實(shí)現(xiàn)的 mvvm。

本項(xiàng)目代碼已經(jīng)開源在github,項(xiàng)目正在持續(xù)完善中,歡迎交流學(xué)習(xí),喜歡請(qǐng)點(diǎn)個(gè) star 吧!

最終效果

<html>
 <body>
  <div id="app">
   <div>{{title}}</div>
  </div>
 </body>
</html>
import MVVM from '@fe_korey/mvvm';
new MVVM({
 view: document.getElementById('app'),
 model: {
  title: 'hello mvvm!'
 },
 mounted() {
  console.log('主程編譯完成,歡迎使用MVVM!');
 }
});

結(jié)構(gòu)概覽

  • Complier 模塊實(shí)現(xiàn)解析、收集指令,并初始化視圖

  • Observer 模塊實(shí)現(xiàn)了數(shù)據(jù)的監(jiān)聽,包括添加訂閱者和通知訂閱者

  • Parser 模塊實(shí)現(xiàn)解析指令,提供該指令的更新視圖的更新方法

  • Watcher 模塊實(shí)現(xiàn)建立指令與數(shù)據(jù)的關(guān)聯(lián)

  • Dep 模塊實(shí)現(xiàn)一個(gè)訂閱中心,負(fù)責(zé)收集,觸發(fā)數(shù)據(jù)模型各值的訂閱列表

流程為:Complier收集編譯好指令后,根據(jù)指令不同選擇不同的Parser,根據(jù)ParserWatcher中訂閱數(shù)據(jù)的變化并更新初始視圖。Observer監(jiān)聽數(shù)據(jù)變化然后通知給 Watcher ,Watcher 再將變化結(jié)果通知給對(duì)應(yīng)Parser里的 update 刷新函數(shù)進(jìn)行視圖的刷新。

如何使用proxy實(shí)現(xiàn)一個(gè)MVVM庫(kù)的方法

模塊詳解

Complier

將整個(gè)數(shù)據(jù)模型 data 傳入Observer模塊進(jìn)行數(shù)據(jù)監(jiān)聽

this.$data = new Observer(option.model).getData();

循環(huán)遍歷整個(gè) dom,對(duì)每個(gè) dom 元素的所有指令進(jìn)行掃描提取

function collectDir(element) {
 const children = element.childNodes;
 const childrenLen = children.length;

 for (let i = 0; i < childrenLen; i++) {
  const node = children[i];
  const nodeType = node.nodeType;

  if (nodeType !== 1 && nodeType !== 3) {
   continue;
  }
  if (hasDirective(node)) {
   this.$queue.push(node);
  }
  if (node.hasChildNodes() && !hasLateCompileChilds(node)) {
   collectDir(element);
  }
 }
}

對(duì)每個(gè)指令進(jìn)行編譯,選擇對(duì)應(yīng)的解析器Parser

const parser = this.selectParsers({ node, dirName, dirValue, cs: this });

將得到的解析器Parser傳入Watcher,并初始化該 dom 節(jié)點(diǎn)的視圖

const watcher = new Watcher(parser);
parser.update({ newVal: watcher.value });

所有指令解析完畢后,觸發(fā) MVVM 編譯完成回調(diào)$mounted()

this.$mounted();

使用文檔碎片document.createDocumentFragment()來代替真實(shí) dom 節(jié)點(diǎn)片段,待所有指令編譯完成后,再將文檔碎片追加回真實(shí) dom 節(jié)點(diǎn)

let child;
const fragment = document.createDocumentFragment();
while ((child = this.$element.firstChild)) {
 fragment.appendChild(child);
}
//解析完后
this.$element.appendChild(fragment);
delete $fragment;

Parser

Complier模塊編譯后的指令,選擇不同聽解析器解析,目前包括ClassParser,DisplayParser,ForParser,IfParser,StyleParser,TextParser,ModelParser,OnParser,OtherParser等解析模塊。

switch (name) {
 case 'text':
  parser = new TextParser({ node, dirValue, cs });
  break;
 case 'style':
  parser = new StyleParser({ node, dirValue, cs });
  break;
 case 'class':
  parser = new ClassParser({ node, dirValue, cs });
  break;
 case 'for':
  parser = new ForParser({ node, dirValue, cs });
  break;
 case 'on':
  parser = new OnParser({ node, dirName, dirValue, cs });
  break;
 case 'display':
  parser = new DisplayParser({ node, dirName, dirValue, cs });
  break;
 case 'if':
  parser = new IfParser({ node, dirValue, cs });
  break;
 case 'model':
  parser = new ModelParser({ node, dirValue, cs });
  break;
 default:
  parser = new OtherParser({ node, dirName, dirValue, cs });
}

不同的解析器提供不同的視圖刷新函數(shù)update(),通過update更新dom視圖

//text.js
function update(newVal) {
 this.el.textContent = _toString(newVal);
}

OnParser 解析事件綁定,與數(shù)據(jù)模型中的 methods字段對(duì)應(yīng)

//詳見 https://github.com/zhaoky/mvvm/blob/master/src/core/parser/on.ts
el.addEventListener(handlerType, e => {
 handlerFn(scope, e);
});

ForParser 解析數(shù)組

詳見 https://github.com/zhaoky/mvvm/blob/master/src/core/parser/for.ts

ModelParser 解析雙向綁定,目前支持input[text/password] & textarea,input[radio],input[checkbox],select四種情況的雙向綁定,雙綁原理:

數(shù)據(jù)變化更新表單:跟其他指令更新視圖一樣,通過update方法觸發(fā)更新表單的value

function update({ newVal }) {
 this.model.el.value = _toString(newVal);
}

表單變化更新數(shù)據(jù):監(jiān)聽表單變化事件如input,change,在回調(diào)里set數(shù)據(jù)模型

this.model.el.addEventListener('input', e => {
 model.watcher.set(e.target.value);
});

Observer

MVVM 模型中的核心,一般通過 Object.definePropertyget,set 方法進(jìn)行數(shù)據(jù)的監(jiān)聽,在 get 里添加訂閱者,set 里通知訂閱者更新視圖。在本項(xiàng)目采用 Proxy 來實(shí)現(xiàn)數(shù)據(jù)監(jiān)聽,好處有三:

Proxy 可以直接監(jiān)聽對(duì)象而非屬性

Proxy 可以直接監(jiān)聽數(shù)組的變化

Proxy 有多達(dá) 13 種攔截方法,查閱

而劣勢(shì)是兼容性問題,且無法通過 polyfill 磨平。查閱兼容性

注意 Proxy 只會(huì)監(jiān)聽自身的每一個(gè)屬性,如果屬性是對(duì)象,則該對(duì)象不會(huì)被監(jiān)聽,所以需要遞歸監(jiān)聽

設(shè)置監(jiān)聽后,返回一個(gè) Proxy 替代原數(shù)據(jù)對(duì)象

var proxy = new Proxy(data, {
 get: function(target, key, receiver) {
  //如果滿足條件則添加訂閱者
  dep.addDep(curWatcher);
  return Reflect.get(target, key, receiver);
 },
 set: function(target, key, value, receiver) {
  //如果滿足條件則通知訂閱者
  dep.notfiy();
  return Reflect.set(target, key, value, receiver);
 }
});

Watcher

Complier 模塊里對(duì)每一個(gè)解析后的 Parser 進(jìn)行指令與數(shù)據(jù)模型直接的綁定,并觸發(fā) Observerget 監(jiān)聽,添加訂閱者(Watcher

this._getter(this.parser.dirValue)(this.scope || this.parser.cs.$data);

當(dāng)數(shù)據(jù)模型變化時(shí),就會(huì)觸發(fā) -> Observerset 監(jiān)聽 -> Depnotfiy 方法(通知訂閱者的所有訂閱列表) -> 執(zhí)行訂閱列表所有 Watcherupdate 方法 -> 執(zhí)行對(duì)應(yīng) Parserupdate -> 完成更新視圖

Watcher 里的 set 方法用于設(shè)置雙向綁定值,注意訪問層級(jí)

Dep

  • MVVM 的訂閱中心,在這里收集數(shù)據(jù)模型的每個(gè)屬性的訂閱列表

  • 包含添加訂閱者,通知訂閱者等方法

  • 本質(zhì)是一種發(fā)布/訂閱模式

class Dep {
 constructor() {
  this.dependList = [];
 }
 addDep() {
  this.dependList.push(dep);
 }
 notfiy() {
  this.dependList.forEach(item => {
   item.update();
  });
 }
}

以上是“如何使用proxy實(shí)現(xiàn)一個(gè)MVVM庫(kù)的方法”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

當(dāng)前文章:如何使用proxy實(shí)現(xiàn)一個(gè)MVVM庫(kù)的方法-創(chuàng)新互聯(lián)
文章地址:http://aaarwkj.com/article48/jsdhp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、企業(yè)網(wǎng)站制作、網(wǎng)頁(yè)設(shè)計(jì)公司網(wǎng)站導(dǎo)航、移動(dòng)網(wǎng)站建設(shè)網(wǎng)站排名

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
欧美日韩国产综合在线观看| 超碰国产熟女一区二区三区| 精品国产乱码一区二区三区| 日本91一区二区不卡| 91精品国语对白人妻刺激| 日韩x级av免费在线观看| 亚洲av第一区综合激情久久久| 亚洲一区成人精品在线| 久久精品噜噜噜成人av农村| 国产传媒在线观看网站| 九九热在线免费观看精品视频| 野花日本免费高清完整| 视频一二区免费在线观看| 国产精彩在线视频成人在线| 农村女人91熟女熟妇| 久久五十路初次拍五十路| 少妇人妻精品一区二区三| 粗暴蹂躏中文一区二区三区| 日本人妻在线一区二区三区| 伊人不卡中文字幕在线一区| 成人精品超碰一区二区| 精品国产不卡在线观看| 久久精品一区二区三区不卡| 亚洲日本av一区二区| 国产男女猛烈无遮挡av| 亚洲国产视频不卡一区| 尤物在线观看精品视频| 免费观看亚洲成人av| 欧美欧美欧美欧美在线| 欧美专区另类综合日韩| 久久精品二区亚洲w码| 日韩精品专区在线影院重磅| 亚洲国产欧美日韩综合| 久久五十路初次拍五十路| 激情毛片av在线免费看| 四季一区二区三区av| 亚洲精品成人午夜av| 亚洲国产中日韩精品综合| 日本韩国亚洲欧美一区二区| 亚洲成人av网址大全| 国产一区二区三区自拍|