摘要:關于前端框架大家都有了解,或多或少的使用過,比如,,等等。那么你是否也想自己手寫一個的前端框架呢,我們從入手,手把手教你寫基于的前端框架,在整個編寫的過程中,希望大家學習更多,理解更多。本節我們以打包工具結合轉換插件實現數據的抽象。
關于MVVM前端框架大家都有了解,或多或少的使用過,比如Angular,React,VUE等等。那么你是否也想自己手寫一個MVVM的前端框架呢,我們從Virtual DOM入手,手把手教你寫基于Virtual DOM的前端框架,在整個編寫的過程中,希望大家學習更多,理解更多。
Github代碼: https://github.com/chalecao/v...
真實的DOM是網頁上的文檔對象模型,由一個個HTML元素節點構成的樹形結構。
如圖中所示,我們用JS創建出來的節點就是虛擬節點,Virtual node,當然由這些虛擬節點vd構成的樹形結構就稱為虛擬DOM,Virtual DOM。我們本節課介紹的就是要如何創建這樣的虛擬DOM。
章節2: 如何構建VirtualDOM首先我們需要分析一個node節點的構成,比如他的節點類型type,節點屬性的集合props,子元素的集合。這樣我們就可以抽象一個數據模型來表示這個節點。虛擬DOM是由許多虛擬節點按照層級結構組合起來的,那么我們實現虛擬節點的數據模型抽象之后,就可以構建虛擬DOM的數據模型抽象。
手工實現DOM模型構建不太合理,我們可以借助JSX的工具來完成這個轉換。本節我們以rollup打包工具結合babel轉換插件實現數據的抽象。具體代碼配置參考:github中package.json配置和rollup.config.js
const vdom = ()hello
上面我們定義的vdom片段采用JSX處理器處理后如下面代碼:
/* fed123.com */ "use strict"; var vdom = vnode( "div", { id: "_Q5", style: "border: 1px solid red;" }, vnode( "div", { style: "text-align: center; margin: 36px auto 18px; width: 160px; line-height: 0;" }, vnode("img", { src: "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_160x56dp.png", height: "56", style: "border: none; margin: 8px 0px;" }), "google" ) );
是不是很好理解,JSX編譯后會自動根據定義好的語法格式提取出元素的類型和屬性和子元素,并填入vnode方法中,我們只需要實現vnode方法就可以。我們可以編寫vnode方法用于構建虛擬節點的模型,編寫createElement方法用于根據vnode模型創建元素。并且把vnode的子元素追加到父元素上,形成樹形層級結構。
function vnode(type, props, ...children) { return { type, props, children }; } function createElement(node) { if (typeof node === "string") { return document.createTextNode(node); } const $el = document.createElement(node.type); node.children .map(createElement) .forEach($el.appendChild.bind($el)); return $el; } document.body.appendChild(createElement(vdom));
這樣我們就完成了虛擬節點vnode和虛擬vDOM的構建。
章節3: Diff VirtualDOM 與Update DOM如圖展示了最簡單的一層DOM的結構變化,無非也就這么幾種:增加元素節點、修改節點,刪除節點。我們可以基于DOM API來實現這些基本的操作,代碼如下:
function updateElement($parent, newnode, oldnode) { var index = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; if (!newnode) { $parent.removeChild($parent.childNodes[index]); } else if (!oldnode) { $parent.appendChild(createElement(newnode)); } else if (isChange(newnode, oldnode)) { $parent.replaceChild(createElement(newnode), $parent.childNodes[index]); } else if (newnode.type) { var newL = newnode.children.length; var oldL = oldnode.children.length; for (var i = 0; i < newL || i < oldL; i++) { updateElement($parent.childNodes[index], newnode.children[i], oldnode.children[i], i); } } }
上面的代碼中我們實際上是把diff VirtualDOM 和update vdom放在一起處理了,采用了深度優先遍歷的算法,從根節點優先查到子節點,判斷子節點是否變化,有變化就進行變更處理,然后再回到上級節點。
章節4: 處理DOM屬性和事件綁定{ type: “div”, props: {“style”: ”…”}, children: [ {type: “img”, props: {“src”: ”…”} ]}
上面我們抽取的vnode的模型中已經把props拿出來了,我們這里需要把這些樣式設置到對應元素上就好了。我們先看下元素的屬性變化有哪幾種情況:
如上,元素屬性可以增加可以減少,我們通過DOM API實現屬性的更新操作,代碼如下:
//handle props function setProp($el, name, value) { if (typeof value == "boolean") { handleBoolProp($el, name, value); } else { $el.setAttribute(name, value); } } function handleBoolProp($el, name, value) { if (!!value) { $el.setAttribute(name, value); $el[name] = !!value; } else { $el[name] = !!value; } } function removeProp($el, name, value) { if (typeof value == "boolean") { $el[name] = false; } $el.removeAttribute(name, value); } function updateProp($el, name, newvalue, oldValue) { if (!newvalue) { removeProp($el, name, oldValue); } else if (!oldValue || newvalue != oldValue) { setProp($el, name, newvalue); } } function updateProps($el) { var newprops = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var oldProps = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var _props = Object.assign({}, newprops, oldProps); Object.keys(_props).forEach(function (key) { updateProp($el, key, newprops[key], oldProps[key]); }); }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107714.html
摘要:和刷新函數是一對多的關系,即一個可以有任意多個處理它的回調函數刷新函數,比如和兩個指令共用一個數據模型字段。添加數據訂閱實現方式為建立緩存回調函數的數組緩存回調函數當數據模型的字段發生改變時,就會觸發緩存數組中訂閱了的所有回調。 MVVM 是 Web 前端一種非常流行的開發模式,利用 MVVM 可以使我們的代碼更專注于處理業務邏輯而不是去關心 DOM 操作。目前著名的 MVVM 框架有...
摘要:發布訂閱現在每個人應該都用微信吧,一個人可以關注多個公眾號,多個人可以同時關注相同的公眾號。公眾號每周都會更新內容,并推送給我們,把寫好的文章在微信管理平臺更新就好了,點擊推送,就相當于發布。 什么是MVVM MVVM——Model-View-ViewModle的縮寫,MVC設計模式的改進版。Model是我們應用中的數據模型,View是我們的UI層,通過ViewModle,可以把我們M...
摘要:模塊則負責維護,以及各個模塊間的調度思考題了解了的實現機制,你能否自己動手也試著用百來行代碼實現一個庫呢好了本教程第一部分設計篇就寫到這里,具體請移步下一篇教學向行代碼教你實現一個低配版的庫代碼篇我會用給出一版實現。 適讀人群 本文適合對MVVM有一定了解(如有主流框架ng,vue等使用經驗配合本文服用則效果更佳),雖然會用這類框架,但是對框架底層核心實現又不太清楚,或者能說出個所以然...
摘要:當我們的視圖和數據任何一方發生變化的時候,我們希望能夠通知對方也更新,這就是所謂的數據雙向綁定。返回值返回傳入函數的對象,即第一個參數該方法重點是描述,對象里目前存在的屬性描述符有兩種主要形式數據描述符和存取描述符。 前言 談起當前前端最熱門的 js 框架,必少不了 Vue、React、Angular,對于大多數人來說,我們更多的是在使用框架,對于框架解決痛點背后使用的基本原理往往關注...
摘要:前言非正經入門是相對正經入門而言的。不過不要緊,正式學習仍需回到正經入門的方式。快速入門建議先學會用拼文寫文檔注冊一個賬號,把庫到自己名下,然后用這個庫寫自己的博客,參見這份介紹。會用拼文寫文章,相當于開發已入門三分之一了。 本系列博文從 Shadow Widget 作者的視角,解釋該框架的設計要點,既作為用戶手冊的補充,也從更本質角度幫助大家理解 Shadow Widget 為什么這...
閱讀 767·2023-04-25 15:13
閱讀 1388·2021-11-22 12:03
閱讀 816·2021-11-19 09:40
閱讀 1898·2021-11-17 09:38
閱讀 1702·2021-11-08 13:18
閱讀 649·2021-09-02 15:15
閱讀 1760·2019-08-30 15:54
閱讀 2623·2019-08-30 11:12