nodom2-过滤器 filter

原创
2019/02/01 17:01
阅读数 28

过滤器改造为由过滤器类、过滤器工厂、模块过滤器工厂、过滤器初始化类

过滤器类型

通过FilterFactory.createFilterType创建,nodom2提供了6个过滤器类型,包括date,currency,number,tolowercase,touppercase,orderBy(数组排序)和select(数组过滤),与nodom1保持一致。用户可以通过createFilterType自定义过滤器类型。

Filter类

把过滤器独立出来,包含type和params两个属性。

代码如下:

/**
 * 过滤器类
 */
class Filter{
	/**
	 * 构造方法
	 * @param param 	[type,param1,param2,...]
	 */
	constructor(paramArr){
		this.type = paramArr[0];
		this.params = paramArr.slice(1);
	}
}

FilterFactory类

class FilterFactory{
	/**
	 * 创建过滤器类型
	 * @param name 		过滤器类型名
	 * @param handler 	过滤器类型处理函数
	 */
	static createFilterType(name,handler){
		if(this.filterTypes.has(name)){
			throw Error.handle('exist1',nodom.words.filter,name);
		}
		if(!nodom.isFunction(handler)){
			throw Error.handle('invoke','FilterFactory.create',1,'Function');	
		}
		this.filterTypes.set(name,handler);
	}

	/**
     * 移除过滤器类型
     * @param name  过滤器类型名
     */
    static removeFilterType(name){
        if(this.cantEditTypes.indexOf(name) !== -1){
            throw Error.handle('notupd',nodom.words.system + nodom.words.filter,name);
        }
        if(!this.filterTypes.has(name)){
            throw Error.handle('notexist1',nodom.words.filter,name);
        }
        delete this.filterTypes.delete(name);
    }

	/**
     * 执行过滤器
     * @param arguments 参数数组  0模块 1过滤器类型名 2待处理值 3-n处理参数
	 */
	static handle(module,type){
		let params = new Array();
		for(let i=2;i<arguments.length;i++){
			params.push(arguments[i]);
		}

		if(!this.filterTypes.has(type)){
			throw Error.handle('notexist1',nodom.words.filterType,type);   
		}
		//调用
		return nodom.apply(this.filterTypes.get(type),module,params);
	}

	/**
	 * 解析过滤器串为数组
	 * @param src 	源字符串,格式为filtertype:param1:param2:... 	
	 */
	static explain(src){
		let startStr,startObj = false;
		let strings = "\"'`"; 	//字符串开始和结束标志
		let splitCh = ':'; 		//分隔符
		let retArr = new Array();
		let tmp = ''; 			//临时串
		for(let i=0;i<src.length;i++){
			let ch = src[i];
			//字符串开始或结束
			if(strings.indexOf(ch) !== -1){
				if(ch === startStr){//字符串结束
					startStr = undefined;
				}else{				//字符串开始
					startStr = ch;
				}
			}else if(startStr === undefined){ 	//非字符串开始情况检查对象
				if(ch === '}' && startObj){ 	//对象结束
					startObj = false;
				}else if(ch === '{'){ 			//对象开始
					startObj = true;
				}
			}

			//分割开始
			if(ch === splitCh && startStr === undefined && !startObj && tmp !== ''){
				retArr.push(handleObj(tmp));
				tmp = '';
				continue;
			}
			tmp += ch;
		}
		//最后一个
		if(tmp !== ''){
			retArr.push(handleObj(tmp));
		}

		return retArr;
		/**
		 * 转化字符串为对象
		 */
		function handleObj(s){
			s = s.trim();
			if(s.charAt(0)==='{'){ //转换为对象
				s = eval('(' + s + ')');
			}

			return s;
		}
	}
}

FilterFactory.filterTypes = new Map();
FilterFactory.cantEditTypes = ['date','currency','number','tolowercase','touppercase','orderBy','filter'];

ModuleFilterFactory

nodom2中为每个模块建立过滤器工厂,该模块所有的过滤器实例都放在该工厂存放,使用时按照编号获取。

/**
 * 模块过滤器工厂,存储模块过滤器
 */
class ModuleFilterFactory{
	constructor(module){
		this.module = module;
		this.filters = new Array();
	}

	/**
	 * 添加过滤器
	 * @param filterStr 	过滤器串
	 * @return 				过滤器id
	 */
	add(filterStr){
		this.filters.push(new Filter(FilterFactory.explain(filterStr)));
		return this.filters.length-1;
	}

