前面的话

  虽然jQuery已经日渐式微,但它里面的许多思想,如选择器、链式调用、方法函数化、取赋值合体等,有的已经变成了标准,有的一直影响到现在。所以,jQuery是一个伟大的前端框架。前端世界日新月异,由于实在是没有时间去精读源码,于是自己封装一个简易版本的jQuery,来梳理jQuery的核心思路

基本构架

  由于火柴的英文是match,应该将这个简单框架称为mQuery。使用面向对象的写法来写mQuery,构造函数是Mquery(),调用$()方法,将根据Mquery()构造函数,创建一个实例对象

//构造函数
function Mquery(arg){}
function $(arg){
return new Mquery(arg);
}

  jquery几大特征:

  1、通过$()选择的元素都是一个集合,即使仅仅是一个元素

  因此,创建一个elements属性为一个数组,去接收获取的元素

//构造函数
function Mquery(arg){
//保存所选择的元素
this.elements = [];
}

  2、链式调用

  所以,原型函数要返回this,以实现链式调用的效果

$函数

  $函数根据参数类型的不同,用途也不同

  1、参数为函数时,则直接运行

$(function(){
console.log(1)
})

  2、参数为对象时,则把DOM对象转换为$对象

$(document.body)

  3、参数为字符串时,则根据字符串选择出元素,并转换为$对象

$('#box')

  下面根据以上三个分类,来编写Mquery构建函数

//事件绑定兼容写法
function _addEvent(target,type,handler){
if(target.addEventListener){
target.addEventListener(type,function(e){
//如果事件函数中出现 return false;则阻止默认事件和阻止冒泡
if(typeof handler == 'function' && handler() === false){
e.preventDefault();
e.cancelBubble = true;
}
},false);
}else{
target.attachEvent('on'+type,function(event){
if(typeof handler == 'function' && handler() === false){
event.cancelBubble = true;
event.returnValue = false;
}
return handler.call(target,event);
});
}
} //将类数组转换成数组
function _toArray(arrayLike){
return Array.prototype.slice.call(arrayLike);
}
//构造函数
function Mquery(arg){
//保存所选择的元素
this.elements = [];
switch(typeof arg){
//当参数是函数时,如$(function(){})(),直接运行里面的代码
case 'function':
_addEvent(window,'load',arg);
break;
//当参数是字符串时,选择元素
case 'string':
this.elements = _toArray(document.querySelectorAll(arg));
break;
//当参数是DOM对象时,将DOM对象转换为$对象
case 'object':
if(arg.constructor == Array){
this.elements = arg;
}else{
this.elements.push(arg);
}
break;
}
}

HTML、CSS及特性设置

  下面来介绍常用的HTML、CSS及特性设置

【HTML】

  对于文本内容来说,一般地,有三种方法:html()、text()和val()。本文只实现最常用的html()方法

  当html()方法没有参数时,表示获取内容;有一个参数时,表示设置内容

//HTML获取与设置
Mquery.prototype.html = function(str){
//设置
if(str){
for(var i = 0; i < this.elements.length; i++){
this.elements[i].innerHTML = str;
}
//获取
}else{
return this.elements[0].innerHTML;
}
return this;
}

【CSS】

  对于CSS来说,有两种参数格式:一种是json格式,一种是字符串格式

  当第一个参数为对象时,则判断为json格式,否则为字符串格式

  对于字符串格式来说,只有一个参数时,为获取样式,两个参数时,为设置样式

  获取样式时,仅获取当前集合中第0个元素的样式;设置样式时,则设置当前集合中所有元素的样式

//获取计算样式兼容写法
function _getCSS(obj,style){
if(window.getComputedStyle){
return getComputedStyle(obj)[style];
}
return obj.currentStyle[style];
}
//CSS获取与设置
Mquery.prototype.css = function(attr,value){
//如果是对象的形式,以对象的形式设置
if(typeof attr == 'object'){
for(var att in attr){
for(var j = 0; j < this.elements.length; j++){
this.elements[j].style[att] = attr[att];
}
}
//如果不是对象的形式
}else{
//设置
if(arguments.length == 2){
for(var i = 0; i < this.elements.length; i++){
this.elements[i].style[attr] = value;
}
//获取
}else if(arguments.length == 1){
return _getCSS(this.elements[0],attr)
}
}
return this;
}

【attr】

  特性设置与获取的思路与CSS类似,只是方法变成了setAttribute()和getAttribute()

