在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,我们的需求已经实现了。分享就到这里,希望对你有所帮助。

相关推荐
tonysh_zds2 小时前
antdesign对话框输出html格式
前端·javascript·html
ClareXi3 小时前
react项目通过http调用后端springboot服务最简单示例
spring boot·react.js·http
八眼鱼11 小时前
css冒泡效果,使用动画实现
css·html·css3
赵闪闪16811 小时前
使用纯HTML和CSS绘制圣诞树:打造网页中的冬日奇景
前端·css·html
咔咔库奇14 小时前
react动态路由
前端·react.js·前端框架
yqcoder16 小时前
react 中 FC 模块作用
前端·react.js·前端框架
刘志辉16 小时前
react的创建与书写
前端·react.js·前端框架
One_Blanks17 小时前
网络安全-HTML基础
前端·安全·html
豆包MarsCode17 小时前
使用 Vue 配合豆包MarsCode 实现“小恐龙酷跑“小游戏
开发语言·前端·javascript·vue.js·html
凉风听雪18 小时前
免费HTML模板和CSS样式网站汇总
前端·javascript·css·html