▼ 关注「之家前端共享」,获取更多技术干货 ▼
遇到一个有趣需求,需要将页面内的一些链接按照规则判断是否需要打开新的窗口或使用已存在的窗口,如:当前存在的链接格式为 www.autohome.com.cn/[path]/[x].… , 当path相同时,使用已存在的窗口打开新的页面,否则打开新的窗口。
window.open 是我们熟知打开新的窗口的方法。open(url, target, windowFeatures) 方法第一个参数url是要打开的URL,第二个参数 target 是窗口的名字,第三个参数 windowFeatures 是窗口的属性。更多信息查看MDN:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/open
target
参数target
一个不含空格的字符串,用于指定加载资源的浏览上下文的名称。如果该名称无法识别现有的上下文,则会创建一个新的上下文,并赋予指定的名称。还可以使用特殊的 target 关键字:_self
、_blank
、_parent
和_top
。该名称可用作 <a> 或 <form> 元素的 target 属性
。
1const article = [{
2 title: 'A 路径 / 1.html',
3 path: 'https://www.autohome.com.cn/A/1.html',
4}, {
5 title: 'B 路径 / 1.html',
6 path: 'https://www.autohome.com.cn/B/1.html',
7}, {
8 title: 'A 路径 / 2.html',
9 path: 'https://www.autohome.com.cn/A/2.html',
10}, {
11 title: 'B 路径 / 2.html',
12 path: 'https://www.autohome.com.cn/B/2.html',
13}]
14
15export default function App() {
16 return (
17 <ul>
18 {article.map((item) => {
19 return (
20 <li
21 key={item.path}
22 onClick={() => {
23 {/* window.open 的第二个参数 target 将会为 "A" 或 "B" */}
24 window.open(item.path, new URL(item.path).pathname.split('/')?.[1])
25 }}
26 >
27 {item.title}
28 </li>
29 );
30 })}
31 </ul>
32 );
33}
分别点击以上的链接,我们会发现,当点击第一个和第三个链接时,会在同一个窗口打开页面,而点击第二个和第四个链接时,会在同一窗口打开新的页面。点击上面所有链接后,我们会发现,浏览器只新打开了两个窗口。这样做还有一些缺陷,继续探究...
使用 window.open 会对SEO(搜索引擎优化)有一些影响,因为使用 window.open 打开的页面,搜索引擎不会对其进行抓取。所以我们期望可以使用 <a> 标签的 target 属性来打开新的窗口。
<a>
标签的 target
属性我们熟知的 <a> 标签的 target 属性有以下几个值:
_self 默认值,当前窗口打开
_blank 新窗口打开
_parent 父窗口打开
_top 顶层窗口打开
在 MDN 中介绍 windown.open 中的 target 参数中我们可以看到 target参数名称可用作 <a> 或 <form> 元素的 target 属性, <a> 标签的 target 同window.open 的 target 参数一样,可以指定一个窗口的名字。
1const article = [{
2 title: 'A 路径 / 1.html',
3 path: 'https://www.autohome.com.cn/A/1.html',
4}, {
5 title: 'B 路径 / 1.html',
6 path: 'https://www.autohome.com.cn/B/1.html',
7}, {
8 title: 'A 路径 / 2.html',
9 path: 'https://www.autohome.com.cn/A/2.html',
10}, {
11 title: 'B 路径 / 2.html',
12 path: 'https://www.autohome.com.cn/B/2.html',
13}]
14
15export default function App() {
16 return (
17 <ul>
18 {article.map((item) => {
19 return (
20 <li
21 key={item.path}
22 >
23 <a
24 href={item.path}
25 {/* 这里的 target 将会为 "A" 或 "B" */}
26 target={new URL(item.path).pathname.split('/')?.[1]}
27 >
28 {item.title}
29 </a>
30 </li>
31 );
32 })}
33 </ul>
34 );
35}
结果是可喜的,符合所有预期结果。
还没完>>>
接下来我们考虑将这个功能封装成一个组件。解决一下 target="A" 或 target="B" 属性暴露以及target生成方法优化。
1// 简单的封装
2export default function ALink(props: {
3 children: React.ReactNode;
4 href: string;
5 [key: string]: any;
6}) {
7 const { children, href, target = '_self' } = props;
8 return (
9 <a
10 href={props.href}
11 target={props.target}
12 onClick={(e) => {
13 e.preventDefault();
14 if(target != '_blank') {
15 window.open(href, target);
16 } else {
17 window.open(href, new URL(href).pathname.split('/')?.[1]);
18 }
19 }}
20 >
21 {children}
22 </a>
23 );
24}
1// 使用
2import ALink from './ALink';
3
4const article = [{
5 title: 'A 路径 / 1.html',
6 path: 'https://www.autohome.com.cn/A/1.html',
7}, {
8 title: 'B 路径 / 1.html',
9 path: 'https://www.autohome.com.cn/B/1.html',
10}, {
11 title: 'A 路径 / 2.html',
12 path: 'https://www.autohome.com.cn/A/2.html',
13}, {
14 title: 'B 路径 / 2.html',
15 path: 'https://www.autohome.com.cn/B/2.html',
16}]
17
18export default function App() {
19 return (
20 <ul>
21 {article.map((item) => {
22 return (
23 <li
24 key={item.path}
25 >
26 <ALink
27 href={item.path}
28 target="_blank"
29 >
30 {item.title}
31 </ALink>
32 </li>
33 );
34 })}
35 </ul>
36 );
37}
感兴趣的同学 去试试吧>>>
▼ 关注「之家前端共享」,获取更多技术干货 ▼