jQuery2 高级教程(三)
八、操纵元素
在这一章中,我将向您展示如何使用 jQuery 操作元素,包括如何获取和设置属性,如何使用 jQuery 方便的方法处理类和 CSS 属性,以及如何获取和设置 HTML 和文本内容。我还向您展示了一个很好的特性,它允许您将数据与元素相关联。表 8-1 对本章进行了总结。
表 8-1 。章节总结
| 问题 | 解决办法 | 列表 |
|---|---|---|
从jQuery对象中的第一个元素获取属性值 | 使用attr方法 | one |
从jQuery对象中的每个元素获取属性值 | 一起使用each和attr方法 | Two |
为jQuery对象中的所有元素设置属性 | 使用attr方法,可以选择使用函数 | three |
| 在一次操作中设置多个属性 | 对地图对象使用attr方法 | 4, 5 |
| 取消设置属性 | 使用removeAttr方法 | six |
获取或设置由HTMLElement对象定义的属性 | 使用与attr方法相对应的prop | seven |
| 控制元素所属的类 | 使用addClass、hasClass和removeClass方法,可以选择使用函数 | 8–10 |
| 切换元素所属的类 | 使用toggleClass方法 | 11–16 |
设置style属性的内容 | 使用css方法 | 17–21 |
| 获取元素位置的详细信息 | 使用 CSS 属性特定的方法 | 22–24 |
| 获取或设置元素的文本或 HTML 内容 | 使用text或html方法 | 25–27 |
| 获取或设置表单元素的值 | 使用val方法 | 28–30 |
| 将数据与元素相关联 | 使用data方法 | Thirty-one |
自上一版以来,JQUERY 发生了变化
jQuery 1.9/2.0 引入了一个新版本的css方法,它允许获取多个 CSS 属性的值——详见“获取多个 CSS 属性”一节。
jQuery 1.9/2.0 还强制分离了attr和prop方法的角色。在早期版本中,jQuery 允许用户使用attr方法,而为了保持与 1.6 之前版本的向后兼容性,应该使用prop方法,而 1.6 之前的版本是添加了prop方法。
最后一个变化是 jQuery 的当前版本允许使用attr方法来设置input元素上的type属性值,前提是浏览器支持。小心使用这个特性,因为如果浏览器不支持它,jQuery 将抛出一个异常,这包括旧版本的 Internet Explorer。我的建议是,当你需要不同类型的input元素时,替换元素,完全避免这个问题。
使用属性和属性
您可以获取并设置jQuery对象中元素的属性值。表 8-2 显示了与属性相关的方法。
表 8-2 。使用属性的方法
| 方法 | 描述 |
|---|---|
attr(name) | 为jQuery对象中的第一个元素获取具有指定名称的属性值 |
attr(name, value) | 将具有指定名称的属性值设置为jQuery对象中所有元素的指定值 |
attr(map) | 为jQuery对象中的所有元素设置在地图对象中指定的属性 |
attr(name, function) | 使用函数为jQuery对象中的所有元素设置指定的属性 |
removeAttr(name) removeAttr(name[]) | 从jQuery对象的所有元素中删除属性 |
prop(name) | 返回jQuery对象中第一个元素的指定属性值 |
prop(name, value) prop(map) | 为jQuery对象中的所有元素设置一个或多个属性值 |
prop(name, function) | 使用函数为jQuery对象中的所有元素设置指定属性的值 |
removeProp(name) | 从jQuery对象的所有元素中删除指定的属性 |
当用单个参数调用attr方法时,jQuery 从选择中的第一个元素返回指定属性的值。清单 8-1 包含了一个演示。
清单 8-1 。读取属性的值
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
<script src="jquery-2.0.2.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="styles.css"/>
<script type="text/javascript">
$(document).ready(function() {
var srcValue = $("img").attr("src");
console.log("Attribute value: " + srcValue);
});
</script>
</head>
<body>
<h1>Jacqui's Flower Shop</h1>
<form method="post">
<div id="oblock">
<div class="dtable">
<div id="row1" class="drow">
<div class="dcell">
<img src="aster.png"/><label for="aster">Aster:</label>
<input name="aster" value="0" required />
</div>
<div class="dcell">
<img src="daffodil.png"/><label for="daffodil">Daffodil:</label>
<input name="daffodil" value="0" required />
</div>
<div class="dcell">
<img src="rose.png"/><label for="rose">Rose:</label>
<input name="rose" value="0" required />
</div>
</div>
<div id="row2"class="drow">
<div class="dcell">
<img src="peony.png"/><label for="peony">Peony:</label>
<input name="peony" value="0" required />
</div>
<div class="dcell">
<img src="primula.png"/><label for="primula">Primula:</label>
<input name="primula" value="0" required />
</div>
<div class="dcell">
<img src="snowdrop.png"/><label for="snowdrop">Snowdrop:</label>
<input name="snowdrop" value="0" required />
</div>
</div>
</div>
</div>
<div id="buttonDiv"><button type="submit">Place Order</button></div>
</form>
</body>
</html>
在这个脚本中,我选择了文档中所有的img元素,然后使用attr方法获取src属性的值。当您读取属性值时,attr方法的结果是一个字符串,我将它写到控制台。该脚本的控制台输出如下:
Attribute value: aster.png
each方法可以与attr结合使用,读取 jQuery 对象中所有元素的属性值。我在第五章中描述了each方法,而清单 8-2 展示了你如何在这种情况下使用它。
清单 8-2 。使用 each 和 attr 方法从多个对象读取属性值
...
<script type="text/javascript">
$(document).ready(function() {
$("img").each(function(index, elem) {
var srcValue = $(elem).attr("src");
console.log("Attribute value: " + srcValue);
});
});
</script>
...
在这个脚本中,我将HTMLElement对象作为参数传递给函数,通过$函数创建一个新的jQuery对象。该对象只包含一个元素,非常适合于attr方法。该脚本的控制台输出如下:
Attribute value: aster.png
Attribute value: daffodil.png
Attribute value: rose.png
Attribute value: peony.png
Attribute value: primula.png
Attribute value: snowdrop.png
设置一个属性值
当attr方法被用来设置一个属性值时,这个改变被应用到jQuery对象中所有元素的中。这与该方法的 read 版本形成对比,后者只从第一个元素返回一个值。清单 8-3 展示了如何设置一个属性。
清单 8-3 。设置属性
...
<script type="text/javascript">
$(document).ready(function() {
$("img").attr("src", "lily.png");
});
</script>
...
提示当设置一个值时,
attr方法返回一个 jQuery 对象,这意味着你可以执行方法链接。
我选择了所有的img元素,并将src属性的值设置为lily.png。该值应用于所有选中元素的src属性,您可以在图 8-1 中看到效果。
图 8-1 。为多个元素设置相同的属性值
设置多个属性
通过向attr方法传递一个对象,可以在一个方法调用中设置多个属性。该对象的属性被解释为属性名,属性值将被用作属性值。这就是所谓的地图对象??。清单 8-4 提供了一个演示。
清单 8-4 。使用地图对象设置多个元素
...
<script type="text/javascript">
$(document).ready(function() {
var attrValues = {
src: "lily.png",
style: "border: thick solid red"
};
$("img").attr(attrValues);
});
</script>
...
在这个脚本中,我创建了一个 map 对象,它具有名为src和style的属性。我选择文档中的img元素,并将地图对象传递给attr值。你可以在图 8-2 中看到效果。
图 8-2 。使用 attr 方法设置多个属性
提示虽然我已经在这个例子中明确设置了
style属性,但是 jQuery 提供了一些简化 CSS 工作的方法。有关详细信息,请参见“使用 CSS”一节。
动态设置属性值
您可以通过向attr方法传递一个函数来定制分配给属性的值。清单 8-5 提供了一个演示。
清单 8-5 。使用函数设置属性值
...
<script type="text/javascript">
$(document).ready(function() {
$("img").attr("src", function(index, oldVal) {
if (oldVal.indexOf("rose") > -1) {
return "lily.png";
} else if ($(this).closest("#row2").length > 0) {
return "carnation.png";
}
});
});
</script>
...
传递给该函数的参数是正在处理的元素的索引和旧属性值。将this变量设置为正在处理的HTMLElement。如果你想改变属性,那么你的函数必须返回一个包含新值的字符串。如果没有返回结果,则使用现有值。在清单 8-5 中,我使用函数有选择地改变img元素显示的图像。你可以在图 8-3 中看到效果。
图 8-3 。使用函数更改属性值
删除属性
你可以通过使用removeAttr方法删除(取消设置)属性,如清单 8-6 所示。
清单 8-6 。删除属性值
...
<script type="text/javascript">
$(document).ready(function() {
$("img").attr("style", "border: thick solid red");
$("img:odd").removeAttr("style");
});
</script>
...
我使用attr方法设置style属性,然后使用removeAttr方法从奇数编号的元素中删除相同的属性。你可以在图 8-4 中看到效果。
图 8-4 。从元素中移除属性
使用属性
对于每种形式的attr方法,都有相应的prop方法。不同之处在于,prop方法处理由HTMLElement对象定义的属性,而不是属性值。通常,属性和特性是相同的,但情况并非总是如此。一个简单的例子是class属性,它使用className属性在HTMLElement对象中表示。清单 8-7 显示了使用prop方法来读取这个属性。
清单 8-7 。使用 prop 方法读取属性值
...
<script type="text/javascript">
$(document).ready(function() {
$("*[class]").each(function(index, elem) {
console.log("Element:" + elem.tagName + " " + $(elem).prop("className"));
});
});
</script>
...
在这个例子中,我选择了所有具有class属性的元素,并使用each方法来枚举它们。对于每个元素,我打印出type和className属性的值,产生以下控制台输出:
Element:DIV dtable
Element:DIV drow
Element:DIV dcell
Element:DIV dcell
Element:DIV dcell
Element:DIV drow
Element:DIV dcell
Element:DIV dcell
Element:DIV dcell
使用类
虽然您可以使用通用的属性方法来管理类,但是 jQuery 提供了一组更方便的方法。表 8-3 描述了这些方法。HTML 文档中类最常见的用途是让浏览器应用一组在style元素中定义的 CSS 属性。详见第七章。
表 8-3 。使用类的方法
| 方法 | 描述 |
|---|---|
addClass(name name) | 将jQuery对象中的所有元素添加到指定的类中 |
addClass(function) | 将jQuery对象中的元素动态分配给类 |
hasClass(name) | 如果jQuery对象中至少有一个元素是指定类的成员,则返回true |
removeClass(name name) | 从指定的类中移除jQuery对象中的元素 |
removeClass(function) | 从类中动态移除jQuery对象中的元素 |
toggleClass() | 切换jQuery对象中的元素所属的所有类 |
toggleClass(boolean) | 在一个方向上切换jQuery对象中的元素所属的所有类 |
toggleClass(name) toggleClass(name name) | 为jQuery对象中的所有元素切换一个或多个命名类 |
toggleClass(name, boolean) | 单向切换jQuery对象中所有元素的命名类 |
toggleClass(function, boolean) | 动态切换一个jQuery对象中所有元素的类 |
可以使用addClass方法 将元素分配给类,使用removeClass方法从类中移除元素,并使用hasClass方法确定元素是否属于某个类。清单 8-8 展示了所有三种正在使用的方法。
清单 8-8 。添加、移除和测试类成员资格
...
<style type="text/css">
img.redBorder {border: thick solid red}
img.blueBorder {border: thick solid blue}
</style>
<script type="text/javascript">
$(document).ready(function() {
$("img").addClass("redBorder");
$("img:even").removeClass("redBorder").addClass("blueBorder");
console.log("All elements: " + $("img").hasClass("redBorder"));
$("img").each(function(index, elem) {
console.log("Element: " + $(elem).hasClass("redBorder") + " " + elem.src);
});
});
</script>
...
首先,我使用了一个style元素来定义两种基于类成员的样式。不一定要用类来管理 CSS,但是它们使得本章中演示变化的效果更加容易。
我选择文档中所有的img元素,并使用addClass方法将它们分配给redBorder类。然后我选择偶数编号的img元素,将它们从redBorder类中移除,并使用removeClass方法将它们分配给blueBorder类。
提示
addClass方法不会从元素中移除任何现有的类;它只是在已经应用的类之外添加了新的类。
最后,我使用hasClass方法来测试所有img元素集合上的redBorder类(如果至少有一个元素是该类的成员,则返回true)和每个元素。你可以在图 8-5 中看到类成员的效果。
图 8-5 。通过类成员关系应用样式
我测试类成员的脚本输出如下:
All elements: true
Element: falsehttp://www.jacquisflowershop.com/jquery/aster.png
Element: truehttp://www.jacquisflowershop.com/jquery/daffodil.png
Element: falsehttp://www.jacquisflowershop.com/jquery/rose.png
Element: truehttp://www.jacquisflowershop.com/jquery/peony.png
Element: falsehttp://www.jacquisflowershop.com/jquery/primula.png
Element: truehttp://www.jacquisflowershop.com/jquery/snowdrop.png
使用函数添加和移除类
通过向addClass或removeClass方法传递一个函数,您可以动态地决定应该从一组元素中添加或删除哪些类。清单 8-9 展示了使用addClass方法的函数。
清单 8-9 。将 addClass 方法与函数一起使用
...
<style type="text/css">
img.redBorder {border: thick solid red}
img.blueBorder {border: thick solid blue}
</style>
<script type="text/javascript">
$(document).ready(function() {
$("img").addClass(function(index, currentClasses) {
if (index % 2 == 0) {
return "blueBorder";
} else {
return "redBorder";
}
});
});
</script>
...
该函数的参数是元素的索引和该元素所属的当前类集。对于类似的函数,jQuery 将变量this设置为正在处理的元素的HTMLElement对象。您返回希望元素加入的类。在这个例子中,我使用了index参数为blueBorder或redBorder类分配替换元素。效果与图 8-5 中所示的效果相同。
您可以采用类似的方法从类中移除元素。你传递一个函数给removeClass方法,如清单 8-10 所示。
清单 8-10 。使用函数从类中移除元素
...
<style type="text/css">
img.redBorder {border: thick solid red}
img.blueBorder {border: thick solid blue}
</style>
<script type="text/javascript">
$(document).ready(function() {
$("img").filter(":odd").addClass("redBorder").end()
.filter(":even").addClass("blueBorder");
$("img").removeClass(function(index, currentClasses) {
if ($(this).closest("#row2").length > 0
&¤tClasses.indexOf("redBorder") > -1) {
return "redBorder";
} else {
return "";
}
});
});
</script>
...
在这个脚本中,我传递给removeClass方法的function使用HTMLElement对象和当前的一组类从任何作为成员的img元素中删除redBorder类,该元素是 ID 为row2的元素的后代。你可以在图 8-6 中看到这个脚本的效果。
图 8-6 。使用函数删除类
提示注意,当我不想删除任何类时,我返回空字符串。如果不返回值,jQuery 将从元素中移除所有的类。
切换类别
在最基本的形式中,切换一个类意味着将它添加到任何不是成员的元素中,并从任何是成员的元素中移除它。你可以通过将你想要切换的类名传递给toggleClass方法来达到这个效果,如清单 8-11 所示。
清单 8-11 。使用 toggleClass 方法
...
<style type="text/css">
img.redBorder {border: thick solid red}
img.blueBorder {border: thick solid blue}
</style>
<script type="text/javascript">
$(document).ready(function() {
$("img").filter(":odd").addClass("redBorder").end()
.filter(":even").addClass("blueBorder");
$("<button>Toggle</button>").appendTo("#buttonDiv").click(doToggle);
function doToggle(e) {
$("img").toggleClass("redBorder");
e.preventDefault();
};
});
</script>
...
我通过将redBorder类应用于奇数编号的img元素并将blueBorder类应用于偶数编号的元素来开始这个脚本。然后我创建了一个button元素,并将其添加到id为buttonDiv的元素中。这将我的新button放在已经在页面上的旁边。我已经使用了click方法来指定当用户单击button时 jQuery 将调用的函数。这是 jQuery 对事件支持的一部分,我在第九章中有完整的描述。
点击按钮时执行的功能称为doToggle ,关键语句为
...
$("img").toggleClass("redBorder");
...
该语句选择文档中所有的img元素,并切换redBorder类。函数的参数和对preventDefault方法的调用在本章中并不重要,我会在第九章的中解释它们。你可以在图 8-7 中看到这个脚本的效果,尽管这种例子在你将文档加载到浏览器中并自己点击button时最有意义。
图 8-7 。使用 toggleClass 方法切换类成员身份
如果你特别善于观察,你会注意到图中有些奇怪的地方。那些有红色边框的元素已经没有了,但是以蓝色边框开始的元素仍然有蓝色边框。正如所料,jQuery 从奇数编号的img元素中移除了redBorder类,并将其添加到偶数编号的元素中,但是添加了redBorder类的元素也是blueBorder的成员。在style元素中的redBorder之后定义了blueBorder样式,这意味着它的属性值具有更高的优先级,正如我在第三章中解释的那样。因此,类切换是有效的,但是你也必须考虑 CSS 的微妙之处。如果你想让红色边框显示出来,那么你可以颠倒样式的声明顺序,如清单 8-12 所示。
清单 8-12 。匹配样式声明以适应类切换
...
<style type="text/css">
img.blueBorder {border: thick solid blue}
img.redBorder {border: thick solid red}
</style>
<script type="text/javascript">
$(document).ready(function() {
$("img").filter(":odd").addClass("redBorder").end()
.filter(":even").addClass("blueBorder");
$("<button>Toggle</button>").appendTo("#buttonDiv").click(doToggle);
function doToggle(e) {
$("img").toggleClass("redBorder");
e.preventDefault();
};
});
</script>
...
现在,当一个元素同时属于blueBorder和redBorder类时,浏览器将使用border属性的redBorder设置。你可以在图 8-8 中看到这种变化的效果。
图 8-8 。协调 CSS 声明顺序和类切换的效果
切换多个类别
您可以向toggleClass方法提供多个类名称,用空格分隔,每个名称将为所选元素切换。清单 8-13 显示了一个例子。
清单 8-13 。切换多个类别
...
<style type="text/css">
img.blueBorder {border: thick solid blue}
img.redBorder {border: thick solid red}
</style>
<script type="text/javascript">
$(document).ready(function() {
$("img").filter(":odd").addClass("redBorder").end()
.filter(":even").addClass("blueBorder");
$("<button>Toggle</button>").appendTo("#buttonDiv").click(doToggle);
function doToggle(e) {
$("img").toggleClass("redBorder blueBorder");
e.preventDefault();
};
});
</script>
...
在这个例子中,我在所有的img元素上切换了redBorder和blueBorder类。你可以在图 8-9 中看到效果。
图 8-9 。切换多个元素
切换所有类别
您可以通过不带参数调用toggleClass方法来切换一组元素所属的所有类。这是一项巧妙的技术,因为 jQuery 存储了已经切换的类,因此它们可以被正确地应用和删除。清单 8-14 包含了一个使用该方法的例子。
清单 8-14 。切换选定元素的所有类别
...
<style type="text/css">
img.blueBorder {border: thick solid blue}
img.redBorder {border: thick solid red}
label.bigFont {font-size: 1.5em}
</style>
<script type="text/javascript">
$(document).ready(function() {
$("img").filter(":odd").addClass("redBorder").end()
.filter(":even").addClass("blueBorder");
$("label").addClass("bigFont");
$("<button>Toggle</button>").appendTo("#buttonDiv").click(doToggle);
function doToggle(e) {
$("img, label").toggleClass();
e.preventDefault();
};
});
</script>
...
在这个例子中,我使用了addClass方法向img和label元素添加类。当点击Toggle按钮时,我选择这些相同的元素,并不带任何参数地调用toggleClass方法。你得到一个特定的效果,如图图 8-10 所示。
图 8-10 。切换元素的所有类
当您第一次单击该按钮时,选定元素的所有类都被关闭。jQuery 会记下哪些类被删除,以便在您再次单击按钮时可以重新应用它们。
向一个方向切换类别
您可以通过向toggleClass方法传递一个boolean参数来限制切换的执行方式。如果你通过了false,等级只会被移除,如果你通过了true,等级只会被增加。清单 8-15 给出了一个例子。
清单 8-15 。限制切换方向
...
<style type="text/css">
img.blueBorder {border: thick solid blue}
img.redBorder {border: thick solid red}
</style>
<script type="text/javascript">
$(document).ready(function() {
$("img").filter(":odd").addClass("redBorder").end()
.filter(":even").addClass("blueBorder");
$("<button>Toggle On</button>").appendTo("#buttonDiv").click(doToggleOn);
$("<button>Toggle Off</button>").appendTo("#buttonDiv").click(doToggleOff);
function doToggleOff(e) {
$("img, label").toggleClass("redBorder", false);
e.preventDefault();
};
function doToggleOn(e) {
$("img, label").toggleClass("redBorder", true);
e.preventDefault();
};
});
</script>
...
我在文档中添加了两个button元素,每个元素将只在一个方向上切换redBorder类。一旦其中一个button元素被点击,它将没有进一步的影响,直到另一个button也被点击(因为每个button只在一个方向切换类)。你可以在图 8-11 中看到效果。
图 8-11 。单向切换类别
动态切换类别
您可以通过向toggleClass方法传递一个函数来决定应该为元素动态地切换哪些类。清单 8-16 提供了一个简单的演示。
清单 8-16 。用函数切换类
...
<style type="text/css">
img.blueBorder {border: thick solid blue}
img.redBorder {border: thick solid red}
</style>
<script type="text/javascript">
$(document).ready(function() {
$("img").addClass("blueBorder");
$("img:even").addClass("redBorder");
$("<button>Toggle</button>").appendTo("#buttonDiv").click(doToggle);
function doToggle(e) {
$("img").toggleClass(function(index, currentClasses) {
if (index % 2 == 0) {
return "redBorder";
} else {
return "";
}
});
e.preventDefault();
};
});
</script>
...
我将blueBorder类应用于所有的img元素,将redBorder类应用于偶数的img元素。该函数的参数是您正在处理的元素的索引和它所属的当前类集。此外,this变量被设置为当前元素的HTMLElement对象。该函数的结果是应该切换的类的名称。如果您不想切换元素的任何类,那么您返回空字符串(不返回元素的结果将切换它的所有类)。你可以在图 8-12 中看到清单创建的效果。
图 8-12 。动态切换类别
使用 CSS
在前面的例子中,我使用了基本的属性方法来设置style属性的值,以定义一组元素的 CSS 属性值。jQuery 提供了一组便利的元素,使得处理 CSS 更加容易。表 8-4 描述了这些方法中最广泛使用的css
表 8-4 。css 方法
| 方法 | 描述 |
|---|---|
css(name) | 从jQuery对象中的第一个元素获取指定属性的值 |
css(names) | 获取多个 CSS 属性的值,以数组形式表示 |
css(name, value) | 设置jQuery对象中所有元素的特定属性值 |
css(map) | 使用地图对象为jQuery对象中的所有元素设置多个属性 |
css(name, function) | 使用函数为jQuery对象中的所有元素设置指定属性的值 |
提示这些方法操作单个元素的
style属性。如果你想使用在一个style元素中定义的样式,那么你应该使用本章前面描述的与类相关的方法。
获取和设置单个 CSS 值
要读取 CSS 属性的值,需要将属性名传递给css方法。您收到的只是来自jQuery对象中第一个元素的值。但是,当您设置属性时,更改将应用于所有元素。清单 8-17 展示了css属性的基本用法。
清单 8-17 。使用 css 方法获取和设置 CSS 属性值
...
<script type="text/javascript">
$(document).ready(function() {
var sizeVal = $("label").css("font-size");
console.log("Size: " + sizeVal);
$("label").css("font-size", "1.5em");
});
</script>
...
提示虽然我使用了实际的属性名(
font-size)而不是由HTMLElement对象(fontSize)定义的 camel-case 属性名,但是 jQuery 很高兴两者都支持。
在这个脚本中,我选择了所有的label元素,并使用css方法获取font-size属性的值,并将其写入控制台。然后,我再次选择所有的label元素,并对它们应用相同属性的新值。
该脚本的输出如下:
Size: 16px
提示将属性设置为空字符串(
"")具有从元素的style属性中移除属性的效果。
获取多个 CSS 属性
通过向css方法传递一个属性名数组,可以获得多个 CSS 属性的值。此方法返回一个对象,该对象具有数组中每个名称的属性,并且该对象中每个属性的值被设置为所选内容中第一个元素的相应 CSS 属性的值。在清单 8-18 的中,您可以看到我是如何使用css方法来获取三个 CSS 属性的值的。
清单 8-18 。使用 css 方法获取多个 CSS 属性值
...
<script type="text/javascript">
$(document).ready(function () {
var propertyNames = ["font-size", "color", "border"];
var cssValues = $("label").css(propertyNames);
for (var i = 0; i < propertyNames.length; i++) {
console.log("Property: " + propertyNames[i]
+ " Value: " + cssValues[propertyNames[i]]);
}
});
</script>
...
注这个版本的
css方法是在 jQuery 1.9/2.0 中引入的。
我创建了一个数组,包含我感兴趣的三个 CSS 属性的名称:font - size、color和border。我将这个数组传递给css方法,并接收一个包含我想要的值的对象。该目标可以表示如下:
{font-size: "16px", color: "rgb(0, 0, 0)", border: "0px none rgb(0, 0, 0)"}
为了处理对象,我遍历属性名数组并读取相应的属性值,产生以下控制台输出:
Property: font-size Value: 16px
Property: color Value: rgb(0, 0, 0)
Property: border Value: 0px none rgb(0, 0, 0)
设置多个 CSS 属性
您可以用两种不同的方式设置多个属性。第一种是简单地通过链接对css方法的调用,如清单 8-19 所示。
清单 8-19 。链接对 css 方法的调用
...
<script type="text/javascript">
$(document).ready(function() {
$("label").css("font-size", "1.5em").css("color", "blue");
});
</script>
...
在这个脚本中,我设置了font-size和color属性的值。你可以使用一个地图对象达到同样的效果,如清单 8-20 所示。map 对象遵循与我在前面部分中使用css方法获取多个属性值时收到的对象相同的模式。
清单 8-20 。使用地图对象设置多个值
...
<script type="text/javascript">
$(document).ready(function() {
var cssVals = {
"font-size": "1.5em",
"color": "blue"
};
$("label").css(cssVals);
});
</script>
...
这两个脚本都创建了如图 8-13 所示的效果。
图 8-13 。设置多个属性
设置相对值
css方法可以接受相对值,这些值是以+=或-=为前缀的数值,可以在当前值上加或减。这项技术只能用于以数字单位表示的 CSS 属性。清单 8-21 展示了。
清单 8-21 。在 css 方法中使用相对值
...
<script type="text/javascript">
$(document).ready(function() {
$("label:odd").css("font-size", "+=5")
$("label:even").css("font-size", "-=5")
});
</script>
...
这些值被假定为与读取属性值时返回的单位相同。在这种情况下,我将奇数编号的label元素的字体大小增加了 5 个像素,并将偶数编号的label元素的字体大小减少了相同的量。你可以在图 8-14 中看到效果。
图 8-14 。使用相对值
使用函数设置属性
你可以通过向css方法传递一个函数来动态设置属性值,如清单 8-22 所示。传递给函数的参数是元素的索引和属性的当前值。将元素的this变量设置为HTMLElement对象,然后返回想要设置的值。
清单 8-22 。用函数设置 CSS 值
...
<script type="text/javascript">
$(document).ready(function() {
$("label").css("border", function(index, currentValue) {
if ($(this).closest("#row1").length > 0) {
return "thick solid red";
} else if (index % 2 == 1) {
return "thick double blue";
}
});
});
</script>
...
你可以在图 8-15 中看到这个脚本的效果。
图 8-15 。用函数设置 CSS 属性值
使用特定于属性的 CSS 便利方法
除了css方法之外,jQuery 还定义了许多方法,可以用来获取或设置常用的 CSS 属性以及从中派生的信息。表 8-5 描述了这些方法。
表 8-5 。使用特定 CSS 属性的方法
| 方法 | 描述 |
|---|---|
height() | 获取jQuery对象中第一个元素的高度,以像素为单位 |
height(value) | 设置jQuery对象中所有元素的高度 |
innerHeight() | 获取jQuery对象中第一个元素的内部高度(这是包括填充但不包括边框和边距的高度) |
innerWidth() | 获取jQuery对象中第一个元素的内部宽度(这是包括填充但不包括边框和边距的宽度) |
offset() | 返回jQuery对象中第一个元素相对于文档的坐标 |
outerHeight(boolean) | 获取jQuery对象中第一个元素的高度,包括填充和边框;该参数确定是否包括边距 |
outerWidth(boolean) | 获取jQuery对象中第一个元素的宽度,包括填充和边框;该参数确定是否包括边距 |
position() | 返回jQuery对象中第一个元素相对于偏移量的坐标 |
scrollLeft() scrollTop() | 获取jQuery对象中第一个元素的水平或垂直位置 |
scrollLeft(value) scrollTop(value) | 设置jQuery对象中所有元素的水平或垂直位置 |
width() | 获取jQuery对象中第一个元素的宽度 |
width(value) | 设置jQuery对象中所有元素的宽度 |
height(function) width(function) | 使用函数设置jQuery对象中所有元素的宽度或高度 |
这些方法中的大多数是不言而喻的,但是有几个值得解释。来自offset和position方法的结果是一个具有top和left属性的对象,指示元素的位置。清单 8-23 提供了一个使用position方法 的演示。
清单 8-23 。使用位置方法
...
<script type="text/javascript">
$(document).ready(function() {
var pos = $("img").position();
console.log("Position top: " + pos.top + " left: " + pos.left);
});
</script>
...
此脚本写出方法返回的对象的 top 和 left 属性值。结果如下:
Position top: 108.078125 left: 18
使用函数设置宽度和高度
您可以通过向width或height方法传递一个函数来动态设置一组元素的宽度和高度。此方法的参数是元素的索引和当前属性值。正如您现在所期望的,变量this被设置为当前元素的HTMLElement,您返回您想要赋值的值。清单 8-24 提供了一个例子。
清单 8-24 。使用函数设置元素的高度
...
<script type="text/javascript">
$(document).ready(function() {
$("#row1 img").css("border", "thick solid red")
.height(function(index, currentValue) {
return (index + 1) * 25;
});
});
</script>
...
在这个脚本中,我使用索引值作为高度的乘数。你可以在图 8-16 中看到效果。
图 8-16 。使用函数设置元素的高度
使用元素内容
到目前为止,我在本章中描述的方法是对元素定义的属性进行操作的,但是 jQuery 也提供了处理元素内容的方法,如表 8-6 中所述。
表 8-6 。处理元素内容的方法
| 方法 | 描述 |
|---|---|
text() | 获取 jQuery 对象中所有元素及其后代的组合文本内容 |
text(value) | 设置jQuery对象中每个元素的内容 |
html() | 获取jQuery对象中第一个柠檬的 html 内容 |
html(value) | 设置jQuery对象中每个元素的 HTML 内容 |
text(function) html(function) | 使用函数设置文本或 HTML 内容 |
与 jQuery 不同的是,当您使用不带参数的text方法时,您收到的结果是从所有选定元素的生成的,而不仅仅是第一个元素。html方法与 jQuery 的其余部分更加一致,只返回第一个元素的内容,如清单 8-25 所示。
清单 8-25 。使用 html 方法读取元素内容
...
<script type="text/javascript">
$(document).ready(function() {
var html = $("div.dcell").html();
console.log(html);
});
</script>
...
这个脚本使用html方法读取由div.dcell选择器匹配的第一个元素的 HTML 内容。这被写入控制台,产生以下结果。请注意,元素本身的 HTML 不包括在内。
<img src="aster.png">
<label for="aster">Aster:</label>
<input name="aster" value="0" required="">
设置元素含量
您可以使用html或text方法设置元素的内容。我的花店示例文档没有任何文本内容,所以清单 8-26 展示了如何使用html方法。
清单 8-26 。使用 html 方法设置元素内容
...
<script type="text/javascript">
$(document).ready(function() {
$("#row2 div.dcell").html($("div.dcell").html());
});
</script>
...
这个脚本设置了dcell类中div元素的 HTML 内容,这些元素是row2元素的后代。对于内容,我使用了html方法从第一个div.dcell元素读取 HTML。这具有将布局中的下一行单元格设置为 aster 内容的效果,如图 8-17 中的所示。
图 8-17 。用 html 方法设置元素的内容
使用功能设置元素内容
与本章中的许多其他方法一样,您可以使用带有函数的html和text方法来动态设置内容。在这两种情况下,参数都是jQuery对象中元素的索引和当前文本或 HTML 内容。this变量被设置为元素的HTMLElement对象,您返回想要设置为函数结果的值。清单 8-27 展示了如何通过文本方法使用一个函数。
清单 8-27 。使用函数设置文本内容
...
<script type="text/javascript">
$(document).ready(function() {
$("label").css("border", "thick solid red").text(function(index, currentValue) {
return "Index " + index;
});
});
</script>
...
在这个脚本中,我使用索引值设置了label元素的文本内容(我还使用了css方法为我更改的元素添加了一个边框)。你可以在图 8-18 中看到结果。
图 8-18 。使用函数设置文本内容
使用表单元素
您可以使用val方法获取和设置form元素(如input)的值,该方法在表 8-7 中有描述。
表 8-7 。瓦尔法
| 方法 | 描述 |
|---|---|
val() | 返回jQuery对象中第一个元素的值 |
val(value) | 设置jQuery对象中所有元素的值 |
val(function) | 使用函数设置jQuery对象中元素的值 |
清单 8-28 展示了如何使用val方法从jQuery对象的第一个元素中获取值。在这个脚本中,我使用了each方法,这样我就可以枚举文档中的一组input元素的值。
清单 8-28 。使用 val 方法从输入元素中获取值
...
<script type="text/javascript">
$(document).ready(function() {
$("input").each(function(index, elem) {
console.log("Name: " + elem.name + " Val: " + $(elem).val());
});
});
</script>
...
我将这些值写入控制台,控制台会产生以下输出:
Name: aster Val: 0
Name: daffodil Val: 0
Name: rose Val: 0
Name: peony Val: 0
Name: primula Val: 0
Name: snowdrop Val: 0
设置表单元素值
您可以使用val方法来设置jQuery对象中所有元素的值,只需将您想要的值作为参数传递给该方法。清单 8-29 演示了。
清单 8-29 。使用 val 方法设置元素值
...
<script type="text/javascript">
$(document).ready(function () {
$("<button>Set Values</button>").appendTo("#buttonDiv")
.click(function (e) {
$("input").val(100);
e.preventDefault();
})
});
</script>
...
在这个脚本中,我在文档中添加了一个button元素,并指定了一个单击时调用的内嵌函数。该函数选择文档中所有的input元素,并使用val方法将它们的值设置为100。你可以在图 8-19 中看到效果。(对preventDefault方法的调用会阻止浏览器将 HTML 表单发送回 web 服务器——我会在第九章中详细解释 jQuery 如何支持事件)。
图 8-19 。使用 val 方法设置输入元素值
使用函数设置表单元素值
正如您现在所期望的,您也可以使用函数通过val方法来设置值。方法的参数是元素的索引和元素的当前值。变量this被设置为代表被处理元素的HTMLElement对象。通过以这种方式使用val方法,你可以动态地设置新值,如清单 8-30 所示。
清单 8-30 。对函数使用 val 方法
...
<script type="text/javascript">
$(document).ready(function() {
$("input").val(function(index, currentVal) {
return (index + 1) * 100;
});
});
</script>
...
在本例中,我根据 index 参数设置了值。你可以在图 8-20 中看到效果。
图 8-20 。使用 val 方法和函数动态设置值
将数据与元素相关联
jQuery 允许您将任意数据与一个元素相关联,然后您可以对其进行测试并在以后进行检索。表 8-8 描述了与该特性相关的方法。
表 8-8 。处理任意元素数据的方法
| 方法 | 描述 |
|---|---|
data(key, value) data(map) | 将一个或多个键/值对与jQuery对象中的元素相关联 |
data(key) | 从jQuery对象的第一个元素中检索与指定键相关联的值 |
data() | 从jQuery对象的第一个元素中检索键/值对 |
removeData(key) | 从jQuery对象的所有元素中删除与指定键相关的数据 |
removeData() | 从jQuery对象的所有元素中删除所有数据项 |
清单 8-31 演示了数据值的设置、测试、读取和删除。
清单 8-31 。使用元素数据
...
<script type="text/javascript">
$(document).ready(function() {
// set the data
$("img").each(function () {
$(this).data("product", $(this). siblings("input[name]").attr("name"));
});
// find elements with the data and read the values
$("*").filter(function() {
return $(this).data("product") != null;
}).each(function() {
console.log("Elem: " + this.tagName + " " + $(this).data("product"));
});
// remove all data
$("img").removeData();
});
</script>
...
注意当您使用 clone 方法时,您与元素关联的数据将从新复制的元素中删除,除非您明确告诉 jQuery 您想要保留它。关于
clone方法以及如何保存数据的详细信息,参见第七章。
这个脚本有三个阶段。首先,我使用data方法将一个数据项与product键关联起来。我通过从每个img元素导航到具有name属性的input兄弟元素来获取数据。
在第二阶段,我选择文档中的所有元素,然后使用filter方法找到那些具有与product键相关联的值的元素。然后,我使用each方法来枚举这些元素,并将数据值写入控制台。这是重复的,但是我想展示选择包含数据的元素的最佳技术。没有专用的选择器或方法,所以您必须使用filter方法和一个函数。
最后,我使用removeData从所有的img元素中删除所有的数据。该脚本在控制台上产生以下输出:
Elem: IMG aster
Elem: IMG daffodil
Elem: IMG rose
Elem: IMG peony
Elem: IMG primula
Elem: IMG snowdrop
摘要
在这一章中,我向你展示了在 DOM 中操作元素的不同方法。我向您展示了如何获取和设置属性,包括处理类和 CSS 属性的 jQuery 便利方法。我还展示了如何获取和设置元素的文本或 HTML 内容,以及 jQuery 如何支持任意数据与元素的关联。
九、处理事件
在这一章中,我描述了 jQuery 对事件的支持。如果你不熟悉事件,那么我在第二章中提供了一个关于它们如何工作以及它们如何通过 DOM(域对象模型)传播的简要概述。jQuery 提供了一些有用的与事件相关的特性,其中我最喜欢的是在元素被添加到 DOM 时自动将事件处理函数与元素关联起来的能力。表 9-1 对本章进行了总结。
表 9-1 。章节总结
| 问题 | 解决办法 | 列表 |
|---|---|---|
| 注册一个函数来处理一个或多个事件 | 使用绑定方法或一种速记方法 | 1–4, 19, 20, 23 |
| 禁止事件的默认操作 | 使用 Event.preventDefault 方法或使用 bind 方法,而不指定处理函数 | 5–6 |
| 从元素中移除事件处理函数 | 使用解除绑定方法 | 7–9 |
| 创建一个处理函数,该函数只对与之关联的每个元素执行一次 | 使用一的方法 | Ten |
| 当元素被添加到文档中时,自动将事件处理函数应用于元素 | 使用上的方法 | 11–13 |
| 移除使用 live 方法创建的处理程序 | 使用关的方法 | Fourteen |
| 将自动添加的处理程序应用于 DOM 中的特定元素 | 使用委托和取消委托的方法 | Fifteen |
| 手动调用元素的事件处理函数 | 使用触发器或触发器处理程序方法或一种速记方法 | 16–18, 21, 22 |
自上一版以来,JQUERY 发生了变化
jQuery 1.9/2.0 移除了live和die方法。通过on和off方法可以获得相同的功能,这在“执行实时事件绑定”一节中有描述
使用trigger方法时,对focus和blur事件的发送顺序进行了一些幕后更改,以便它们更好地遵循用户触发事件时看到的顺序。有关如何使用trigger方法的详细信息,请参见“手动调用事件处理程序”一节。
一个相关的变化是,当您在复选框或单选按钮input元素上触发click事件时,事件处理程序将接收元素的新状态,这与用户更改元素状态所产生的效果一致。在以前版本的 jQuery 中,处理程序会接收旧的状态。
我在本书的上一版中省略了一些 jQuery 特性,因为它们被标记为不推荐使用。jQuery 最新版本中的变化不会影响本章的内容,但是如果您在jquery.com上找到了对它们的引用并开始在项目中使用它们,那么这些变化是值得一提的:jQuery Event对象中已经删除了attrChange、attrName、relatedNode和srcElement属性;不再支持hover伪事件(但是我在“使用事件速记方法”一节中描述的hover方法不受影响);在同一个事件的两个事件处理函数之间交替的toggle方法已经被删除。
处理事件
jQuery 提供了一组方法,允许您注册在感兴趣的元素上触发指定事件时调用的函数。表 9-2 描述了这些方法。
表 9-2 。处理事件的方法
| 方法 | 描述 |
|---|---|
bind(eventType, function) bind(eventType, data, function) | 向带有可选数据项的 jQuery 对象中的元素添加事件处理程序 |
bind(eventType, boolean) | 创建一个总是返回 false 的默认处理程序,阻止默认操作。布尔参数控制事件冒泡 |
bind(map) | 向 jQuery 对象中的所有元素添加一组基于 map 对象的事件处理程序 |
one(eventType, function) one(eventType, data, function) | 向带有可选数据项的 jQuery 对象中的每个元素添加事件处理程序;一旦元素被执行,处理程序将被注销。 |
unbind() | 移除 jQuery 对象中所有元素的所有事件处理程序 |
unbind(eventType) | 从 jQuery 对象的所有元素中删除先前注册的事件处理程序 |
unbind(eventType, boolean) | 从 jQuery 对象的所有元素中删除先前注册的始终为假的处理程序 |
unbind(Event) | 使用事件对象删除事件处理程序 |
各种风格的bind方法允许您指定一个当事件被触发时将被调用的函数,由于这是 jQuery,该函数用于调用bind方法的jQuery对象中的所有元素。清单 9-1 显示了一个简单的例子。
清单 9-1 。使用 bind 方法注册事件处理函数
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
<script src="jquery-2.0.2.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="styles.css"/>
<script type="text/javascript">
$(document).ready(function() {
function handleMouseEnter(e) {
$(this).css({
"border": "thick solid red",
"opacity": "0.5"
});
};
function handleMouseOut(e) {
$(this).css({
"border": "",
"opacity": ""
});
}
$("img").bind("mouseenter", handleMouseEnter)
.bind("mouseout", handleMouseOut);
});
</script>
</head>
<body>
<h1>Jacqui's Flower Shop</h1>
<form method="post">
<div id="oblock">
<div class="dtable">
<div id="row1" class="drow">
<div class="dcell">
<img src="aster.png"/><label for="aster">Aster:</label>
<input name="aster" value="0" required />
</div>
<div class="dcell">
<img src="daffodil.png"/><label for="daffodil">Daffodil:</label>
<input name="daffodil" value="0" required />
</div>
<div class="dcell">
<img src="rose.png"/><label for="rose">Rose:</label>
<input name="rose" value="0" required />
</div>
</div>
<div id="row2"class="drow">
<div class="dcell">
<img src="peony.png"/><label for="peony">Peony:</label>
<input name="peony" value="0" required />
</div>
<div class="dcell">
<img src="primula.png"/><label for="primula">Primula:</label>
<input name="primula" value="0" required />
</div>
<div class="dcell">
<img src="snowdrop.png"/><label for="snowdrop">Snowdrop:</label>
<input name="snowdrop" value="0" required />
</div>
</div>
</div>
</div>
<div id="buttonDiv"><button type="submit">Place Order</button></div>
</form>
</body>
</html>
在清单 9-1 中,我选择了文档中所有的img元素,并使用bind方法为mouseenter和mouseout事件注册处理函数。这些处理程序使用css方法来设置border和opacity属性的值。当用户将鼠标指针移动到其中一个img元素上时,会绘制边框,图像会变得更加透明,当指针移开时,图像会恢复到原来的状态。
当 jQuery 调用处理程序函数时,this变量被设置为处理程序所附加的元素。传递给 handler 函数的对象是 jQuery 自己的Event对象,不同于 DOM 规范定义的Event对象。表 9-3 描述了 jQuery Event对象的属性和方法。
表 9-3 。jQuery 事件对象的成员
| 名字 | 描述 | 返回 |
|---|---|---|
currentTarget | 获取当前正在调用其侦听器的元素 | HTMLElement |
Data | 获取注册处理程序时传递给 bind 方法的可选数据;有关详细信息,请参见“注册一个函数来处理多种事件类型”一节 | Object |
isDefaultPrevented() | 如果调用了 preventDefault 方法,则返回 true | Boolean |
isImmediatePropagationStopped() | 如果调用了停止立即传播方法,则返回真值 | Boolean |
isPropagationStopped() | 如果调用了停止传播方法,则返回真值 | Boolean |
originalEvent | 返回原始 DOM 事件对象 | Event |
pageX pageY | 返回相对于文档左边缘的鼠标位置 | number |
preventDefault() | 阻止执行与事件相关联的默认操作 | void |
relatedTarget | 对于鼠标事件,返回相关元素;这取决于触发了哪个事件 | HTMLElement |
Result | 返回处理此事件的最后一个事件处理程序的结果 | Object |
stopImmediatePropagation() | 防止为此事件调用任何其他事件处理程序 | void |
stopPropagation() | 防止事件冒泡,但允许附加到当前目标元素的处理程序接收事件 | void |
Target | 获取触发事件的元素 | HTMLElement |
timeStamp | 获取事件的触发时间 | number |
Type | 获取事件的类型 | string |
Which | 返回为鼠标和键盘事件按下的按钮或按键 | number |
jQuery Event对象还定义了标准 DOM Event对象的大多数属性。因此,对于几乎所有情况,您都可以将 jQuery Event对象视为具有 DOM 标准定义的功能的超集。
注册一个函数来处理多个事件类型
一种常见的技术是使用一个函数来处理两种或多种事件。这些事件通常以某种方式相关联,例如mouseenter和mouseout事件。使用bind方法时,可以在第一个参数中指定多个事件类型,用空格分隔。清单 9-2 展示了这种方法。
清单 9-2 。注册一个函数来处理多个事件类型
...
<script type="text/javascript">
$(document).ready(function() {
function handleMouse(e) {
var cssData = {
"border": "thick solid red",
"opacity": "0.5"
}
if (event.type == "mouseout") {
cssData.border = "";
cssData.opacity = "";
}
$(this).css(cssData);
}
$("img").bind("mouseenter mouseout", handleMouse);
});
</script>
...
在这个脚本中,我使用了一个对bind方法的调用来指定文档中所有img元素的mouseenter和mouseout事件应该由handleMouse函数来处理。当然,您也可以使用单个函数并链接绑定调用,如下所示:
...
$("img").bind("mouseenter", handleMouse).bind("mouseout", handleMouse);
...
还可以使用 map 对象注册处理程序。对象的属性是事件的名称,它们的值是事件被触发时将被调用的函数。清单 9-3 展示了一个地图对象和bind方法的使用。
清单 9-3 。使用映射对象注册事件处理程序
...
<script type="text/javascript">
$(document).ready(function() {
$("img").bind({
mouseenter: function() {
$(this).css("border", "thick solid red");
},
mouseout: function() {
$(this).css("border", "");
}
});
});
</script>
...
在清单 9-3 中,我已经定义了内嵌的处理函数,作为 map 对象的一部分。bind方法使用我指定的函数作为事件的处理程序,这些事件对应于 map 对象中的属性名称。
向事件处理函数提供数据
您可以将一个对象传递给bind方法,然后 jQuery 将通过Event.data属性将该对象提供给处理函数。当使用单个函数处理来自不同元素集的事件时,这可能很有用。data值可以帮助确定需要什么样的响应。清单 9-4 展示了如何定义和使用数据值。
清单 9-4 。通过 bind 方法将数据传递给事件处理函数
...
<script type="text/javascript">
$(document).ready(function() {
function handleMouse(e) {
var cssData = {
"border": "thick solid " + e.data,
}
if (event.type == "mouseout") {
cssData.border = "";
}
$(this).css(cssData);
}
$("img:odd").bind("mouseenter mouseout", "red", handleMouse);
$("img:even").bind("mouseenter mouseout", "blue", handleMouse);
});
</script>
...
我使用了bind方法的可选参数来指定当mouseenter事件被触发时应该显示哪种颜色的边框。对于奇数编号的img元素,边界将为red,对于偶数编号的元素,边界将为blue。在事件处理函数中,我使用Event.data属性读取数据,并用它来创建 CSS(级联样式表)border属性的值。你可以在图 9-1 中看到效果。
图 9-1 。通过 bind 方法将数据传递给处理函数
取消默认操作
正如我在第二章的中提到的,一些事件在某些元素上被触发时会有一个默认的动作。一个很好的例子是当用户点击一个按钮,它的属性是 ??。如果button包含在form元素中,浏览器的默认动作是提交表单。为了防止默认动作被执行,你可以在Event对象上调用preventDefault方法,如清单 9-5 所示。
清单 9-5 。阻止对事件的默认操作
...
<script type="text/javascript">
$(document).ready(function() {
$("button:submit").bind("click", function(e) {
e.preventDefault();
});
});
</script>
...
这个脚本为所有button元素上的click事件设置了一个处理函数,这些元素的type属性被设置为submit。该函数只包含一个对preventDefault方法的调用,这意味着单击按钮不会做任何事情,因为默认操作是禁用的,并且处理函数没有设置任何替代选项。
通常你想取消默认动作,这样你就可以执行一些其他的活动——例如,阻止浏览器提交表单,因为你想用 Ajax 来完成(这是第十四章和第十五章的主题)。不要像我在清单 9-5 中那样写一行函数,你可以使用不同版本的bind方法,如清单 9-6 所示。
清单 9-6 。使用 bind 方法创建阻止默认操作的处理程序
...
<script type="text/javascript">
$(document).ready(function() {
$("button:submit").bind("click", false);
});
</script>
...
第一个参数是您想要抑制其默认动作的一个或多个事件,第二个参数允许您指定是否应该阻止事件在 DOM 中冒泡(我在第二章的中解释了事件冒泡)。
删除事件处理函数
unbind方法从一个元素中移除一个处理函数。您可以通过不带参数调用unbind方法来解除与一个jQuery对象中所有元素的所有事件相关联的所有处理程序的绑定,如清单 9-7 所示。
清单 9-7 。取消绑定所有事件处理程序
...
<script type="text/javascript">
$(document).ready(function() {
function handleMouse(e) {
var cssData = {
"border": "thick solid red",
"opacity": "0.5"
}
if (event.type == "mouseout") {
cssData.border = "";
cssData.opacity = "";
}
$(this).css(cssData);
}
$("img").bind("mouseenter mouseout", handleMouse);
$("img[src*=rose]").unbind();
});
</script>
...
在清单 9-7 中,我为所有img元素的mouseenter和mouseout事件设置了一个处理程序,然后使用unbind方法移除img元素的所有处理程序,该元素的src属性包含rose。通过将您想要解除绑定的事件作为参数传递给unbind方法,您可以更有选择性,如清单 9-8 所示。
清单 9-8 。选择性解除事件绑定
...
<script type="text/javascript">
$(document).ready(function() {
function handleMouse(e) {
var cssData = {
"border": "thick solid red",
"opacity": "0.5"
}
if (event.type == "mouseout") {
cssData.border = "";
cssData.opacity = "";
}
$(this).css(cssData);
}
$("img").bind("mouseenter mouseout", handleMouse);
$("img[src*=rose]").unbind("mouseout");
});
</script>
...
在这个脚本中,我只解除了mouseout事件的绑定,而没有触动mouseenter事件的处理程序。
从事件处理函数中取消绑定
解除绑定的最后一个选项是从事件处理函数中进行。例如,如果您想要处理某个事件一定次数,这可能会很有用。清单 9-9 包含了一个简单的演示。
清单 9-9 。从事件处理程序中的事件解除绑定
...
<script type="text/javascript">
$(document).ready(function() {
var handledCount = 0;
function handleMouseEnter(e) {
$(this).css("border", "thick solid red");
}
function handleMouseExit(e) {
$(this).css("border", "");
handledCount ++;
if (handledCount == 2) {
$(this).unbind(e);
}
}
$("img").bind("mouseenter", handleMouseEnter).bind("mouseout", handleMouseExit)
});
</script>
...
在handleMouseEvent函数中,我每处理一次mouseout事件就增加一个计数器。在我处理了两次事件之后,我将Event对象传递给unbind方法,以取消该函数作为处理程序的注册。jQuery 从事件对象中找出它需要的细节。
执行一次处理程序
one方法允许您注册一个事件处理程序,该程序对于一个元素只执行一次,然后被删除。清单 9-10 提供了一个例子。
清单 9-10 。使用 one 方法注册单次事件处理函数
...
<script type="text/javascript">
$(document).ready(function() {
function handleMouseEnter(e) {
$(this).css("border", "thick solid red");
};
function handleMouseOut(e) {
$(this).css("border", "");
};
$("img").one("mouseenter", handleMouseEnter).one("mouseout", handleMouseOut);
});
</script>
...
我已经使用了one方法来注册mouseenter和mouseout事件的处理程序。当用户将鼠标移入和移出其中一个img元素时,将调用处理函数,然后该函数将被解除绑定(但只是针对那个元素;其他的仍然有处理程序,直到鼠标移到它们上面)。
执行实时事件绑定
bind方法的一个限制是,您的事件处理函数不与您添加到 DOM 的任何新元素相关联。清单 9-11 包含了一个例子。
清单 9-11 。设置事件处理程序后添加元素
...
<script type="text/javascript">
$(document).ready(function() {
$("img").bind({
mouseenter: function() {
$(this).css("border", "thick solid red");
},
mouseout: function() {
$(this).css("border", "");
}
});
$("#row1").append($("<div class='dcell'/>")
.append("<img src='lily.png'/>")
.append("<label for='lily'>Lily:</label>")
.append("<input name='lily' value='0' required />"));
});
</script>
...
在这个脚本中,我使用bind方法为所有img元素的mouseenter和mouseout事件设置处理程序。然后我使用append方法在文档中插入一些新元素,包括另一个img元素。当我使用bind方法时,这个新的img元素并不存在,我的处理函数也没有与之关联。这样做的结果是,我有六个img元素在鼠标悬停在它们上面时显示边框,而一个没有。
在一个像清单 9-11 中的这样简单的例子中,简单的答案是再次调用bind方法,但是很难记住不同类型的元素需要哪些处理程序。幸运的是,jQuery 为您提供了一组方法,当匹配选择器的新元素被添加到 DOM 时,这些方法会自动注册事件处理程序。表 9-4 描述了这些方法。
表 9-4 。自动注册事件处理程序的方法
| 方法 | 描述 |
|---|---|
on(events, selector, data, function) on (map, selector, data) | 为现在或将来存在的元素定义事件处理程序 |
off(events, selector, function) off(map, selector) | 移除使用 on 方法创建的事件处理程序 |
delegate(selector, eventType, function)``delegate(selector, eventType, data,``function) | 将事件处理程序添加到与附加到 jQuery 对象中元素的选择器(现在或将来)相匹配的元素中 |
undelegate() undelegate(selector, eventType) | 为指定的事件类型移除使用委托方法创建的事件处理程序 |
清单 9-12 显示了之前的例子更新为使用on方法 。变化很小,但影响很大。我添加到 DOM 中与选择器img匹配的任何元素都将在 map 对象中拥有函数,这些函数被设置为mouseenter和mouseout事件的处理程序。
清单 9-12 。使用 on 方法
...
<script type="text/javascript">
$(document).ready(function () {
$(document).on({
mouseenter: function () {
$(this).css("border", "thick solid red");
},
mouseout: function () {
$(this).css("border", "");
}
}, "img");
$("#row1").append($("<div class='dcell'/>")
.append("<img src='lily.png'/>")
.append("<label for='lily'>Lily:</label>")
.append("<input name='lily' value='0' required />"));
});
</script>
...
注意,我在从document创建的jQuery对象上调用了on方法。这确保了我的事件处理程序被应用于添加到 DOM 中任何地方的任何img元素。我可以通过更改初始选择器来缩小关注范围——例如,如果我只想将我的处理函数应用于添加到row1元素的img元素,我可以使用下面的调用来代替:
...
$("#row1").on(*...map...*, "img");
...
提示
on方法不需要直接给元素添加处理函数。事实上,它在document对象上创建了一个事件处理程序,并寻找由匹配选择器的元素触发的事件。当它看到这样的事件时,它会触发事件处理程序。然而,实际上,更容易想象的是on方法努力为新元素添加句柄。
使用on方法时,可以指定多个事件。事件名由空格字符分隔,或者在地图对象的属性名中,或者在不使用地图时在第一个参数中,如清单 9-13 所示。
清单 9-13 。使用 on 方法指定多个事件
...
<script type="text/javascript">
$(document).ready(function () {
function handleMouse(event) {
if (event.type == "mouseenter") {
$(this).css("border", "thick solid red");
} else if (event.type == "mouseout") {
$(this).css("border", "");
}
}
$("#row1").on("mouseenter mouseout", "img", handleMouse);
$("#row1").append($("<div class='dcell'/>")
.append("<img src='lily.png'/>")
.append("<label for='lily'>Lily:</label>")
.append("<input name='lily' value='0' required />"));
});
</script>
...
在清单 9-13 中,我使用了不依赖于地图对象的on方法版本,指定handleMouse函数应该用于由所有img元素发出的mouseenter和mouseout事件,这些【】元素是row1元素的后代。
对on方法的补充是off,它用于从现有元素中移除事件处理程序,并防止它们被用来响应新创建元素的事件。清单 9-14 展示了off方法 的使用。
清单 9-14 。使用关闭方法
...
<script type="text/javascript">
$(document).ready(function () {
function handleMouse(event) {
if (event.type == "mouseenter") {
$(this).css("border", "thick solid red");
} else if (event.type == "mouseout") {
$(this).css("border", "");
}
}
$("#row1").on("mouseenter mouseout", "img", handleMouse);
$("#row1").off("mouseout", "img");
$("#row1").append($("<div class='dcell'/>")
.append("<img src='lily.png'/>")
.append("<label for='lily'>Lily:</label>")
.append("<input name='lily' value='0' required />"));
});
</script>
...
注意使用与
on和off方法相同的选择器很重要;否则,off方法无法解除on的效果。
限制实时事件处理程序的 DOM 遍历
on方法的一个问题是,在执行处理函数之前,事件必须一直传播到document元素。您可以采取一种更直接的方法,使用delegate方法 ,它允许您指定事件监听器将位于文档中的什么位置。清单 9-15 提供了一个例子。
清单 9-15 。使用委托方法
...
<script type="text/javascript">
$(document).ready(function() {
$("#row1").delegate("img", {
mouseenter: function() {
$(this).css("border", "thick solid red");
},
mouseout: function() {
$(this).css("border", "");
}
});
$("#row1").append($("<div class='dcell'/>")
.append("<img src='carnation.png'/>")
.append("<label for='carnation'>Carnation:</label>")
.append("<input name='carnation' value='0' required />"));
$("#row2").append($("<div class='dcell'/>")
.append("<img src='lily.png'/>")
.append("<label for='lily'>Lily:</label>")
.append("<input name='lily' value='0' required />"));
});
</script>
...
在清单 9-15 中,我使用delegate方法将监听器添加到 ID 为#row1的元素中,我指定的选择器与img元素相匹配。这样做的效果是,当源于img元素的mouseenter或mouseout事件传播到row1元素时,我的处理函数将被执行。当我向row1添加另一个img元素时,它会被我对delegate方法的调用自动覆盖,而当我向row2添加元素时却不是这样。
使用delegate方法的主要好处是速度,如果您有一个特别大而复杂的文档和许多事件处理程序,这可能会成为一个问题。通过将事件被拦截的点下推到文档中,可以减少事件在导致处理函数被调用之前在 DOM 中必须经过的距离。
提示要删除用
delegate方法添加的处理程序,必须使用undelegate。off方法仅适用于on方法。
手动调用事件处理程序
您可以使用表 9-5 中描述的方法手动调用元素上的事件处理函数。
表 9-5 。手动调用事件处理程序的方法
| 方法 | 描述 |
|---|---|
trigger(eventType) | 在一个 jQuery 对象的所有元素上触发指定事件类型的处理函数 |
trigger(event) | 在一个 jQuery 对象的所有元素上触发指定事件的处理函数 |
triggerHandler(eventType) | 在 jQuery 对象的第一个元素上触发处理函数,而不执行默认操作或冒泡事件 |
清单 9-16 展示了如何手动触发事件处理程序。
清单 9-16 。手动触发事件处理程序
...
<script type="text/javascript">
$(document).ready(function() {
$("img").bind({mouseenter: function() {
$(this).css("border", "thick solid red");
},
mouseout: function() {
$(this).css("border", "");
}
});
$("<button>Trigger</button>").appendTo("#buttonDiv").bind("click", function (e) {
$("#row1 img").trigger("mouseenter");
e.preventDefault();
});
});
</script>
...
在这个脚本中,我使用bind方法在文档中的img元素上设置一对事件处理函数。然后,我使用appendTo方法将一个button元素插入到文档方法中,并使用bind方法为click事件注册一个处理函数。
当按钮被按下时,事件处理函数选择作为row1的后代的img元素,并使用trigger方法为mouseenter按钮调用它们的处理程序。效果如图 9-2 中的所示,就好像鼠标移动到了所有三个img元素上。
图 9-2 。手动触发事件处理函数
使用事件对象
您还可以使用一个Event对象来触发其他元素的事件处理程序。这是一种在处理程序中使用的方便技术,如清单 9-17 所示。
清单 9-17 。用事件对象手动触发事件句柄
...
<script type="text/javascript">
$(document).ready(function() {
$("#row1 img").bind("mouseenter", function() {
$(this).css("border", "thick solid red");
});
$("#row2 img").bind("mouseenter", function(e) {
$(this).css("border", "thick solid blue");
$("#row1 img").trigger(e);
});
});
</script>
...
在清单 9-17 中,我使用bind方法给row1元素的img后代添加一个红色边框,以响应mouseenter事件。我对row2 img元素使用了蓝色边框,但是在处理程序中,我添加了以下语句:
..
$("#row1 img").trigger(e);
...
这种添加的效果是,当鼠标进入其中一个row2 img元素时,相同事件类型的处理程序也会在row1 img元素上被触发。你可以在图 9-3 中看到效果。
图 9-3 。使用事件触发事件处理程序
当您希望触发当前正在处理的事件类型的处理程序时,这种方法很方便,但是您也可以通过指定事件类型来轻松获得相同的效果。
使用触发器处理程序方法
triggerHandler方法 调用处理函数,而不执行事件的默认动作,也不允许事件在 DOM 中冒泡。而且,与trigger方法不同,triggerHandler只在 jQuery 对象的第一个元素上调用处理函数。清单 9-18 展示了这种方法的使用。
清单 9-18 。使用触发器处理程序方法
...
<script type="text/javascript">
$(document).ready(function() {
$("#row1 img").bind("mouseenter", function() {
$(this).css("border", "thick solid red");
});
$("#row2 img").bind("mouseenter", function(e) {
$(this).css("border", "thick solid blue");
$("#row1 img").triggerHandler("mouseenter");
});
});
</script>
...
提示
triggerHandler方法的结果是 handler 函数返回的结果,这意味着不能链接triggerHandler方法。
你可以在图 9-4 中看到这个脚本的效果。
图 9-4 。使用触发器处理程序方法
使用事件速记方法
jQuery 定义了一些方便的方法,您可以用它们来为常用事件注册事件处理程序。在下面的表格中,我用一个function参数展示了这些速记方法。这是最常见的用法,相当于调用bind方法,但是这些方法需要更少的输入,并且(至少在我看来)使绑定到哪个事件变得更加明显。清单 9-19 展示了如何以这种方式使用速记方法。
清单 9-19 。使用事件速记方法绑定处理函数
...
<script type="text/javascript">
$(document).ready(function() {
$("img").mouseenter(function() {
$(this).css("border", "thick solid red");
});
});
</script>
...
这相当于将bind事件用于mouseenter事件,我已经在清单 9-20 中展示了这一点。
清单 9-20 。对 mouseenter 事件使用 bind 方法
...
<script type="text/javascript">
$(document).ready(function() {
$("img").bind("mouseenter", function() {
$(this).css("border", "thick solid red");
});
});
</script>
...
这一切都很好,到目前为止,您应该对这个示例的工作方式感到满意了。但是,您也可以使用速记方法来模拟trigger方法。通过调用不带参数的方法可以做到这一点。清单 9-21 展示了如何做到这一点。
清单 9-21 。使用事件速记方法触发事件处理程序
...
<script type="text/javascript">
$(document).ready(function() {
$("img").bind("mouseenter", function() {
$(this).css("border", "thick solid red");
});
$("<button>Trigger</button>").appendTo("#buttonDiv").click(function (e) {
$("img").mouseenter();
e.preventDefault();
});
});
</script>
...
我在文档中添加了一个button,单击它会选择img元素并调用它们的mouseenter事件处理程序。为了完整起见,清单 9-22 显示了使用trigger方法编写的等效功能。
清单 9-22 。使用触发方法
...
<script type="text/javascript">
$(document).ready(function() {
$("img").bind("mouseenter", function() {
$(this).css("border", "thick solid red");
});
$("<button>Trigger</button>").appendTo("#buttonDiv").click(function (e) {
$("img").trigger("mouseenter");
e.preventDefault();
});
});
</script>
...
在接下来的部分中,我列出了不同类别的速记方法和它们对应的事件。
使用文档事件速记方法
表 9-6 描述了适用于document对象的 jQuery 简写方法。
表 9-6 。文档事件速记方法
| 方法 | 描述 |
|---|---|
load(function) | 对应于 load 事件,当文档中的元素和资源已经被加载时触发 |
ready(function) | 当文档中的元素已经被处理并且 DOM 可以使用时触发 |
unload(function) | 对应于 unload 事件,当用户离开页面时触发 |
ready法值得特别一提。它不直接对应于 DOM 事件,但是在使用 jQuery 时非常有用。你可以在第五章中看到使用ready方法的不同方式,在那里我解释了如何推迟脚本的执行直到 DOM 准备好,以及如何控制ready事件的执行。
使用浏览器事件速记方法
表 9-7 描述了浏览器事件,这些事件通常针对window对象(尽管error和scroll事件也用于元素)。
表 9-7 。浏览器事件速记方法
| 方法 | 描述 |
|---|---|
error(function) | 对应于错误事件,当加载外部资源(如图像)出现问题时触发 |
resize(function) | 对应于调整浏览器窗口大小时触发的 resize 事件 |
scroll(function) | 对应于使用滚动条时触发的滚动事件 |
使用鼠标事件速记方法
表 9-8 描述了 jQuery 为处理鼠标事件而提供的一组速记方法。
表 9-8 。鼠标事件速记方法
| 方法 | 描述 |
|---|---|
click(function) | 对应于用户按下并释放鼠标时触发的 click 事件 |
dblclick(function) | 对应于 dblclick 事件,当用户快速连续按下并释放鼠标两次时触发 |
focusin(function) | 对应于当元素获得焦点时触发的 focusin 事件 |
focusout(function) | 对应于当元素失去焦点时触发的 focusout 事件 |
hover(function) hover(function, function) | 当鼠标进入或离开一个元素时触发;当一个函数被指定时,它被用于进入和退出事件 |
mousedown(function) | 对应于 mousedown 事件,当在元素上按下鼠标按钮时触发 |
mouseenter(function) | 对应于 mouseenter 事件,当鼠标进入元素占据的屏幕区域时触发 |
mouseleave(function) | 对应于 mouseleave 事件,当鼠标离开元素占据的屏幕区域时触发 |
mousemove(function) | 对应于 mousemouse 事件,当鼠标在元素占据的屏幕区域内移动时触发 |
mouseout(function) | 对应于 mouseout 事件,当鼠标离开元素占据的屏幕区域时触发 |
mouseover(function) | 对应于 mouseover 事件,当鼠标进入元素占据的屏幕区域时触发 |
mouseup(function) | 对应于 mouseup 事件,当在元素上按下鼠标按钮时触发 |
hover方法是一种将处理函数绑定到mouseenter和mouseleave事件的便捷方式。如果您提供两个函数作为参数,那么第一个函数被调用以响应mouseenter事件,第二个函数被调用以响应mouseleave。如果您只指定了一个函数,那么这两个事件都会调用它。清单 9-23 显示了hover方法的使用。
清单 9-23 。使用悬停方法
...
<script type="text/javascript">
$(document).ready(function() {
$("img").hover(handleMouseEnter, handleMouseLeave);
function handleMouseEnter(e) {
$(this).css("border", "thick solid red");
};
function handleMouseLeave(e) {
$(this).css("border", "");
}
});
</script>
...
使用表单事件速记方法
表 9-9 描述了 jQuery 提供的处理通常与表单相关的事件的速记方法。
表 9-9 。表单事件速记方法
| 方法 | 描述 |
|---|---|
blur(function) | 对应于当元素失去焦点时触发的模糊事件 |
change(function) | 对应于 change 事件,当元素的值改变时触发 |
focus(function) | 对应于焦点事件,当元素获得焦点时触发 |
select(function) | 对应于用户选择元素值时触发的选择事件 |
submit(function) | 对应于提交事件,当用户提交表单时触发 |
使用键盘事件速记方法
表 9-10 描述了 jQuery 提供的处理键盘事件的速记方法。
表 9-10 。键盘事件速记方法
| 方法 | 描述 |
|---|---|
keydown(function) | 对应于用户按键时触发的 keydown 事件 |
keypress(function) | 对应于用户按下并释放按键时触发的按键事件 |
keyup(function) | 对应于用户释放按键时触发的 keyup 事件 |
摘要
在本章中,我向您展示了 jQuery 对事件的支持。与大多数 jQuery 一样,事件功能的好处是简单和优雅。您可以轻松创建和管理事件处理程序。我特别喜欢对创建实时事件处理程序的支持,这样添加到 DOM 中与特定选择器匹配的元素就会自动与事件处理程序相关联。这大大减少了我在 web 应用中跟踪事件处理问题所花费的时间。在第十章中,我描述了 jQuery 对效果的支持。