在HTML中如何在一个新窗口打开多个的页面

遇到一个有趣需求,需要将页面内的一些链接按照规则判断是否需要打开新的窗口或使用已存在的窗口,如:当前存在的链接格式为 www.autohome.com.cn/[path]/[x]...., 当path相同时,使用已存在的窗口打开新的页面,否则打开新的窗口。

graph TD A[用户点击链接] -->|判断是否存path的窗口| B(存在) A -->|不存在| C(打开新的窗口) B -->|path相同| D(使用已存在的窗口打开新的页面) B -->|path不同| C

1. 使用window.open打开新的窗口

window.open 是我们熟知打开新的窗口的方法。open(url, target, windowFeatures) 方法第一个参数url是要打开的URL,第二个参数target是窗口的名字,第三个参数windowFeatures是窗口的属性。更多信息查看MDN

1.1 target参数

target 一个不含空格的字符串,用于指定加载资源的浏览上下文的名称。如果该名称无法识别现有的上下文,则会创建一个新的上下文,并赋予指定的名称。还可以使用特殊的 target 关键字:_self_blank_parent_top该名称可用作 <a> 或 <form> 元素的 target 属性。

tsx 复制代码
const article = [{
  title: 'A 路径 / 1.html',
  path: 'https://www.autohome.com.cn/A/1.html',
}, {
  title: 'B 路径 / 1.html',
  path: 'https://www.autohome.com.cn/B/1.html',
}, {
  title: 'A 路径 / 2.html',
  path: 'https://www.autohome.com.cn/A/2.html',
}, {
  title: 'B 路径 / 2.html',
  path: 'https://www.autohome.com.cn/B/2.html',
}]

export default function App() {
  return (
    <ul>
      {article.map((item) => {
        return (
          <li
            key={item.path}
            onClick={() => {
              {/* window.open 的第二个参数 target 将会为 "A" 或 "B" */}
              window.open(item.path, new URL(item.path).pathname.split('/')?.[1])
            }}
          >
            {item.title}
          </li>
        );
      })}
    </ul>
  );
}

分别点击以上的链接,我们会发现,当点击第一个和第三个链接时,会在同一个窗口打开页面,而点击第二个和第四个链接时,会在同一窗口打开新的页面。点击上面所有链接后,我们会发现,浏览器只新打开了两个窗口。

2. 使用<a>标签打开新的窗口

使用 window.open 会对SEO(搜索引擎优化)有一些影响,因为使用 window.open 打开的页面,搜索引擎不会对其进行抓取。所以我们期望可以使用 <a> 标签的 target 属性来打开新的窗口。

2.1 <a> 标签的 target 属性

我们熟知的 <a> 标签的 target 属性有以下几个值:

  • _self 默认值,当前窗口打开
  • _blank 新窗口打开
  • _parent 父窗口打开
  • _top 顶层窗口打开

MDN 中介绍 windown.open 中的 target 参数中我们可以看到 target参数名称可用作 <a> 或 <form> 元素的 target 属性。, <a> 标签的 targetwindow.opentarget 参数一样,可以指定一个窗口的名字。

tsx 复制代码
const article = [{
  title: 'A 路径 / 1.html',
  path: 'https://www.autohome.com.cn/A/1.html',
}, {
  title: 'B 路径 / 1.html',
  path: 'https://www.autohome.com.cn/B/1.html',
}, {
  title: 'A 路径 / 2.html',
  path: 'https://www.autohome.com.cn/A/2.html',
}, {
  title: 'B 路径 / 2.html',
  path: 'https://www.autohome.com.cn/B/2.html',
}]

export default function App() {
  return (
    <ul>
      {article.map((item) => {
        return (
          <li
            key={item.path}
          >
            <a
              href={item.path}
              {/* 这里的 target 将会为 "A" 或 "B" */}
              target={new URL(item.path).pathname.split('/')?.[1]}
            >
              {item.title}
            </a>
          </li>
        );
      })}
    </ul>
  );
}

结果是可喜的,点击所有链接后,浏览器只新打开了两个窗口。

封装成一个组件

接下来我们考虑将这个功能封装成一个组件。解决一下 target="A"target="B" 属性暴露以及target生成方法优化。

tsx 复制代码
// 简单的封装
export default function ALink(props: {
  children: React.ReactNode;
  href: string;
  [key: string]: any;
}) {
  const { children, href, target = '_self' } = props;
  return (
    <a
      href={props.href}
      target={props.target}
      onClick={(e) => {
        e.preventDefault();
        if(target != '_blank') {
          window.open(href, target);
        } else {
          window.open(href, new URL(href).pathname.split('/')?.[1]);
        }
      }}
    >
      {children}
    </a>
  );
}
tsx 复制代码
// 使用
import ALink from './ALink';

const article = [{
  title: 'A 路径 / 1.html',
  path: 'https://www.autohome.com.cn/A/1.html',
}, {
  title: 'B 路径 / 1.html',
  path: 'https://www.autohome.com.cn/B/1.html',
}, {
  title: 'A 路径 / 2.html',
  path: 'https://www.autohome.com.cn/A/2.html',
}, {
  title: 'B 路径 / 2.html',
  path: 'https://www.autohome.com.cn/B/2.html',
}]

export default function App() {
  return (
    <ul>
      {article.map((item) => {
        return (
          <li
            key={item.path}
          >
            <ALink
              href={item.path}
              target="_blank"
            >
              {item.title}
            </ALink>
          </li>
        );
      })}
    </ul>
  );
}

看下在浏览器中的效果:

Nice,我们的需求已经实现了。分享就到这里,希望对你有所帮助。

相关推荐
太阳花ˉ1 小时前
html+css+js实现step进度条效果
javascript·css·html
小白学习日记2 小时前
【复习】HTML常用标签<table>
前端·html
道爷我悟了3 小时前
Vue入门-指令学习-v-html
vue.js·学习·html
l1x1n06 小时前
No.3 笔记 | Web安全基础:Web1.0 - 3.0 发展史
前端·http·html
zqx_77 小时前
随记 前端框架React的初步认识
前端·react.js·前端框架
神之王楠9 小时前
如何通过js加载css和html
javascript·css·html
茶卡盐佑星_10 小时前
meta标签作用/SEO优化
前端·javascript·html
金灰10 小时前
HTML5--裸体回顾
java·开发语言·前端·javascript·html·html5
Zheng11312 小时前
【可视化大屏】将柱状图引入到html页面中
javascript·ajax·html