文章目录
- 一、jQuery 属性操作
- 1. 设置或获取元素固有属性 prop()
- 2. 设置或获取元素自定义属性 attr()
- 3. 数据缓存 data()
- 案例:购物车模块 — 全选
- 二、jQuery 内容文本值
- 1. 普通元素内容 html()
- 2. 普通元素文本内容 text()
- 3. 表单的值 val()
- 案例:购物车模块 — 增减商品数量
- 案例:购物车模块 — 修改商品小计
- 三、jQuery 元素操作
- 1. 遍历元素
- 案例:购物车模块 — 总计和总额
- 2. 创建元素
- 3. 添加元素
- 4. 删除元素
- 案例:购物车模块 — 删除商品
- 案例:购物车模块 — 选中商品添加背景颜色
- 四、jQuery 尺寸、位置操作
- 1. jQuery 尺寸
- 2. jQuery 位置
- 案例:电梯导航
一、jQuery 属性操作
1. 设置或获取元素固有属性 prop()
所谓元素固有属性就是元素本身自带的属性,比如 <a>
元素中的 href
属性;或者 <input>
元素里面的 type
。
介绍一下获取和设置元素的方法 prop()
。prop()
方法设置或返回被选元素的属性和值。当该方法用于返回属性值时,则返回第一个匹配元素的值。
- 获取属性
prop("属性")
当该方法用于返回属性值时,则返回第一个匹配元素的值。
- 设置属性
prop("属性","属性值")
当该方法用于设置属性值时,则为匹配元素集合设置一个或多个属性/值对。
- 示例
<a href="http://www.mi.com"></a>
<script>
$(function () {
console.log($("a").prop("href")); // http://www.mi.com/
$("a").prop("href", "http://www.huawei.com")
console.log($("a").prop("href")); // http://www.huawei.com/
})
</script>
注意: prop
方法只能用于获取元素固定的属性值,而不能获取自定义属性值。如下:
<div index="1"></div>
<script>
$(function () {
console.log($("div").prop("index")); // undefined
})
</script>
而要获取元素自定义属性值,可以通过下面的 attr()
方法。
2. 设置或获取元素自定义属性 attr()
attr()
方法设置或返回被选元素的属性值。
<div index="1"></div>
<script>
$(function () {
console.log($("div").attr("index")); // 1
})
</script>
- 获取属性
attr("属性");
类似于原生 JS 中 getAttribute()
。
- 设置属性
attr("属性","属性值");
类似于原生 JS 中 setAttribute()
。
- 有个问题
这样看,貌似 attr()
比 prop
功能更多、更方便啊,它们分别在什么场景下应用呢 ?
官方的建议:具有 true
和 false
两个属性的属性,如 checked
,selected
或者 disabled
使用 prop()
,其他的使用 attr()
。
看下区别:
3. 数据缓存 data()
data()
方法可以在指定的元素上存取数据或者从被选元素获取数据,并不会修改 DOM 元素结构。一旦页面刷新,之前存放的数据都将被移除。
- 附加数据
data("name", "value") // 向被选元素附加数据
- 获取数据
data("uname") // 向被选元素获取数据
- 示例
$("span").data("uname", "andy");
console.log($("span").data("uname")); // andy
此外,attr()
和 data()
方法都可以读取 HTML5 自定义属性 data-*
。下面先简单介绍一下 HTML5 自定义属性,再给出示例。
关于HTML5自定义属性说明可以查看此文档 HTML data-* 属性
data-*
属性用于存储私有页面后应用的自定义数据。data-*
属性可以在所有的 HTML 元素中嵌入数据。- 自定义的数据可以让页面拥有更好的交互体验(不需要使用 Ajax 或去服务端查询数据)。
data-*
属性由以下两部分组成:
属性名不要包含大写字母,在 data- 后必须至少有一个字符;
该属性可以是任何字符串。
可以在标签中直接设置自定义属性 data-age
,
<span id="test" data-age="21">test</span>
等同于 jQuery 中下面两种写法:
$("#test").data("age", "21");
$("#test").attr("data-age", "21");
案例:购物车模块 — 全选
几点说明
- 此案例只是实现了全选和取消全选功能,更多功能后文逐一实现。
- 代码中
.checkall
是全选按钮所属类,.j-checkbox
是单选按钮所属类。 - 可以利用
$(".j-checkbox:checked").length
来判断被选中小按钮个数。
jQuery
:checked
选择器
:checked
选择器选取所有选中的复选框或单选按钮。- 如此案例中
$(".j-checkbox:checked")
表示被选中的单选按钮
JS 代码如下:
$(function () {
// 全选 (checkall) 改变,状态赋给小按钮 (j-checked)
$(".checkall").change(function () {
$(".j-checkbox, .checkall").prop("checked", $(this).prop("checked"));
})
// 小按钮全被选中,则全选按钮也被选中
$(".j-checkbox").change(function () {
if ($(".j-checkbox:checked").length === $(".j-checkbox").length) { // <== 小按钮个数!!
$(".checkall").prop("checked", true);
} else {
$(".checkall").prop("checked", false);
}
})
})
二、jQuery 内容文本值
jQuery 内容文本值主要是针对 元素的内容 还有 表单的值 进行操作。
1. 普通元素内容 html()
jQuery 中 html()
相当于原生 JS 中的 innerHTML()
。
- 获取元素内容
$(selector).html()
- 设置元素内容
$(selector).html("内容")
- 示例
可以发现,打印结果包含文本内容(含换行)还有标签。那如果单纯想获得文本内容,可以利用下面的 text()
。
2. 普通元素文本内容 text()
jQuery 中 text()
相当于原生 JS 中的 innerText()
。
- 获取元素内容
- 设置元素值
3. 表单的值 val()
jQuery 中 val()
相当于原生 JS 中的 value
。
- 获取值
$(selector).val()
- 设置值
$(selector).val("内容")
- 示例
案例:购物车模块 — 增减商品数量
几点说明
- 部分 HTML 结构和类说明,如下图
- 注意商品数量最多减少到 0
JS 代码
// 点击 + 让新声明的变量 n++
$(".increment").click(function () {
var n = $(this).siblings(".itxt").val();
n++;
$(this).siblings(".itxt").val(n);
})
// 点击 - 让新声明的变量 n--
$(".decrement").click(function () {
var n = $(this).siblings(".itxt").val();
if (n == 1) return false;
n--;
$(this).siblings(".itxt").val(n);
})
案例:购物车模块 — 修改商品小计
几点说明
- 部分 HTML 结构和类说明,如下图
- 修改的是当前元素的
p-price
,即$(this).parent().parent().siblings(".p-price")
。不能直接对p-price
做修改,否则所有商品的小计都会被改动。
还有更简单的方法
parents()
parents()
获得当前匹配元素集合中每个元素的祖先元素,使用选择器进行筛选是可选的。- 因此上述代码可以用
$(this).parents(".p-num").siblings(".p-price")
来代替,写法更简单。
- 获得当前商品价格时,需要利用
substr(1)
截取字符串,将¥
符号截取掉。 -
(p * n).toFixed(2)
,将p*n
的计算结果保留两位小数。
JavaScript
toFixed()
方法 (原生 JS 方法)
- toFixed() 方法可把 Number 四舍五入为指定小数位数的数字。
NumberObject.toFixed(num)
- 还需考虑,如果用户直接修改表单值时,该如何处理?答:表单修改 (
chang
事件)时,小计及时改正。
其实还是有个 bug
- 如果修改成了负数,或者汉字,该怎么办?
- 京东实现时,限定了文本框只能输入正整数,这也是目前我没有解决的,即如何限定只能输入正整数(尚未解决)
- 姑且,利用正则将非正整数情况统一改为正整数 1
JS 代码
// 用户修改文本框
$(".itxt").change(function () {
var reg_n = /^[1-9]\d*$/;
// 获取文本框值
var n = $(this).val();
var p = $(this).parents(".p-num").siblings(".p-price").html();
p = p.substr(1);
if (!reg_n.test(n)) {
$(this).val(1); // 存在问题:改变为定值
alert('请输入1-200之间数值');
$(this).parents(".p-num").siblings(".p-sum").html("¥" + (p * 1).toFixed(2));
return false;
}
$(this).parents(".p-num").siblings(".p-sum").html("¥" + (p * n).toFixed(2));
})
三、jQuery 元素操作
主要讲述 jQuery 中遍历、创建、添加、删除元素的操作。
1. 遍历元素
我们知道,隐式迭代可以对同一类元素做同样的操作,可如果想对同一类元素进行不同操作,就需要用到此处的 jQuery 遍历方法。
each()
方法
each()
方法规定为每个匹配元素规定运行的函数。其实,也就是通过循环,每次获取元素索引,然后进行当前循环的操作。此外,返回 false
可用于及早停止循环。
$(selector).each(function (index,element) { })
-
each()
方法遍历匹配的每一个元素。主要用 DOM 处理。 - 里面的回调函数有 2 个参数:
index
是每个元素的索引;element
是索引对应元素。 - 注意获取的元素是 DOM 元素对象,而不是 jQuery 对象,不能直接用 jQuery 方法对其操作,需要转换,即
$(element)
- 示例一
- 示例二
<div>1</div>
<div>2</div>
<div>3</div>
<script>
$(function () {
var sum = 0;
$("div").each(function (index, element) {
sum += parseInt($(element).text());
})
console.log(sum); // 6
})
</script>
$.each()
方法
$.each()
方法可用于遍历任何对象。主要用于处理数据,比如处理数组、对象。
$.each(object, function (index,element) { })
- 函数的两个参数:
index
:元素索引;element
遍历的内容。 - 当 object 为对象时,
index
对应属性名,element
对应属性值。
案例:购物车模块 — 总计和总额
定义一个计算总额和总件数的函数 getSum()
,每次进行 +
、-
、改变表单值、勾选商品时就对此函数调用。注意,在页面初始化时要先调用此函数,初始化件数和总价。
底侧 HTML 结构如下
// 首次打开页面时就调用
getSum();
// 总计和总额
function getSum() {
var count = 0; // 总件数
var money = 0; // 总额
$(".itxt").each(function (i, ele) {
if ($(".j-checkbox").eq(i).prop("checked")) {
count += parseInt($(ele).val());
}
});
$(".amount-sum em").text(count);
$(".p-sum").each(function (i, ele) {
if ($(".j-checkbox").eq(i).prop("checked")) {
money += parseFloat($(ele).text().substr(1));
}
});
$(".price-sum em").text("¥" + money.toFixed(2));
}
2. 创建元素
如下代码,动态创建一个 <li>
标签
$("<li></li>")
但是如果只是将标签创建出来是没什么用的,还要将标签添加至 HTML 结构中。
3. 添加元素
- 内部添加
element.append("内容")
注意: 此方法是将内容放在匹配元素的最后,类似于原生 JS 的 appendChild()
。
如果我想添加到匹配元素最前面呢?可以使用 prepend()
。
element.prepend("内容")
- 示例
和上节创建元素的方法配合起来,就有了下面效果
- 外部添加
element.after("内容") // 把内容放入目标元素后面
element.before("内容") // 把内容放入目标元素前面
- 示例
总的来说,内部添加元素:生成后,是父子关系;外部添加元素:生成后,是兄弟关系。
4. 删除元素
三种方法,但各有千秋。前一种相当于是把自己删除了,而后两种是把自己的孩子删除。
element.remove() // 删除匹配元素本身
element.empty() // 删除匹配的元素集合中所有的子节点
element.html("") // 清空匹配的元素内容
案例:购物车模块 — 删除商品
几点说明
-
.cart-item
是单样商品所在的顶层盒子 .remove-batch
和.clear-all
在 HTML 结构中关系如下图- 注意每次操作后,要计算总件数、总价
// 1.商品后面删除按钮
$(".p-action a").click(function () {
$(this).parents(".cart-item").remove();
getSum();
});
// 2.选中的商品
$(".remove-batch").click(function () {
$(".j-checkbox:checked").parents(".cart-item").remove();
getSum();
});
// 3.清理购物车
$(".clear-all").click(function () {
$(".cart-item").remove();
getSum();
})
案例:购物车模块 — 选中商品添加背景颜色
几点说明
- 设置背景类
.check-cart-item
- 当选中时,
addClass
添加此类;否则,removeClass
移除此类
全选按钮改变时,所有商品背景都会变化,代码如下:
if ($(this).prop("checked")) {
$(".cart-item").addClass("check-cart-item");
} else {
$(".cart-item").removeClass("check-cart-item");
}
单选按钮改变时,只改变当前商品背景
if ($(this).prop("checked")) {
$(this).parents(".cart-item").addClass("check-cart-item");
} else {
$(this).parents(".cart-item").removeClass("check-cart-item");
}
四、jQuery 尺寸、位置操作
1. jQuery 尺寸
- 以上参数为空,则是获取相应值,返回的是数字型
- 如果参数为数字,则是修改相应值
- 参数可以不必写单位
2. jQuery 位置
jQuery 关于位置主要有三个方法:offset()
、scrollTop() / scrollLeft()
- offset() 设置或获取元素偏移
$("div").offset({
top: 200,
left: 200
});
console.log($("div").offset()); // {top: 200, left: 200}
-
offset()
方法设置或返回被选元素 相对于文档 - 该方法有 2 个属性
left
、top
。offset().top
用于获取距离文档顶部距离,offset().left
用于获取距离文档左侧的距离
- position() 获取元素偏移
- position() 方法用于返回被选元素 相对于带有定位的父级
- 此方法只能用于获取偏移,而不能进行设置偏移
- scrollTop() / scrollLeft() 设置或获取元素被卷去的头部和左侧
- scrollTop()
$(selector).scrollTop() // 返回垂直滚动条位置
$(selector).scrollTop(position) // 设置垂直滚动条位置
- scrollLeft()
$(selector).scrollLeft() // 返回水平滚动条位置
$(selector).scrollLeft(position) // 设置水平滚动条位置
案例:电梯导航
几点说明
.recommend
为推荐模块所含的类,当滚动到此位置时,使用fadeIn()
fadeOut()
实现左侧电梯导航淡入淡出效果。- 利用
animate
函数实现动画滚动,设置其参数scrollTop
值指定滚动位置。注意做动画的元素是$("body,html")
。 - 搞清楚节流阀(互斥锁)的应用原理,见文末。
$(function () {
// 节流阀、互斥锁
var flag = true;
// 获取推荐模块距离页面顶部距离
var toolTop = $(".recommend").offset().top;
toggleTool();
function toggleTool() {
if ($(document).scrollTop() >= toolTop) {
$(".fixedtool").fadeIn();
} else {
$(".fixedtool").fadeOut();
}
}
$(window).scroll(function () {
toggleTool();
if (flag) {
$(".floor .w").each(function (i, ele) {
// 滚动到某区域,当前区域对应的导航变色
if ($(document).scrollTop() >= $(ele).offset().top) {
console.log(i);
$(".fixedtool li").eq(i).addClass("current").siblings().removeClass();
}
})
}
})
// 滚动到指定模块
$(".fixedtool li").click(function () {
flag = false;
// 对应索引的盒子
var current = $(".floor .w").eq($(this).index()).offset().top;
// 页面动画
$("body, html").stop().animate({
scrollTop: current
}, function () {
flag = true;
})
// 点击后变色
$(this).addClass("current").siblings().removeClass();
})
})
有个小 bug ,虽然代码中已经解决,还是强调一下。当点击左侧导航栏时,页面会进行滚动,因此会不断触发 $(window).scroll(function () {}
事件,出现下面效果:
而代码中采取的解决方式是 节流阀,也就是 互斥锁 。设置全局变量 flag 当点击导航栏时,将滚动事件内容上锁,即 flag = false
。当点击事件结束时,可以调用动画函数 animate
里的回调函数,重新设置 flag = true
。