zoukankan      html  css  js  c++  java
  • 仿照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;
    
    };
    

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

  • 相关阅读:
    Python中Random随机数返回值方式
    SQL跨库查询
    正则表达式基本语法
    excel VBA使用教程
    使用某些Widows API时,明明包含了该头文件,却报错“error C2065: undeclared identifier”
    电脑开机后数字键盘为关闭状态
    编译Boost 详细步骤 适用 VC6 VS2003 VS2005 VS2008 VS2010
    变量作用域,不能理解,先记下
    解决MySQL 在 Java 检索遇到timestamp空值时报异常的问题
    Annotation
  • 原文地址:https://www.cnblogs.com/susantong/p/6958788.html
Copyright © 2011-2022 走看看