【JavaScript框架封装】公共框架的封装

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。更多学习资料请访问我爱科技论坛:www.52tech.tech https://blog.csdn.net/m0_37981569/article/details/81056006 ...
版权声明:本文为博主原创文章,未经博主允许不得转载。更多学习资料请访问我爱科技论坛:www.52tech.tech https://blog.csdn.net/m0_37981569/article/details/81056006

/*
* @Author: 我爱科技论坛
* @Time: 20180706
* @Desc: 实现一个类似于JQuery功能的框架

// 公共框架
// 种子模块:命名空间、对象扩展、数组化、类型的判定、domReady机制,无冲突处理
(function (xframe) {
    // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法)
    xframe.extend({
        each: function (fn) {
            var i = 0,
                len = this.length;
            for (; i < len; i++) {
                // call第一个参数传递的实际上就是this的执行,后面的参数就是目标函数fn需要传递的参数(可省略)
                // this[i] 里面的取值方式类似于json取值,每一个参数存储了选择器获取的所有的nodeList元素集合中的一个元素
                fn.call(this[i]);
            }
            return this;
        }
    });

    // 不需要参与链式访问的
    /*公共部分*/
    xframe.extend(xframe, {});

    /*字符串处理模块*/
    xframe.extend(xframe, {
        /*
        * 下面的这几个都会用到正则表达式,会在后面补充
        * camelCase函数的功能就是将形如background-color转化为驼峰表示法:backgroundColor
        * */
        camelCase: function (str) {
            //  all: -c, letter: c
            return str.replace(/\-(\w)/g, function (all, letter) {
                // 把所有的字母都转换为大写的状态
                return letter.toUpperCase();
            });
        },
        /**
         * 去掉左边的空格 str = ' ()'
         * @param str
         * @returns {*}
         */
        ltrim: function (str) {
            /*
            ^ :表示以XX开头
            \s: 表示空格
            *:  表示匹配零个或者多个
            g: 表示匹配全部,如果没有的话默认只会匹配一个
            (^\s*): 表示以空格开头的一个或者多个字符
            str.replace(, ''): 替换……


            ----------------------------------------------------[其他用法归纳]-------------------------------------
            ^, $: 匹配字符串开始,结束的位置      eg:
            g, i:匹配所有,不区分大小写的字符串; eg: /a/g, /a/i
            *, +, ?: 匹配任意次数, 匹配前面的字符一次或者多次, 0次或者1次

            [] : 匹配一个字符集合; eg: [a-z]所有小写字母的集合, [0-9]所有数字的集合
                                  eg: [a-zA-Z]所有大小写字母的集合
            脱字符^: 匹配任何不在该集合中的字符,与上面的用法正好相反
            {}: 指定重复前面的一个字符多少遍  eg:{N} 重复n遍
                                            eg:{n, m}重复n-m遍
                                            eg: {n, }至少重复n遍
                                            eg:{,m}至多重复m遍



            // 【熟记:同类记忆法】
            \s: 表示空格:包括空格、换行、回车、tab,等价于[\n\r\t\f]
            \S: 匹配非空格字符,等价于[^ \n\r\t\f]
            \d: 表示十进制数字,等价于[0-9]
            \D: 匹配一个非数字字符, 等价于[^0-9]
            \w(小写): 表示字母或者数字,等价于[a-zA-Z0-9]
            \W: 非字母且非数字,与\w相反,等价于:[^a-zA-Z0-9]*

            * */
            return str.replace(/(^\s*)/g, '');
        },
        /* 去掉右边的空格, str = '() '
        * @param str
        */
        rtrim: function (str) {
            return str.replace(/(\s*$)/g, '');
        },
        /**
         * 用于去掉两边的空格(去掉所有的空格) str  =' () '
         * @param str
         * @returns {*}
         */
        trimOld: function (str) {
            return str.replace(/(\s*$)/g, '');
        },
        /**
         * 【使用模板来实现一个简单的数据绑定】
         * 实现简单的数据绑定: @(name), @(sex)
         * data: var user = {name : 'xiugang', role, '钻石会员'}
         * str: = '欢迎@(name), 等级:@(role)光临本站!';
         * @param str   原始的数据格式
         * @param data  需要绑定的数据对象,是一个json格式的数据, json = {name : 'xiuxiu', age : 18}
         * @returns {*}
         */
        formateString: function (str, data) {
            // 使用后面的值去替换掉前面的值
            // 细节分析:((\w+))使用括号匹配的值在JavaScript中实际上就是一个$1, 把这个参数传给match
            // (\w+) 第二个括号实际上匹配到的就是一个$2, 把这个参数传给key
            // match: @(name), @(age), @(sex)
            // key: name, age, sex
            return str.replace(/@\((\w+)\)/g, function (match, key) {
                // 先判断有没有匹配到相应的字符串
                // 找到@()开始的字符串, 使用数据域中的数据去替换
                // 如果json数据data里面么有找到相应的data[key]数据,返回的实际上就是一个空的字符串
                return typeof  data[key] === 'undefined' ? '' : data[key];
            });

        },
        /**
         * @param str
         * @returns {*}
         */
        trimLeft: function (str) {
            return str.replace(/^\s*/g, '');
        },
        /**
         * @param str
         * @returns {*}
         */
        trimRight: function (str) {
            return str.replace(/\s*$/g, '');
        },
        /**
         * 去掉所有的空格(两边的空格), 可以针对任意格式的字符串
         * 先去掉左边的空格,然后去掉右边的空格
         * @param str
         * @returns {*}
         */
        trim: function (str) {
            // var regx = '/^\s*\s*$/g';
            // return str.replace(regx, '');
            // | 表示或的意思, 也就是满足| 左边的也成立, 满足 | 右面的也成立
            // (^\s*) 表示的就是以0个空格或者多个空格开头
            // (\s*$) 的意思就是, 以0个空格或者多个空格结尾
            // /…/g 是正则表达式的属性, 表示全文匹配, 而不是找到一个就停止
            return str.replace(/(^\s*)|(\s*$)/g, "");
            //return this.trimRight(this.trimLeft(str));
        },
        /**
         * 发送一个ajax请求
         * @param url  请求的URL地址信息
         * @param fn, 请求成功的回调函数
         */
        ajax: function (url, fn) {
            // 创建一个XMLHTTPRequest对象
            var xhr = createXHR();
            // 每当 readyState 改变时,就会触发 onreadystatechange 事件。
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    // 接受到响应之后,第一步检查status属性,为200则表明成功,此时responseText已经准备就绪;
                    // 为304表明请求资源未被修改,可以直接使用浏览器中的缓存版本。
                    if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
                        fn(xhr.responseText);
                    } else {
                        alert('错误的文件!');
                    }
                }
            };


            // 定义请求参数, 对于指定的url发送一个get请求
            xhr.open('get', url, true);
            // 发送请求
            // 第三个参数:指示请求使用应该异步地执行。
            // 如果这个参数是 false,请求是同步的,后续对 send() 的调用将阻塞,直到响应完全接收。
            // 如果这个参数是 true 或省略,请求是异步的,且通常需要一个 onreadystatechange 事件句柄。
            xhr.send();


            /**
             *   创建一个XHR
             */
            function createXHR() {
                //本函数来自于《JavaScript高级程序设计 第3版》第21章
                if (typeof XMLHttpRequest != "undefined") {
                    return new XMLHttpRequest();
                } else if (typeof ActiveXObject != "undefined") {
                    // arguments.callee用于指向他的回调函数
                    if (typeof arguments.callee.activeXString != "string") {
                        var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                                "MSXML2.XMLHttp"
                            ],
                            i, len;

                        for (i = 0, len = versions.length; i < len; i++) {
                            try {
                                new ActiveXObject(versions[i]);
                                arguments.callee.activeXString = versions[i];
                                break;
                            } catch (ex) {
                                //skip
                            }
                        }
                    }

                    return new ActiveXObject(arguments.callee.activeXString);
                } else {
                    throw new Error("No XHR object available.");
                }
            }


        },
        /**
         * json转换为字符串
         * @param json
         * @returns {string}
         */
        json2String: function (json) {
            return JSON.stringify(json);
        },
        /**
         * 字符串转换为json
         * @param str
         * @returns {any}
         */
        string2Json: function (str) {
            return eval(str);
        }
    });


    /*数组相关*/
    xframe.extend(xframe, {
        /**
         * 将一个数组清空,并返回数组的引用
         * 只需要把数组的元素置空为0即可
         * @return {xframe}
         */
        clear: function () {
            this.length = 0;
            return this;

        },
        /**
         * 返回数组的第0个元素
         * @return {*}
         */
        first: function () {
            return this[0];

        },
        /**
         * 返回数组的最后一个元素
         * @return {*}
         */
        last: function () {
            return this[this.length - 1];
        },
        /**
         * 计算一个数组的大小尺寸
         * @return {number|*}
         */
        size: function () {
            return this.length;
        },
        cacl: function (arr, callback) {
            var ret;
            for (var i = 0; i < arr.length; i++) {
                // 专门用于处理每一项的计算机过程
                ret = callback(arr[i], ret);
            }
            return ret;
        },
        /**
         * 对数组里面的所有元素求和
         * @return {*}
         */
        sum: function () {
            // 1. 正常写法
            var ret;
            for (var i = 0; i < this.length; i++) {
                ret = ret + this[i];
            }
            return ret;
        },
        max: function () {

        },
        min: function () {

        },
        avg: function () {

        },
        intersect: function () {

        },
        union: function () {

        },
        diff: function () {

        },
        unique: function () {

        },
        forEach: function () {

        },
        map: function () {

        },
        filter: function () {

        },
        every: function () {

        },
        some: function () {

        },
        reduce: function () {

        },
        reduceRight: function () {

        },
        indexOf: function () {

        },
        lastIndexOf: function () {

        },
        enhanceUnique: function () {

        },
        without: function () {

        },
        flatten: function () {

        },
        random: function () {

        },
        removeAt: function () {

        },
        contains: function () {

        }
    });


    /*Math*/
    xframe.extend(xframe, {
        random: function () {

        }

    });


    /*数据类型检验*/
    xframe.extend(xframe, {
        // 鸭子类型(duck typing)如果它走起路来像鸭子,叫起来也是鸭子,那么它就是鸭子。
        // 只关注对象的行为,不关注对象本身面向接口编型 ,而不是面向实现编程,是设计模式中最重要的思想。
        // 【理解】:一个对象有效的语义,不是由集成自特定的类或实现特定的接口, 而是由当前方法和属性的集合决定的!!!
        isNumber: function (val) {
            // 如果这个数字是有限的话, 而且是数字类型
            return (typeof val === 'number' && isFinite(val)) && (Object.prototype.toString.call(val) === '[object Number]');
        },
        /***
         * 判断一个变量是不是Boolean类型
         * @param val
         * @returns {boolean}
         */
        isBoolean: function (val) {
            return (typeof val === 'boolean') && (Object.prototype.toString.call(val) === '[object Boolean]');
        },
        /**
         * 判断一个变量是不是字符串类型
         * @param val
         * @returns {boolean}
         */
        isString: function (val) {
            return (typeof val === 'string') && (Object.prototype.toString.call(val) === '[object String]');
        },
        /**
         * 判断一个变量是不是undefined
         * @param val
         * @returns {boolean}
         */
        isUndefined: function (val) {
            // oid 0 is a correct and standard way to produce undefined.
            return (val === void 0) || (typeof val === 'undefined') && (Object.prototype.toString.call(val) === '[object Undefined]');
        },
        /**
         * 判断一个变量是不是为空
         * @param val
         * @returns {boolean}
         */
        isNull: function (val) {
            return (val === null) && (Object.prototype.toString.call(val) === '[object Null]');
        },
        /**
         * 检测
         * @param obj
         * @returns {*}
         */
        isNaN: function (val) {
            // 只要这个数字通过判断是不是和他自身相同或者使用typef的方式去检测
            return val !== val;
        },
        /**
         * 判断一个变量是不是一个对象类型
         * @param val
         * @returns {boolean}
         */
        isObject: function (val) {
            if (val !== null && val !== undefined) {
                if ((typeof val === 'object') && (Object.prototype.toString.call(val))) {
                    return true;
                }
            }
            return false;
        },
        /**
         * 判断一个对象是不是数组对象
         * @param val
         * @returns {boolean|void|string}
         */
        isArray: function (val) {
            // 判断上不是一个数组的先判断这个数组对象是不是为空, 因为如果val为空的话,就是val.constructor这个属性实际上是没有的,error
            if (val !== null || typeof val !== "undefined") {
                // 注意在使用constructor判断数据类型的时候比较的实际上是他的原型对象的constructor属性, 这个属性指向的实际上是这个变量的原型对象
                return (val.constructor === Array) && (Object.prototype.toString.call(val));
            }
            return false;
        }

    });


    /*数组化:arguments, document.forms, document.getElementsByName, document.getElementsByTagName()*/
    xframe.extend(xframe, {
        /**
         * 把一个伪数组转换为一个新的数组
         * 实现思路: 取出伪数组中的每一个元素, 然后把取出来的这些元素重新放入到一个新的数组里面去!!!
         * @param start
         * @param end
         * @returns {Array}
         */
        toArray: function (start, end) {
            var result = [];
            var start = start || 0,
                // 这里的this指向调用的对象,使用了call之后, 改变了this的指向, 指向传进来的对象(外边必须要修改this的指向)
                // 如果外边不修改this的指向,这里的this默认指向的是xframe这个框架对象
                end = end || this.length;
            for (var i = start; i < end; i++) {
                result.push(this[i]);
            }
            return result;
        },

        /**
         * 方法二: 直接把一个伪数组转换为JavaScript中的一个数组对象
         * @param obj
         * @returns {T[]}
         */
        slice: function (obj) {
            return Array.prototype.slice.apply(obj);
        }
    });

    /*domReady的实现*/
    xframe.extend(xframe, {
        //arguments 的主要用途是保存函数参数, 但这个对象还有一个名叫 callee 的属性,该属性是一个指针,指向拥有这个 arguments 对象的函数
        /**
         * 实现一个domReady方法:所有元素都加载完毕之后一个回调函数
         * @param domElement
         * @param fn
         */
        onDOMReady: function (fn) {
            if (document.addEventListener) {
                // W3C组织: 如果传过来的是一个DOM元素的话,就直接对这个DOM元素添加监听, 否则,就对整个document添加事件监听
                document.addEventListener('DOMContentLoaded', fn, false);
            } else {
                // IE浏览器
                IEContentLoaded(fn);
            }


            /**
             * 微软的IE浏览器的处理方法
             * @param fn
             * @constructor
             */
            function IEContentLoaded(fn) {
                // 定义需要的全局变量
                var done = false, document = window.document;


                // 这个函数只会在所有的DOM节点树创建完毕的时候才会继续向下执行
                var init = (function () {
                    if (!done) {
                        console.log('done……');
                        // 如果DOM树创建完毕的话
                        done = true;
                        fn();
                    }
                })();


                /*
                使用这个立即函数来调用IE浏览器的内置函数实现domReady的功能
                 */
                (function () {
                    try {
                        // DOM树在未创建完毕之后调用 doScroll的话,会抛出错误
                        document.documentElement.doScroll('left');

                    } catch (err) {
                        // 延迟1秒之后再次执行这个函数, 形成一个函数递归调用的功能【回调函数】
                        // clllee是一个函数指针,指向的是拥有这个arguments对象的函数, 从而实现再次调用这个函数
                        setTimeout(arguments.callee, 1);
                        return;
                    }

                    // 如果没有错误的话,表示DOM树已经完全创建完毕, 此时开始执行用户的回调函数
                    init();
                })();

                // 监听document的加载状态(DOM加载的过程中会不断回调这个函数)
                document.onreadystatechange = function () {
                    console.log('onreadystatechange……');
                    if (document.readyState === 'complete') {
                        console.log('complete……');
                        // 如果加载完成的话
                        document.onreadystatechange = null;
                        init();
                    }
                }
            }
        }
    });
})(xframe);