	/**
	 * 获取过滤器
	 * @param filterId 	过滤器id
	 */
	get(filterId){
		return this.filters[filterId];
	}

	/**
	 * 处理过滤器
	 */
	handle(data,filterId){
		let filter = this.get(filterId);
		//增加模块、类型和数据到参数
		let p = [this.module,filter.type,data].concat(filter.params);
		return nodom.apply(FilterFactory.handle,FilterFactory,p);
	}
}

内置过滤器类型初始化

/**
 * 过滤器类型初始化
 */

/**
 * 格式化日期
 * @param format    日期格式
 */
FilterFactory.createFilterType('date',(value,param)=>{
 	if(nodom.isEmpty(value)){
        return '';
    }
    if(!nodom.isArray(param)){
        throw Error.handle('paramException',nodom.words.filter,'date');
    }
    let format = param[0];
    //去掉首尾" '
    format = format.substr(1,format.length-2);
    return nodom.formatDate(value,format);
});


/**
 * 转换为货币
 * @param sign  货币符号¥ $ 等,默认 ¥
 */
FilterFactory.createFilterType('currency',(value,param)=>{
    let sign;
    if(nodom.isArray(param)){
        sign = param[0];
    }
    if(isNaN(value)){
        return '';
    }
    
    sign = sign || '¥';

    if(typeof value === 'string'){
        value = parseFloat(value);
    }
    
    return sign + ((value * 100 + 0.5 | 0) / 100);
});
/**
 * 格式化,如果为字符串,转换成数字,保留小数点后位数
 * @param digits    小数点后位数
 */
FilterFactory.createFilterType('number',(value,param)=>{
    if(!nodom.isArray(param)){
        throw Error.handle('paramException',nodom.words.filter,'number');
    }
    let digits = param[0]||0;
    if(isNaN(value) || digits < 0){
        return '';
    }
    if(typeof value === 'string'){
        value = parseFloat(value);
    }
    
    let x = 1;
    for(let i=0;i<digits;i++){
        x*=10;
    }
    return (value * x + 0.5 | 0) / x;
});
/**
 * 转换为小写字母
 */
FilterFactory.createFilterType('tolowercase',(value)=>{
    if(nodom.isEmpty(value)){
        return '';
    }
    if(!nodom.isString(value) || nodom.isEmpty(value)){
        throw Error.handle('invoke1',nodom.words.filter + ' tolowercase',0,'string');
    }
    return value.toLowerCase();
});

/**
 * 转换为大写字母
 */
FilterFactory.createFilterType('touppercase',(value)=>{
    if(nodom.isEmpty(value)){
        return '';
    }
    if(!nodom.isString(value) || nodom.isEmpty(value)){
        throw Error.handle('invoke1',nodom.words.filter + ' touppercase',0,'string');
    }
    return value.toUpperCase();
});

/**
 * 数组排序
 * @param arr       数组
 * @param param     
 *     用法: orderBy:字段:desc/asc
 */
FilterFactory.createFilterType('orderBy',function(){
    let args = arguments;
    let arr = args[0];				//数组
    let field = args[1];			//比较字段
    let odr = args[2] || 'asc';    	//升序或降序,默认升序
    if(!nodom.isArray(arr)){
        throw Error.handle('invoke1',nodom.words.filter + ' orderBy',0,'array');
    }
    //复制数组
    let ret = arr.concat([]);
    if(field && nodom.isObject(arr[0])){ //对象数组
    	if(odr === 'asc'){
	        ret.sort((a,b)=>a[field]>=b[field]?1:-1);
    	}else{
    		ret.sort((a,b)=>b[field]<=a[field]?1:-1);
    	}
    }else{  //值数组
    	if(odr === 'asc'){
	        ret.sort((a,b)=>a>=b?1:-1);
    	}else{
    		ret.sort((a,b)=>b<=a?1:-1);
    	}
    }
    return ret;
});

/**
 * 数组过滤
 * 用法: 无参数select:odd 带参数 select:range:1:5
 * odd      奇数,返回索引号为奇数的数组元素
 * even     偶数,返回索引号为偶数的数组元素
 * value    返回值中含有指定字符的数组元素
 *          {prop1:v1,prop2:v2,...} 满足所有属性prop的值中含有对应字符或相等值的数组元素
 * func     自定义函数过滤
 * range    数组范围1:5 返回索引1到5的数组元素
 * index    数组索引序列1:2:3 返回索引1,2,3的元素
 */
