摘要:再獲取其事件屬性,我們這里只簡單地獲取屬性,我們將它的屬性值和元素標識保存到中最后等待模版掛載在元素中后,我們遍歷數組,掛載事件至此,我的已基本實現了實現的是一個簡單的計數器有興趣的小伙伴可以復制以下代碼運行查看效果
這周參考了一些博文,自己寫了一個簡單的vue,網上這類實現很多,我的實現也沒什么新奇,權當一個自我練習吧
本文同時發在我的github博客上,歡迎star
具體實現首先,得先有一個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構造函數接受一個options,options中包含data,root(即html中指定的根結點),template模版,methods四個option,我們把這些option掛載到this方法上,以便后續的函數能輕松地拿到他們。然后執行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中的數據進行遍歷,這里沒有考慮更深層的結構,只對第一層數據進行遍歷,利用閉包緩存它的當前值val和一個觀察者observer,并用Object.defineProperty方法設置它的get和set屬性,在獲取值的時候判斷Observer.target是否存在,若存在,則將Observer.target加入訂閱者(后面再詳述其作用),最后返回val;設置值的時候,將新值與val對比,若不同,則更新val值,并通知訂閱者更新
下面是Observer的代碼,實現了一個簡單的觀察者模式:
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,方便根據表示標示獲取真實dom(為什么不直接保存node?可以試試使用了createElement創建的元素再設置innerHTML,會出現一些問題)。
先根據正則匹配{},若符合條件,獲取了大括號的標識符后,先將Object.target設為元素的標識,在將元素的innerHTML置為data中的數據,要注意,在此時,我們獲取了一次this.data[key],會觸發之前設置的get屬性,在其中判斷Observer.target是否存在,因為我們剛剛設置過,Observer.target當前為元素的標識,所以,它被加到訂閱者中。
再獲取其事件屬性,我們這里只簡單地獲取v-on:click屬性,我們將它的屬性值和元素標識保存到events中
最后等待模版掛載在root元素中后,我們遍歷events數組,掛載事件
至此,我的BabyVue已基本實現了
Demo實現的是一個簡單的計數器:
有興趣的小伙伴可以復制以下代碼運行查看效果:
BabyVue
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106383.html
摘要:前言最近在學習框架的基本原理,看了一些技術博客以及一些對源碼的簡單實現,對數據代理數據劫持模板解析變異數組方法雙向綁定有了更深的理解。 前言 最近在學習vue框架的基本原理,看了一些技術博客以及一些對vue源碼的簡單實現,對數據代理、數據劫持、模板解析、變異數組方法、雙向綁定有了更深的理解。于是乎,嘗試著去實踐自己學到的知識,用vue的一些基本原理實現一個簡單的todo-list,完成...
摘要:兩個對象鍵名沖突時,取組件對象的鍵值對。允許聲明擴展另一個組件可以是一個簡單的選項對象或構造函數,而無需使用。這主要是為了便于擴展單文件組件。 Vue作為最近最炙手可熱的前端框架,其簡單的入門方式和功能強大的API是其優點。而同時因為其API的多樣性和豐富性,所以他的很多開發方式就和一切基于組件的React不同,如果沒有對Vue的API(有一些甚至文檔都沒提到)有一個全面的了解,那么在...
摘要:的使用相信大家都很熟練了,使用起來簡單。但是大部分人不知道其內部的原理是怎么樣的,今天我們就來一起實現一個簡單的實現之前我們得先看一下的實現,因為主要是通過數據劫持來實現的,通過來完成數據的讀取和更新。 vue的使用相信大家都很熟練了,使用起來簡單。但是大部分人不知道其內部的原理是怎么樣的,今天我們就來一起實現一個簡單的vue Object.defineProperty() 實現之前我...
摘要:是什么為什么我們要使用說到了,我們就不得不先聊一下是什么以及為什么我們要使用,他能給我們的開發帶來什么樣的便利呢首先,我們來看一下的自我介紹讀音,類似于是一套用于構建用戶界面的漸進式框架。 作為一個剛入行不久的菜鳥不知從什么時候開始就有了寫一個自己的專欄的想法,剛好今天沒事就給自己挖一個坑,分享一下我對vue的見解和一些領悟,整個專欄應該會包括vue,vue-cli,vue-route...
摘要:通過裝作這些變化,我們實現了從而到達了數據變化觸發函數的過程。于此同時,我們還實現了來擴展這個可響應的結構,讓這個對象擁有了觸發和響應事件的能力。最后,根據我們的實現,這是最終的產出,一個框架,了解一下系列文章地址優化優化總結 看這篇之前,如果沒有看過之前的文章,移步拉到文章末尾查看之前的文章。 provide / inject 在上一步我們實現了,父子組件,和 props 一樣 pr...
閱讀 1711·2021-11-11 10:58
閱讀 4186·2021-09-09 09:33
閱讀 1257·2021-08-18 10:23
閱讀 1548·2019-08-30 15:52
閱讀 1625·2019-08-30 11:06
閱讀 1867·2019-08-29 14:03
閱讀 1507·2019-08-26 14:06
閱讀 2943·2019-08-26 10:39