//attr获取与设置
Mquery.prototype.attr = function(attr,value){
//如果是对象的形式
if(typeof attr == 'object'){
for(var att in attr){
for(var j = 0; j < this.elements.length; j++){
this.elements[j].setAttribute(att,attr[att]);
}
}
//如果不是对象的形式
}else{
//设置
if(arguments.length == 2){
for(var i = 0; i < this.elements.length; i++){
this.elements[i].setAttribute(attr,value);
}
//获取
}else if(arguments.length == 1){
return this.elements[0].getAttribute(attr);
}
}
return this;
}

事件绑定

【on】

  在jQuery中,最常用的事件绑定方法就是on方法。在on方法中要特别注意的是this的绑定,由于函数fn中的this实际上是window,所以应该将fn的this绑定到当前元素

//事件绑定
Mquery.prototype.on = function(eventType,fn){
for(var i = 0; i < this.elements.length; i++){
_addEvent(this.elements[i],eventType,fn.bind(this.elements[i));
}
return this;
}

【click和hover】

  click方法是一个简写方法

Mquery.prototype.click = function(fn){
this.on('click',fn);
return this;
}

  hover方法是mouseover和mouseout的合成方法

Mquery.prototype.hover = function(fnOver,fnOut){
this.on('mouseover',fnOver);
this.on('mouseout',fnOut);
return this;
}

【return false】

  在jQuery中,使用return false可以同时阻止默认行为和阻止冒泡

//事件绑定兼容写法
function _addEvent(target,type,handler){
if(target.addEventListener){
target.addEventListener(type,function(e){
//如果事件函数中出现 return false;则阻止默认事件和阻止冒泡
if(typeof handler == 'function' && handler() === false){
e.preventDefault();
e.cancelBubble = true;
}
},false);
}else{
target.attachEvent('on'+type,function(event){
if(typeof handler == 'function' && handler() === false){
event.cancelBubble = true;
event.returnValue = false;
}
return handler.call(target,event);
});
}
}

其他设置

  jQuery的功能非常强大。下面选择一些常用功能进行实现

【显示隐藏】

//隐藏
Mquery.prototype.hide = function(){
for(var i = 0; i < this.elements.length; i++){
//保存当前元素的display值
this.elements[i].displayValue = this.elements[i].style.display;
this.elements[i].style.display = 'none';
}
return this;
}
//显示
Mquery.prototype.show = function(){
for(var i = 0; i < this.elements.length; i++){
this.elements[i].style.display = this.elements[i].displayValue;
//删除保存的元素的display值
delete this.elements[i].displayValue;
}
return this;
}

【插件设置】

$.extend = function(json){
for(var attr in json){
$[attr] = json[attr];
}
};
$.fn = {};
$.fn.extend = function(json){
for(var attr in json){
Mquery.prototype[attr] = json[attr];
}
};

【索引设置】

//根据索引选择元素
Mquery.prototype.eq = function(number){
return $(this.elements[number]);
} //根据元素获取索引
Mquery.prototype.index = function(){
var elements = this.elements[0].parentNode.children;
for(var i = 0; i < elements.length; i++){
if(elements[i] === this.elements[0]){
return i;
}
}
}

【子级筛选】

//筛选出当前匹配的元素集合中每个元素的后代
Mquery.prototype.find = function(str){
var arr = [];
for(var i = 0; i < this.elements.length; i++){
Array.prototype.push.apply(arr,this.elements[i].querySelectorAll(str));
}
return $(arr);
}

完整源码

  下面是mQuery的完整源码

//事件绑定兼容写法
function _addEvent(target,type,handler){
if(target.addEventListener){
target.addEventListener(type,function(e){
//如果事件函数中出现 return false;则阻止默认事件和阻止冒泡
if(typeof handler == 'function' && handler() === false){
e.preventDefault();
e.cancelBubble = true;
}
},false);
}else{
target.attachEvent('on'+type,function(event){
if(typeof handler == 'function' && handler() === false){
event.cancelBubble = true;
event.returnValue = false;
}
return handler.call(target,event);
});
}
}
//获取计算样式兼容写法
function _getCSS(obj,style){
if(window.getComputedStyle){
return getComputedStyle(obj)[style];
}
return obj.currentStyle[style];
} //将类数组转换成数组
function _toArray(arrayLike){
return Array.prototype.slice.call(arrayLike);
}
//构造函数
function Mquery(arg){
//保存所选择的元素
this.elements = [];
switch(typeof arg){
//当参数是函数时,如$(function(){})(),直接运行里面的代码
case 'function':
_addEvent(window,'load',arg);
break;
//当参数是字符串时,选择元素
case 'string':
this.elements = _toArray(document.querySelectorAll(arg));
break;
//当参数是DOM对象时,将DOM对象转换为$对象
case 'object':
if(arg.constructor == Array){
this.elements = arg;
}else{
this.elements.push(arg);
}
break;
}
}
//根据索引选择元素
Mquery.prototype.eq = function(number){
return $(this.elements[number]);
}
//根据元素获取索引
Mquery.prototype.index = function(){
var elements = this.elements[0].parentNode.children;
for(var i = 0; i < elements.length; i++){
if(elements[i] === this.elements[0]){
return i;
}
}
}
//筛选出当前匹配的元素集合中每个元素的后代
Mquery.prototype.find = function(str){
var arr = [];
for(var i = 0; i < this.elements.length; i++){
Array.prototype.push.apply(arr,this.elements[i].querySelectorAll(str));
}
return $(arr);
}
//CSS获取与设置
Mquery.prototype.css = function(attr,value){
//如果是对象的形式,以对象的形式设置
if(typeof attr == 'object'){
for(var att in attr){
for(var j = 0; j < this.elements.length; j++){
this.elements[j].style[att] = attr[att];
}
}
//如果不是对象的形式
}else{
//设置
if(arguments.length == 2){
for(var i = 0; i < this.elements.length; i++){
this.elements[i].style[attr] = value;
}
//获取
}else if(arguments.length == 1){
return _getCSS(this.elements[0],attr)
}
}
return this;
}
//attr获取与设置
Mquery.prototype.attr = function(attr,value){
//如果是对象的形式
if(typeof attr == 'object'){
for(var att in attr){
for(var j = 0; j < this.elements.length; j++){
this.elements[j].setAttribute(att,attr[att]);
}
}
//如果不是对象的形式
}else{
//设置
if(arguments.length == 2){
for(var i = 0; i < this.elements.length; i++){
this.elements[i].setAttribute(attr,value);
}
//获取
}else if(arguments.length == 1){
return this.elements[0].getAttribute(attr);
}
}
return this;
}
//HTML获取与设置
Mquery.prototype.html = function(str){
//设置
if(str){
for(var i = 0; i < this.elements.length; i++){
this.elements[i].innerHTML = str;
}
//获取
}else{
return this.elements[0].innerHTML;
}
return this;
}
//隐藏
Mquery.prototype.hide = function(){
for(var i = 0; i < this.elements.length; i++){
//保存当前元素的display值
this.elements[i].displayValue = this.elements[i].style.display;
this.elements[i].style.display = 'none';
}
return this;
}
//显示
Mquery.prototype.show = function(){
for(var i = 0; i < this.elements.length; i++){
this.elements[i].style.display = this.elements[i].displayValue;
//删除保存的元素的display值
delete this.elements[i].displayValue;
}
return this;
}
//事件绑定
Mquery.prototype.on = function(eventType,fn){
for(var i = 0; i < this.elements.length; i++){
_addEvent(this.elements[i],eventType,fn.bind(this.elements[i]));
}
return this;
}
//click简写
Mquery.prototype.click = function(fn){
this.on('click',fn);
return this;
}
//鼠标移入移出
Mquery.prototype.hover = function(fnOver,fnOut){
this.on('mouseover',fnOver);
this.on('mouseout',fnOut);
return this;
}
$.extend = function(json){
for(var attr in json){
$[attr] = json[attr];
}
};
$.fn = {};
$.fn.extend = function(json){
for(var attr in json){
Mquery.prototype[attr] = json[attr];
}
};
function $(arg){
return new Mquery(arg);
}

实际应用

  下面使用mQuery来实现一个简单的效果

<style>
div { width:60px; height:60px; margin:5px; float:left; }
</style>
<span id="result"></span>
<div style="background-color:blue;"></div>
<div style="background-color:rgb(15,99,30);"></div>
<div style="background-color:#123456;"></div>
<div style="background-color:#f11;"></div>
<script src="mQuery.js"></script>
<script>
$("div").click(function(){
$("#result").html("背景颜色是 " + $(this).css("background-color"));
})
</script>

  点击不同颜色的元素块,将在右侧显示具体的颜色值

  

简易版jQuery——mQuery的更多相关文章

  1. 简易版jquery

    最近写了一个简易版的jquery   github地址:https://github.com/jiangzhenfei/Easy-Jquery 完成的方法: 1.$('#id') 2.extend扩展 ...

  2. 贫下中农版jQuery

    之前写过一篇JavaScript命名空间的文章,写完后一对比对jQuery的简单使用很是惊羡,看了看人家源码,用的原理很类似啊,改进一下之前的版本,做个简易版的jQuery 之前的代码 (functi ...

  3. 学生管理系统(SSM简易版)总结

    之前用 Servlet + JSP 实现了一个简易版的学生管理系统,在学习了 SSM 框架之后,我们来对之前写过的项目重构一下! 技术准备 为了完成这个项目,需要掌握如下技术: Java 基础知识 前 ...

  4. 实现简易版德州扑克|学习麻瓜编程以项目为导向入门前端 HTML+CSS+JS

    实现简易版德州扑克 1.先上达到网页效果图(简易版德州扑克) 网页分为发牌区和牌池,上面为发牌区,下面是牌池区 2. 代码实现 2.1 HTML和JS代码 ` <link rel="s ...

  5. .NET Core的文件系统[5]:扩展文件系统构建一个简易版“云盘”

    FileProvider构建了一个抽象文件系统,作为它的两个具体实现,PhysicalFileProvider和EmbeddedFileProvider则分别为我们构建了一个物理文件系统和程序集内嵌文 ...

  6. MVC 验证码实现( 简易版)

    现在网站上越来越多的验证码,使用场景也是越来越多,登陆.注册.上传.下载...等等地方,都有可能大量使用到验证码,那么制作验证码到底有多简单呢?我们一起来看下最简易版的验证码实现过程- 验证码的基本步 ...

  7. 简易版自定义BaseServlet

    这几天在学Java Web,一直在思考Servlet重用的问题,就用java的反射机制实现自定义的简易版BaseServlet; 该方式有点像struts2 利用映射获取前端的参数.有兴趣的同学可以自 ...

  8. 简易版的TimSort排序算法

    欢迎探讨,如有错误敬请指正 如需转载,请注明出处http://www.cnblogs.com/nullzx/ 1. 简易版本TimSort排序算法原理与实现 TimSort排序算法是Python和Ja ...

  9. 迷你版jQuery——zepto核心源码分析

    前言 zepto号称迷你版jQuery,并且成为移动端dom操作库的首选 事实上zepto很多时候只是借用了jQuery的名气,保持了与其基本一致的API,其内部实现早已面目全非! 艾伦分析了jQue ...

随机推荐

  1. mysql存储过程详细讲解及完整实例下载

    一.存储过程概念 1.存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集.经编译后存储在数据库 中. 2.存储过程是数据库中的一个重要对象,用户通过指定存储过程的名字并给 ...

  2. Linq to Objects for Java 发布 1.0.1 版本

    现在 java 支持 linq 啦.比原生 stream api 更好用,功能更强大.现已发布 version 1.0.1 地址: https://github.com/timandy/linq. A ...

  3. C++数组和指针加减法和sizeof问题

    关于指针和加减法: 指针的加减法:指针的加减法,加多少或者减多少,主要是看所指对象的sizeof值. 例子: double m = 3.0; ; double *p=&m; int* p1=& ...

  4. dll的两种加载方式(pend)+ delayload

    看过关于动态库的调用例子,于是决定动手做一做:dll的对外接口声明头文件,Mydll.h: //Mydll.h #include <stdio.h> #include <stdlib ...

  5. CSS中的盒模型

    CSS的盒模型描述了一些长方形盒子,这些长方形盒子被用来表示文档树中的元素,并根据视觉格式化模型进行定位. 1. 盒子的尺寸 每个盒子都有一个content区域(比如文本.图片等)和可选的包围cont ...

  6. StringBulider简单用法

    StringBuild的是个动态对象,可直接拼加上字符串:而string对象的步骤:先初始化对象并赋值了,而后在拼加字符串时,先要创建需要拼加的字符串,然后再拼加,所以这就是StirngBuild远比 ...

  7. 为什么我们要使用Async、Await关键字

    前不久,在工作中由于默认(xihuan)使用Async.Await关键字受到了很多质问,所以由此引发这篇博文“为什么我们要用Async/Await关键字”,请听下面分解: Async/Await关键字 ...

  8. 删除多余的win10软件

    第一步:开始→所有程序→WindowsPowershell→然后右键以管理员方式运行 全部应用: Get-AppxPackage | Remove-AppxPackage 计算器: Get-AppxP ...

  9. java 数组去重总结

    如果一个数组中有重复元素,用什么方法可以去重?有其他方法继续更新 一.用List集合实现 int[] str = {5, 6, 6, 6, 8, 8, 7,4}; List<Integer> ...

  10. Struts2学习笔记(十一)——文件上传

    1.单文件上传 单文件上传步骤: 1)创建上传jsp页面 文件上传的表单提交方式必须是POST方式,编码类型:enctype="multipart/form-data",默认是 a ...