为什么需要自定义数据属性?

很多时候我们需要存储一些与不同DOM元素相关联的信息。这些信息对于读者来说可能是不需要的,但是可以轻松的访问这些信息将会给我们开发者的工作带来极大的便利。

例如,假设你有一份某个餐饮类网站上所有餐馆的名单。在HTML5之前,如果你想存储餐馆提供的食物种类或餐馆与用户之间的距离等信息,那么你将使用HTML的class属性。但是如果你还需要存储餐馆的id以便查看用户想要访问的特定餐厅该怎么办?

以下是基于HTMLclass属性的方法存在的一些问题:

HTMLclass属性不是用来存储这样的数据的,其主要目的是允许开发人员给一组元素添加样式信息。

我们需要为每个追加的信息向元素中添加一个新class,这使得解析JavaScript中的数据得到我们所需要的内容变得更加困难。

假设给定的类名以数字开头。如果你决定稍后根据类名来设计元素的样式,那么你在样式表中将不得不回避数字或者使用属性选择器。

为了解决这些问题,HTML5引入了自定义数据属性。一个元素上属性名以data-开头的属性都是数据属性。你也可以使用这些数据属性来给元素设计样式。

接下来,让我们深入了解数据属性的基础知识、学习如何在CSS和JavaScript中访问数据属性的值。

HTML语法

如上所述,data属性的名称始终以data-开头。以下是一个例子:

<lidata-type="veg"data-distance="2miles"data-identifier="10318">SaladKing</li>

你现在可以使用这些数据属性为你的用户搜索和排序餐厅。例如,你现在可以向他们展现在一定距离内的所有素食餐厅。

除了data-前缀之外,有效的自定义数据属性的名称必须只能包含字母、数字、连字符( - )、点(。)、冒号(:)或下划线(_),不能包含大写字母。

在使用数据属性时,你应该记住下面两个规则:

第一:存储在这些属性中的数据应该是字符串类型。任何可以被编码为字符串类型的东西也可以存储在数据属性中。所有的类型转换都需要使用JavaScript完成。

第二:数据属性应该只在没有其他合适的HTML元素或属性时使用。例如,使用data-class属性存储元素class属性的值是不恰当的。

一个元素可以具有任意数量的数据属性,这些数据属性也可以具有任何所需要的值。

数据属性与CSS

你可以根据数据属性使用CSS中的属性选择器来为元素设计样式。你还可以借助attr()函数将数据属性中存储的信息显示给用户(以工具提示或其他方式)。

设计元素样式

现在回到我们餐厅的例子,你可以使用数据属性向用户提供关于餐厅类型或者他们与餐厅之间的距离等信息,或者为餐厅设计不同的背景颜色。以下是一个例子:

