成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

用JavaScript自己寫MVVM前端框架-VM實(shí)現(xiàn)篇

VincentFF / 1239人閱讀

摘要:關(guān)于前端框架大家都有了解,或多或少的使用過,比如,,等等。那么你是否也想自己手寫一個(gè)的前端框架呢,我們從入手,手把手教你寫基于的前端框架,在整個(gè)編寫的過程中,希望大家學(xué)習(xí)更多,理解更多。本節(jié)我們以打包工具結(jié)合轉(zhuǎn)換插件實(shí)現(xiàn)數(shù)據(jù)的抽象。

關(guān)于MVVM前端框架大家都有了解,或多或少的使用過,比如Angular,React,VUE等等。那么你是否也想自己手寫一個(gè)MVVM的前端框架呢,我們從Virtual DOM入手,手把手教你寫基于Virtual DOM的前端框架,在整個(gè)編寫的過程中,希望大家學(xué)習(xí)更多,理解更多。
Github代碼: https://github.com/chalecao/v...

章節(jié)1: 認(rèn)識DOM與VirtualDOM

真實(shí)的DOM是網(wǎng)頁上的文檔對象模型,由一個(gè)個(gè)HTML元素節(jié)點(diǎn)構(gòu)成的樹形結(jié)構(gòu)。

如圖中所示,我們用JS創(chuàng)建出來的節(jié)點(diǎn)就是虛擬節(jié)點(diǎn),Virtual node,當(dāng)然由這些虛擬節(jié)點(diǎn)vd構(gòu)成的樹形結(jié)構(gòu)就稱為虛擬DOM,Virtual DOM。我們本節(jié)課介紹的就是要如何創(chuàng)建這樣的虛擬DOM。

章節(jié)2: 如何構(gòu)建VirtualDOM

首先我們需要分析一個(gè)node節(jié)點(diǎn)的構(gòu)成,比如他的節(jié)點(diǎn)類型type,節(jié)點(diǎn)屬性的集合props,子元素的集合。這樣我們就可以抽象一個(gè)數(shù)據(jù)模型來表示這個(gè)節(jié)點(diǎn)。虛擬DOM是由許多虛擬節(jié)點(diǎn)按照層級結(jié)構(gòu)組合起來的,那么我們實(shí)現(xiàn)虛擬節(jié)點(diǎn)的數(shù)據(jù)模型抽象之后,就可以構(gòu)建虛擬DOM的數(shù)據(jù)模型抽象。

手工實(shí)現(xiàn)DOM模型構(gòu)建不太合理,我們可以借助JSX的工具來完成這個(gè)轉(zhuǎn)換。本節(jié)我們以rollup打包工具結(jié)合babel轉(zhuǎn)換插件實(shí)現(xiàn)數(shù)據(jù)的抽象。具體代碼配置參考: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編譯后會(huì)自動(dòng)根據(jù)定義好的語法格式提取出元素的類型和屬性和子元素,并填入vnode方法中,我們只需要實(shí)現(xiàn)vnode方法就可以。我們可以編寫vnode方法用于構(gòu)建虛擬節(jié)點(diǎn)的模型,編寫createElement方法用于根據(jù)vnode模型創(chuàng)建元素。并且把vnode的子元素追加到父元素上,形成樹形層級結(jié)構(gòu)。

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));

這樣我們就完成了虛擬節(jié)點(diǎn)vnode和虛擬vDOM的構(gòu)建。

章節(jié)3: Diff VirtualDOM 與Update DOM

如圖展示了最簡單的一層DOM的結(jié)構(gòu)變化,無非也就這么幾種:增加元素節(jié)點(diǎn)、修改節(jié)點(diǎn),刪除節(jié)點(diǎn)。我們可以基于DOM API來實(shí)現(xiàn)這些基本的操作,代碼如下:

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);
        }
    }
}

上面的代碼中我們實(shí)際上是把diff VirtualDOM 和update vdom放在一起處理了,采用了深度優(yōu)先遍歷的算法,從根節(jié)點(diǎn)優(yōu)先查到子節(jié)點(diǎn),判斷子節(jié)點(diǎn)是否變化,有變化就進(jìn)行變更處理,然后再回到上級節(jié)點(diǎn)。

章節(jié)4: 處理DOM屬性和事件綁定
{
  type: “div”,
  props: {“style”: ”…”}, 
  children: [
      {type: “img”, props: {“src”: ”…”}
]}

上面我們抽取的vnode的模型中已經(jīng)把props拿出來了,我們這里需要把這些樣式設(shè)置到對應(yīng)元素上就好了。我們先看下元素的屬性變化有哪幾種情況:

如上,元素屬性可以增加可以減少,我們通過DOM API實(shí)現(xiàn)屬性的更新操作,代碼如下:

//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]);
    });
}

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/107714.html

