摘要:再獲取其事件屬性,我們這里只簡單地獲取屬性,我們將它的屬性值和元素標識保存到中最后等待模版掛載在元素中后,我們遍歷數(shù)組,掛載事件至此,我的已基本實現(xiàn)了實現(xiàn)的是一個簡單的計數(shù)器有興趣的小伙伴可以復制以下代碼運行查看效果
這周參考了一些博文,自己寫了一個簡單的vue,網(wǎng)上這類實現(xiàn)很多,我的實現(xiàn)也沒什么新奇,權(quán)當一個自我練習吧
本文同時發(fā)在我的github博客上,歡迎star
具體實現(xiàn)首先,得先有一個Vue類,當然,我寫的一個很粗糙的Vue類,所以我把它叫做BabyVue:
function BabyVue(options) { const { data, root, template, methods } = options; this.data = data; this.root = root; this.template = template; this.methods = methods; this.observe(); this.resolveTemplate(); }
BabtVue構(gòu)造函數(shù)接受一個options,options中包含data,root(即html中指定的根結(jié)點),template模版,methods四個option,我們把這些option掛載到this方法上,以便后續(xù)的函數(shù)能輕松地拿到他們。然后執(zhí)行observe和resolveTemplate方法
observe方法:
BabyVue.prototype.observe = function() { Object.keys(this.data).forEach(key => { let val = this.data[key]; const observer = new Observer(); Object.defineProperty(this.data, key, { get: () => { if (Observer.target) { observer.subscribe(Observer.target); } return val; }, set: newValue => { if (val === newValue) { return; } val = newValue; observer.publish(newValue); } }); }); };
observe方法中先對this.data中的數(shù)據(jù)進行遍歷,這里沒有考慮更深層的結(jié)構(gòu),只對第一層數(shù)據(jù)進行遍歷,利用閉包緩存它的當前值val和一個觀察者observer,并用Object.defineProperty方法設置它的get和set屬性,在獲取值的時候判斷Observer.target是否存在,若存在,則將Observer.target加入訂閱者(后面再詳述其作用),最后返回val;設置值的時候,將新值與val對比,若不同,則更新val值,并通知訂閱者更新
下面是Observer的代碼,實現(xiàn)了一個簡單的觀察者模式:
function Observer() { this.subscribers = []; } Observer.prototype.subscribe = function(subscriber) { !~this.subscribers.indexOf(subscriber) && this.subscribers.push(subscriber); }; Observer.prototype.publish = function(newVal) { this.subscribers.forEach(subscriber => { const ele = document.querySelector(`[${subscriber}]`); ele && (ele.innerHTML = newVal); }); };
訂閱者用其特殊屬性進行標識,在更新時,先通過屬性選擇器拿到目標dom再更新其值
下面是resolveTemplate的代碼,其主要是渲染模版、增加元素標識和掛載事件,Vue中對模版解析使用的應當是更高級的方法,我這里只是對template字符串一些簡單的解析
BabyVue.prototype.resolveTemplate = function() { const root = document.createElement("div"); root.innerHTML = this.template; const children = root.children; const nodes = [].slice.call(children); let index = 0; const events = []; while (nodes.length !== 0) { const node = nodes.shift(); const _index = index++; node.setAttribute(`v-${_index}`, ""); if (node.children.length > 0) { nodes.push(...node.children); } else { if (/{{(.*)}}/.test(node.innerHTML)) { const key = node.innerHTML.replace(/{{(.*)}}/, "$1"); Observer.target = `v-${_index}`; node.innerHTML = this.data[key]; Observer.target = null; } const method = node.getAttribute("v-on:click"); if (method) { events.push({ key: `v-${_index}`, type: "click", method }); } } } this.root.innerHTML = root.innerHTML; events.forEach(event => { const { key, type, method } = event; const ele = document.querySelector(`[${key}]`); ele.addEventListener(type, this.methods[method].bind(this)); }); };
我對模版中的每一個元素增加一個特殊標示,形似v-xxx,方便根據(jù)表示標示獲取真實dom(為什么不直接保存node?可以試試使用了createElement創(chuàng)建的元素再設置innerHTML,會出現(xiàn)一些問題)。
先根據(jù)正則匹配{},若符合條件,獲取了大括號的標識符后,先將Object.target設為元素的標識,在將元素的innerHTML置為data中的數(shù)據(jù),要注意,在此時,我們獲取了一次this.data[key],會觸發(fā)之前設置的get屬性,在其中判斷Observer.target是否存在,因為我們剛剛設置過,Observer.target當前為元素的標識,所以,它被加到訂閱者中。
再獲取其事件屬性,我們這里只簡單地獲取v-on:click屬性,我們將它的屬性值和元素標識保存到events中
最后等待模版掛載在root元素中后,我們遍歷events數(shù)組,掛載事件
至此,我的BabyVue已基本實現(xiàn)了
Demo實現(xiàn)的是一個簡單的計數(shù)器:
有興趣的小伙伴可以復制以下代碼運行查看效果:
BabyVue
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/106383.html
摘要:前言最近在學習框架的基本原理,看了一些技術博客以及一些對源碼的簡單實現(xiàn),對數(shù)據(jù)代理數(shù)據(jù)劫持模板解析變異數(shù)組方法雙向綁定有了更深的理解。 前言 最近在學習vue框架的基本原理,看了一些技術博客以及一些對vue源碼的簡單實現(xiàn),對數(shù)據(jù)代理、數(shù)據(jù)劫持、模板解析、變異數(shù)組方法、雙向綁定有了更深的理解。于是乎,嘗試著去實踐自己學到的知識,用vue的一些基本原理實現(xiàn)一個簡單的todo-list,完成...
摘要:兩個對象鍵名沖突時,取組件對象的鍵值對。允許聲明擴展另一個組件可以是一個簡單的選項對象或構(gòu)造函數(shù),而無需使用。這主要是為了便于擴展單文件組件。 Vue作為最近最炙手可熱的前端框架,其簡單的入門方式和功能強大的API是其優(yōu)點。而同時因為其API的多樣性和豐富性,所以他的很多開發(fā)方式就和一切基于組件的React不同,如果沒有對Vue的API(有一些甚至文檔都沒提到)有一個全面的了解,那么在...
摘要:的使用相信大家都很熟練了,使用起來簡單。但是大部分人不知道其內(nèi)部的原理是怎么樣的,今天我們就來一起實現(xiàn)一個簡單的實現(xiàn)之前我們得先看一下的實現(xiàn),因為主要是通過數(shù)據(jù)劫持來實現(xiàn)的,通過來完成數(shù)據(jù)的讀取和更新。 vue的使用相信大家都很熟練了,使用起來簡單。但是大部分人不知道其內(nèi)部的原理是怎么樣的,今天我們就來一起實現(xiàn)一個簡單的vue Object.defineProperty() 實現(xiàn)之前我...
摘要:是什么為什么我們要使用說到了,我們就不得不先聊一下是什么以及為什么我們要使用,他能給我們的開發(fā)帶來什么樣的便利呢首先,我們來看一下的自我介紹讀音,類似于是一套用于構(gòu)建用戶界面的漸進式框架。 作為一個剛?cè)胄胁痪玫牟锁B不知從什么時候開始就有了寫一個自己的專欄的想法,剛好今天沒事就給自己挖一個坑,分享一下我對vue的見解和一些領悟,整個專欄應該會包括vue,vue-cli,vue-route...
摘要:通過裝作這些變化,我們實現(xiàn)了從而到達了數(shù)據(jù)變化觸發(fā)函數(shù)的過程。于此同時,我們還實現(xiàn)了來擴展這個可響應的結(jié)構(gòu),讓這個對象擁有了觸發(fā)和響應事件的能力。最后,根據(jù)我們的實現(xiàn),這是最終的產(chǎn)出,一個框架,了解一下系列文章地址優(yōu)化優(yōu)化總結(jié) 看這篇之前,如果沒有看過之前的文章,移步拉到文章末尾查看之前的文章。 provide / inject 在上一步我們實現(xiàn)了,父子組件,和 props 一樣 pr...
閱讀 1724·2021-11-11 10:58
閱讀 4210·2021-09-09 09:33
閱讀 1267·2021-08-18 10:23
閱讀 1555·2019-08-30 15:52
閱讀 1632·2019-08-30 11:06
閱讀 1877·2019-08-29 14:03
閱讀 1513·2019-08-26 14:06
閱讀 2960·2019-08-26 10:39