模拟jQuery框架,利用原生的js技术,封装一个js框架,以加深对jQuery的常用api的使用和面向对象原理的理解;
一:结构部分
首先利用闭包,构造一个自执行函数,然后利用选择器函数Sizzle,获取dom元素;其后设置入口函数jQuery,返回一个F的实例;
然后对jQuery.prototype进行设置;其后修改F的原型指向jQuery的原型,最后暴露出去两个接口$和jQuery;
二:jQuery.fn.extend = jQuery.extend = function(){}
通过向jQuery的原型和jQuery上添加一个extend方法(详见下面代码extend部分);
可以实现扩展工具类方法和dom操作、css操作类的方法;
jQuery.fn.extend(object); 对jQuery.fn即jQuery.prototype
得扩展,就是为jQuery类添加“成员函数”。jQuery类的实例可以使用这个“成员函数”。 代码如下,欢迎指正
(function (window) {
  //伪数组借用数组的push和splice方法
var arr = [];//Array.prototype;
var push = arr.push;
var splice = arr.splice; //jQuery.extend()工具类方法中的type部分代码预处理
var toString = Object.prototype.toString;
var types = "Number,String,Boolean,Null,Undefined,Array,Object,Function,Math,Date,RegExp".split(",");
var class2type = {};
for (var i = 0; i < types; i++) {
var type = types[i];
class2type["[object " + type + "]"] = type.toLowerCase();
}
/**
* 获取dom元素的伪数组nodelist 不考虑兼容性问题;
* @param selector
* @returns {NodeList}
* @constructor
*/
var Sizzle = function (selector) {
return document.querySelectorAll(selector);
} /**
* 设置入口函数,返回F的实例对象
* @param selector
* @returns {*}
*/
function jQuery(selector) {
return jQuery.fn.F(selector);
} /**
* jQuery.prototype设置
* @type {{constructor: jQuery, F: Function}}
*/
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
version: "0.0.1",
F: function (selector) {
if (jQuery.isString(selector)) {
if (selector.charAt(0) === "<" && selector.charAt(selector.length - 1) === ">" && selector.length >= 3) {
//eg:$("<input>");
var div = document.createElement("div");
div.innerHTML = selector;
//for(var i =0;i<div.childNodes.length;i++){
// var child = div.childNodes[i];
// push.call(this.child);
//}
push.apply(this, div.childNodes);
} else {
//eg:$("div")
splice.call(this, 0, this.length);
var elements = Sizzle(selector);
push.apply(this, elements);
}
} else if (selector.nodeType) {
//鸭式辨型思想
//this[0] = selector;
//this.length = 1;
push.call(this, selector);
} else if (selector.version === this.version) {
return selector;
}
return this;//实现链式编程
}
} /**
* extend方法
* @type {Function}
*/
jQuery.fn.extend = jQuery.extend = function () {
var argLen = arguments.length;
var arg0 = arguments[0];
var sources = [];
var target;
if (argLen === 0) return this;
if (argLen === 1) {
sources.push(arg0);
target = this;
} else {
//for(var i=1;i<argLen;i++){
// sources.push(arguments[i]);
//}
push.apply(sources, arguments);
target = arg0;
} for (var i = 0; i < sources.length; i++) {
var source = sources[i];
for (var key in source) {
target[key] = source[key];
}
}
return target;
}
/**
* 工具类方法,添加到jQuery中,使用$.方法名()调用
*/
jQuery.extend({
    //判断数据类型
type: function (data) {
return class2type[toString.call(data)];
},
    //判断是不是字符串
isString: function (str) {
return jQuery.type(str) === "string";
},
    //判断是不是函数
isFunction: function (fn) {
return jQuery.type(fn) === "function";
},
     //抛出异常
error: function (msg) {
throw new Error(msg);
},
     //去除字符串两边的空格
trim: function (str) {
return str.replace(/^\s+|\s+$/g, "");
},
     //遍历(数组的遍历或者对象的遍历)
each: function (array, callback) {
var len = array.length;
var i;
if (typeof len === "number" && len >= 0) {
for (i = 0; i < len;) {
if (callback.call(array[i], i, array[i++]) === false) {
break;
}
}
} else {
for (i in array) {
if (callback.call(array[i], i, array[i]) === false) {
break;
}
}
}
}
}) //jQuery.fn中的each方法:这样F的实例,即jQuery的对象拥有的each方法
jQuery.fn.extend({
each: function (callback) {
jQuery.each(this, callback);
return this;
}
})
//css模块
jQuery.fn.extend({
css: function () {
var argLen = arguments.length;
var arg0 = arguments[0];
var arg1 = arguments[1];
if (argLen === 0) return this;
if (argLen === 1) {
if (jQuery.isString(arg0)) {
//表示获取第一个dom元素的css样式
var firstDom = this[0];
return window.getComputedStyle(firstDom, null)[arg0];
} else {
//是一个对象的时候表示设置多个样式
//return this.each(function(){
// var dom = this;
// jQuery.each(arg0,function(styleName,styleValue){
// dom.style[styleName] = styleValue;
// })
//})
return this.each(function () {
jQuery.extend(this.style, arg0);
});
}
} else {
//传递两个参数;设置单个css样式
return this.each(function () {
this.style[arg0] = arg1;
})
} },
    //显示
show: function () {
return this.css("display", "block");
},
    //隐藏
hide: function () {
return this, css("display", "none");
},
    //切换显示和隐藏
toggle: function () {
return this.each(function () {
var $this = $(this);
$this.css("display") === "none" ? $this.show() : $this.hide();
})
}
})
//属性模块
jQuery.fn.extend({
attr: function (arg0, arg1) {
var argLen = arguments.length;
if (argLen === 0) return this;
if (argLen === 1) {
if (jQuery.isString(arg0)) {
//获取第一个dom元素的属性值
var firstDom = this[0];
return firstDom.getAttribute(arg0);
} else {
//设置一个对象的属性
return this.each(function () {
var dom = this;
jQuery.each(function (className, classValue) {
dom.setAttribute(className, classValue);
}) })
}
} else {
//两个参数;设置属性
return this.each(function () {
this.setAttribute(arg0, arg1);
})
}
},
hasClass: function (className) {
//遍历,只要有一个dom元素含有className这个类名就返回true
var isExist = false;
this.each(function () {
if ((" " + this.className + " ").indexOf(" " + className + " ") > -1) {
isExist = true;
return false;
}
})
return isExist;
},
addClass: function (className) {
var classNames = className.split(" ");
return this.each(function () {
for (var i = 0; i < classNames.length; i++) {
var singleClassName = className[i];
if (!$(this).hasClass(singleClassName)) {
this.className += " " + singleClassName;
}
}
}) },
removeClass: function (className) {
if (!className) {
//删除全部类名
return this.each(function () {
this.className = "";
})
} else {
//删除一个或者多个类名
var classNames = className.split(" ");
return this.each(function () {
var domClassName = " " + this.className + " ";
for (var i = 0; i < classNames.length; i++) {
var singleClassName = " " + classNames[i] + " ";
domClassName = domClassName.replace(singleClassName, " ");
}
this.className = $.trim(domClassName);
})
}
}
})
//dom操作方法模块
jQuery.fn.extend({
appendTo: function () {
var $parent = $(arguments[0]);
return this.each(function () {
var child = this;
$parent.each(function () {
var parent = this;
parent.appendChild(child.cloneNode(true));
})
}) },
prependTo: function () {
var $parent = $(arguments[0]);
return this.each(function () {
var child = this;
$parent.each(function () {
var parent = this;
parent.insertBefore(child.cloneNode(true), parent.firstChild);
})
})
},
append: function () {
var $parent = $this;
var $child = $(arguments[0]);
$child.appendTo($parent);
return this;
},
prepend: function () {
var $parent = $this;
var $child = $(arguments[0]);
$child.prependTo($parent);
return this;
},
remove: function () {
return this.each(function(){
this.parentNode.removeChild(this);
})
},
html: function (html) {
if (html === undefined) {
//返回第一个dom元素的html
var firstDom = this[0];
return firstDom.innerHTML;
}
//如果为null或者其他参数时候
return this.each(function () {
this.innerHTML = html;
//this.innerHTML = html===null?"":html;
})
},
text: function (text) {
if (html === undefined) {
var str = "";
this.each(function () {
str += this.innerText;
})
return str;
}
return this.each(function () {
this.innerText = text;
})
}
}) //事件模块
jQuery.fn.extend({
on:function(type,callback){
return this.each(function(){
this.addEventListener(type,callback);
})
}
})
var eventTypes = "click dblclivk keydown keyup mousedown mouseup mouseout mouseenter mouseleave load".split(" ");
for(var i =0;i<eventTypes.length;i++){
var eventType = eventTypes[i];
$.fn[eventType] = (function(){
var type = eventType;
return function(callback){
return this.on(type,callback);
}
})()
} //F的实例 = jQuery的实例
jQuery.fn.F.prototype = jQuery.fn;
//暴露出去两个接口
window.$ = window.jQuery = jQuery;
})(window)