FilterFactory.createFilterType('select',function(){
    if(!nodom.isArray(arguments[0])){
        throw Error.handle('invoke1',nodom.words.filter + ' filter',0,'array');
    }

    let params = new Array();
    for(let i=0;i<arguments.length;i++){
    	params.push(arguments[i]);
    }

    //内部处理方法对象
    let handler = {
    	//奇数索引过滤
        odd:function(){
        	let arr = arguments[0];
            let ret = [];
            for(let i=0;i<arr.length;i++){
                if(i%2 === 1){
                    ret.push(arr[i]);
                }
            }
            return ret;
        },
        //偶数索引过滤
        even:function(){
        	let arr = arguments[0];
            let ret = [];
            for(let i=0;i<arr.length;i++){
                if(i%2 === 0){
                    ret.push(arr[i]);
                }
            }
            return ret;
        },
        //索引区域过滤
        range:function(){
        	let args = arguments;
        	let arr = args[0];
            let ret = [];
            //第一个索引,第二个索引
            let first = args[1];
            let last = args[2];
            if(isNaN(first)){
                throw Error.handle('paramException',nodom.words.filter , 'filter range');
            }
            if(!nodom.isNumber(first)){
            	first = parseInt(first);	
            }
            //判断数字
            if(isNaN(last)){
                throw Error.handle('paramException',nodom.words.filter , 'filter range');
            }

            //字符串转数字
            if(!nodom.isNumber(last)){
            	last = parseInt(last);	
            }
            
            if(first > last){
                throw Error.handle('paramException',nodom.words.filter , 'filter range');   
            }
            return arr.slice(first,last+1);
        },
        //索引过滤
        index:function(){
            let args = arguments;
            let arr = args[0];
            if(!nodom.isArray(args[0])){
                throw Error.handle('paramException',nodom.words.filter,'filter index');
            }
            let ret = [];
            //读取所有index
            if(arr.length>0){
            	for(let i=1;i<args.length;i++){
	            	if(isNaN(args[i])){
	                    continue;
	                }
	                let k = parseInt(args[i]);
	                if(k < arr.length){
	                	ret.push(arr[k]);
	                }
	            }	
            }
            return ret;
        },
        //函数过滤
        func:function(arr,param){
            if(!nodom.isArray(arr) || nodom.isEmpty(param)){
                throw Error.handle('paramException',nodom.words.filter,'filter func');   
            }
            //自定义函数
            let foo = this.methodFactory.get(param[0]);
            if(nodom.isFunction(foo)){
                return foo(arr);    
            }
            return arr;
        },
        //值过滤
        value:function(arr,param){
        	if(!nodom.isArray(arr) || nodom.isEmpty(param)){
                throw Error.handle('paramException',nodom.words.filter,'filter value');   
            }
            //属性值对象,所有属性值满足才过滤出来
            if(nodom.isObject(param)){
                let keys = nodom.getOwnProps(param);
                return arr.filter(function(item){
                    for(let i=0;i<keys.length;i++){
                        let v =  item[keys[i]];
                        let v1 = param[keys[i]];
                        //找不到属性值,或者不相等并且是字符串且不包含的情况都返回false
                        if(v === undefined || v !== v1 && typeof v === 'string' && v.indexOf(v1) === -1){
                            return false;
                        }
                    }
                    //都匹配则返回true
                    return true;
                });
            }else{//字符串
                return arr.filter(function(item){
                    let props = nodom.getOwnProps(item);
                    for(let i=0;i<props.length;i++){
                        let v = item[props[i]];
                        if(nodom.isString(v) && v.indexOf(param) !== -1){
                            return item;
                        }
                    }
                });
            }
        }
    }

    //类型匹配并处理
    let type = params[1].trim();
    //默认为value
    if(!handler.hasOwnProperty(type)){
        type = 'value';
    }

    //去掉type
   	params.splice(1,1);
    //校验输入参数是否为空
    if(type === 'range' || type === 'index' || type === 'func'){
        if(params.length < 2){
            throw Error.handle('paramException',nodom.words.filter);
        }
    }
    
    //方法调用
    return nodom.apply(handler[type],this,params);
});

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部