首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >js学习: 自定义类库 - miniQuery 2.0

js学习: 自定义类库 - miniQuery 2.0

作者头像
剽悍一小兔
发布于 2018-05-17 06:41:06
发布于 2018-05-17 06:41:06
1.8K00
代码可运行
举报
运行总次数:0
代码可运行

Paste_Image.png

在上一篇 零基础打造自己的 js 类库(1) 中,原本只是为了写个小案例,说明一下闭包,js对象的作用。

后来我隐约有一个想法,我是不是可以将miniQuery写得更完善一些呢。我的意思是说,尽量使用jQuery的调用规则,看看自己能不能把常用的方法模拟出来?

这个想法产生以后,我感觉挺兴奋,正好可以藉由这个机会把js的知识点再复习一下。

今后只要有时间,我就把miniQuery更新一下,添加新的api方法进去。作为自己的一个学习记录。

零基础打造自己的 js 类库(1) 写完后,我又陆陆续续地改了很多代码,继而有了下面这个版本,暂且就叫做miniQuery v2.0吧,嘿嘿。

Paste_Image.png

Paste_Image.png

API方法目前大概分为 三个区域:

1. dom 相关 : 主要获取dom元素

2. css 相关:给dom元素设置css样式

3. 事件相关 :给元素添加事件

4. 属性相关:对元素属性进行各种操作

5. 简易ui : 额,目前只写了一个按钮

我利用零碎时间写了一个礼拜,没想到假模假式的也弄了不少方法了,当然,这些肯定是远远不够的。不够以后写案例的时候我差不多就可以直接调用这个miniQuery.js了,主要方便了自己,如果觉得有必要,我就可以立即在里面添加新的方法,实现了订制功能。

当然,目前这个版本功能还比较少,bug估计还有很多,不过没关系,反正就搞着玩玩,出了问题自己背锅就行了。主要还是用于培养兴趣,我本身不是做前端开发的,但是个人隐约感觉js在未来必定会火,当然现在也非常受欢迎了,我打算继续学下去。

首先来看看miniQuery怎么使用吧。

来一个测试页面,引入miniQuery

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <script type="text/javascript" src="js/miniQuery.js"></script>
        <title>测试页面</title>
        <script type="text/javascript">
        
            window.onload = function(){
                
            }
            
        </script>
    </head>
    <body>
        <div class='box'></div>
    </body>
</html>

页面上只画了一个div,其他啥也没有。

Paste_Image.png

div没有宽高。

接下来,我们用miniQuery来拿到这个对象。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var $box = $('.box').eq(0);
console.log($box);

Paste_Image.png

可见,返回的并不是一个dom对象,而是一个miniQuery对象,具体的原理在上一节中已经阐明。

OK,我们来给它定义宽高和背景色。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var $box = $('.box').eq(0);
$box.css({
    width : 80 ,
    height : 80 ,
    background : 'deeppink'
});

效果:

Paste_Image.png

我们在api上还看到有width,height,backgroundColor方法,而且miniQuery还支持链式调用,所以能这么写:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$box.height(80).width(80).backgroundColor('deeppink');

效果是一样的。

然后,我们给它添加一个事件,当点击的时候就把颜色换为skyblue:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var $box = $('.box').eq(0);
$box.css({
    width : 80 ,
    height : 80 ,
    background : 'deeppink'
}).on('click',function(){
    this.css({
        background:'skyblue'
    });
});

123.gif

再来看一看简单的ui。

我们来引入css文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<link rel="stylesheet" type="text/css" href="css/mui.css"/>
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var $box = $('.box').eq(0);
$box.linkbutton();

Paste_Image.png

按钮的样式就出来了,然后我们来设置按钮的属性。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var $box = $('.box').eq(0);
$box.linkbutton({
    text : '保存' ,
    click : function(){
        alert('保存成功!');
    }
});

Paste_Image.png

按钮的大小也自动变大了。