相關(guān)文章

  • JavaScript 數(shù)據(jù)綁定實(shí)現(xiàn)一個(gè)簡單的 MVVM

    摘要:和刷新函數(shù)是一對多的關(guān)系,即一個(gè)可以有任意多個(gè)處理它的回調(diào)函數(shù)刷新函數(shù),比如和兩個(gè)指令共用一個(gè)數(shù)據(jù)模型字段。添加數(shù)據(jù)訂閱實(shí)現(xiàn)方式為建立緩存回調(diào)函數(shù)的數(shù)組緩存回調(diào)函數(shù)當(dāng)數(shù)據(jù)模型的字段發(fā)生改變時(shí),就會(huì)觸發(fā)緩存數(shù)組中訂閱了的所有回調(diào)。 MVVM 是 Web 前端一種非常流行的開發(fā)模式,利用 MVVM 可以使我們的代碼更專注于處理業(yè)務(wù)邏輯而不是去關(guān)心 DOM 操作。目前著名的 MVVM 框架有...

    hzx 評論0 收藏0
  • 基于Vue的MVVM學(xué)習(xí)筆記

    摘要:發(fā)布訂閱現(xiàn)在每個(gè)人應(yīng)該都用微信吧,一個(gè)人可以關(guān)注多個(gè)公眾號,多個(gè)人可以同時(shí)關(guān)注相同的公眾號。公眾號每周都會(huì)更新內(nèi)容,并推送給我們,把寫好的文章在微信管理平臺更新就好了,點(diǎn)擊推送,就相當(dāng)于發(fā)布。 什么是MVVM MVVM——Model-View-ViewModle的縮寫,MVC設(shè)計(jì)模式的改進(jìn)版。Model是我們應(yīng)用中的數(shù)據(jù)模型,View是我們的UI層,通過ViewModle,可以把我們M...

    Alan 評論0 收藏0
  • 【教學(xué)向】150行代碼教你實(shí)現(xiàn)一個(gè)低配版的MVVM庫(1)- 原理

    摘要:模塊則負(fù)責(zé)維護(hù),以及各個(gè)模塊間的調(diào)度思考題了解了的實(shí)現(xiàn)機(jī)制,你能否自己動(dòng)手也試著用百來行代碼實(shí)現(xiàn)一個(gè)庫呢好了本教程第一部分設(shè)計(jì)篇就寫到這里,具體請移步下一篇教學(xué)向行代碼教你實(shí)現(xiàn)一個(gè)低配版的庫代碼篇我會(huì)用給出一版實(shí)現(xiàn)。 適讀人群 本文適合對MVVM有一定了解(如有主流框架ng,vue等使用經(jīng)驗(yàn)配合本文服用則效果更佳),雖然會(huì)用這類框架,但是對框架底層核心實(shí)現(xiàn)又不太清楚,或者能說出個(gè)所以然...

    selfimpr 評論0 收藏0
  • JavaScript 進(jìn)階之深入理解數(shù)據(jù)雙向綁定

    摘要:當(dāng)我們的視圖和數(shù)據(jù)任何一方發(fā)生變化的時(shí)候,我們希望能夠通知對方也更新,這就是所謂的數(shù)據(jù)雙向綁定。返回值返回傳入函數(shù)的對象,即第一個(gè)參數(shù)該方法重點(diǎn)是描述,對象里目前存在的屬性描述符有兩種主要形式數(shù)據(jù)描述符和存取描述符。 前言 談起當(dāng)前前端最熱門的 js 框架,必少不了 Vue、React、Angular,對于大多數(shù)人來說,我們更多的是在使用框架,對于框架解決痛點(diǎn)背后使用的基本原理往往關(guān)注...

    sarva 評論0 收藏0
  • React 可視化開發(fā)工具 Shadow Widget 非正經(jīng)入門(之一:React 三宗罪)

    摘要:前言非正經(jīng)入門是相對正經(jīng)入門而言的。不過不要緊,正式學(xué)習(xí)仍需回到正經(jīng)入門的方式。快速入門建議先學(xué)會(huì)用拼文寫文檔注冊一個(gè)賬號,把庫到自己名下,然后用這個(gè)庫寫自己的博客,參見這份介紹。會(huì)用拼文寫文章,相當(dāng)于開發(fā)已入門三分之一了。 本系列博文從 Shadow Widget 作者的視角,解釋該框架的設(shè)計(jì)要點(diǎn),既作為用戶手冊的補(bǔ)充,也從更本質(zhì)角度幫助大家理解 Shadow Widget 為什么這...

    dongxiawu 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<