欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

【前端特辑】探索a链接实践奥秘

程序员文章站 2022-03-11 21:50:30
见过a标签各种“千奇百怪”的写法,也探索过它的各种用法;于是迫不及待地想要分享出来 —— 这个在我看来html中最“好玩”的一个标签。...

见过a标签各种“千奇百怪”的写法,也探索过它的各种用法;于是迫不及待地想要分享出来 —— 这个在我看来html中最“好玩”的一个标签。


先来康康“朴实无华”a标签:
【前端特辑】探索a链接实践奥秘
a是行内元素!


a标签实现刷新页面和跳转刷新

你可能会想:这是个什么奇怪的需求?但是它确实发生了:笔者在一个项目中曾接到这样的需求 —— 需要在页面上有一个特定形状的按钮并给用户以提示刷新当前页面。

我首先想到的肯定是<button>啊:因为提示了“按钮”。但很快我就不这么认为了 —— 考虑到浏览器兼容性以及button原生样式问题,在每一次写button之前都至少要加这么一段代码:

margin: 0;
padding: 0;
/*自定义边框*/
border: 0;
/*消除默认点击蓝色边框效果*/
outline: none;
-webkit-appearence: none;

然后再去覆盖。
input —— 不管是 type="button" 还是 type="checkbox" 也都要进行重置。

这时候就显示出a链接的厉害了 —— 它只有一条多余的下划线,去除即可。
比如在circle.html中:

<a href="circle.html">刷新</a>

光凭上面这点可吸引不到我 —— 你可能不知道的是:a标签的target属性中是可以放具体的URL地址的
它的特点是:如果浏览器已经有标签页的地址是circle.html,则点击链接并不会打开新窗口,是直接刷新已经打开的circle.html(而不是打开一个新窗口!);如果浏览器中没有地址是circle.html的标签页,则此时target属性的行为表现类似 '_blank'

这个特点有什么应用呢?
假如有这么个链接:

<a href="circle.html?s=list" target="_search">成绩排名</a>

<!-- 或者 -->
<a href="circle.html?s=list" target="circle.html?s=list">成绩排名</a>

它指向一个新页面,而这个页面是你的网站某个页面答题环节的排名。根据上面的特点,你是否能想到:在每次答完题后点击提交时去触发这个链接就能跳转到排名页面 —— 不管它是否已经存在,并且刷新得到当前排名?
而不再需要Server-Sent Events或者web socket甚至是ajax轮询的使用!

比如这样:

【前端特辑】探索a链接实践奥秘