123.gif

至于其他方法,我就不一一测试了,问题肯定还是有的,以后慢慢完善吧。

至于这个miniQuery的具体实现,以后有机会的话我再开贴记录吧。

附上目前的源代码:

mui.css

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.linkbutton {
    padding: .4em .9em; /*em的好处就是随着父元素的字体大小而变化,当该元素的字体变化时,会自适应*/
    border: 1px solid rgba(0,0,0,.1);
    background-color: #ac0;
    border-radius: .2em;
    box-shadow: 0 1px 5px rgba(0,0,0,.5);
    color: #fff;
    text-shadow: 0 -.06em .24em rgba(0,0,0,.5); /*将阴影设置为半透明,就无所谓底色了,都能很好地适应*/
    font-size: 130%; 
    line-height: 1.5; /*行高是字号的1.5倍*/
    display:inline-block;
    cursor:pointer;
    font-family: "微软雅黑";
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
"use strict";

/**
 * miniQuery 和 工具类库
 * 版本 2.0 (修正了一部分Bug,增加了一些方法)
 * 作者:剽悍一小兔
 */

// ------------------------ 基本扩展, 字符串,数组等---------------------------------//
function extend_base (){
    
    if(!String.prototype.format ){
        String.prototype.format = function() {
            var e = arguments;
            return this.replace(/{(\d+)}/g,function(t, n) {
                return typeof e[n] != "undefined" ? e[n] : t
            })
        };
    }
    
    if (!Array.prototype.forEach && typeof Array.prototype.forEach !== "function") {
        Array.prototype.forEach = function(callback, context) {
           // 遍历数组,在每一项上调用回调函数,这里使用原生方法验证数组。
           if (Object.prototype.toString.call(this) === "[object Array]") {
               var i,len;
               //遍历该数组所有的元素
               for (i = 0, len = this.length; i < len; i++) {
                   if (typeof callback === "function"  && Object.prototype.hasOwnProperty.call(this, i)) {
                       if (callback.call(context, this[i], i, this) === false) {
                           break; // or return;
                       }
                   }
               }
           }
        };
    }
    
    if(!String.prototype.format ){
        Array.isArray = function(obj){
            return obj.constructor.toString().indexOf('Array') != -1;
        }
    }
    
}


extend_base(); 


// ------------------------ 工具包---------------------------------//
var utils = {
            center : function(dom){
                dom.style.position = 'absolute';
                dom.style.top = '50%';
                dom.style.left = '50%';
                dom.style['margin-top'] = - dom.offsetHeight / 2 + 'px';
                dom.style['margin-left'] = - dom.offsetWidth / 2 + 'px';
            },
        
            /** dom相关 * */
            isDom : ( typeof HTMLElement === 'object' ) ?
                function(obj){
                    return obj instanceof HTMLElement;
                } :
                function(obj){
                    return obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string';
                } ,
             
            /** 数组相关 * */
            isArray : function(obj){
                return obj.constructor.toString().indexOf('Array') != -1;
            }
            
        }
        


// ------------------------ miniQuery.js ---------------------------------//
;(function(win){
    
    var miniQuery = function(selector){
        var miniQuery = null;
        var length = 0;
        var children = [];
        if(!selector) return;
        
        /** 1. 传入的是id * */
        if(selector.toString().indexOf('#') != -1) {
            selector = selector.replace('#','');
            miniQuery = document.getElementById(selector);
        } 
        
        /** 2. 传入的是class * */
        else if(selector.toString().indexOf('.') != -1){
            selector = selector.replace('.','');
            miniQuery = document.getElementsByClassName(selector);
        }
        
        
        /** 3. 传入的是dom元素 * */
        else if(utils.isDom(selector)){
            miniQuery = selector;
        }
        
        if(!miniQuery) return; //如果本类库包装不了,就返回
        
        if(miniQuery.length){   //如果是一个类数组元素的话,就获取他的长度
            length = miniQuery.length; 
        }else{
            length = 1; //这种情况,说明成功包裹了元素,但是该元素还是存在的,就将长度设定为1
        }
        
        children = miniQuery.children; //取得所有的孩子节点
        
        return {
            
            /** 属性区 */
            obj : miniQuery,    //返回的dom元素
            index : 0 ,         //默认的角标(假如 miniquery 是一个类数组的话)
            length : length,    //元素的个数(假如 miniquery 是一个类数组的话)
            children : children,//所有孩子节点
            
            
            /** 方法区 */
            
            // ------------------------ dom 相关 ---------------------------------//
            
            /**获取dom对象本身,返回纯粹的dom元素,而非miniQuery元素*/
            getObj : function(){
                return this.obj;
            } ,
            
            /**获取元素的长度*/
            size : function(){
                return this.length;
            } ,
            
            /** 假如 miniquery 是一个类数组的话,用于返回其中一个元素 */
            eq : function(index){
                if(length > 0) {
                    return $(this.obj[index]); //eq返回的还是miniQuery对象
                }else{
                    return null;
                }
            } ,
            
            /** 获得第一个匹配元素 */
            first : function(){
                return $(this.obj[0]);
            } ,
            
            /** 获得最后一个匹配元素 */
            last : function(){
                return $(this.obj[this.length - 1]);
            } ,
            
            /** 获得最后一个匹配元素 */
            getChildren : function(){
                return this.obj.children;
            } ,
            
            /** 获得某一个孩子节点 */
            getChild : function(i){
                return $(this.children[i]);
            } ,
            
            /** 获得父节点 */
            getParent : function(){
                return $(this.obj.parentElement);
            } ,
            
            /** 获得上一个节点 */
            previous : function(){
                var parent = this.getParent();
                var children = parent.children;
                for(var i = 0; i < children.length; i++){
                    if(this.obj == children[i]) {
                        return $(children[i - 1]);
                    }
                }
                return null;
            } ,
            
            /** 获得下一个节点 */
            next : function(){
                var parent = this.getParent();
                var children = parent.children;
                for(var i = 0; i < children.length; i++){
                    if(this.obj == children[i]) {
                        return $(children[i + 1]);
                    }
                }
                return null;
            } ,
            
            findClassDom : function(className){
                 this.obj = this.obj.getElementsByClassName(className) ;
                 return this ;
            } ,
            
            findIdDom : function(id){
                 var $this = this; 
                 var children = this.getChildren();
                 children = Array.prototype.slice.call(children); //obj 转  []
                 children.forEach(function(item){
                    //console.log(item.id);
                    (id === item.id) && ($this = item) ;
                 });
                 return this ;
            } ,
            
            // ------------------------ css 相关 ---------------------------------//
            /** 添加背景色 */
            backgroundColor : function(color){
                this.obj.style.backgroundColor = color;
                return this;
            } ,
            
            /** 获取style */
            getStyle : function(){
                var styleEle = null;
                if(window.getComputedStyle){
                    styleEle = window.getComputedStyle(this.obj,null);
                }else{
                    styleEle = ht.currentStyle;
                }
                return styleEle;
             } ,
            
            /** 设置或者拿到高度 */ 
            height : function(h){
                if(!h) return this.getStyle().getPropertyValue('height');
                (typeof h == 'number') && (h = h + 'px');
                this.obj.style.height = h;
                return this;
            } ,
            
            /** 设置或者拿到宽度 */ 
            width : function(w){
                if(!w) return this.getStyle().getPropertyValue('width');
                (typeof w == 'number') && (w = w + 'px');
                this.obj.style.width = w;
                return this;
            } ,
            
            /** 设置自定义样式 */
            css : function(obj){
                if(!obj) return;
                for(var key in obj){
                    //console.log(key + '=========' + obj[key]);
                    this.obj.style[key] = typeof obj[key] === 'number' ? obj[key] + 'px' : obj[key];
                }
                return this;
            } ,
            
            /** 设置放大 倍数*/
            scale : function(scaleNumber){
                this.css({
                    scale : scaleNumber
                });
                return this;
            } ,
            
            
            hasClass : function(cls) {  
                return this.obj.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));  
            }  ,
            
            addClass : function(cls){
                if (!this.hasClass(cls)) this.obj.className += " " + cls;  
            } ,
            
            removeClass : function(cls) {  
                if (this.hasClass(cls)) {  
                    var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');  
                    this.obj.className = obj.className.replace(reg, ' ');  
                }  
            } ,
            
            toggleClass : function(cls){  
                if(this.hasClass(cls)){  
                    this.removeClass(cls);  
                }else{  
                    this.addClass(cls);  
                }  
            }  ,
            
            
            
            // ------------------------ 动画 相关 ---------------------------------//
            
            //TODO
            animate : function(){
                
            } ,
            
            // ------------------------ 事件相关 ---------------------------------//
            
            on : function(eventName,callback){
                var $this = this;
                this.obj['on' + eventName] = function(){
                    callback.call($this,$this.obj); //context指向$this,参数传入dom对象
                };
                return this;
            } ,
            
            // ------------------------ 属性相关 ---------------------------------//
            
            attr : function(attr){
                return this.obj.attributes[attr];
            } ,
            
            
            // ------------------------ ui ---------------------------------//
            
            linkbutton : function(opts){
                var opts = opts || {};
                /**添加基本样式* */
                this.addClass('linkbutton');
                this.on('mouseover' , function(e){
                    //console.log(e);
                    this.css({
                        backgroundColor: '#d4ef50'
                    });
                }).on('mouseout',function(e){
                    this.css({
                        backgroundColor: '#ac0'
                    });
                });
                
                opts.text && (this.obj.innerText = opts.text);
                opts.click && (this.on('click' , opts.click));
                
                
            }
            
            
            
        }
    }
    
    win.$ = miniQuery;
    
})(window);

