深入理解JQuery设计思想--基于手写DOM库

深入理解JQuery设计思想

从封装DOM开始

由于原生DOM操作比较麻烦,我使用原生JavaScript对常用DOM操作进行了封装。

[代码连接](jsDOM/dom.js at master · yichang8421/jsDOM (github.com))

API使用范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// document.createElement('div');
const div = dom.create("<div>newDiv1</div>");
console.log(div);

// dom.after()
dom.after(window.test, div);

const div2 = dom.create("<div>newDiv2</div>");
dom.before(window.test, div2);

// dom.wrap()
const div3 = dom.create("<div id='parent'></div>");
dom.wrap(window.test, div3);

// dom.empty()
const node = dom.empty(window.testEmpty);
console.log(node);

// dom.attr()
// 设置title属性
dom.attr(window.test, 'title', 'helloWorld');
// 读取title属性
const title = dom.attr(window.test, 'title');
console.log(`title:${title}`);

// dom.text()
// 设置节点的文本内容(会整体替换节点内容)
dom.text(window.test, '你好,这是新的内容');
//获取节点的文本内容
dom.text(window.test);

// dom.style()
// 设置节点的样式
dom.style(window.test, {border: '1px solid red', color: 'green'});
// 获取节点的样式
console.log(`test.color: ${dom.style(window.test, 'color')}`);
// 修改样式属性值
dom.style(window.test, 'color', 'blue');

// dom.class.add()
// 给节点添加class属性
dom.class.add(window.test, 'red');
// 删除class属性
dom.class.remove(window.test, 'red');
// 判断某个class属性是否存在
console.log(`含有class=red? ${dom.class.contains(window.test, 'red')}`);

const testClick = () => {
console.log('点击事件');
};

// dom.on()
// 添加点击事件
dom.on(window.test, 'click', testClick);
// 移出点击事件
dom.off(window.test, 'click', testClick);

// dom.find()
const testDiv = dom.find('#test2')[0];
console.log(testDiv);
console.log(dom.find('.red',testDiv)[0]);

// dom.parent()
console.log(dom.parent(window.test));

// dom.siblings()
const sibling2 =dom.find('#siblings2')[0];
console.log('兄弟节点:');
console.log(dom.siblings(sibling2));

// dom.next()
console.log('前一个兄弟节点:');
console.log(dom.next(sibling2));

// dom.previous()
console.log('后一个兄弟节点:');
console.log(dom.previous(sibling2));

// dom.each()
// 设置子元素属性
const t = dom.find("#testTravel")[0];
dom.each(dom.children(t),(n)=> dom.style(n,'color','red'));

// dom.index()
// 找到节点在平级节点中的索引
console.log(`siblings的索引:${dom.index(sibling2)}`);

jQuery基本用法

jQuery是一套跨浏览器的JavaScript函数库,它可以简化HTML与JavaScript之间的操作。其语法设计模式使得许多操作变得容易,如操作文档对象(document)、选择文档对象模型(DOM)元素、创建动画效果、处理事件、以及开发Ajax程序等等。

jQuery的核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的css选择器,并且可对CSS选择器进行扩展;拥有便捷的插件扩展机制和丰富的插件;兼容各种主流浏览器(如IE 6.0+、FF 1.5+、Safari 2.0+、Opera 9.0+等)。

截至2021年2月,全球前1万名访问最高的网站中,有79.76%的网站使用了jQuery[1],仍是目前最受欢迎的JavaScript函数库。

jQuery官方文档

引入jQuery

1
2
3
4
5
6
7
8
<!-- 注意:要把JQuery库的引用放到第一个<script>引用前面,这样顺序执行后面的js文件才能识别$符号 -->

<!-- 1.yran add jquery后引入 -->
<script src="jquery.js"></script>

<!-- 2.https://jquery.com/download/
或 https://www.bootcdn.cn/jquery/ -->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>

页面加载即执行jQuery

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// jQuery可以用$代替
/* 写法一:DOM树结构完整即执行 */
$(document).ready(function(){
// 操作代码
});

/* 简写 */
$(function(){
// 操作代码
});

/* 写法二:等整个窗口加载完毕(含图片)才执行 */
window.onload = function(){
//操作代码
};

写法一的简写形式较为多用。

选择网页元素

jQuery基本思想是:选择某个元素,然后对其进行操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 选择表达式,类似JavaScript选择器
$(document);
$('#myId');
$('div.myClass');
$('input[name=first]');

//特有的选择表达式
$('a:first');
$('tr:odd'); //选择表格的奇数行
$('#myForm :input');
$('div:visible'); //选择可见的元素
$('div:gt(2)'); //选择索引大于2的所有div元素
$('div:animated'); //选择当前出于动画状态的div元素

改变数据集

jQuery提供了各种过滤器对数据进行筛选,得到较为精确的选择结果。

