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 相关文章推荐
jquery中的sortable排序之后的保存状态的解决方法
Jan 28 Javascript
基于jquery实现页面滚动到底自动加载数据的功能
Dec 19 Javascript
js实现文字垂直滚动和鼠标悬停效果
Dec 31 Javascript
JS实现根据文件字节数返回文件大小的方法
Aug 02 Javascript
微信小程序 for 循环详解
Oct 09 Javascript
JS如何生成一个不重复的ID的函数
Dec 25 Javascript
Angular利用trackBy提升性能的方法
Jan 26 Javascript
vue使用better-scroll实现下拉刷新、上拉加载
Nov 23 Javascript
React 使用Hooks简化受控组件的状态绑定
Mar 18 Javascript
js 实现ajax发送步骤过程详解
Jul 25 Javascript
bootstrap-treeview实现多级树形菜单 后台JSON格式如何组织?
Jul 26 Javascript
layui树形菜单动态遍历的例子
Sep 23 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生成文件
2007/01/15 PHP
PHP 函数学习简单小结
2010/07/08 PHP
抓取并下载CSS中所有图片文件的php代码
2011/09/26 PHP
PHP中4个加速、缓存扩展的区别和选用建议
2014/03/12 PHP
PHP实现获取并生成数据库字典的方法
2016/05/04 PHP
PHP数据库处理封装类实例
2016/12/24 PHP
js版本A*寻路算法
2006/12/22 Javascript
JavaScript 特殊字符
2007/04/05 Javascript
DWZ table的原生分页浅谈
2013/03/01 Javascript
利用JQuery和Servlet实现跨域提交请求示例分享
2014/02/12 Javascript
使用GruntJS构建Web程序之安装篇
2014/06/04 Javascript
深入讲解AngularJS中的自定义指令的使用
2015/06/18 Javascript
JS非Alert实现网页右下角“未读信息”效果弹窗
2015/09/26 Javascript
prototype框架中美元符号$用法分析
2016/01/22 Javascript
详解js的作用域、预解析机制
2018/02/05 Javascript
jQuery实现点击旋转,再点击恢复初始状态动画效果示例
2018/12/11 jQuery
nodejs中方法和模块用法示例
2018/12/24 NodeJs
JavaScript Math对象和调试程序的方法分析
2019/05/13 Javascript
node.js 微信开发之定时获取access_token
2020/02/07 Javascript
pygame学习笔记(6):完成一个简单的游戏
2015/04/15 Python
Python中operator模块的操作符使用示例总结
2016/06/28 Python
对python GUI实现完美进度条的示例详解
2018/12/13 Python
Flask框架踩坑之ajax跨域请求实现
2019/02/22 Python
Pytorch DataLoader 变长数据处理方式
2020/01/08 Python
Pyecharts绘制全球流向图的示例代码
2020/01/08 Python
澳大利亚在线床零售商:Bedworks
2020/09/01 全球购物
六查六看剖析材料
2014/02/15 职场文书
幼儿园爱国卫生月活动总结
2014/06/30 职场文书
关于工作时间玩手机的检讨书
2014/09/18 职场文书
统计工作个人总结
2015/03/03 职场文书
奥巴马开学演讲观后感
2015/06/12 职场文书
2016高考感言
2015/08/01 职场文书
2016年感恩教师节校园广播稿
2015/12/18 职场文书
调研报告的主要写法
2019/04/18 职场文书
MySQL 数据类型选择原则
2021/05/27 MySQL
Java设计模式之代理模式
2022/04/22 Java/Android