我没具体测试,如果发现目前代码中的bug,欢迎评论或者简信我哦 _ 。

本章结束 ...

剽悍一小兔,电气自动化毕业。

参加工作后对计算机感兴趣,深知初学编程之艰辛。

希望将自己所学记录下来,给初学者一点帮助。

免责声明: 博客中所有的图片素材均来自百度搜索,仅供学习交流,如有问题请联系我,侵立删,谢谢。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016.09.01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
spring cloud利用feign和sentinel进行内部或外部远程调用
    基于上篇讲解的Sentinel之后,这次讲讲spring cloud环境下最优雅的远程调用方式Feign
chinotan
2019/04/03
3.5K0
spring cloud利用feign和sentinel进行内部或外部远程调用
【Kotlin Spring Boot 服务端开发: 问题集锦】Spring Security 5 : There is no PasswordEncoder mapped for the id "
【Kotlin Spring Boot 服务端开发: 问题集锦】Spring Security 5 : There is no PasswordEncoder mapped for the id "null" 错误
一个会写诗的程序员
2018/08/17
6630
apollo升级1.2版本后Spring Security导致的问题
首先说下背景,博主公司有大概30多个大小应用将配置信息托管在apollo上,因公司业务复杂环境众多,导致idc的配置多达七八个,因为早期apollo(0.8.x)版本不支持idc,namespace等的管理,故今天升级了下apollo到1.2.。升级后发现有的客户端在通过config service meta接口获取接口信息的时候抛rg.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL was not normalized.这个异常,而有的客户端可以正常的拿到接口信息,异常详情如下:
kl博主
2023/11/18
4660
HTTP重定向到HTTPS,post请求成了GET请求 报 Required request body is missing 和 Request method GET not supported
看到: Required request body is missing 和 Request method 'GET' not supported
HaC
2020/12/30
3.8K0
HTTP重定向到HTTPS,post请求成了GET请求  报 Required request body is missing 和 Request method GET not supported
Can't convert the date-like value to string because it isn't known if it's a date (no time part), ti
报错 ERROR - 2021-05-17 15:35:22 [http-nio-8080-exec-8]freemarker.log._Log4jLoggerFactory$Log4jLogger.error(_Log4jLoggerFactory.java:59) -- Error executing FreeMarker template FreeMarker template error: Can't convert the date-like value to string because it
彼岸舞
2021/05/18
1.1K0
The consumer group[PushConsumer] has been created before, specify another name please
报错 org.apache.rocketmq.client.exception.MQClientException: The consumer group[PushConsumer] has been created before, specify another name please. See http://rocketmq.apache.org/docs/faq/ for further details. at org.apache.rocketmq.client.impl.consumer.
MickyInvQ
2020/09/27
3.4K0
jxls工具导出excel,报错:Cannot load XLS transformer. Please make sure a Transformer implementation is in cl
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/163882.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/15
1.3K0
.MysqlDataTruncation: Data truncation: Data too long for column 'content' at row 1
版权声明:本文为博主原创文章,欢迎转载。 https://blog.csdn.net/chengyuqiang/article/details/89037174
程裕强
2019/07/02
1.7K0
.MysqlDataTruncation: Data truncation: Data too long for column 'content' at row 1
【黄啊码】网友:我用kill -9终止程序,结果被辞退了
1、kill -9 id:一般不加参数kill是使用15来杀,这相当于正常停止进程,停止进程的时候会释放进程所占用的资源;他们的区别就好比电脑关机中的软关机(通过“开始”菜单选择“关机”)与硬关机(直接切断电源),虽然都能关机,但是程序所作的处理是不一样的。
黄啊码
2023/06/19
6710
【黄啊码】网友:我用kill -9终止程序,结果被辞退了
mybatis-plus DEBUG之旅
直接上报错信息 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): cn.tompro.eduservice.mapper.EduCourseMapper.getPublishCourseInfo at com.baomidou.mybatisplus.core.override.PageMapperMethod$SqlCommand.<init>(PageMapperMethod.java:2
Tom2Code
2022/11/21
4910
mybatis-plus DEBUG之旅
local class incompatible: stream classdesc serialVersionUID = 61,local class serialVersionUID = 1
序列化失败: 场景:一个JPA实体类Person 业务层使用redis缓存 一开始没有添加serialVersionUID ,使用默认的,后面改为手动指定,结果就出现序列化失败。这是因为jdk序列化会根据这个UID版本号来做一些细节处理,UID不一样的话,就无法实现反序列化了,并且将会得到InvalidClassException。 将redis中的缓存清除,后再次访问即可。 @Entity @Table(name = "tb_person") @Data @Builder @NoArgsConstruc
青山师
2023/05/05
6880
Java连接Redis时出现“ERR Client sent AUTH, but no password is set”异常的原因及解决办法
他可能只注意到 “Could not get a resource from the pool” 的报错,没有注意到下面还有一句 “ERR Client sent AUTH, but no password is set”
Li_XiaoJin
2022/06/10
2.6K0
Java连接Redis时出现“ERR Client sent AUTH, but no password is set”异常的原因及解决办法
Swagger-ui在文件上传时报错net::ERR_CONNECTION_RESET
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
yingzi_code
2019/08/30
2K0
聊聊springcloud的serviceRegistryEndpoint
本文主要研究一下springcloud的serviceRegistryEndpoint
code4it
2018/09/17
1.4K0
feign.FeignException$MethodNotAllowed: status 405 reading xxx#yyy(Integer)
使用feign 调用异常 feign.FeignException$MethodNotAllowed: status 405 reading ConsumerService#findById(Integer)
时间静止不是简史
2020/07/27
2.3K0
feign.FeignException$MethodNotAllowed: status 405 reading xxx#yyy(Integer)
Spring Cloud Config Server迁移节点或容器化带来的问题
为了说明下面的内容,我们可以先尝试重现一下问题:在一个测试环境中,将Spring Cloud Config的配置中心迁移到另外一个节点上,即配置中心的IP地址发生了变化。在完成迁移之后,我们会发现该环境下各个微服务应用的健康状态会变得时好时坏,并且在日志中会出现类似下面的报错:
程序猿DD
2018/07/31
1.3K0
Spring Cloud Config Server迁移节点或容器化带来的问题
BadSqlGrammarException:PageHelper use near 'LIMIT 50'
作为一名Java开发人员,你可能在某个深夜,面对着那令人头秃的错误日志,不禁发问:“为什么我的SQL语句总是出错?”今天,就让我们一起深入探讨这个在Java开发项目中常见的问题——org.springframework.jdbc.BadSqlGrammarException,特别是在处理Excel导入时,如何避免这个让人头疼的错误。
疯狂的KK
2025/01/16
2000
BadSqlGrammarException:PageHelper use near 'LIMIT 50'
springBoot系列教程07:异常捕获
发生异常是很正常的事,异常种类也是千奇百怪,发生异常并不可怕,只要正确的处理,并正确的返回错误信息并无大碍,如果不进行捕获或者处理,分分钟服务器宕机是很正常的事
肖哥哥
2018/08/02
9150
springBoot系列教程07:异常捕获
springboot2.0配置多数据源出错HikariPool-1 - jdbcUrl is required with driverClassName.
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
suveng
2019/09/18
3.5K0
《Springboot极简教程》MappingMongoConverter:Failed to convert from type [java.lang.String] to type [long]
Failed to convert from type [java.lang.String] to type [long] for value 'null'; nested exception is java.lang.IllegalArgumentException: A null value cannot be assigned to a primitive type>
一个会写诗的程序员
2018/08/20
6470
推荐阅读
spring cloud利用feign和sentinel进行内部或外部远程调用
3.5K0
【Kotlin Spring Boot 服务端开发: 问题集锦】Spring Security 5 : There is no PasswordEncoder mapped for the id "
6630
apollo升级1.2版本后Spring Security导致的问题
4660
HTTP重定向到HTTPS,post请求成了GET请求 报 Required request body is missing 和 Request method GET not supported
3.8K0
Can't convert the date-like value to string because it isn't known if it's a date (no time part), ti
1.1K0
The consumer group[PushConsumer] has been created before, specify another name please
3.4K0
jxls工具导出excel,报错:Cannot load XLS transformer. Please make sure a Transformer implementation is in cl
1.3K0
.MysqlDataTruncation: Data truncation: Data too long for column 'content' at row 1
1.7K0
【黄啊码】网友:我用kill -9终止程序,结果被辞退了
6710
mybatis-plus DEBUG之旅
4910
local class incompatible: stream classdesc serialVersionUID = 61,local class serialVersionUID = 1
6880
Java连接Redis时出现“ERR Client sent AUTH, but no password is set”异常的原因及解决办法
2.6K0
Swagger-ui在文件上传时报错net::ERR_CONNECTION_RESET
2K0
聊聊springcloud的serviceRegistryEndpoint
1.4K0
feign.FeignException$MethodNotAllowed: status 405 reading xxx#yyy(Integer)
2.3K0
Spring Cloud Config Server迁移节点或容器化带来的问题
1.3K0
BadSqlGrammarException:PageHelper use near 'LIMIT 50'
2000
springBoot系列教程07:异常捕获
9150
springboot2.0配置多数据源出错HikariPool-1 - jdbcUrl is required with driverClassName.
3.5K0
《Springboot极简教程》MappingMongoConverter:Failed to convert from type [java.lang.String] to type [long]
6470
相关推荐
spring cloud利用feign和sentinel进行内部或外部远程调用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档