一、jQuery中的 $
1. 顶级对象
可以使用$('DOM对象')将 DOM 对象转换成一个jQuery对象,使其具备jQuery对象的方法。比如下文的入口函数,将 document 对象转换成了 jQuery 对象,调用了 ready 方法。
2.入口函数
$(function(){
// DOMContentLoaded之后需要执行的代码
});
等价于
$(document).ready(function(){
// DOMContentLoaded之后需要执行的代码
});
其作用都等价于:
document.addEventListener("DOMContentLoaded", function(){
// DOMContentLoaded之后需要执行的代码
});
3. jQuery对象和DOM对象的转换
jQuery 对象和 DOM 对象相互独立,各自有各自的方法和属性,不能混用,但是可以转换。
jQuery对象的本质是通过选择器进行筛选获取DOM对象后,对其进行伪数组形式的封装,让其具备jQuery对象的方法,观察下面的打印结果:
// html
<div class="first"></div>
<div></div>
// js
var divs = $('div');
console.dir(divs);
var domDiv = document.querySelector('div');
console.dir(domDiv);
结果:
展开 __proto__ 就可以看到很多方法,比如 hide,也就是说,这个对象包含 2 个 DOM 中的 div 对象,额外添加了许多方法和属性。当调用这些方法时,默认会对 jQuery 对象中的伪数组中的所有元素生效,也就是隐式迭代,而伪数组中的元素就是 DOM 对象。
用图表示就是这样:
因为是伪数组的形式,那么 jQuery 和 DOM 的转换就简单了,取出 jQuery 伪数组中的元素即可:
jQuery 对象转 DOM 对象:
// 直接取数组中的元素
divs[1].style.display = "none";
// 使用get方法获取数组中的元素
divs.get(1).style.display = "none";
DOM 对象转 jQuery 对象,使用 $ 符号所得到的对象就是 jQuery 对象:
// 标签选择器
var divs = $('div');
// 类型选择器
$('.first').hide();
注意:get 和 eq 含义不同。 get 是转换对象,eq 是取出 jQuery 对象
二、选择器
使用方法:
$("选择器")
1. 基础选择器:
2. 层级选择器
3. 筛选选择器
使用:
$(function(){
$(function(){
// 获取结果中的第一个元素
$("ul li:first").css("color", "red");
// 奇数
$("ul li:odd").css("color", "red");
// 索引值
$("ul li:eq(4)").css("color", "red");
});
})
4. 筛选方法
prevAll():之前的所有的符合选择器的元素,默认无选择器表达式
prev():前一个符合选择器的元素,默认无选择器表达式
如下代码就不会改变,因为ul .item
的前一个不符合选择器要求:
$("ul .item").prev(".first").css("color", "red");
<li class="first">哈哈啊</li>
<li class="second">哈哈啊</li>
<li class="item">哈哈啊</li>
<!-- <li class="item">哈哈啊</li> -->
另外,siblings的执行对象中的元素不止一个的话,会出现问题,使用时最好确保调用对象只有一个:
<script>
$(function() {
$("ul .item").siblings("li").css("color", "red");
})
</script>
<ul>
<li class="first">哈哈啊</li>
<li class="second">哈哈啊</li>
<li class="item">哈哈啊</li>
<li class="item">哈哈啊</li>
<li>哈哈啊</li>
<li>哈哈啊</li>
<li>哈哈啊</li>
<li>哈哈啊</li>
<li>哈哈啊</li>
<li>哈哈啊</li>
<li>哈哈啊</li>
</ul>
结果就是所有的<li>都变成了红色。
5. 两个 eq
选择器中的 eq 遇到变量时,需要使用字符串拼接的方式来使用变量:
var index = 2;
$("ul li:eq("+index+")").css("color", "red");
方法 eq 则可以直接使用变量:
var index = 2;
// $("ul li:eq("+index+")").css("color", "red");
$("ul li").eq(index).css("color", "red");
所以,推荐使用 eq 方法。
另外,eq(index) 是取得对应 inde 的 jQuery 对象,而 get(index) 方法是将 jQuery 对象转换成 DOM 对象。
6. 排他思想
使用 this + siblings来实现:
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
<script>
$(function () {
$("button").click(function() {
$(this).css("background", "red");
$(this).siblings().css("background", "none");
});
})
</script>
三、样式操作
1. 操作CSS
获取属性值
$("div").css("width");
修改单一属性值
$("div").css("width", "300px"); // px可以省略
修改多个属性值
使用对象的形式来修改多个属性值
$("div").css({
"width": "300px",
"height" : "200px",
"background-color" : "red"
})
注意:
- 属性和数字可以不加引号;
- 如果属性不加引号,命名方式是驼峰命名,而不是带 "-";
- 非数字和属性都要加引号,比如颜色;
- jQuery会默认识别数字单位
上述的第二种写法:
$("div").css({
width: 300,
height : 200,
backgroundColor : "red"
})
总结:
加引号是最好的
2. 添加/删除类
写好一个类的样式之后,直接将这个类添加到元素中,这样就不需要一个个地去修改样式了
添加类:addClass
删除类:removeClass
切换类(没有就加,有就删除):toggleClass
举个栗子🌰:
<style>
div {
background-color: yellow;
width: 50px;
height: 50px;
}
.redBox {
background-color: red;
width: 300px;
height: 200px;
}
</style>
<body>
<div></div>
<script>
$(function () {
$("div").mouseover(function () {
$(this).addClass("redBox")
});
$("div").click(function () {
$(this).removeClass("redBox")
});
})
</script>
</body>
以上代码可以直接使用切换类:
$("div").click(function () {
$(this).toggleClass("redBox")
});
再来看一个过渡动画的栗子🌰:
<style>
div {
background-color: yellow;
width: 50px;
height: 50px;
/* 所有可以动画的属性都添加上过渡效果 */
transition: all 0.5s;
}
.redBox {
background-color: red;
transform: rotate(360deg);
}
</style>
<body>
<div></div>
<script>
$(function () {
$("div").click(function () {
$(this).toggleClass("redBox")
});
})
</script>
</body>
结果是:
例子中主要是 使用了 transition: all 0.5s;
让所有可动画的属性在变换时都进行动画,接下来看看真正的动画效果~~
四、动画
1. show/hide
show([speed], [easing], [fn])
speed:速度,slow、normal、fast、毫秒数
easing:swing(秋千)、linear(线性)
fn:完成后的回调函数
2. slide
<style>
div {
background-color: red;
width: 150px;
height: 400px;
display: none;
}
</style>
<body>
<button>下拉</button>
<button>上滑</button>
<button>切换</button>
<div></div>
<script>
$(function(){
$("button").first().click(function(){
$("div").slideDown()
})
$("button").eq(1).click(function(){
$("div").slideUp()
})
$("button").last().click(function(){
$("div").slideToggle()
})
})
</script>
</body>
效果:
3. hover
hover([over,]out):鼠标经过时的事件,附带切换功能;
第一个参数是经过时的回调,第二个是离开时的回调。至少需要传一个函数。
如果只有一个 function,那么鼠标经过和离开都会调用这个函数,所以和 toggle 来配合使用代码会非常简洁,如下:
$("button").hover(function(){
$("div").slideToggle()
})
4. 动画队列和停止排队
简易的下拉菜单的 JS 代码如下:
<script>
$(function(){
$(".nav>li>a").hover(function(){
$(this).next("ul").slideToggle(300)
})
})
</script>
默认情况下的效果是这样的:
如图,当快速在导航栏滑动时,滑动停止之后会出现动画排队必须执行完,所以就有了鼠标离开了仍然继续加载动画的情况。因为默认情况下,事件触发了多少次,动画就会排队执行多少次,所以需要使用stop()
来终止之前的动画。
stop():停止之前的动画,开始最新的动画
代码如下:
$(this).next("ul").stop().slideToggle(300)
切记必须写在动画方法的前面,写到后面就想到与停止动画了,代码如下:
$(this).next("ul").slideToggle(300).stop()
如果这样写,结果会出错。
5. 淡入淡出
fadeIn:由透明变成不透明,0->1;
fadeOut:由不透明变成透明,1->0;
fadeTo:变化到指定的透明度;
fadeToggle:切换;
仍然是接收三个参数:speed、easing、fn
其中,fadeTo 第二个参数为新增参数:opacity
6. 自定义动画
animate(params,[speed],[easing],[fn])
第一个参数是需要动画的属性,以对象形式表示。和 .css()
是一样的道理,最好都使用引号。
代码如下:
<style>
div {
position: absolute;
left: 50px;
top: 0;
background-color: yellow;
margin: 100px auto;
width: 100px;
height: 100px;
/* 所有可以动画的属性都添加上过渡效果 */
/* transition: all 0.5s; */
}
</style>
<body>
<div></div>
<script>
$(function () {
$("div").animate({
width: 200,
left: 200,
top: 300
}, 1000, "swing", function(){
console.log("动画执行完毕")
})
})
</script>
</body>
五、属性操作
1. prop
意义:只能获取和设置元素的固有属性,返回字符串。
示例如下:
<input type="checkbox">
<script>
console.log($("input").prop("checked"));
</script>
2. attr
意义:获取和设置自定义属性,返回字符串。设置时没有就新增,可获取和设置的属性包括 H5 新增的以data-
开头的自定义属性。
示例:
<div data-index="2">1</div>
<script>
console.log($("div").attr("index")); // undefined
console.log($("div").attr("data-index")); // 2
$("div").attr("index","1")
console.log($("div").attr("index")); // 1
</script>
因为自定义的属性如果没有规范,很容易和固有属性引起歧义,结果就是使用 attribute 和 点方法属性获取到为空。所以 H5 新增
data-xxx
就是规范了自定义属性,由此就成就了prop
和attr
两套独立的方法。
3. data
意义:数据缓存,可以理解成attr
,但是和attr
最大的不同是data()
方法不会改变 DOM 的结构。所以这个方法更适合理解成数据缓存。
该方法同样可以获取 H5 中新规定的以 "data-" 开头的自定义属性,但是不能加"data-"。但是设置时,不管有没有"data-",都不会在 DOM 中显示。
总之:就用这个方法来存储数据即可。
示例代码:
<input type="checkbox" data-index2="2">
<script>
// 获取和设置存储数据,不改变DOM结构
$("input").data("data-index", "1");
console.log($("input").attr("data-index"));
// 获取自定义属性时,data不能加data-,attr必须加
console.log($("input").attr("data-index2"));
console.log($("input").data("index2"));
</script>
六、文本操作
html()
:获取和设置文本/元素
text()
:获取和设置文本
val()
:获取和设置 val 属性,没有 val 属性时无效
代码示例:
<div>
<div><span>我是span</span></div>
<input type="text" name="" id="" value="" placeholder="请输入文字">
</div>
<script>
// html
console.log($("div>div").html());
$("div>div").html("123");
$("div>div").html("<p>我是段落</p>");
// text
$("div>div p").text("段落文本被修改了");
// val
$("div>input").val("文本框的值被修改了")
</script>
七、元素操作
1. 遍历
方法一:$("div").each(function(index, domEle){})
注意:domEle 是 DOM 对象,而不是 jQuery 对象,所以需要使用 $()
转换。
方法二:$.each(object, function(index, domEle){})
该方法区别于以上方法,方法一主要用于元素循环添加一些操作,方法二一般用来处理数据。新增的 object 对象可以是数组,也可以是对象,可以是 DOM 对象,也可以是 JS 对象,还可以是 jQuery 对象。
遍历数组:
var array = [1, 2, 3]
$.each(array, function(index, ele){
console.log(index)
console.log(ele)
})
遍历对象:
var obj = {"name" : "Jack", "height" : 180, "weight" : 50.0}
$.each(obj, function(index, ele){
console.log(index)
console.log(ele)
})
遍历 jQuery 对象:
$.each($("div"), function(index, ele){
console.log(index)
console.log(ele)
})
2. 创建
jQuery:$("<div>0</div>")
DOM:ele.html("<div>0</div>")
、document.createElement("<div>0</div>")
、document.write("<div>0</div>")
3. 添加
内部添加:ele.append()
、ele.prepend()
外部添加:ele.after()
、ele.before()
4. 删除
删除自身:ele.remove()
删除自身所有子元素:ele.empty()
、ele.html("")
这里需要注意
html ("")
的用法。html()
本来就是设置自身的子元素,只不过比text()
具备识别标签的能力,同时具备创建元素的能力,所以字符串为非标签时,就是设置元素的文本属性,字符串为标签时,就是给元素添加子元素。
示例代码:
<div>1</div>
<div>2</div>
<div class="lastDiv">3</div>
<ul>
<li>1</li>
<li>2</li>
<li class="lastLi">3</li>
</ul>
<script>
// 创建元素
var newDiv = $("<div>4</div>")
var newLi = $("<li>4</li>")
// 内部添加
$("ul").append(newLi)
$("ul").prepend($("<li>0</li>"))
// 外部添加
$("ul").before($(newDiv))
$("ul").after($("<div>5</div>"))
// 删除
newLi.remove() // 删除自身
$("ul").empty() // 删除自身所有子元素,但是不删除自身
newDiv.html("") // 删除自身所有子元素,但是不删除自身
newDiv.text("123")
newDiv.html("<span>789</span>")
</script>
八、事件绑定
使用 on 来进行事件绑定,使用 one() 来添加一次性事件绑定。
语法:on(events,[selector],[data],fn)
1. 绑定多个事件
$("div").on("mouseenter mouseout", function(){
// 这里不能携程".pink""
$(this).toggleClass("pink")
})
2. 对象形式传参
$("div").on({
"mouseenter": function(){
console.log("mouseenter");
},
"mouseout": function(){
console.log("mouseout");
}
})
3. 数据传递
function myHandler(event) {
alert(event.data.foo);
}
$("p").on("click", {foo: "bar"}, myHandler)
4. 事件委派
事件委派只能是将后代元素的事件委派给父元素来处理,第三个参数就是要进行委派的子元素,注意必须是后代。
举个栗子🌰:
<script>
// 设置自身子元素的事件委派
$("ul").on("mouseenter mouseout", "li", function () {
$(this).toggleClass("pink")
});
// 子元素
$(".box").on("mouseenter mouseout", ".childDiv", function () {
$(this).toggleClass("pink")
});
// 后代元素
$(".box").on("mouseenter mouseout", ".grandsonDiv", function () {
$(this).toggleClass("pink")
});
</script>
5. 动态元素事件绑定
即使符合选择器的要求,事件绑定之后创建的元素也不会有对应的事件,而 on 是动态的,即使在 on 函数之后创建的元素,也具备对应的事件。
注意:仅限事件委派条件下
举个栗子:
<script>
// 不影响后续动态创建的li
$("ul>li").click(function(){
console.log("normal-click");
})
// 不影响后续动态创建的li
$("ul>li").on("click", function(){
console.log("on--click");
})
// 影响后续动态创建的li
$("ul").on("click", "li", function(){
console.log("on-delegate-click");
})
$("ul").append($("<li>5</li>"))
</script>
结果:
on 的这个特性其实很有用,在动态列表页的需求上,利用 on + 事件委派可以保证每一个 cell 都具备相同的事件。否则就需要创建之后再添加对应的事件,稍微麻烦。
6. 一次性事件绑定
意义:绑定的事件只执行一次。one 方法不能进行委托绑定,不需要解绑。
语法:one(type,[data],fn)
使用 one 绑定的事件如果在执行之前被解绑了,那么就不会执行。但是,必须使用 off() 来解除所有事件绑定,只使用
off("eventName")
并不会解除所有绑定。
示例代码:
$("ul>li").one("click", function(){
console.log("click");\
})
7. 事件解绑
意义:用 off 来解绑使用 on 绑定的时间,one() 事件不需要解绑,但可以使用 off() 来解除所有事件绑定的同时一并解除。
语法:off(events,[selector],[fn])
用法:
- 解绑所有事件
- 结束特定事件
- 解除事件委托
示例代码:
// 解除 li 的所有绑定事件
$("ul>li").off()
// 解除 ul 的所有绑定事件,包括委托事件
$("ul").off()
// 解除特定事件
$("ul>li").first().off("click", "li")
8. 自动触发事件
ele.event():直接调用
trigger():自动触发,但是会触发元素默认行为,比如光标
triggerHandle():自动触发,不会触发元素默认行为
示例代码:
$("input").focus(function(){
console.log("focus");
})
// 触发默认行为
$("input").focus()
$("input").trigger("focus")
// 不触发默认行为
$("input").triggerHandler("focus")
9. 事件对象
10.
九、jQuery其他使用
1. 拷贝对象
浅拷贝:被拷贝的对象中包含对象时,拷贝的是地址,对象属性不递归合并。
深拷贝:被拷贝的对象中包含对象时,产生新的对象,拷贝的是新对象的地址,对象属性会进行递归合并。
举个栗子🌰:
var targetObj = {classMsg: {
rank: "1"
}}
var obj = {
name: "Jack",
age: 18,
classMsg: {
classNo: "201",
studentNo: "001"
}
}
浅拷贝:
// 浅拷贝只拷贝内存地址
$.extend(targetObj, obj);
targetObj.classMsg.studentNo = "002"
console.log(obj.classMsg.studentNo); // 002
// 浅拷贝不递归合并
console.log(targetObj.classMsg); // classMsg包含classNo、studentNo
深拷贝:
// 深拷贝是创建一个新的对象
$.extend(true, targetObj, obj);
targetObj.classMsg.studentNo = "002"
console.log(obj.classMsg.studentNo); // 001
// 深拷贝会递归合并
console.log(targetObj.classMsg); // classMsg包含classNo、studentNo、rank
总结:
- 拷贝时,非对象属性冲突都会覆盖;
- 对象属性在深拷贝时,会递归合并,即属性不冲突时会合并,属性冲突时会覆盖;
- 对象属性在💰拷贝时,该对象属性会被直接覆盖,不会递归合并;
- 深浅拷贝针对的是对象属性而言;
2. 多库共存
原因:因为 ` 冲突;
目的:解决冲突;
方案:
- 使用 jQuery 来代替
$
; - 使用
$.noConflict()
或者jQuery.noConflict()
自定义前缀;
代码如下:
$(function(){
// 自定义名为$的函数
function $(ele){
return document.querySelector(ele)
}
console.log($("div"));
// 此时使用 $ 调用 jQuery 方法就会报错
// $.each()
// 方案一:使用 jQuery 代替 $
jQuery.each();
// 方案二:自定义前缀
var heheda = jQuery.noConflict()
console.log(heheda("div")[0]);
})