(:如果跳转后不能刷新页面,则可把target链接中“?”及后面删掉(也就是没有search参数)即可 —— target指向(任意)一个一样的字符串,这没什么。


a链接实现下载文件

关于这方面,笔者最早是在“canvas图片压缩”中使用,并且在遇到最近这个需求之前甚至以为这么用就足够了:
在html5时代,a标签中多了一个属性 —— download,用于下载href中的链接(在线)文件。
拿canvas来说,经过 ctx.drawImage(...)ctx.fillText(...) 之后得到的是一个“类图片”格式,这时候怎么拿到href中?

js提供了一些转化为URL的方法:
canvas.toDataURL("image/png") ——对canvas
URL.createObjectURL() ——对大部分js对象
fileReader.readAsDataURL() ——对文件对象

var Imgload = function (domImg, filename="photo.png") {
    // 创建隐藏的可下载链接
    var eleLink = document.createElement('a');
    eleLink.download = filename; // 设置图片名称;
    eleLink.style.display = 'none';
    // 图片转base64地址
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    var width = domImg.naturalWidth;
    var height = domImg.naturalHeight;
    ctx.drawImage(domImg, 0, 0);
    // 如果是或要转为PNG,则可用canvas.toDataURL('image/png')
    eleLink.href = canvas.toDataURL('image/jpeg');
    // 触发点击
    document.body.appendChild(eleLink);
    eleLink.click();
    // 然后移除
    document.body.removeChild(eleLink);
};

类似地,对于其它格式的文件,可以将文本或者JS字符串信息借助Blob转换成二进制,然后,作为<a>元素的href属性,配合download属性,实现下载。

巧的是,js也提供了一些转化为blob的api:
xhr.responseType="blob" ——用于ajax请求中
new Blob([...]) ——用于一般js实例(甚至是arraybuffer实例)
一般来说,blob对象被用来转化为URL

比如:将html代码下载为html文件

/**
	content:文本内容
	filename:下载到系统中的文件名称
*/
var Fileload = function (content, filename) {
    // 创建隐藏的可下载链接
    var eleLink = document.createElement('a');
    eleLink.download = filename;
    eleLink.style.display = 'none';
    // 字符内容转变成blob地址
    var blob = new Blob([content]);
    eleLink.href = URL.createObjectURL(blob);
    // 触发点击
    document.body.appendChild(eleLink);
    eleLink.click();
    // 然后移除
    document.body.removeChild(eleLink);
};

【前端特辑】探索a链接实践奥秘

当然,有些时候你并不想下载单个文件 —— 比如压缩包下载(文件夹是不可能的,这辈子都不可能✧(≖ ◡ ≖✿ )!
「在闲逛GitHub时,发现了一个比较流批的开源项目:jszip ,可用于ZIP打包下载。(好多星星,我慕了。。。)」


a链接在某些情况下的缺陷及其替代

这个应该是比较常见的了:简单来说就是 —— 点击某个链接,跳转到对应页面。

但一般不只是这么做,否则我也不会写这篇文章了!
常见的比如一个学校的介绍div,里面有图片、名称、简介,一般这种都是出现在机构的问卷之类的活动页中,所以还能看到点赞(支持度)。就有要求了:点击整体要跳转到学校的官网,但是如果点击的是“简介”部分,就跳转到“百度百科”中。

再复杂一点的还有:点击“点赞”,跳转到投票页面、点击图片跳转到学校风光页面等等。。。

你是否知道:<a>不支持自身嵌套

<a href="#destiny">
	nyist
	<a href="#communite">
		uc
	</a>
</a>

显示出来却是这样的:
【前端特辑】探索a链接实践奥秘
同级?!

这时候,如果我们有链接嵌套的需求,就可以试试使用<area>元素(“热点区域”)!如上面所说的场景:

【前端特辑】探索a链接实践奥秘

以前比较好的方法是通过CSS重新布局定位/浮动改变DOM结构和顺序,使链接内容变成相邻关系,虽然麻烦了点,但在语义和无障碍方面还是很好的;或者使用普通元素,用js为每个“独立元素”分配事件;或者是使用JS,点击目标区域时用 preventDefault 阻止默认事件,然后再 location.href 跳转。

实际上,还有一种更好的做法,就是<a>元素中嵌套<area>元素,可以保证DOM结构符合视觉呈现,又无需JS辅助。

比如图片热点的使用,就是借助<map><area>元素在图片上创造点击热点,把整个图片区域都作为点击热点,既能充分发挥<area>标签本身的特性,又没有什么兼容性问题,键盘访问等都非常良好,还可满足我们链接嵌套功能:

<img src="./img/nan.png" class="book-cover" alt="南阳理工学院" usemap="#bookCover">
<map id="bookCover" name="bookCover">
    <area hidefocus="true" shape="rect" coords="0,0,80,107" href="https://image.baidu.com/search/index?tn=baiduimage&ct=201326592&lm=-1&cl=2&ie=gb18030&word=%C4%CF%D1%F4%C0%ED%B9%A4&fr=ala&ala=1&alatpl=adress&pos=0&hs=2&xthttps=000000" alt="南阳理工学院" target="_blank">
</map>

而标题文字的链接内嵌处理则要麻烦一些。笔者的做法是:在文字前面直接放置了一个裸的<area>元素,通过CSS设置覆盖文字实现的:

<h4 class="book-title">
    <area class="area" href="https://baike.baidu.com/item/%E5%8D%97%E9%98%B3%E7%90%86%E5%B7%A5%E5%AD%A6%E9%99%A2/249491?fromtitle=%E5%8D%97%E9%98%B3%E7%90%86%E5%B7%A5&fromid=1973960&fr=aladdin" target="_blank">
    南阳理工学院
</h4>
.book-title{
	margin: 0;
	float: left;
	position: relative;

}
.area{
	position: absolute;
	left: 0;
	top: 0;
	width: 100%;
	height: 100%;
}

注意:
area的使用必须和map标签一起,且map作为父元素 -> <map> 标签用于客户端图像映射(图像映射指带有可点击区域的一幅图像),<area> 标签定义图像映射内部的区域,且<area> 元素始终嵌套在 <map> 标签内部;
<img> 标签通过 usemap 属性与 <map> 元素中的 name 相关联;
<area>元素是空标签,不支持子元素,只能采用css覆盖或者伪元素(::before 等)的形式

案例代码及效果查看:JSBin在线编译器

更新↓
但是当一切“尘埃落定”,我无意中用火狐浏览器打开了这个页面:
【前端特辑】探索a链接实践奥秘

标题和整体部分怎么跳转到一个页面去了?
上网搜查这个问题时发现 张鑫旭的这篇文章 1 已有研究,并提出:Firefox浏览器不支持area标签覆盖文字(Firefox的<area>元素默认display:none,且无法重置)。

张大也提出了一种解决方法:使用透明图片覆盖的方式实现文字的链接嵌套,也就是把原本裸露的<area>换成<img>,然后再使用<area>元素创建图片热点。

<h4 class="book-title">
    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" class="area" usemap="mapTitle">
    南阳理工学院
</h4>
<map id="mapTitle" name="mapTitle">
    <area shape="rect" coords="0,0,200,21" href="https://baike.baidu.com/item/%E5%8D%97%E9%98%B3%E7%90%86%E5%B7%A5%E5%AD%A6%E9%99%A2/249491?fromtitle=%E5%8D%97%E9%98%B3%E7%90%86%E5%B7%A5&fromid=1973960&fr=aladdin" target="_blank">
</map>

就能达到和想要的一样的效果了!
(:嘿嘿,和笔者在之前一篇css文章中提出的方法一样


  1. 张大的这篇文章中也提到了关于area的其它实践,有兴趣可以品尝一下,感觉怎么说呢:妙不可言! ↩︎

本文地址:https://blog.csdn.net/qq_43624878/article/details/109722712