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

資訊專欄INFORMATION COLUMN

BiuJS[v1.0]說明文檔(4):$if 指令

_ang / 3333人閱讀

摘要:是一個輕巧的框架它實現(xiàn)了數(shù)據(jù)的雙向綁定并提供一些基本的指令幫助你提升效率,比如,,,,是的,如你所見,以開頭的指令是它的獨特標(biāo)識行左右的代碼量,讓應(yīng)用的開發(fā)和加載的一瞬完成倉庫指令往下看之前,請大家沐浴更衣,因為我要講的指令了中的已經(jīng)被占用

BiuJS
BiuJS是一個輕巧的mvvm框架
它實現(xiàn)了數(shù)據(jù)的雙向綁定
并提供一些基本的指令幫助你提升效率,比如$for$model,$if$click$style
是的,如你所見,以$開頭的指令是它的獨特標(biāo)識
1000行左右的代碼量,讓應(yīng)用的開發(fā)和加載biu的一瞬完成
BiuJS倉庫: https://github.com/veedrin/biu
$指令

往下看之前,請大家沐浴更衣,因為我要講BiuJS的$指令了

{{vipName}}

JavaScript中的$已經(jīng)被jQuery占用了,現(xiàn)在html標(biāo)簽中的$也被BiuJS占用了

我已經(jīng)為$指令申請了專利,是真的(假的)

Compiler.prototype.compileElement = function(ele) {
        let self = this;
        Array.from(ele.attributes).forEach((attr) => {
            let name = attr.name;
            let type;
            if (name.indexOf("$") === 0) {
                type = name;
            } else {
                return;
            }
            let exp = attr.value;
            let handler = self[type];
            if (handler) {
                handler.call(self, ele, exp, self.vm);
            }
            ele.removeAttribute(name);
        });
    };

因為每一個指令的編譯規(guī)則都是不一樣的,所以我們要提取出$指令,然后交給相應(yīng)的函數(shù)處理

注意,handler需要用call方法調(diào)用,否則handler內(nèi)部的this不會指向Compiler構(gòu)造函數(shù)

$for

編寫html的時候,我們經(jīng)常會遇到DOM結(jié)構(gòu)一樣但數(shù)據(jù)不一樣的情況

這時候如果有一個工具,能夠遍歷數(shù)據(jù),然后插入到相應(yīng)份拷貝的DOM結(jié)構(gòu)中,簡直太好了

$for指令就是為這個而生的

我們先來看$for指令的用法

這里的itemindex可以隨意更換成你順手的單詞,只需要記住item是總數(shù)據(jù)的一項,如果需要索引則要加一對括號

讓我們提取其中的表達(dá)式

let regIterate = /^(([w,s]+))/;

let split = exp.split("in");
let expItem = split[0].trim();
let expList = split[1].trim();
let expIndex;

if (regIterate.test(expItem)) {
    let match = regIterate.exec(expItem)[1];
    split = match.split(",");
    expItem = split[0].trim();
    expIndex = split[1].trim();
}

目前$for指令有一個缺陷,它需要用一層div包裹起來,雖然頁面效果是一樣的,但畢竟破壞了DOM結(jié)構(gòu)。如果有好的解決方案,可以在文末留言

let divWrap = document.createElement("div");

ele.parentNode.insertBefore(divWrap, ele);
ele.parentNode.removeChild(ele);

ele.removeAttribute("$for");
let cloneOrigin = ele.cloneNode(true);

先插入一個div,然后把元素移除

這里需要克隆一個元素的副本,因為之后數(shù)據(jù)變更,我們要拿這個副本去重新編譯

因為子元素可能會(應(yīng)該是一定會)使用帶有itemindex的胡子模板

所以我們要把它們都替換成實際的值

let regItem = new RegExp(`{{${expItem}}}`, "g");
let regIndex = new RegExp(`{{${expIndex}}}`, "g");

if (child.nodeType === 3 && !regBlank.test(child.textContent)) {
    let content = child.textContent.trim();
    let str = self.replace$for(content, item, regItem);

    if (expIndex) {
        str = self.replace$for(str, index, regIndex);
    }
    child.textContent = str;
}

replace$for和文本編譯是差不多的,算是簡化版

Compiler.prototype.replace$for = function(content, value, reg) {
    let i = 0;
    let match;
    let text;
    let temp = "";

    while (match = reg.exec(content)) {
        if (i < match.index) {
            text = content.slice(i, match.index);
            temp += text;
        }
        i = reg.lastIndex;
        temp += value;
    }
    if (i < content.length) {
        text = content.slice(i);
        temp += text;
    }
    return temp;
};