li[data-type='veg']{background:#8BC34A;}li[data-type='french']{background:#3F51B5;}

HTML代码:

<h3>RestaurantsinNewYork</h3><divclass="hint"><spanclass="french"></span><span>French</span></div><divclass="hint"><spanclass="veg"></span><span>Vegetarian</span></div><divclass="hint"><spanclass="german"></span><span>German</span></div><ul><lidata-type="veg"data-distance="2miles"data-identifier="10318">Bloss</li><lidata-type="german"data-distance="3miles"data-identifier="10318">Heidelberg</li><lidata-type="french"data-distance="1mile"data-identifier="10318">Daniel</li><lidata-type="veg"data-distance="4miles"data-identifier="10548">DirtCandy</li><lidata-type="french"data-distance="3miles"data-identifier="10318">LaGrenouille</li><lidata-type="french"data-distance="1mile"data-identifier="10318">Balthazar</li><lidata-type="veg"data-distance="2miles"data-identifier="12315">AngelicaKitchen</li><lidata-type="german"data-distance="1mile"data-identifier="10318">BlaueGans</li><lidata-type="german"data-distance="2miles"data-identifier="12315">ReichenbachHall</li></ul>

CSS代码:

html{font-family:'Lato';margin:20pxauto;max-width:600px;font-size:1.25em;}ul{list-style:none;padding:0;}li{padding:5px10px;margin:5px0;color:white;border-radius:5px;}.hint{margin-right:30px;display:inline-block;}span.french,span.veg,span.german{width:15px;height:15px;border-radius:50%;display:inline-block;float:left;margin-top:5px;margin-right:5px;}span.french{background:#3F51B5;}span.veg{background:#8BC34A;}span.german{background:#bb6666;}li[data-type='veg']{background:#8BC34A;}li[data-type='french']{background:#3F51B5;}li[data-type='german']{background:#bb6666;}

效果图:

创建工具提示

你可以使用工具提示向用户显示一些与元素相关的附加信息。但是因为纯CSS的工具提示不能完全使用,所以我建议你在简单的模型上使用这种方法而不是在一个产品型的网站上。

你要显示的信息可以存储在一个data-tooltip属性中。

<spandata-tooltip="Asimpleexplanation">Word</span>

然后,你可以使用::before伪元素将数据呈现给用户。

span::before{content:attr(data-tooltip);//其余的样式规则}span:hover::before{display:inline-block;}

HTML代码:

<p>Thegraywolf,alsoknownasthe<spanclass="tooltip"data-tooltip="somemoreinformation"><spanclass="tooltip-info">somemoreinformation</span>timberwolf</span>orwesternwolf,isacaninenativetothewildernessandremoteareasofEurasiaand<spanclass="tooltip"data-tooltip="somemoreinformation"><spanclass="tooltip-info">somemoreinformation</span>NorthAmerica</span>.Itisthelargestextantmemberofitsfamily,withmalesaveraging43–45kg(95–99lb),andfemales36–38.5kg(79–85lb).Liketheredwolf,itisdistinguishedfromother<spanclass="tooltip"data-tooltip="somemoreinformation"><spanclass="tooltip-info">somemoreinformation</span>Canisspecies</span>byitslargersizeandlesspointedfeatures,particularlyontheearsandmuzzle.</p>

CSS代码:

html{font-family:'Lato';margin:20pxauto;line-height:1.5;max-width:600px;font-size:1.25em;}span.tooltip{padding:0px5px;position:relative;background:#FFBB99;cursor:pointer;}.tooltip-info{position:absolute;top:-9999px;left:-9999px;}span.tooltip::before{content:attr(data-tooltip);position:absolute;top:1.5em;font-size:0.9em;padding:1px5px;display:none;color:white;background:rgba(0,0,0,0.75);border-radius:4px;transition:opacity0.1sease-out;z-index:99;text-align:left;}span:hover::before{display:inline-block;}

效果图(鼠标移入淡红色的区域会出黑色背景的提示):

使用JavaScript访问数据属性

在JavaScript中有三种方式访问数据属性。

使用getAttribute和setAttribute

你可以使用JavaScript中的getAttribute()setAttribute()来获取和设置不同数据属性的值。

如果给定的属性不存在,该getAttribute方法将返回null或一个空字符串。以下是使用这些方法的示例:

varrestaurant=document.getElementById("restaurantId");varratings=restaurant.getAttribute("data-ratings");

你可以使用该setAttribute方法修改现有属性的值或添加新属性。

restaurant.setAttribute("data-owner-name","someName");使用dataset属性

访问数据属性的一种更为简单的方法是借助dataset属性。此属性返回一个DOMStringMap对象,此对象拥有一个包含所有自定义数据属性的目录。

使用dataset属性时,你应该记住下面这些步骤:

将自定义数据属性转换为DOMStringMap的键值需要三个步骤:

将该data-前缀从属性名中删除

将任何后跟小写字母的连字符从名称中删除,并将其后面的字母转换为大写字母(即驼峰命名法——译者注)

其他字符保持不变。这意味着任何没有被小写字母跟着的连字符也将保持不变。

然后可以使用存储在对象中按照驼峰命名法命名的名称作为键来访问属性,如element.dataset.keyname

访问属性的另一种方法是使用括号符号,如element.dataset[keyname]

考虑以下的HTML代码:

<lidata-type="veg"data-distance="2miles"data-identifier="10318"data-owner-name="someName">SaladKing</li>

以下是几个例子:

varrestaurant=document.getElementById("restaurantId");varratings=restaurant.dataset.ratings;restaurant.dataset.ratings=newRating;varowner=restaurant.dataset['ownerName'];restaurant.dataset['ownerName']='newOwner';

现在所有的主流浏览器都支持这种方法。相比之前访问自定义数据属性的方法,你应该更喜欢这种方法。

使用 jQuery

你也可以使用jQuery的data()方法来访问元素的数据属性。在jQuery1.6之前,你必须使用以下代码来访问数据属性:

varrestaurant=$("#restaurantId");varowner=restaurant.data("owner-name");restaurant.data("owner-name","newName");

从版本1.6开始,jQuery使用驼峰命名法版本的数据属性。现在,你可以使用以下代码来做同样的事情:

varrestaurant=$("#restaurantId");varowner=restaurant.data("ownerName");restaurant.data("ownerName","newName");

你应该知道,jQuery内部还试图将从数据属性中获取的字符串转换成合适的类型,如数字,布尔值,对象,数组和空值等。

varrestaurant=$("#restaurantId");varidentifier=restaurant.data("identifier");console.log(typeofidentifier);//number

如果你希望jQuery以字符串的形式获取属性的值,而不用尝试将其转换为其他类型,则应该使用jQuery的attr()方法。

jQuery仅在第一次访问时检索数据属性的值。以后不再访问或更改数据属性的值。你对这些属性所做的所有更改都会在内部进行,并且只能使用jQuery访问。

假设你正在操作以下列表项的数据属性:

<liid="salad"data-type="veg"data-distance="2miles"data-identifier="10318">SaladKing</li>

你可以使用以下代码更改其data-distance属性的值:

vardistance=$("#salad").data("distance");console.log(distance);//"2miles"$("#salad").data("distance","1.5miles");console.log(distance);//"1.5miles"document.getElementById("salad").dataset.distance;//"2miles"

你可以看到,使用普通的JavaScript(不是jQuery)获取属性data-distance的值返回给我们的一直是旧的结果。