【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);

 

相关文章
|
2天前
|
XML 前端开发 JavaScript
jQuery与javascript的区别+案例 锋芒毕露
jQuery与javascript的区别+案例 锋芒毕露
|
2天前
|
JavaScript 索引
jQuery 实现 图片框切换【与原生 JS 对比】
jQuery 实现 图片框切换【与原生 JS 对比】
|
4天前
|
资源调度
在 Next.js 中使用自定义服务器框架进行服务器端渲染
在 Next.js 中使用自定义服务器框架进行服务器端渲染
Next.js 的服务器端渲染框架集成
Next.js 的服务器端渲染框架集成
|
4天前
|
前端开发 网络架构 UED
React Next.js框架
React Next.js 是一个基于 React 的服务器渲染框架,用于构建高性能的现代Web应用。它提供内置的服务器渲染、静态导出、动态路由功能,并自动进行代码拆分。Next.js 还支持热模块替换、CSS-in-JS 和客户端路由,拥有丰富的插件生态系统,简化了开发过程,提升了应用的性能和用户体验。
|
4天前
|
移动开发 JavaScript 前端开发
Phaser和Three.js是两个非常流行的JavaScript游戏框架
【5月更文挑战第14天】Phaser是开源的2D游戏引擎,适合HTML5游戏开发,内置物理引擎和强大的图形渲染功能,适用于消消乐等2D游戏。Three.js是基于WebGL的3D库,用于创建3D场景和应用,支持各种3D对象和交互功能,广泛应用于游戏、可视化等领域。选择框架取决于项目需求,2D选Phaser,3D选Three.js。
15 4
|
4天前
|
JavaScript 前端开发
JS实现网页页面的框架(demo)
JS实现网页页面的框架(demo)
10 1
|
4天前
|
JavaScript 前端开发 C++
【Web 前端】JavaScript window.onload 事件和 jQuery ready 函数有何不同?
【5月更文挑战第2天】【Web 前端】JavaScript window.onload 事件和 jQuery ready 函数有何不同?
|
4天前
|
设计模式 前端开发 JavaScript
AngularJS是一款由Google收购的JavaScript结构框架
【5月更文挑战第2天】AngularJS是Google收购的JavaScript框架,用于构建动态Web应用,基于MVC模式,强调模块化和双向数据绑定。它简化了视图与模型的同步,通过语义化标签和依赖注入提升开发效率。适用于复杂单页面应用(SPA),但不适合DOM操作密集型或性能要求极高的场景。
26 0