但是到這里還沒完,因為$click指令有可能把itemindex作為參數(shù)傳進自己的函數(shù)

itemindex并不在data里面,不能用execChain方法獲取實際的值

所以在這里一并把它給編譯了

let regCall = /((.*))$/;

Array.from(child.attributes).forEach((attr) => {
    if (attr.name === "$click") {
        let exp = attr.value;
        let match = regCall.exec(exp);

        if (match) {
            let funcName = exp.slice(0, exp.indexOf("("));
            if (match[1] === expItem) {
                attr.value = `${funcName}("${item}")`;
            } else if (match[1] === expIndex) {
                attr.value = `${funcName}("${index}")`;
            }
        }
    }
});

最后是訂閱器的回調(diào)

做法就是先移除div里面的所有子元素,遍歷一下數(shù)據(jù),看看新值有幾項,然后拿來副本,照上面相應(yīng)的編譯幾次

new Watcher(exp, vm, (newValue) => {
    Array.from(divWrap.childNodes).forEach((child) => {
        divWrap.removeChild(child);
    });

    newValue.forEach((item, index) => {
        let cloneNode = cloneOrigin.cloneNode(true);
        self.compile$for(cloneNode, expItem, item, expIndex, index);
        divWrap.appendChild(cloneNode);
    });
});
寫在后面

以上就是編譯$for指令的過程

歡迎到BiuJS倉庫: https://github.com/veedrin/biu了解詳情

更歡迎StarFork

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

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

相關(guān)文章

  • BiuJS[v1.0]說明文檔(3):文本編譯

    摘要:如此循環(huán),直到結(jié)束如果循環(huán)結(jié)束之后,比字符串的長度要小,那說明后面還有文本匹配失敗了。 showImg(https://segmentfault.com/img/remote/1460000012478667?w=1920&h=926); BiuJS BiuJS是一個輕巧的mvvm框架它實現(xiàn)了數(shù)據(jù)的雙向綁定并提供一些基本的指令幫助你提升效率,比如$for,$model,$if,$cli...

    lucas 評論0 收藏0
  • BiuJS[v1.0]說明文檔(1):總體結(jié)構(gòu)

    摘要:是一個輕巧的框架它實現(xiàn)了數(shù)據(jù)的雙向綁定并提供一些基本的指令幫助你提升效率,比如,,,,是的,如你所見,以開頭的指令是它的獨特標(biāo)識行左右的代碼量,讓應(yīng)用的開發(fā)和加載的一瞬完成倉庫啟動首先我們來看一下是如何啟動的是的掛載點,它決定在多大范圍的樹 showImg(https://segmentfault.com/img/remote/1460000012478667?w=1920&h=926...

    崔曉明 評論0 收藏0
  • BiuJS[v1.0]說明文檔(2):數(shù)據(jù)劫持

    摘要:是一個輕巧的框架它實現(xiàn)了數(shù)據(jù)的雙向綁定并提供一些基本的指令幫助你提升效率,比如,,,,是的,如你所見,以開頭的指令是它的獨特標(biāo)識行左右的代碼量,讓應(yīng)用的開發(fā)和加載的一瞬完成倉庫訂閱清單前文說到提供了一個強大的接口我們就用它來劫持?jǐn)?shù)據(jù)不過在此 showImg(https://segmentfault.com/img/remote/1460000012478667?w=1920&h=926...

    Terry_Tai 評論0 收藏0
  • 是時候擁有一個你自己的命令行工具了

    摘要:本篇博客主要介紹了如何使用以及從零開始,創(chuàng)建屬于自己的命令行工具。一分鐘體驗首先我們先花一分鐘的時間,體驗一下創(chuàng)建自己的命令行工具是什么感覺?;蛘呤且粋€環(huán)境下的命令行接口解決方案。代表了這個工具向用戶暴露的命令行指令。 本篇博客主要介紹了如何使用commander, inquirer以及chalk從零開始,創(chuàng)建屬于自己的命令行工具。 0. 一分鐘體驗 首先我們先花一分鐘的時間,體驗一下...

    int64 評論0 收藏0
  • gulp自動化打包(上)

    摘要:自動化打包上文章概述本文分為上下兩篇,上篇主要介紹一些常用的插件也是此次打包主要用的插件,而下篇主要以一個項目為例,從本地出合適的版本,壓縮合并到最后打成包,發(fā)送至指定目錄,做一個全面的演示。 gulp自動化打包(上) 文章概述 本文分為上下兩篇,上篇主要介紹一些常用的gulp插件(也是此次打包主要用的gulp插件),而下篇主要以一個demo項目為例,從本地checkout出合適的g...

    roland_reed 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<