仿照vue实现简易的MVVM框架(二)

实现文本插值与s-for循环模版。

对于文本插值的实现,我采用正则去匹配还原这个dom节点,以插值{{text}}形式为分界,将这个dom节点的文本分割成多个字符串,存储在this.muscha中,再者,将普通文本字符串以数组形式存储在string属性中,将插值存放在text属性值。当然,拼接的时候要明白先从string还是先从text开始拼接,我采用的方法是设置标志值,tag属性为0时,从text开始,为1时从string开始,存储完成后,解析拼接时只会出现这么几种情况:字串文本在前插值(1个或者多个)在后、只出现插值(1个或者多个)、前面后面插值中间为字串,前面后面为字串中间为插值。这些都可以分别处理,this.muscha函数如下:

this.muscha = function(value) {
    var temp = {
        string: [],
        text: [],
        tag: 0
    };

    var reg = /\{\{((?:.|\\n)+?)\}\}/g;

    if (!reg.test(value)) {
            return null;
    }

    var match;
    
    var lastIndex = reg.lastIndex = 0;
    var index;

    while(match = reg.exec(value)) {
        
        index = match.index;

        if (index > lastIndex) {
            temp.tag = 1;
            temp.string.push(value.slice(lastIndex, index));
        }
    
            temp.text.push(match[1]);
        lastIndex = index + match[0].length;
    }
    
    if (lastIndex < value.length) {
        temp.string.push(value.slice(lastIndex));
    }
    return temp;
}

拼接字串的方式如下:

this.strSplit = function(item) {
    var str = '';

    if (!item.muscha.tag) {
        var len = item.muscha.string.length;
        switch(len) {
            case 0:
                for (var i = 0; i < item.muscha.text.length; i++) {
                    str += data[item.muscha.text[i]];
                }
                break;
            case 1:
                str = data[item.muscha.text[0]] + item.muscha.string[0];
                break;
            default:
                for (var i = 0; i < len; i++) {
                    str = data[item.muscha.text[i]] + item.muscha.string[i];
                }
                str += data[item.muscha.text[i]];
        }
    } else {
        var len = item.muscha.text.length;
        switch(len) {
            case 1:
                //console.log(data[item.muscha.text[0]]);
                str = item.muscha.string[0] + data[item.muscha.text[0]];
                break;
            default:
                for (var j = 0; j < len; j++) {
                    str = item.muscha.string[j] + data[item.muscha.text[j]];
                }
                str += item.muscha.string[j];
        }
    }
    return str; 
}

进一步,实现循环模版。带有非根元素(代码中的最外层节点)的父元素的循环节点处理起来相对容易,只需要将父元素先清理干净(parentNode.innerHTML = ''),循环数据后插入相应的dom节点即可。只是花了不少的时间在父元素为根节点的循环模版上,如果采用相同的方法,页面结构必然会被破坏,当我们重写这个节点后对节点的引用也就失效了,于是上一种的情况采用父节点来辅助,于是在这就联想到,我是否可以借助兄弟元素来实现呢?当然,各种各样的问题也在这里出现,加深了对dom节点操作的知识(唉,太渣!),倒腾了不久,终于写出了代码!(但是就是丑~)。代码如下:

case 's-for':
    var items = data[item.list];
    var fragment = document.createDocumentFragment();
    if (content) {
        for (var i = 0, len = items.length; i < len; i++) {
            var dom = document.createElement(item.node
                .nodeName.toLowerCase());
            dom.innerHTML = items[i][content];
            if (item.event) {
                for (var j = 0; j < item.event.length; j++) {
                    dom.addEventListener(item.event[j].type, that.eventProcess(methods[item.event[j].event]), false);
                }
            }
            fragment.appendChild(dom);
        }
        if (item.parentNode) {
            var dom = document.createElement(item.node
                .nodeName.toLowerCase());
            item.parentNode.innerHTML = '';
            item.parentNode.appendChild(fragment);
        } else{
            if (item.nextElementSibling === undefined) {
                item.nextElementSibling = item.node.nextElementSibling;
                if (item.node.nextElementSibling === null) {
                    item.node.parentNode.insertBefore(fragment, item.node);
                    //console.log(item.node.parentNode.lastElementChild);
                    item.node.parentNode.removeChild(item.node.parentNode.lastElementChild);
                } else { 
                    item.node.nextElementSibling.parentNode.insertBefore(fragment, item.node);
                    item.node.nextElementSibling.parentNode.removeChild(item.node);
                }
            }
        }
    }
    break;

};

好了,暂时就实现这么点,插值的供能是很强大的,这里实现的功能也只是一部分~

转载于:https://www.cnblogs.com/susantong/p/6958788.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值