js框架封装,模拟jQuery封装的更多相关文章

  1. ajx技术解析以及模拟jQuery封装

    1.后台处理程序 <%@ page language="java" contentType="text/html; charset=UTF-8" page ...

  2. 模拟jquery封装选择器

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. javascript模拟jQuery封装委托事件,兼容IE

    var $ = function(id){ var dom = document.getElementById(id); return { on:function(eventType,element, ...

  4. JS 框架安全报告:jQuery 下载次数超过 1.2 亿次

    尽管 JavaScript 库 jQuery 仍被使用,但它已不再像以前那样流行.根据开源安全平台 Snyk 统计,目前至少十分之六的网站受到 jQuery XSS 漏洞的影响,甚至用于扩展 jQue ...

  5. 借鉴一些关于js框架的东西

    八款Js框架介绍及比较,Dojo .Scriptaculous .Prototype .yui-ext .Jquery .Mochikit.mootools .moo.fx,componentartu ...

  6. 不借助jquery封装好的ajax,你能用js手写ajax框架吗

    不借助jquery封装好的ajax,你能手写ajax框架吗?最基础的ajax框架,一起来围观吧. .创建XMLHttpRequest对象 var xhr = new XMLHttpRequest(); ...

  7. 仿照jquery封装一个自己的js库

    所谓造轮子的好处就是复习知识点,加深对原版jquery的理解.本文系笔者学习jquery的笔记,记述一个名为"dQuery"的初级版和缩水版jquery库的实现.主要涉及知识点包括 ...

  8. 仿照jquery封装一个自己的js库(一)

    所谓造轮子的好处就是复习知识点,加深对原版jquery的理解. 本文系笔者学习jquery的笔记,记述一个名为"dQuery"的初级版和缩水版jquery库的实现.主要涉及知识点包 ...

  9. 模拟jQuery简单封装ajax

    /*模拟jQuery的写法 (简单写法)*/ var $={}; /*ajax*/ $.ajax = function (options) { /* * 请求 * 1.请求接口 type get po ...

随机推荐

  1. 取xml文件转成List<T>对象的两种方法

    读取xml文件转成List<T>对象的两种方法(附源码)   读取xml文件转成List<T>对象的两种方法(附源码) 读取xml文件,是项目中经常要用到的,所以就总结一下,最 ...

  2. APNs功能之Node.js和Mysql应用总结

    APNs功能之Node.js和Mysql应用总结 这篇文档主要是总结Node.js和Mysql的学习心得体会.当然也可以看作是此前所写的消息推送服务的续篇. 简单描述下应用背景,我们的应用需要实现苹果 ...

  3. C/C++基础知识总结——继承与派生

    1. 类的继承与派生 1.1 派生类的定义 (1) 定义规范 class 派生类名: 继承方式 基类1名, 继承方式 基类2名... { ...派生类成员声明; }; (2) 从以上形式上看可以多继承 ...

  4. ArcGIS多面体(multipatch)解析(一)

    从几何学的角度来说,再复杂的三维形状都可以通过足够多,足够小的三角形组合起来表达.比如矩形可以表达成两个三角形,如下图: 圆柱形可以由多个三角形排列而成: 但ArcGIS中的多面体构成并没有采用这种“ ...

  5. LinqToXml高级用法介绍

    LinqToXml高级用法介绍 一.函数构造 什么是函数构造?其是指通过单个语句构建XML树的能力. 那么它有什么作用呢? 作用1.用单个表达式快速创建复杂的XML树 见实例代码CreateXml( ...

  6. Ubuntu下使用vpn连接远程服务器

    公司的服务器提供了vpn接入点,这样在家里也可以通过vpn连到公司的服务器里作一些事情.昨天下午申请了vpn帐号,然后先在windows下试着连接vpn服务器,一切okay,证明自己的vpn帐户没有问 ...

  7. 利用HttpWebRequest和HttpWebResponse获取Cookie并实现模拟登录

    利用HttpWebRequest和HttpWebResponse获取Cookie并实现模拟登录 tring cookie = response.Headers.Get("Set-Cookie ...

  8. 反向代理(Reverse Proxy)

    反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时 ...

  9. 三千万数据量下redis2.4的一统计情况

    先说一下工作场景,要求做一个服务,满足:处理千万级别数据,单个请求响应时间在20ms以下.由于是存储的数据格式为key:list[],所以很适合使用redis来存放数据,为了测试一下redis存储的效 ...

  10. hdu 1559 最大子矩阵(DP)

    题目链接:点击链接 #include<stdio.h> #include<string.h> #define max(a,b) a>b?a:b int d[1005][1 ...