JQuery原理笔记
1. jQuery基本结构
- jQuery本质——闭包
- 实际上就是一个立即执行的函数
(function( window, undefined ) {
})( window );
- jQuery为何使用闭包实现?
- 为了避免导入多个框架的时候,变量名重覆盖的问题
(function f1(){
var num = 10;
console.log(num);
})(window);
(function f2(){
var num = 20;
console.log(num);
})(window);
- jQuery如何让外界访问内部定义的局部变量?
window.xxx = xxx;
/*
(function f1(){
var num = 10;
window.num = num;
})();
console.log(num);
*/
(function( window, undefined ) {
var jQuery = function( ) {
return new jQuery.prototype.init( );
}
window.jQuery = window.$ = jQuery;
})( window );
-
jQuery为什么要给自己传递一个window参数?
- 为了方便后期压缩代码
- 为了提升查找的效率
-
jQuery为什么要给自己接收一个undefined参数?
- 为了方便后期压缩代码
- IE9以下的浏览器undefined可以被修改, 为了保证内部使用的undefined不被修改, 所以需要接收一个正确的undefined
自定义jQuery框架
// 基本结构
(function(window,undefined){
var njQuery = function(){
return new njQuery.prototype.init();
}
njQuery.prototype = {
constructor:njQuery
}
njQuery.prototype.init.prototype = njQuery.prototype;
window.njQuery = window.$ = njQuery
})(window);
2. jQuery入口函数
1. jQuery入口函数——测试
jQuery入口函数传入不同参数得到的实例
- 传入 ’ ’ null undefined NaN 0 false
- 返回一个空的jQuery对象
console.log($());
console.log($(''));
console.log($(null));
console.log($(undefined));
console.log($(NaN));
console.log($(0));
console.log($(false));
- 传入html片段
- 会将创建好的DOM元素存储到jQuery对象中返回
console.log($('<p>1</p><p>2</p><p>3</p>'));
- 传入选择器
- 会将找到的所有元素存储到jQuery对象中返回
console.log($('li'));
- 传入数组
- 会将数组中存储的元素依次存储到jQuery对象中立返回
var arr = [1, 2, 3, 4, 5, 6];
console.log($(arr));
- 传入伪数组
- 会将数组中存储的元素依次存储到jQuery对象中立返回
var likeArr = {0:"lnj", 1:"33", 2:"male", length: 3};
console.log($(likeArr));
- 传入对象
- 会将传入的对象存储到jQuery对象中返回
function Person() {}
console.log($(new Person()));
- 传入DOM元素
- 会将传入的DOM元素存储到jQuery对象中返回
console.log($(document.createElement('div')));
- 传入基本数据类型
- 会将传入的基本数据类型存储到jQuery对象中返回
console.log($(123));
console.log($(true));
- 除上述类型以外
- 会将传入的数据存储到jQuery对象中返回
2. jQuery入口函数——代码片段实现
// 基本结构
(function(window,undefined){
var njQuery = function(selector){
return new njQuery.prototype.init(selector);
}
njQuery.prototype = {
constructor:njQuery,
init:function(selecter){
/*
1. 传入 ‘’ null underfined NaN 0 false, 返回空的jQuery对象
2. 字符串:
代码片段:会将创建好的DOM元素存储到jQuery对象中返回
选择器: 会将找到的所有元素存储到jQuery对象中返回
3.数组:
会将数组中存储的元素依次存储到jQuery对象中立返回
4.除上述类型以外的:
会将传入的数据存储到jQuery对象中返回
*/
// 1. 传入 ‘’ null underfined NaN 0 false, 返回空的jQuery对象
if(!selector){
return this;
}
// 2. 字符串
else if(typeof selector === "string"){
//2.1. 判断是否是代码片段
if(selector.charAt(0) === "<" && selector.charAt(selector.length - 1) == ">" && selector.length >= 3){
//1. 根据代码片段创建所有的元素
var temp = document.createElement("div");
temp.innerHTML = selector;
//2. 将创建好的一级元素添加到jQuery当中
for(var i = 0; i < temp.children.length; i++){
this[i] = temp.children[i];
}
//3. 给jQuery对象添加length属性
this.length = temp.children.length;
//4. 返回加工好的this(jQuery)
return this;
}
//2.2. 判断是否是选择器
}
}
}
njQuery.prototype.init.prototype = njQuery.prototype;
window.njQuery = window.$ = njQuery;
})(window);
3. jQuery入口函数——工具方法抽取
// 基本结构
(function(window,undefined){
var njQuery = function(selector){
return new njQuery.prototype.init(selector);
}
njQuery.prototype = {
constructor:njQuery,
init:function(selecter){
/*
1. 传入 ‘’ null underfined NaN 0 false, 返回空的jQuery对象
2. 字符串:
代码片段:会将创建好的DOM元素存储到jQuery对象中返回
选择器: 会将找到的所有元素存储到jQuery对象中返回
3.数组:
会将数组中存储的元素依次存储到jQuery对象中立返回
4.除上述类型以外的:
会将传入的数据存储到jQuery对象中返回
*/
// 0. 去除字符串两端的空格
selector = njQuery.trim(selector);
// 1. 传入 ‘’ null underfined NaN 0 false, 返回空的jQuery对象
if(!selector){
return this;
}
// 2. 字符串
else if(njQuery.isString(selector)){
//2.1. 判断是否是代码片段
if(njQuery.isHTML(selector)){
//1. 根据代码片段创建所有的元素
var temp = document.createElement("div");
temp.innerHTML = selector;
//2. 将创建好的一级元素添加到jQuery当中
for(var i = 0; i < temp.children.length; i++){
this[i] = temp.children[i];
}
//3. 给jQuery对象添加length属性
this.length = temp.children.length;
//此时此刻的this是njQuery对象
//4. 返回加工好的this(jQuery)
return this;
}
//2.2. 判断是否是选择器
}
}
}
njQuery.isString = function(str){
return typeof str === "string"
}
njQuery.isHTML = function(str){
return str.charAt(0) === "<" && str.charAt(str.length - 1) == ">" && str.length >= 3
}
njQuery.trim = function(str){
//判断是否支持trim方法
if(str.trim){
return str.trim();
}else{
return str.replace(/^\s+|\s+$/g,"");
}
njQuery.prototype.init.prototype = njQuery.prototype;
window.njQuery = window.$ = njQuery;
})(window);
4. jQuery入口函数——代码片段优化
// 2. 字符串
else if(njQuery.isString(selector)){
//2.1. 判断是否是代码片段
if(njQuery.isHTML(selector)){
//1. 根据代码片段创建所有的元素
var temp = document.createElement("div");
temp.innerHTML = selector;
/*
//2. 将创建好的一级元素添加到jQuery当中
for(var i = 0; i < temp.children.length; i++){
this[i] = temp.children[i];
}
//3. 给jQuery对象添加length属性
this.length = temp.children.length;
*/
[].pish.apply(this,temp.children);
//此时此刻的this是njQuery对象
//4. 返回加工好的this(jQuery)
return this;
}
- 为什么
[].pish.apply(this,temp.children);
能替换2,3部分
apply和call方法
- 通过window.test找到test方法
- 通过apply(obj)将找到的test方法内部的this修改为自定义的对象
function test() {
console.log(this);
}
// window.test(); // 此时 this 为 window
// 自定义对象
var obj = {"name": "lnj2"};
// 1. 通过window.test找到test方法
// 2. 通过apply(obj)将找到的test方法内部的this修改为自定义的对象
window.test.apply(obj); //此时 this 为 obj 对象
window.test.call(obj); //此时 this 为 obj 对象
- apply和call方法的作用:
- 专门用于修改方法内部的this
- 格式:
- call(对象, 参数1, 参数2, …);
- apply(对象, [数组]);
function sum(a, b) {
console.log(this);
console.log(a + b);
}
window.sum.call(obj,1,2) // 此时 this 为 obj ,a=1,b=2
// 1. 通过window.test找到test方法
// 2. 通过apply(obj)将找到的test方法内部的this修改为自定义的对象
// 3. 将传入数组中的元素依次取出, 传递给形参
window.test.apply(obj,[3,5]); //此时 this 为 obj 对象, a=3.b=5
- 通过 push 方法连接 apply
/*
1.通过[].push找到数组中的push方法
2.通过apply(obj)将找到的push方法内部的this修改为自定义的对象
3.将传入数组中的元素依次取出, 传递给形参
*/
var arr = [1, 3, 5, 7, 9];
var obj = {};
[].push.apply(obj, arr); // arr 中的元素都转到 obj 对象中了
console.log(obj);
5. jQuery入口函数——真伪数组转
- 真数组转伪数组
// 真数组转换伪数组的一个过程
var arr = [1, 3, 5, 7, 9];
var obj = {};
[].push.apply(obj, arr);
console.log(obj);
- 系统自带的伪数组转化为真数组 (IE8及其以下有bug)
window.onload = function (ev) {
// 系统自带的伪数组
var res = document.querySelectorAll("div");
// 自定义的伪数组
var obj = {0:"lnj", 1:"33", length: 2};
var arr = []; // 真数组
[].push.apply(arr, obj);
console.log(arr);
- 利用 slice 方法将伪数组转化真数组(推荐)
- 如果slice方法什么参数都没有传递, 会将数组中的元素放到一个新的数组中原样返回
window.onload = function (ev) {
// 系统自带的伪数组
var res = document.querySelectorAll("div");
// 自定义的伪数组
var obj = {0:"lnj", 1:"33", length: 2};
// 如果想将伪数组转换为真数组那么可以使用如下方法
var arr = [].slice.call(obj);
console.log(arr);
}
6. jQuery入口函数——选择器处理
// 2.2判断是否是选择器
else{
// 1.根据传入的选择器找到对应的元素
var res = document.querySelectorAll(selector);
// 2.将找到的元素添加到njQuery上
[].push.apply(this, res);
// 3.返回加工上的this
return this;
}
7. jQuery入口函数——数组处理
else if(typeof selector === "objector" && "length" in selector && selector !== window){
// 1.真数组
if(({}).toString.apply(selector) === "[object Array]"){
[].push.apply(this,selector);
return this;
}
// 2.假数组
else{
// 将自定义的伪数组转换为真数组
var arr = [].slice.call(selector);
// 将真数组转换为伪数组
[].push.apply(this,arr);
return this;
}
}
- 优化
else if(njQuery.isArray(selector){
/*
// 1.真数组
if(({}).toString.apply(selector) === "[object Array]"){
[].push.apply(this,selector);
return this;
}
// 2.假数组
else{
// 将自定义的伪数组转换为真数组
var arr = [].slice.call(selector);
// 将真数组转换为伪数组
[].push.apply(this,arr);
return this;
}
*/
// 将自定义的伪数组转换为真数组
var arr = [].slice.call(selector);
// 将真数组转换为伪数组
[].push.apply(this,arr);
return this;
}
}
njQuery.isObject = function(sele){
return typeof sele === "object"
}
njQuery.isWindow = function(sele){
return sele === window;
}
njQuery.isArray = function(sele){
if(njQuery.isObject(sele) && !njQuery.isWindow(sele) && "length" in sele){
return true;
}
return false;
}
8. jQuery入口函数——其他类型处理
// 5.除上述类型以外
else{
this[0] = selector;
this.length = 1;
// return this;
}
return this;
9. jQuery入口函数——extend方法
function njQuery(){
}
njQuery.extend = function(obj){
// 此时此刻 this 就是 njQuery 这个类
for(var key in obj){
//njQuery["isTest"] = function(){console.log("test");}
this[key] = obj[key];
}
}
njQuery.extend({
isTest:function(){
console.log("test");
}
});
njQuery.isTest();
njQuery.prototype.extend = function (obj) {
// 此时此刻的this是njQuery对象
// console.log(this);
for(var key in obj){
// q["isDemo"] = function () {console.log("demo");}
this[key] = obj[key];
}
}
var q = new njQuery();
q.extend({
isDemo: function () {
console.log("demo");
}
});
q.isDemo();
njQuery.extend = njQuery.prototype.extend = function (obj) {
// console.log(this);
for(var key in obj){
this[key] = obj[key];
}
}
// njQuery.extend({});
var q = new njQuery();
q.extend({});
10. jQuery入口函数——函数处理
njQuery.extend({
ready: function (fn) {
// 判断DOM是否加载完毕
if(document.readyState == "complete"){
fn();
}else if(document.addEventListener){
document.addEventListener("DOMContentLoaded", function () {
fn();
});
}else{
document.attachEvent("onreadystatechange", function () {
if(document.readyState == "complete"){
fn();
}
});
}
}
});
- jQuery 监听 DOM 加载
/*
onload事件会等到DOM元素加载完毕, 并且还会等到资源也加载完毕才会执行
DOMContentLoaded事件只会等到DOM元素加载完毕就会执行回调
*/
window.onload = function (ev) {
var res = document.querySelectorAll("div");
// console.log(res);
console.log("onload");
}
document.addEventListener("DOMContentLoaded", function () {
var res = document.querySelectorAll("div");
// console.log(res);
console.log("DOMContentLoaded");
});
/*
document.readyState属性有如下的状态
uninitialized - 还未开始载入
loading - 载入中
interactive - 已加载,文档与用户可以开始交互
complete - 载入完成
onreadystatechange事件就是专门用于监听document.readyState属性的改变的
*/
document.attachEvent("onreadystatechange", function () {
if(document.readyState == "complete"){
console.log("onreadystatechange");
}
});
3. jQuery原型属性与方法
1. jQuery原型上的属性
jQuery原型上的属性:
- jquery 获取jQ版本号
- selector 实例默认的选择器取值
- length 实例默认的长度
- push 给实例添加新元素
- sort 对实例中的元素进行排序
- splice 按照指定下标指定数量删除元素,也可以替换删除的元素
njQuery.prototype = {
constructor: njQuery,
jquery:"1.1.0",
selector:"",
length:0,
// [].push找到数组的push方法
// 冒号前面的push将来由njQuery对象调用
// 相当于[].push.apply(this);
push:[].push,
sort:[].sort,
splice:[].splice
}
2. jQuery原型上的方法
jQuery原型上的核心方法:
- toArray 把实例转换为数组返回
- get 获取指定下标的元素,获取的是原生DOM
- eq 获取指定下标的元素,获取的是jQuery类型的实例对象
- first 获取实例中的第一个元素,是jQuery类型的实例对象
- last 获取实例中的最后一个元素,是jQuery类型的实例对象
- each 遍历实例,把遍历到的数据传给回调使用
- map 遍历实例,把遍历到的数据传给回调使用,然后把回调的返回值收集起来组成一个新的数组返回
1. toArray
把实例转换为数组返回
var res = $("div");
console.log(res);
var res2 = res.toArray();
console.log(res2);
njQuery.prototype = {
toArray:function(){
// 伪数组转真数组
return [].slice.call(this)
}
}
结果:
2. get
获取指定下标的元素,获取的是原生DOM
var res = $("div");
console.log(res); // length = 3
// get方法如果不传递参数, 相当于调用toArray()
console.log(res.get());
console.log(res.get(0));//取第0个div
console.log(res.get(1));//取第1个div
console.log(res.get(-1)); // (3 + -1) = 2 //取第2个div
console.log(res.get(-2)); // (3 + -2) = 1 //取第1个div
njQuery.prototype = {
get:function(num){
// 没有传递参数
if(arguments.length === 0){
return this.toArray();
}
// 传递不是负数
else if(num >= 0){
return this[num]
}
// 传递负数
else {
return this[this.length + num];
}
}
}
3. eq
获取指定下标的元素,获取的是jQuery类型的实例对象
var res = $("div");
console.log(res.eq());
console.log(res.eq(0));
console.log(res.eq(-1));
njQuery.prototype = {
eq:function (num) {
// 没有传递参数
if(arguments.length === 0){
return new jQuery()
}else{
return njQuery(this.get(num));
}
}
}
4. first 和 last
- first 获取实例中的第一个元素,是jQuery类型的实例对象
- last 获取实例中的最后一个元素,是jQuery类型的实例对象
var res = $("div");
console.log(res.first());
console.log(res.last());
njQuery.prototype = {
first:function(){
return this.eq(0);
},
last:function(){
return this.eq(-1);
}
}
5. each
遍历实例,把遍历到的数据传给回调使用
var arr = [1, 3, 5, 7, 9];
var obj1 = {0:"lnj",1:"333",2:"male",length:3};
var obj2 = {"name":"lnj","age":"33"};
njQuery.each(arr,function(key,value){
console.log(key,value);
});
njQuery.each(arr, function (key, value) {
if(key === 2){
// true 为跳过2,下面继续执行
// return true
// false 为2下面所有都不执行
return false;
}
console.log(key, value);
console.log(this); // this 为 value -->为了方便使用
});
var arr = [1, 3, 5, 7, 9];
var obj1 = {0:"lnj",1:"333",2:"male",length:3};
var obj2 = {"name":"lnj","age":"33"};
$(arr).each(function (key, value) {
// console.log(key, value);
console.log(this);
});
each:function(obj,fn){
// 1. 判断是否是数组
if(njQuery.isArray(obj)){
for(var i = 0; i < obj.length; i++){
// var res = fn(i,obj[i]);
var res = fn.call(obj[i],i,obj[i]);
if(res == true){
continue;
}else if(res === false){
break;
}
}
}
// 2. 判断是否是对象
else if (njQuery.isObject(obj)) {
for(var key in obj){
// var res = fn(key,obj[key]);
var res = fn.call(obj[key],key,obj[key]);
if(res == true){
continue;
}else if(res === false){
break;
}
}
}
}
6. map
遍历实例,把遍历到的数据传给回调使用,然后把回调的返回值收集起来组成一个新的数组返回
var arr = [1, 3, 5, 7, 9];
var obj1 = {0:"lnj",1:"333",2:"male",length:3};
var obj2 = {"name":"lnj","age":"33"};
var res = njQuery.map(arr, function (value, key) {
// console.log(value, key);
if(key === 2){
return value;
}
});
console.log(res);
map:function(obj,fn){
var res = [];
// 1. 判断是否是数组
if(njQuery.isArray(obj)){
for(var i = 0; i < obj.length; i++){
var temp = fn(obj[i],i);
if(temp){
res.push(temp);
}
}
}
// 2. 判断是否是对象
else if(njQuery.isObject(obj)){
for(var key in objd{
var temp = fn(obj[key],key);
if(temp){
res.push(temp);
}
})
}
return res;
}
4. jQueryDOM操作相关方法
1. empty 方法
清空指定元素中的所有内容
$(function () {
var btn = document.getElementsByTagName("button")[0];
btn.onclick = function () {
$("div").empty();
console.log($("div").empty());
}
});
// DOM操作相关方法
njQuery.prototype.extend({
empty: function () {
// 1.遍历指定的元素
this.each(function (key, value) {
value.innerHTML = "";
});
// 2.方便链式编程
return this;
}
})
2. remove 方法
删除所有的元素或指定元素
$(function () {
var btn = document.getElementsByTagName("button")[0];
btn.onclick = function () {
$("div").remove();
console.log($("div").remove());
$("div").remove(".box");
}
});
// DOM操作相关方法
njQuery.prototype.extend({
remove: function (sele) {
if(arguments.length === 0){
// 1.遍历指定的元素
this.each(function (key, value) {
// 根据遍历到的元素找到对应的父元素
var parent = value.parentNode;
// 通过父元素删除指定的元素
parent.removeChild(value);
});
}else{
var $this = this;
// 1.根据传入的选择器找到对应的元素
$(sele).each(function (key, value) {
// 2.遍历找到的元素, 获取对应的类型
var type = value.tagName;
// 3.遍历指定的元素
$this.each(function (k, v) {
// 4.获取指定元素的类型
var t = v.tagName;
// 5.判断找到元素的类型和指定元素的类型
if(t === type){
// 根据遍历到的元素找到对应的父元素
var parent = value.parentNode;
// 通过父元素删除指定的元素
parent.removeChild(value);
}
});
})
}
return this;
}
})
3. html 方法
置所有元素的内容,获取第一个元素的内容
$(function () {
var btn = document.getElementsByTagName("button")[0];
btn.onclick = function () {
var $div = $("div");
console.log($div.html());
$div.html("123");
$div.html("<div><span>我是span</span></div>");
}
});
// DOM操作相关方法
njQuery.prototype.extend({
html: function (content) {
if(arguments.length === 0){
return this[0].innerHTML;
}else{
this.each(function (key, value) {
value.innerHTML = content;
})
}
}
})
4. text 方法
设置所有元素的文本内容,获取所有元素的文本内容
$(function () {
var btn = document.getElementsByTagName("button")[0];
btn.onclick = function () {
var $div = $("div");
console.log($div.text());
$div.text("123");
$div.text("<div><span>我是span</span></div>");
console.log($div.get(0).innerText);
}
});
// DOM操作相关方法
njQuery.prototype.extend({
text: function (content) {
if(arguments.length === 0){
var res = "";
this.each(function (key, value) {
res += value.innerText;
});
return res;
}else{
this.each(function (key, value) {
value.innerText = content;
});
}
}
})
5. appendTo 方法
将元素添加到指定元素内部的最后
- 特点:
- 如果指定元素有多个,会将元素拷贝多份添加到指定元素中
- 给appendTo方法传递字符串, 会根据字符串找到所有对应元素后再添加
- 给appendTo方法传递jQuery对象,会将元素添加到jQuery对象保存的所有指定元素中
- 给appendTo方法传递DOM元素, 会将元素添加到所有指定DOM元素中
// DOM操作相关方法
njQuery.prototype.extend({
appendTo: function (sele) {
// 1.统一的将传入的数据转换为jQuery对象
var $target = $(sele);
var $this = this;
var res = [];
// 2.遍历取出所有指定的元素
$.each($target, function (key, value) {
// 2.遍历取出所有的元素
$this.each(function (k, v) {
// 3.判断当前是否是第0个指定的元素
if(key === 0){
// 直接添加
value.appendChild(v);
res.push(v);
}else{
// 先拷贝再添加
var temp = v.cloneNode(true);
value.appendChild(temp);
res.push(temp);
}
});
});
// 3.返回所有添加的元素
return $(res);
}
})
6. prependTo 方法
将元素添加到指定元素内部的最前面
// DOM操作相关方法
njQuery.prototype.extend({
prependTo: function (sele) {
// 1.统一的将传入的数据转换为jQuery对象
var $target = $(sele);
var $this = this;
var res = [];
// 2.遍历取出所有指定的元素
$.each($target, function (key, value) {
// 2.遍历取出所有的元素
$this.each(function (k, v) {
// 3.判断当前是否是第0个指定的元素
if(key === 0){
// 直接添加
value.insertBefore(v, value.firstChild);
res.push(v);
}else{
// 先拷贝再添加
var temp = v.cloneNode(true);
value.insertBefore(temp, value.firstChild);
res.push(temp);
}
});
});
// 3.返回所有添加的元素
return $(res);
}})
7. append 方法
将元素添加到指定元素内部的最后
// DOM操作相关方法
njQuery.prototype.extend({
append: function (sele) {
// 判断传入的参数是否是字符串
if(njQuery.isString(sele)){
this[0].innerHTML += sele;
}else{
$(sele).appendTo(this);
}
return this;
}
})
8. prepend 方法
将元素添加到指定元素内部的最前面
// DOM操作相关方法
njQuery.prototype.extend({
prepend: function (sele) {
// 判断传入的参数是否是字符串
if(njQuery.isString(sele)){
this[0].innerHTML = sele + this[0].innerHTML;
}else{
$(sele).prependTo(this);
}
return this;
}
})
9. insertBefore,insertAfter
insertBefore—将元素添加到指定元素外部的前面
insertAfter—将元素添加到指定元素外部的后面
注意:实现insertAfter需要用到原生JavaScript的nextSibling属性
function insertBefore(source, target) {
/*
调用者.insertBefore(插入的元素, 参考的元素);
insertBefore方法, 调用者是谁就会将元素插入到谁里面
*/
// 1.拿到指定元素的父元素
var parent = target.parentNode;
// 2.利用指定元素的父元素来调用insertBefore方法
parent.insertBefore(source, target);
}
var p = document.querySelector("p");
var div = document.querySelector("div");
// insertBefore(p, div);
// DOM操作相关方法
njQuery.prototype.extend({
insertBefore: function (sele) {
// 1.统一的将传入的数据转换为jQuery对象
var $target = $(sele);
var $this = this;
var res = [];
// 2.遍历取出所有指定的元素
$.each($target, function (key, value) {
var parent = value.parentNode;
// 2.遍历取出所有的元素
$this.each(function (k, v) {
// 3.判断当前是否是第0个指定的元素
if(key === 0){
// 直接添加
parent.insertBefore(v, value);
res.push(v);
}else{
// 先拷贝再添加
var temp = v.cloneNode(true);
parent.insertBefore(temp, value);
res.push(temp);
}
});
});
// 3.返回所有添加的元素
return $(res);
},
insertAfter: function (sele) {
// 1.统一的将传入的数据转换为jQuery对象
var $target = $(sele);
var $this = this;
var res = [];
// 2.遍历取出所有指定的元素
$.each($target, function (key, value) {
var parent = value.parentNode;
var nextNode = $.get_nextsibling(value);
// 2.遍历取出所有的元素
$this.each(function (k, v) {
// 3.判断当前是否是第0个指定的元素
if(key === 0){
// 直接添加
parent.insertBefore(v, nextNode);
res.push(v);
}else{
// 先拷贝再添加
var temp = v.cloneNode(true);
parent.insertBefore(temp, nextNode);
res.push(temp);
}
});
});
// 3.返回所有添加的元素
return $(res);
}
})
10. next 方法
获取紧邻的后面同辈元素的元素
// DOM操作相关方法
njQuery.prototype.extend({
next: function (sele) {
var res = [];
if(arguments.length === 0){
// 返回所有找到的
this.each(function (key, value) {
var temp = njQuery.get_nextsibling(value);
if(temp != null){
res.push(temp);
}
});
}else{
// 返回指定找到的
this.each(function (key, value) {
var temp = njQuery.get_nextsibling(value)
$(sele).each(function (k, v) {
if(v == null || v !== temp) return true;
res.push(v);
});
});
}
return $(res);
}
})
11. prev 方法
获取元素紧邻的前一个同辈元素
// DOM操作相关方法
njQuery.prototype.extend({
prev: function (sele) {
var res = [];
if(arguments.length === 0){
this.each(function (key, value) {
var temp = njQuery.get_previoussibling(value);
if(temp == null) return true;
res.push(temp);
});
}else{
this.each(function (key, value) {
var temp = njQuery.get_previoussibling(value);
$(sele).each(function (k, v) {
if(v == null || temp !== v) return true;
res.push(v);
})
});
}
return $(res);
}
})
12. replaceAll 方法
替换所有指定元素
// DOM操作相关方法
njQuery.prototype.extend({
replaceAll: function (sele) {
// 1.统一的将传入的数据转换为jQuery对象
var $target = $(sele);
var $this = this;
var res = [];
// 2.遍历取出所有指定的元素
$.each($target, function (key, value) {
var parent = value.parentNode;
// 2.遍历取出所有的元素
$this.each(function (k, v) {
// 3.判断当前是否是第0个指定的元素
if(key === 0){
// 1.将元素插入到指定元素的前面
$(v).insertBefore(value);
// 2.将指定元素删除
$(value).remove();
res.push(v);
}else{
// 先拷贝再添加
var temp = v.cloneNode(true);
// 1.将元素插入到指定元素的前面
$(temp).insertBefore(value);
// 2.将指定元素删除
$(value).remove();
res.push(temp);
}
});
});
// 3.返回所有添加的元素
return $(res);
}
})
5. jQuery 属性操作相关方法
1. attr 方法
设置或者获取元素的属性节点值
$(function () {
// 传递一个参数, 返回第一个元素属性节点的值
console.log($("span").attr("class"));
// 传递两个参数, 代表设置所有元素属性节点的值
// 并且返回值就是方法调用者
console.log($("span").attr("class", "abc"));
// 传递一个对象, 代表批量设置所有元素属性节点的值
$("span").attr({
"class": "123",
"name": "888"
});
});
// 属性操作相关的方法
njQuery.prototype.extend({
attr: function (attr, value) {
// 1.判断是否是字符串
if(njQuery.isString(attr)){
// 判断是一个字符串还是两个字符串
if(arguments.length === 1){
return this[0].getAttribute(attr);
}else{
this.each(function (key, ele) {
ele.setAttribute(attr, value);
});
}
}
// 2.判断是否是对象
else if(njQuery.isObject(attr)){
var $this = this;
// 遍历取出所有属性节点的名称和对应的值
$.each(attr, function (key, value) {
// 遍历取出所有的元素
$this.each(function (k, ele) {
ele.setAttribute(key, value);
});
});
}
return this;
}
})
2. prop 方法
设置或者获取元素的属性值
$(function () {
// 传递两个参数, 代表设置所有元素属性节点的值
// 并且返回值就是方法调用者
console.log($("span").prop("abc", "lnj"));
// 传递一个参数, 返回第一个元素属性节点的值
console.log($("span").prop("abc"));
// 传递一个对象, 代表批量设置所有元素属性节点的值
$("span").prop({
"aaa": "111",
"bbb": "222"
});
});
// 属性操作相关的方法
njQuery.prototype.extend({
prop: function (attr, value) {
// 1.判断是否是字符串
if(njQuery.isString(attr)){
// 判断是一个字符串还是两个字符串
if(arguments.length === 1){
return this[0][attr];
}else{
this.each(function (key, ele) {
ele[attr] = value;
});
}
}
// 2.判断是否是对象
else if(njQuery.isObject(attr)){
var $this = this;
// 遍历取出所有属性节点的名称和对应的值
$.each(attr, function (key, value) {
// 遍历取出所有的元素
$this.each(function (k, ele) {
ele[key] = value;
});
});
}
return this;
}
})
3. css 方法
设置获取样式
$(function () {
// 传递一个参数, 返回第一个元素指定的样式
console.log($('div').css('height'));
// 传递两个参数, 代表设置所有元素样式
// 并且返回值就是方法调用者
console.log($('div').css('height', '50px'));
// 传递一个对象, 代表批量设置所有元素样式
$('div').css({
height: '50px',
backgroundColor: 'pink'
});
// 获取样式
var div = document.querySelector("div");
console.log(window.getComputedStyle(div)["height"]);
console.log(div.currentStyle["height"]);
// 设置样式
div.style["height"] = "200px";
});
// 属性操作相关的方法
njQuery.prototype.extend({
css: function (attr, value) {
// 1.判断是否是字符串
if(njQuery.isString(attr)){
// 判断是一个字符串还是两个字符串
if(arguments.length === 1){
return njQuery.getStyle(this[0], attr);
}else{
this.each(function (key, ele) {
ele.style[attr] = value;
});
}
}
// 2.判断是否是对象
else if(njQuery.isObject(attr)){
var $this = this;
// 遍历取出所有属性节点的名称和对应的值
$.each(attr, function (key, value) {
// 遍历取出所有的元素
$this.each(function (k, ele) {
ele.style[key] = value;
});
});
}
return this;
}
})
// 工具方法
njQuery.extend({
getStyle: function (dom, styleName) {
if(window.getComputedStyle){
return window.getComputedStyle(dom)[styleName];
}else{
return dom.currentStyle[styleName];
}
}
})
4. val 方法
获取设置value的值
$(function () {
// 不传递参数, 返回第一个元素指定的样式
console.log($('input').val());
// 传递两个参数, 代表设置所有元素样式
// 并且返回值就是方法调用者
console.log($('input').val( '新设置的' ));
var input = document.querySelector("input");
// input.setAttribute("value", "123456");
var btn = document.querySelector("button");
btn.onclick = function (ev) {
// console.log(input.getAttribute("value"));
// console.log($('input').val());
console.log(input.value);
}
});
// 属性操作相关的方法
njQuery.prototype.extend({
val: function (content) {
if(arguments.length === 0){
return this[0].value;
}else{
this.each(function (key, ele) {
ele.value = content;
});
return this;
}
}
})
5. hasClass 方法
判断元素中是否包含指定类
$(function () {
// 传递参数, 只要调用者其中一个包含指定类就返回true,否则返回false
console.log($("div").hasClass("cc"));
console.log($("div").hasClass("abc"));
// 没有传递参数, 返回false
console.log($("div").hasClass());
var div = document.querySelector("div");
// console.log(div.getAttribute("class"));
// console.log(div.className);
// 1.获取元素中class保存的值
var className = " "+div.className+" ";
// 2.通过indexOf判断是否包含指定的字符串
// console.log(className.indexOf("abc") != -1);
// console.log(className.indexOf("bb"));
// console.log(className.indexOf(" "+"bb"+" "));
console.log(className.indexOf(" "+"dd"+" "));
});
// 属性操作相关的方法
njQuery.prototype.extend({
hasClass: function (name) {
var flag = false;
if(arguments.length === 0){
return flag;
}else{
this.each(function (key, ele) {
// 1.获取元素中class保存的值
var className = " "+ele.className+" ";
// 2.给指定字符串的前后也加上空格
name = " "+name+" ";
// 3.通过indexOf判断是否包含指定的字符串
if(className.indexOf(name) != -1){
flag = true;
return false;
}
});
return flag;
}
}
})
6. addClass 方法
给元素添加一个或多个指定的类
$(function () {
// 传递参数, 如果元素中没有指定类就添加, 有就不添加
// 会返回this方便链式编程
// console.log($("div").addClass("abc"));
// console.log($("div").addClass("abc def"));
// 没有传递参数,不做任何操作,返回this
console.log($("div").addClass());
// "aabb" + " " + "abc" = "aabb abc"
});
// 属性操作相关的方法
njQuery.prototype.extend({
addClass: function (name) {
if(arguments.length === 0) return this;
// 1.对传入的类名进行切割
var names = name.split(" ");
// 2.遍历取出所有的元素
this.each(function (key, ele) {
// 3.遍历数组取出每一个类名
$.each(names, function (k, value) {
// 4.判断指定元素中是否包含指定的类名
if(!$(ele).hasClass(value)){
ele.className = ele.className + " " + value;
}
});
});
return this;
}
})
7. removeClass 方法
删除元素中一个或多个指定的类
$(function () {
// 传递参数, 如果元素中有指定类就删除
// 会返回this方便链式编程
console.log($("div").removeClass("aabb"));
// console.log($("div").removeClass("aabb abc"));
// 没有传递参数, 删除所有类
// console.log($("div").removeClass());
});
// 属性操作相关的方法
njQuery.prototype.extend({
removeClass: function (name) {
if(arguments.length === 0){
this.each(function (key, ele) {
ele.className = "";
});
}else{
// 1.对传入的类名进行切割
var names = name.split(" ");
// 2.遍历取出所有的元素
this.each(function (key, ele) {
// 3.遍历数组取出每一个类名
$.each(names, function (k, value) {
// 4.判断指定元素中是否包含指定的类名
if($(ele).hasClass(value)){
ele.className = (" "+ele.className+" ").replace(" "+value+" ", "");
}
});
});
}
return this;
}
})
8. toggleClass 方法
没有则添加,有则删除
(function () {
// 传递参数, 如果元素中没有指定类就添加, 有就不添加
// 会返回this方便链式编程
console.log($("div").toggleClass("abc"));
console.log($("div").toggleClass("aabb abc"));
// 没有传递参数, 删除所有类
console.log($("div").toggleClass());
});
// 属性操作相关的方法
njQuery.prototype.extend({
toggleClass: function (name) {
if(arguments.length === 0){
this.removeClass();
}else{
// 1.对传入的类名进行切割
var names = name.split(" ");
// 2.遍历取出所有的元素
this.each(function (key, ele) {
// 3.遍历数组取出每一个类名
$.each(names, function (k, value) {
// 4.判断指定元素中是否包含指定的类名
if($(ele).hasClass(value)){
// 删除
$(ele).removeClass(value);
}else{
// 添加
$(ele).addClass(value);
}
});
});
}
return this;
}
})
9. clone 方法
复制一个元素
$(function () {
$("button").eq(0).on("click",function () {
// 1.浅复制一个元素
var $li = $("li").clone(false);
console.log($li);
// 2.将复制的元素添加到ul中
$("ul").append($li);
});
$("button").eq(1).on("click", function () {
// 1.深复制一个元素
var $li = $("li").clone(true);
// 2.将复制的元素添加到ul中
$("ul").append($li);
});
/*
li.eventsCache = {
click: [];
};
*/
$("li").on("click", function () {
alert($(this).html());
});
var li = document.querySelector("li");
li.onclick = function (ev) {
alert(123);
}
var temp = JSON.parse(JSON.stringify(li));
var ul = document.querySelector("ul");
ul.appendChild(temp);
});
// 属性操作相关的方法
njQuery.prototype.extend({
clone: function (deep) {
var res = [];
// 判断是否是深复制
if(deep){
// 深复制
this.each(function (key, ele) {
var temp = ele.cloneNode(true);
// 遍历元素中的eventsCache对象
njQuery.each(ele.eventsCache, function (name, array) {
// 遍历事件对应的数组
njQuery.each(array, function (index, method) {
// 给复制的元素添加事件
$(temp).on(name, method);
});
});
res.push(temp);
});
return $(res);
}else{
// 浅复制
this.each(function (key, ele) {
var temp = ele.cloneNode(true);
res.push(temp);
});
return $(res);
}
}
})
6. jQuery 事件操作相关方法
1. on(type, callback)
注册事件
- 注册多个相同类型事件, 后注册的不会覆盖先注册的
- 注册多个不同类型事件, 后注册的不会覆盖先注册的
// 事件操作相关的方法
njQuery.prototype.extend({
on: function (name, callBack) {
// 1.遍历取出所有元素
this.each(function (key, ele) {
// 2.判断当前元素中是否有保存所有事件的对象
if(!ele.eventsCache){
ele.eventsCache = {};
}
// 3.判断对象中有没有对应类型的数组
if(!ele.eventsCache[name]){
ele.eventsCache[name] = [];
// 4.将回调函数添加到数据中
ele.eventsCache[name].push(callBack);
// 5.添加对应类型的事件
njQuery.addEvent(ele, name, function () {
njQuery.each(ele.eventsCache[name], function (k, method) {
method.call(ele);
});
});
}else{
// 6.将回调函数添加到数据中
ele.eventsCache[name].push(callBack);
}
});
return this;
}
});
2. off(type, callback)
移出事件
$(function () {
// 1.不传参, 会移除所有事件
$("button").off();
// 2.传递一个参数, 会移除对应类型所有事件
$("button").off("click");
// 3.传递两个参数, 会移除对应类型对应事件
$("button").off("click", test1);
});
// 事件操作相关的方法
njQuery.prototype.extend({
off: function (name, callBack) {
// 1.判断是否没有传入参数
if(arguments.length === 0){
this.each(function (key, ele) {
ele.eventsCache = {};
});
}
// 2.判断是否传入了一个参数
else if(arguments.length === 1){
this.each(function (key, ele) {
ele.eventsCache[name] = [];
});
}
// 3.判断是否传入了两个参数
else if(arguments.length === 2){
this.each(function (key, ele) {
njQuery.each(ele.eventsCache[name], function (index, method) {
// 判断当前遍历到的方法和传入的方法是否相同
if(method === callBack){
ele.eventsCache[name].splice(index, 1);
}
});
});
}
return this;
}
});