JS链式调用的实现方法


Posted in Javascript onMarch 07, 2013

链式调用
    链式调用其实只不过是一种语法招数。它能让你通过重用一个初始操作来达到用少量代码表达复杂操作的目的。该技术包括两个部分:

一个创建代表HTML元素的对象的工厂。

一批对这个HTML元素执行某些操作的方法。

调用链的结构
$函数负责创建支持链式调用的对象

(function() {
    /*
     * 创建一个私有class
     * @param {Object} els  arguments 所有参数组成的类数组
     */
    function _$(els) {
        this.elements = [];             //存放HTML元素
        for(var i=0, len=els.length; i<len; i++) {
            var element = els[i];
            if(typeof element === 'string') {
                element = document.getElementById(element);
            }
            this.elements.push(element);
        }
    }
    //对HTML元素可执行的操作
    _$.prototype = {
        each: function() {},
        setStyle: function() {},
        show: function() {},
        addEvent: function() {},
    };    
    //对外开放的接口
    window.$ = function() {
        return new _$(arguments);
    };   
})();

由于所有对象都会继承其原型对象的属性和方法,所以我们可以让定义在原型对象中的那些方法都返回用以调用方法的实例对象的引用,这样就可以对那些方法进行链式调用了。

(function() {
    /*
     * 创建一个私有class
     * @param {Object} els  arguments 所有参数组成的类数组
     */
    function _$(els) {
        //...
    }
    //对HTML元素可执行的操作
    _$.prototype = {
        each: function(fn) {        //fn 回调函数
            for(var i=0; i<this.elements.length; i++) {
                //执行len次,每次把一个元素elements[i]作为参数传递过去
                fn.call(this, this.elements[i]);
            }
            return this;
        },
        setStyle: function(prop, value) {
            this.each(function(el) {
                el.style[prop] = value;
            });
            return this;
        },
        show: function() {
            var that = this;
            this.each(function(el) {
                that.setStyle('display', 'block');
            });
            return this;
        },
        addEvent: function(type, fn) {
            var addHandle = function(el) {
                if(document.addEventListener) {
                    el.addEventListener(type, fn, false);
                }else if(document.attachEvent) {
                    el.attachEvent('on'+type, fn);
                }
            };
            this.each(function(el) {
                addHandle(el);
            });
            return this;  
        }
    };
    //对外开放的接口
    window.$ = function() {
        return new _$(arguments);
    }})();

//----------------------- test --------
$(window).addEvent('load', function() {
    $('test-1', 'test-2').show()
    .setStyle('color', 'red')
    .addEvent('click', function() {
        $(this).setStyle('color', 'green');
    });
})

链式调用的方法获取数据
    使用回调函数从支持链式调用的方法获取数据。链式调用很适合赋值器方法,但对于取值器方法,你可能希望他们返回你要的数据而不是this(调用该方法的对象).解决方案:利用回调技术返回所要的数据.

window.API = window.API || function() {
    var name = 'mackxu';
    //特权方法
    this.setName = function(name0) {
        name = name0;
        return this;
    };
    this.getName = function(callback) {
        callback.call(this, name);
        return this;
    };
};
//------------- test ---
var obj = new API();
obj.getName(console.log).setName('zhangsan').getName(console.log);

设计一个支持方法链式调用的JS库
JS库特征:

事件: 添加和删除事件监听器、对事件对象进行规划化处理

DOM: 类名管理、样式管理

Ajax: 对XMLHttpRequest进行规范化处理

Function.prototype.method = function(name, fn) {
    this.prototype[name] = fn;
    return this;
};
(function() {
    function _$(els) {
        //...
    }
    /*
     * Events
     *      addEvent
     *      removeEvent
     */
    _$.method('addEvent', function(type, fn) {
        //...  
    }).method('removeEvent', function(type, fn) {    })
    /*
     * DOM
     *      addClass
     *      removeClass
     *      hover
     *      hasClass
     *      getClass
     *      getStyle
     *      setStyle
     */
    .method('addClass', function(classname) {
        //...
    }).method('removeClass', function(classname) {
        //...
    }).method('hover', function(newclass, oldclass) {
        //...
    }).method('hasClass', function(classname) {
        //...
    }).method('getClass', function(classname) {
        //...
    }).method('getStyle', function(prop) {
        //...
    }).method('setStyle', function(prop, val) {
        //...
    })
    /*
     * AJAX
     *      ajax
     */
    .method('ajax', function(url, method) {
        //...
    });
    window.$ = function() {
        return new _$(arguments);
    };
    //解决JS库命名冲突问题
    window.installHelper = function(scope, interface) {
        scope[interface] = function() {
            return _$(arguments)
        }
    }  
})();