筛选选择结果

1
2
3
4
5
$('div').has('p');			//选择包含p元素的div元素
$('div').not('.myClass'); //选择class不等于myClass的div元素
$('div').filter('.myClass');
$('div').first();
$('div').eq(5); //选择索引等于5的元素(第六个元素)

通过遍历DOM树进行筛选

1
2
3
4
5
6
$('div').next('p');			//同级下一个元素
$('div').parent();
$('div').children();
$('div').find(); //选择后代元素
$('div').siblings();
$('div').closest('form'); //选择最近元素

链式操作

jQuery允许将各种操作连在一起,以链式语法形式书写,有效简化代码。

1
2
3
4
5
6
7
8
9
10
//$('.test').find('.child').addClass('red').addClass('blue').addClass('green').end().html('修改test');

//分解写法,便于读代码
$('.test')
.find('.child')
.addClass('red')
.addClass('blue')
.addClass('green')
.end() // end()回退上一次选择的节点,然后进行后续操作
.html('修改test');

jQuery提供end()方法使当前选择器回退到上一次选择的节点,然后对其进行操作。上面的html()方法最终作用在.test元素上。end()方法使得jQuery链式操作不会因为选择器的来回切换而断开,因此是“真”链式操作

读写操作

jQuery可以使用同一个方法来完成getset操作:

1
2
$('header').html();				//读取header的html内容
$('header').html('andy8421'); //设置header值为andy8421

常见读写操作函数:

html() 取出或设置html内容

 text() 取出或设置text内容,读取时只有文本内容(不含html标签)

 attr()

 width()

 height()

 val() 取出或设置某个表单元素的值

需要注意的是,如果结果集包含多个元素,那么赋值的时候,将对其中所有的元素赋值;取值的时候,则是只取出第一个元素的值

text()除外,它读取所有元素的text内容。

html()、text()和val()的区别

  • html()读取已被渲染的内容,未被渲染的标签不会读取

  • text()只读取文本内容,但是读取的是所有元素的文本内容

  • var()操作对象是表单元素,主要用于读写表单元素的value

举例:

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<body>
<div id="div1"><strong>HelloWorld</strong></div>
<div id="div2"><em>/FrontEnd</em></div>
<input type="text" id="input1" value="val读取内容" />
<br />
<br />

html()是:
<div id="html"></div>

text()是:
<div id="text"></div>

val()是:
<input type="text" id="val" />
<br />
<br />

input的value设为html:
<input type="text" id="htmlVal" />
<br />
input的value设为text:
<input type="text" id="textVal" />

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script src="main.js"></script>
</body>

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$(function () {
/* 拿到文本值 */
let strHtml = $('div').html();
let strText = $('div').text();
let strVal = $('#input1').val();

/* 设置文本值 */
$("#html").html(strHtml);
$("#text").text(strText);


$("#val").val(strVal);
console.log(strVal);
console.log($('#val').val());

/* input的value设置为html */
// $("#htmlVal").val(strHtml);
console.log($("#htmlVal").val(strHtml).val());

/* input的value设置为text */
console.log($("#textVal").val(strText).val());
});

输出结果:

1618739381161

插入操作

外部插入

1
2
3
4
5
$('aside').insertAfter($('article'));
$('article').after($('aside'));

$('h2').insertBefore($('section'));
$('section').before($('h2'));

内部插入

1
2
3
4
5
$('footer').appendTo(document.body);
(document.body).append($('footer')); //可用于创建元素

$('header').prependTo(document.body);
(document.body).prepend('header');

以上内部插入和外部操作中,成对的两个代码操作效果相同。jQuery之所以这样设计是为了便于链式操作,可以灵活选择。

元素的复制、删除

1
2
3
4
5
6
$('div').clone();		

$('div').remove(); //真删除
$('div').detach(); //假删除,保留被删除元素的事件

$('header').empty; //清空header元素内容,而不删除header元素

用jQuery的设计思想封装DOM库

为进一步简化手写DOM操作,我使用jQuery设计思想,即封装了DOM库。

源码连接

获取网页元素

使用jQuery的第一步,就是要得到你选中的元素,放在jQuery()(或者$())里面。

实现方法: 使用重载设计模式获取对应的元素,利用闭包,在调用方法时使用到elements

链式操作

链式操作: 选中网页元素以后,可以对它进行一系列操作,并且所有操作可以连接在一起,以链条的形式写出来.

实现思想: 于每一步的jQuery操作,返回的都是一个新的jQuery对象。

方法放在原型上

优点:

  • 把方法都移到jQuery原型身上,这样每次创建一个jQuery对象时,就不会再去开一块内存存放方法了。
  • 所有创建的jQuery对象中的方法都放在原型上,这样省内存。

版权声明:本文作者为「Andy8421」.本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!