【JavaScript框架封装】实现一个类似于JQuery的选择框架的封装

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。更多学习资料请访问我爱科技论坛:www.52tech.tech https://blog.csdn.net/m0_37981569/article/details/81123799 ...
版权声明:本文为博主原创文章,未经博主允许不得转载。更多学习资料请访问我爱科技论坛:www.52tech.tech https://blog.csdn.net/m0_37981569/article/details/81123799
// 选择框架
(function (xframe) {
    // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法)
    xframe.extend({});


    // 不需要参与链式访问的
    xframe.extend(xframe, {
        /**
         * ID选择器
         * @param context
         * @return {HTMLElement | *}
         */
        $id: function (context) {
            // context是一个DOM对象还是字符串
            context = this.isString(context) ? document.getElementById(context) : context;
            return context;
        },
        /**
         * tag选择器, context;里面存储了上下文信息(尽量少的使用局部变量)
         * @param tag
         * @param context
         * @return {NodeListOf<HTMLElementTagNameMap[keyof HTMLElementTagNameMap]>}
         */
        $tag: function (tag, context) {
            // 分为两种情况
            if (typeof context === 'string') {
                context = this.$id(context);
            }

            // 按照这种思路,只有可能是一种情况
            if (context) {
                if (context.length) {
                    // 这里默认只会返回数组中的第0个元素
                    return [].slice.call(context)[0].getElementsByTagName(tag);
                } else {
                    return context.getElementsByTagName(tag);
                }
            }
            return document.getElementsByTagName(tag);
        },
        /**
         * 实现一个类选择器
         * @param className
         * @param context
         * @return {*}
         */
        $class: function (className, context) {
            // context里面此时存储的是一个DOM节点元素
            // 如果直接传过来的是一个DOM元素节点context(DOM元素的话就单独处理)
            context = this.$id(context) || document;

            // 1.由于getElementByClassName()这个方法是不兼容的,因此需要使用浏览器内置的方法去获取类选择器
            // 2. 可以使用getElementByTagName()的方法去获取所有的标签元素,然后把再使用className的属性间接去实现一个类似的class选择器的功能
            if (context.getElementsByClassName) {
                // 如果支持这个方法的话
                return context.getElementsByClassName(className);
            } else {
                // 不支持的话就间接获取
                var doms = context.getElementsByTagName('*'),
                    res = [];
                // 使用自己定义的方法去实现一个类选择器
                doms.each(function () {
                    if (this.className === className) {
                        // 只要是找到了这个class的集合,就放入到一个数组里面
                        res.push(this);
                    }
                });
                return res;

            }
        },
        /**
         * 使用管道思想实现一个层次选择器
         * @return {Array}
         */
        $cengci: function () {
            var self = this;
            // 主要功能:实现一个层次选择器
            // 输入字符串: str = '#className div  a p'  选择所有的className 下面的P标签
            // 1. 获取穿过来的参数(数组元素去重)
            var args = Array.prototype.slice.call(arguments)[0].toString().split(' '),
                index,
                first,
                item,
                selector,
                res = [],           // 存储了本次的结果信息
                context = [];            // 存储了上一次的上下文信息【管道思想!】, context = 'tag .class #id'


            // 思考: 为了实现一个层次选择器, 如何实现一个吧上一次选择的元素全部存储起来???


            // 2. 开始解析参数信息
            args.each(function () {
                // 每次重复之前,先把本次需要存储的数组清空(res里面存储了每次的最新数据)
                res = [];

                // 对获取到的每一项进行处理
                item = this.trim();
                first = item.charAt(0);
                index = item.indexOf(first);
                selector = item.slice(index + 1);


                // 使用管道思想实现一个层次选择器!!!
                switch (first) {
                    case '.':  // class 选择器
                        if (context.length) {
                            // 说明这一次的class类选择器中的元素不是第一次出现
                            context.each(function () {
                                pushArray(self.$class(selector, this));
                            });
                        } else {
                            // 如果是第一次出现的话
                            pushArray(self.$class(selector));
                        }
                        // 把上一次执行的结果存起来
                        context = res;
                        break;
                    case '#':  // ID选择器
                        // 由于ID选择器获取的元素始终是唯一的,因此直接放进去即可
                        res.push(self.$id(selector));
                        // 把上一次执行的结果存起来
                        context = res;
                        break;
                    default:    // tag选择器
                        if (context.length) {
                            // 说明不是第一次出现
                            context.each(function () {
                                // 注意在使用tag选择器的时候,第二个参数必须是一个ID选择器,或者是一个
                                // 1. 注意在放入数组的时候,需要逐个遍历然后放进去
                                pushArray(self.$tag(item, this));
                            });
                        } else {
                            // 第一次出现的
                            pushArray(self.$tag(item));
                        }
                        // 把上一次执行的结果存起来
                        context = res;
                        break;
                }
            });


            /**
             * 把公共的部分代码封装起来
             * @param doms
             */
            function pushArray(doms) {
                if (doms) {
                    [].slice.call(doms).each(function () {
                        res.push(this);
                    });
                }
            }

            return context;
        },
        /**
         * group选择器
         * @return {Array}
         */
        $group: function () {
            var self = this;
            // '.moshou,#moshou,span,.dream'
            // 1. 获取传过来的参数
            var args = [].slice.call(arguments),
                arr = args[0].split(',').unique(),      // 这里在拿到这个分割后的字符串后,开始进行数组元素去重
                item,
                index,
                first,
                selector;
            res = [];

            // 2. 开始遍历参数集合,解析参数信息
            arr.each(function () {
                // 3. 开始遍历得到结果,获取每一项
                item = this.trim();
                // 4. 开始获取首字母信息,和后面的选择器信息
                // 4. 获取指定下标位置对应的字符
                first = item.charAt(0);
                index = item.indexOf(first);
                selector = item.slice(index + 1);


                // 开始根据第一个字母向下进行判断,把满足相应条件的放在数组里面
                switch (first) {
                    case '.':
                        // class选择器
                        res.push(self.$class(selector));
                        break;
                    case '#':
                        // ID 选择器
                        res.push(self.$id(selector));
                        break;
                    default:
                        // TAG选择器(直接就是first本身,这里不用再判断了使用selector这个变量了)
                        res.push(self.$tag(item));
                        break;
                }
            });

            return res;
        },
        /**
         * 多组+层次选择器
         * @return {Array}
         */
        $select: function () {
            // str = '#tag , .calss'
            var args = [].slice.call(arguments)[0].toString().split(','),
                ret = [],
                self = this;

            // 遍历args数组,对数组的每一项采用层次选择器
            args.each(function () {
                // 1. 对于逗号分隔的部分采用层次选择,获取层次选择器的结果信息, 是一个数组集合
                var res = self.$cengci(this);
                // 2. 遍历层次选择器的集合,把信息放入到一个新的数组里面, 就是得到的多组选择器的结果信息
                pushArray(res);
            });


            // 层次选择器
            function pushArray(doms) {
                if (doms.length) {
                    doms.each(function () {
                        ret.push(this);
                    });
                }
            }

            return ret;
        }
    });
})(xframe);

 