小结:

    链式调用有助于简化代码的编写工作,并在某种程度上可以让代码更加简洁、易读。很多时候使用链式调用可以避免多次重复使用一个对象变量,从而减少代码量。如果想让类的接口保持一致,让赋值器和取值器都支持链式调用,那么你可以在取值器中使用回调函数来解决获取数据问题。

Javascript 相关文章推荐
浅说js变量
May 25 Javascript
Jquery实现网页跳转或用命令打开指定网页的解决方法
Jul 09 Javascript
使用Jquery获取带特殊符号的ID 标签的方法
Apr 30 Javascript
javascript实现表单提交后,提交按钮不可用的方法
Apr 18 Javascript
Javascript中setTimeOut和setInterval的定时器用法
Jun 12 Javascript
javascript生成img标签的3种实现方法(对象、方法、html)
Dec 25 Javascript
详谈jQuery中使用attr(), prop(), val()获取value的异同
Apr 25 jQuery
浅谈vue中慎用style的scoped属性
Nov 28 Javascript
详解vue项目中调用百度地图API使用方法
Apr 25 Javascript
element-ui点击查看大图的方法示例
Dec 14 Javascript
详解vue3中组件的非兼容变更
Mar 03 Vue.js
如何用JS实现网页瀑布流布局
Apr 24 Javascript
jQuery滚动加载图片效果的实现
Mar 06 #Javascript
HTML上传控件取消选择
Mar 06 #Javascript
jQuery操作Select选择的Text和Value(获取/设置/添加/删除)
Mar 06 #Javascript
JQuery操作tr和td内容的方法实例
Mar 06 #Javascript
node在两个div之间移动,用ztree实现
Mar 06 #Javascript
js实现一个省市区三级联动选择框代码分享
Mar 06 #Javascript
自己写了一个展开和收起的多更能型的js效果
Mar 05 #Javascript
You might like
一个典型的PHP分页实例代码分享
2011/07/28 PHP
php中使用临时表查询数据的一个例子
2013/02/03 PHP
php实现把url转换迅雷thunder资源下载地址的方法
2014/11/07 PHP
一张表搞清楚php is_null、empty、isset的区别
2015/07/07 PHP
常见的四种POST 提交数据方式(小总结)
2015/10/08 PHP
php生成酷炫的四个字符验证码
2016/04/22 PHP
thinkPHP5.0框架简单配置作用域的方法
2017/03/17 PHP
laravel5.1框架model类查询的实现方法
2019/10/08 PHP
php的instanceof和判断闭包Closure操作示例
2020/01/26 PHP
不错的asp中显示新闻的功能
2006/10/13 Javascript
推荐40个非常优秀的jQuery插件和教程【系列三】
2011/11/09 Javascript
Javascript基础教程之数据类型 (数值 Number)
2015/01/18 Javascript
详解Vue路由开启keep-alive时的注意点
2017/06/20 Javascript
详解在Angular项目中添加插件ng-bootstrap
2017/07/04 Javascript
Vue单页式应用(Hash模式下)实现微信分享的实例
2017/07/21 Javascript
详解Angular调试技巧之报错404(not found)
2018/01/31 Javascript
js中el表达式的使用和非空判断方法
2018/03/28 Javascript
jQuery Ajax实现Select多级关联动态绑定数据的实例代码
2018/10/26 jQuery
[41:52]DOTA2-DPC中国联赛 正赛 CDEC vs Dynasty BO3 第二场 2月22日
2021/03/11 DOTA
python学习之第三方包安装方法(两种方法)
2015/07/30 Python
详解Python进程间通信之命名管道
2017/08/28 Python
python set内置函数的具体使用
2019/07/02 Python
深入浅析python变量加逗号,的含义
2020/02/22 Python
解决pymysql cursor.fetchall() 获取不到数据的问题
2020/05/15 Python
Python爬虫requests库多种用法实例
2020/05/28 Python
TensorFlow Autodiff自动微分详解
2020/07/06 Python
完美解决Pycharm中matplotlib画图中文乱码问题
2021/01/11 Python
aden + anais官方网站:婴儿襁褓、毯子、尿布和服装
2017/06/21 全球购物
表演方阵解说词
2014/02/08 职场文书
战略合作意向书范本
2014/04/01 职场文书
小学生感恩演讲稿
2014/04/25 职场文书
2015元旦家电促销活动策划方案
2014/12/09 职场文书
2015年九一八事变纪念日演讲稿
2015/03/19 职场文书
莫言获奖感言(全文)
2015/07/31 职场文书
早安问候语大全
2015/11/10 职场文书
申论不会写怎么办?教您掌握这6点思维和原则
2019/07/17 职场文书