博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BiuJS[v1.0]说明文档(4):$if 指令
阅读量:6226 次
发布时间:2019-06-21

本文共 3683 字,大约阅读时间需要 12 分钟。

logo

BiuJS

BiuJS是一个轻巧的mvvm框架
它实现了数据的双向绑定
并提供一些基本的指令帮助你提升效率,比如
$for
$model
$if
$click
$style
是的,如你所见,以
$开头的指令是它的独特标识
1000行左右的代码量,让应用的开发和加载biu的一瞬完成
:
https://github.com/veedrin/biu

$指令

往下看之前,请大家沐浴更衣,因为我要讲BiuJS的$指令了

{
{vipName}}

JavaScript中的$已经被jQuery占用了,现在html标签中的$也被BiuJS占用了

我已经为$指令申请了专利,是真的(假的)

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

因为每一个指令的编译规则都是不一样的,所以我们要提取出$指令,然后交给相应的函数处理

注意,handler需要用call方法调用,否则handler内部的this不会指向Compiler构造函数

$for

编写html的时候,我们经常会遇到DOM结构一样但数据不一样的情况

这时候如果有一个工具,能够遍历数据,然后插入到相应份拷贝的DOM结构中,简直太好了

$for指令就是为这个而生的

我们先来看$for指令的用法

这里的itemindex可以随意更换成你顺手的单词,只需要记住item是总数据的一项,如果需要索引则要加一对括号

让我们提取其中的表达式

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结构。如果有好的解决方案,可以在文末留言

let divWrap = document.createElement('div');ele.parentNode.insertBefore(divWrap, ele);ele.parentNode.removeChild(ele);ele.removeAttribute('$for');let cloneOrigin = ele.cloneNode(true);

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

这里需要克隆一个元素的副本,因为之后数据变更,我们要拿这个副本去重新编译

因为子元素可能会(应该是一定会)使用带有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作为参数传进自己的函数

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

最后是订阅器的回调

做法就是先移除div里面的所有子元素,遍历一下数据,看看新值有几项,然后拿来副本,照上面相应的编译几次

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指令的过程

欢迎到: https://github.com/veedrin/biu了解详情

更欢迎StarFork

转载地址:http://hsxna.baihongyu.com/

你可能感兴趣的文章
Kali-linux Arpspoof工具
查看>>
PDF文档页面如何重新排版?
查看>>
基于http协议使用protobuf进行前后端交互
查看>>
bash腳本編程之三 条件判断及算数运算
查看>>
php cookie
查看>>
linux下redis安装
查看>>
弃 Java 而使用 Kotlin 的你后悔了吗?| kotlin将会是最好的开发语言
查看>>
JavaScript 数据类型
查看>>
量子通信和大数据最有市场突破前景
查看>>
对‘初学者应该选择哪种编程语言’的回答——计算机达人成长之路(38)
查看>>
如何申请开通微信多客服功能
查看>>
Sr_C++_Engineer_(LBS_Engine@Global Map Dept.)
查看>>
非监督学习算法:异常检测
查看>>
jquery的checkbox,radio,select等方法总结
查看>>
Linux coredump
查看>>
Ubuntu 10.04安装水晶(Mercury)无线网卡驱动
查看>>
我的友情链接
查看>>
nginx在reload时候报错invalid PID number
查看>>
ElasticSearch 2 (32) - 信息聚合系列之范围限定
查看>>
VS2010远程调试C#程序
查看>>