相关文章
|
13天前
|
Web App开发 JavaScript 前端开发
构建高效后端服务:Node.js与Express框架的实战指南
【9月更文挑战第6天】在数字化时代的潮流中,后端开发作为支撑现代Web和移动应用的核心,其重要性不言而喻。本文将深入浅出地介绍如何使用Node.js及其流行的框架Express来搭建一个高效、可扩展的后端服务。通过具体的代码示例和实践技巧,我们将探索如何利用这两个强大的工具提升开发效率和应用性能。无论你是后端开发的新手还是希望提高现有项目质量的老手,这篇文章都将为你提供有价值的见解和指导。
|
23天前
|
JavaScript 前端开发 中间件
构建高效后端服务:Node.js与Express框架的完美搭档
【8月更文挑战第28天】在追求高性能、可扩展和易维护的后端开发领域,Node.js和Express框架的组合提供了一种轻量级且灵活的解决方案。本文将深入探讨如何利用这一组合打造高效的后端服务,并通过实际代码示例展示其实现过程。
|
24天前
|
JavaScript 前端开发 开发者
Vue.js 框架大揭秘:响应式系统、组件化与路由管理,震撼你的前端世界!
【8月更文挑战第27天】Vue.js是一款备受欢迎的前端JavaScript框架,以简洁、灵活和高效著称。本文将从三个方面深入探讨Vue.js:响应式系统、组件化及路由管理。响应式系统为Vue.js的核心特性,能自动追踪数据变动并更新视图。例如,通过简单示例代码展示其响应式特性:`{{ message }}`,当`message`值改变,页面随之自动更新。此外,Vue.js支持组件化设计,允许将复杂界面拆分为独立且可复用的组件,提高代码可维护性和扩展性。如创建一个包含标题与内容的简单组件,并在其他页面中重复利用。
47 3
|
21天前
|
存储 JavaScript NoSQL
构建高效Web应用:使用Node.js和Express框架
【8月更文挑战第30天】本文将引导你了解如何使用Node.js和Express框架快速搭建一个高效的Web应用。通过实际的代码示例,我们将展示如何创建一个简单的API服务,并讨论如何利用中间件来增强应用功能。无论你是新手还是有经验的开发者,这篇文章都将为你提供有价值的见解。
|
1天前
|
缓存 监控 JavaScript
构建高效后端服务:Node.js与Express框架的完美结合
【9月更文挑战第18天】在数字化时代的浪潮中,后端服务的效率和稳定性成为了企业竞争力的关键。本文将深入探讨如何使用Node.js和Express框架来构建一个既高效又稳定的后端服务,同时通过实际代码示例,展示如何优化性能并确保服务的高可用性。
|
9天前
|
设计模式 JavaScript
JS发布订阅模式封装(纯手工)
发布订阅模式是JS常用的设计模式,在面试中也会经常遇到,以下是我的手写实现方式,经测试效果不错,小伙伴们们可以直接拷贝使用。
|
8天前
|
Web App开发 缓存 JavaScript
构建高效后端服务:Node.js与Express框架的完美结合
【9月更文挑战第11天】本文将引导开发者探索如何利用Node.js和Express框架搭建一个高效的后端服务。文章不仅深入讲解了这两个工具的核心概念,还通过实际示例展示了它们的强大功能和易用性。读者将学会如何处理HTTP请求、设计RESTful API以及优化应用性能。无论你是初学者还是有经验的开发者,这篇文章都将为你提供宝贵的知识,帮助你在后端开发领域更进一步。
|
24天前
|
Web App开发 JavaScript 中间件
构建高效后端服务:Node.js与Express框架的深度整合
【8月更文挑战第27天】 在现代Web开发中,后端服务的高效性至关重要。本文深入探讨了如何利用Node.js的非阻塞I/O特性和Express框架的简洁性来打造高性能的后端服务。我们将通过具体案例,展示如何在不牺牲代码可读性和可维护性的前提下,实现高效的请求处理和服务端逻辑。文章旨在为开发者提供一个清晰的指导,帮助他们在构建后端服务时做出更明智的技术选择。
|
20天前
|
Devops 持续交付 测试技术
JSF遇上DevOps:开发流程将迎巨变?一篇文章带你领略高效协同的魅力!
【8月更文挑战第31天】本文探讨了如何在JavaServer Faces(JSF)开发中融入DevOps文化,通过持续集成与部署、自动化测试、监控与日志记录及反馈机制,提升软件交付速度与质量。文中详细介绍了使用Jenkins进行自动化部署、JUnit与Selenium进行自动化测试、ELK Stack进行日志监控的具体方法,并强调了持续改进的重要性。
28 0
|
23天前
|
JSON JavaScript 中间件
深入浅出Node.js后端开发之Express框架应用
【8月更文挑战第29天】本文将带领读者快速了解并掌握使用Express框架进行Node.js后端开发的基础和进阶知识。我们将一起探索Express的安装、基本使用方法,并通过实际代码示例学习如何搭建一个简单的Web服务器。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供有价值的指导和灵感。