相关文章
|
15天前
|
Web App开发 JavaScript 前端开发
深入浅出Node.js后端框架
【10月更文挑战第34天】在数字化时代,后端开发如同一座桥梁,连接着用户界面与数据处理的两端。本文将通过Node.js这一轻量级、高效的平台,带领读者领略后端框架的魅力。我们将从基础概念出发,逐步深入到实战应用,最后探讨如何通过代码示例来巩固学习成果,使读者能够在理论与实践之间架起自己的桥梁。
|
1月前
|
JavaScript 前端开发 中间件
探索后端技术:Node.js与Express框架的完美融合
【10月更文挑战第7天】 在当今数字化时代,Web应用已成为日常生活不可或缺的一部分。本文将深入探讨后端技术的两大重要角色——Node.js和Express框架,分析它们如何通过其独特的特性和优势,为现代Web开发提供强大支持。我们将从Node.js的非阻塞I/O和事件驱动机制,到Express框架的简洁路由和中间件特性,全面解析它们的工作原理及应用场景。此外,本文还将分享一些实际开发中的小技巧,帮助你更有效地利用这些技术构建高效、可扩展的Web应用。无论你是刚入门的新手,还是经验丰富的开发者,相信这篇文章都能为你带来新的启发和思考。
|
3天前
|
缓存 监控 JavaScript
Vue.js 框架下的性能优化策略与实践
Vue.js 框架下的性能优化策略与实践
|
1月前
|
JavaScript 前端开发 API
Vue.js:现代前端开发的强大框架
【10月更文挑战第11天】Vue.js:现代前端开发的强大框架
69 41
|
21天前
|
JavaScript 中间件 API
Node.js进阶:Koa框架下的RESTful API设计与实现
【10月更文挑战第28天】本文介绍了如何在Koa框架下设计与实现RESTful API。首先概述了Koa框架的特点,接着讲解了RESTful API的设计原则,包括无状态和统一接口。最后,通过一个简单的博客系统示例,详细展示了如何使用Koa和koa-router实现常见的CRUD操作,包括获取、创建、更新和删除文章。
38 4
|
28天前
|
Web App开发 JavaScript 中间件
构建高效后端服务:Node.js与Express框架的完美结合
【10月更文挑战第21天】本文将引导你走进Node.js和Express框架的世界,探索它们如何共同打造一个高效、可扩展的后端服务。通过深入浅出的解释和实际代码示例,我们将一起理解这一组合的魅力所在,并学习如何利用它们来构建现代Web应用。
47 1
|
16天前
|
Web App开发 JavaScript 前端开发
构建高效后端服务:Node.js与Express框架的实践
【10月更文挑战第33天】在数字化时代的浪潮中,后端服务的效率和可靠性成为企业竞争的关键。本文将深入探讨如何利用Node.js和Express框架构建高效且易于维护的后端服务。通过实践案例和代码示例,我们将揭示这一组合如何简化开发流程、优化性能,并提升用户体验。无论你是初学者还是有经验的开发者,这篇文章都将为你提供宝贵的见解和实用技巧。
|
18天前
|
Web App开发 JavaScript 中间件
构建高效后端服务:Node.js与Express框架的融合之道
【10月更文挑战第31天】在追求快速、灵活和高效的后端开发领域,Node.js与Express框架的结合如同咖啡遇见了奶油——完美融合。本文将带你探索这一组合如何让后端服务搭建变得既轻松又充满乐趣,同时确保你的应用能够以光速运行。
24 0
|
1月前
|
JSON JavaScript 前端开发
Node.js Express 框架
10月更文挑战第7天
30 2
|
1月前
|
JavaScript 前端开发 API
下一篇
无影云桌面