当前位置: 首页 > news >正文

前端构建URL的几种方法比对,以及函数实现

当我们在前端开发中处理 URL 时,可能会用到字符串拼接、ES6 模板语法 (template literals) 或者使用 new URL() 构造函数。这三者各有优劣,适用于不同的场景。

1. 字符串拼接与 ES6 模板语法

字符串拼接ES6 模板语法 都是将不同的字符串片段组合在一起生成 URL。区别在于语法上:

  • 字符串拼接 使用 + 号:

    const baseUrl = "https://example.com";
    const path = "/api/data";
    const query = "?id=123";
    const fullUrl = baseUrl + path + query;
    
  • ES6 模板语法 使用反引号和 ${} 插入变量:

    const baseUrl = "https://example.com";
    const path = "/api/data";
    const query = "?id=123";
    const fullUrl = `${baseUrl}${path}${query}`;
    

优点:

  • 简单、直观,适合拼接简单的字符串。

缺点:

  • 对于复杂的 URL(如需要处理相对路径、不同的协议、查询参数编码等),容易出错且难以维护。
  • 手动拼接可能会忽略一些细节,比如自动编码特殊字符等需要enUrlcode。

2. new URL() 构造函数

new URL() 是一个更强大的方式,用于生成和解析 URL。它不仅可以拼接 URL,还可以处理 URL 的各个组成部分(协议、主机、路径、查询参数等),并且可以自动处理编码、路径规范化等问题。

const baseUrl = "https://example.com";
const path = "/api/data";
const query = "?id=123";
const fullUrl = new URL(path + query, baseUrl);console.log(fullUrl.toString()); // "https://example.com/api/data?id=123"

优点:

  • 自动处理 URL 的规范化和编码。
  • 允许直接操纵 URL 的各个部分(如更改查询参数、路径等)。
  • 适用于处理复杂 URL 或需要确保 URL 结构正确的场景。

缺点:

  • 相对来说,写法稍显复杂,尤其在处理简单 URL 时。

什么时候使用哪种方法?

  • 简单拼接:对于简单的 URL,字符串拼接或模板语法通常就足够了,尤其是在你非常确定路径和参数不会产生问题时。

  • 复杂 URL 操作:如果需要处理 URL 的不同部分,或要确保生成的 URL 是有效的(尤其是在处理用户输入或多个路径时),使用 new URL() 更加安全和可靠。

总结

  • 简单场景:字符串拼接或 ES6 模板语法。
  • 复杂场景new URL() 构造函数。

这两种方法没有绝对的优劣,关键是选择适合场景的工具。


详解new URL()参数使用

new URL() 构造函数在处理 URL 时非常强大和灵活,它不仅可以帮助我们构建 URL,还能解析和操作 URL 的各个部分。下面是对它的使用参数和能力的详解。

1. new URL() 构造函数的参数

new URL() 可以接收两个参数:

  1. 第一个参数(必选):表示目标 URL 的路径或完整的 URL 字符串。

    • 如果是完整的 URL,则直接使用。
    • 如果是相对路径,则需要结合第二个参数来解析为完整的 URL。
  2. 第二个参数(可选):表示基准 URL(base URL)。如果第一个参数是相对路径,那么会基于这个 URL 解析出完整的 URL。

示例 1:使用完整 URL
const url = new URL('https://example.com/path?name=value#hash');
console.log(url.toString()); // "https://example.com/path?name=value#hash"
示例 2:使用相对路径和基准 URL
const url = new URL('/path?name=value#hash', 'https://example.com');
console.log(url.toString()); // "https://example.com/path?name=value#hash"

2. new URL() 的能力与方法

一旦使用 new URL() 创建了 URL 对象,它会暴露出一些属性和方法,这些可以用来操作和查询 URL 的不同部分。

2.1. 属性
  • href:整个 URL 字符串。

    console.log(url.href); // "https://example.com/path?name=value#hash"
    
  • origin:协议、域名和端口号的组合。

    console.log(url.origin); // "https://example.com"
    
  • protocol:URL 的协议部分(包括结尾的冒号 :)。

    console.log(url.protocol); // "https:"
    
  • host:主机部分(域名和端口号,如果有)。

    console.log(url.host); // "example.com"
    
  • hostname:主机名部分(不包括端口号)。

    console.log(url.hostname); // "example.com"
    
  • port:端口号(如果有)。

    const urlWithPort = new URL('https://example.com:8080/path');
    console.log(urlWithPort.port); // "8080"
    
  • pathname:路径部分。

    console.log(url.pathname); // "/path"
    
  • search:查询字符串部分(包括开头的问号 ?)。

    console.log(url.search); // "?name=value"
    
  • searchParamsURLSearchParams 对象,允许操作查询参数。

    console.log(url.searchParams.get('name')); // "value"
    url.searchParams.append('age', '25');
    console.log(url.search); // "?name=value&age=25"
    
  • hash:哈希部分(包括开头的 #)。

    console.log(url.hash); // "#hash"
    
2.2. 方法
  • toString():返回 URL 的字符串表示,等同于 href 属性。

    console.log(url.toString()); // "https://example.com/path?name=value#hash"
    
  • toJSON():返回 URL 的字符串表示,适合 JSON 序列化。

    console.log(url.toJSON()); // "https://example.com/path?name=value#hash"
    

3. 常见用法示例

3.1. 动态构建 URL
const baseUrl = 'https://example.com';
const url = new URL('/api/data', baseUrl);
url.searchParams.append('id', '123');
url.searchParams.append('filter', 'active');
console.log(url.toString()); // "https://example.com/api/data?id=123&filter=active"
3.2. 操作查询参数
const url = new URL('https://example.com/api/data?id=123&filter=active');
console.log(url.searchParams.get('id')); // "123"
url.searchParams.set('id', '456'); // 修改参数
url.searchParams.delete('filter'); // 删除参数
console.log(url.toString()); // "https://example.com/api/data?id=456"
3.3. 处理相对路径
const baseUrl = 'https://example.com/some/path/';
const url = new URL('../other/path', baseUrl);
console.log(url.toString()); // "https://example.com/some/other/path"

4. 使用场景

  • 处理动态查询参数:可以轻松添加、修改或删除查询参数。
  • 解析和操作 URL:从 URL 中提取信息或修改其中的部分。
  • 构建完整的 URL:基于基准 URL 生成新的完整 URL,适合 RESTful API 或页面导航等场景。

通过 new URL(),我们可以更好地管理和操作 URL,使代码更健壮和易于维护。比如以下实际场景中的使用


拼接数组参数
假设我们有一个URL,需要将一个数组作为查询参数添加到URL中。

const baseUrl = 'https://example.com';
const url = new URL(baseUrl);const arrayParam = ['value1', 'value2', 'value3'];
// 将数组转换为逗号分隔的字符串
url.searchParams.set('array', arrayParam.join(','));console.log(url.toString()); // https://example.com/?array=value1,value2,value3

解析数组参数
当我们获取URL并需要解析其中的数组参数时,可以使用URLSearchParams对象进行解析。

const urlString = 'https://example.com/?array=value1,value2,value3';
const url = new URL(urlString);const arrayParamString = url.searchParams.get('array');
// 将逗号分隔的字符串转换回数组
const arrayParam = arrayParamString ? arrayParamString.split(',') : [];console.log(arrayParam); // ['value1', 'value2', 'value3']

处理多个同名参数
有时我们可能会遇到需要处理多个同名参数的情况,例如?array=value1&array=value2&array=value3。可以使用URLSearchParamsgetAll方法:

// 拼接多个同名参数到URL
const url = new URL(baseUrl);const arrayParam = ['value1', 'value2', 'value3'];
arrayParam.forEach(value => url.searchParams.append('array', value));console.log(url.toString()); // https://example.com/?array=value1&array=value2&array=value3// 解析多个同名参数从URL
const urlString = url.toString();
const parsedUrl = new URL(urlString);const parsedArrayParam = parsedUrl.searchParams.getAll('array');console.log(parsedArrayParam); // ['value1', 'value2', 'value3']

但实际情况往往比上面的示例更复杂,比如参数是一个对象、根据实际情况来设置参数的值、要处理undefined0'0'Boolean'true'NaN等不同类型和异常的值,每次使用时都去处理显然是不合理的,这时候就可以将拼接和移除参数的函数封装成方法来使用。

/*** 获取URL查询参数并返回一个对象,支持数组* @param {string} urlString - 需要解析的URL字符串* @returns {Object} - 包含查询参数的对象*/
function getURLParams(urlString) {const url = new URL(urlString);const params = new URLSearchParams(url.search);const result = {};for (const [key, value] of params.entries()) {if (result[key]) {if (Array.isArray(result[key])) {result[key].push(value);} else {result[key] = [result[key], value];}} else {result[key] = value;}}return result;
}/*** 设置URL的查询参数,支持对象和数组* @param {string} urlString - 基础URL字符串* @param {Object} params - 需要设置的查询参数对象* @returns {string} - 带有查询参数的URL字符串*/
function setURLParams(urlString, params) {const url = new URL(urlString);const searchParams = new URLSearchParams();for (const key in params) {if (params.hasOwnProperty(key)) {const value = params[key];if (Array.isArray(value)) {value.forEach(val => {if (val !== undefined && !Number.isNaN(val)) {searchParams.append(key, val);} else {console.warn(`Warning: The value of "${key}" is ${val}, which is invalid and will be ignored.`);}});} else if (value !== undefined && !Number.isNaN(value)) {searchParams.append(key, value);} else {console.warn(`Warning: The value of "${key}" is ${value}, which is invalid and will be ignored.`);}}}url.search = searchParams.toString();return url.toString();
}// 测试用例
const baseUrl = 'https://example.com';// 测试 getURLParams 方法
const testUrl = 'https://example.com/?param1=value1&param2=value2&param2=value3';
const parsedParams = getURLParams(testUrl);
console.log(parsedParams); // { param1: 'value1', param2: ['value2', 'value3'] }// 测试 setURLParams 方法
const params = {param1: 'value1',param2: ['value2', 'value3'],param3: undefined,param4: NaN,param5: 'value5',param6: 0,
};const newUrl = setURLParams(baseUrl, params);
console.log(newUrl); // 'https://example.com/?param1=value1&param2=value2&param2=value3&param5=value5'

实现一个url解析参数和拼接参数的功能。这时候一个简单的解析和拼接的函数就可以搞定。
当然方法有多种实现方式,下面还有一种通过正则来实现的,但下面拼接的时候会忽略数字0,所以参数一定要用字符串。

/*** 合并查询参数到 URL 的函数* 将给定的查询对象 Query 合并到指定的 URL 中** @param {Object} query - 要合并到 URL 中的查询对象* @param {string} url - 作为基础的 URL,默认为当前页面的 URL* @returns {string} 生成的合并查询参数后的新 URL*/
export function getUrlMergeQuery(query = {}, url) {url = url || window.location.hrefconst _orgQuery = getQueryObject(url)const _query = {..._orgQuery,...query }let _arr = []for (let key in _query) {const value = _query[key]if (value) _arr.push(`${key}=${encodeURIComponent(_query[key])}`)}return `${url.split('?')[0]}${_arr.length > 0? `?${_arr.join('&')}` : ''}`
}/*** 从 URL 中提取查询参数对象** @param {string} [url=window.location.href] - 要解析的 URL 字符串。如果未提供,则使用当前页面的 URL* @returns {Object} - 包含提取的查询参数的对象*/
export function getQueryObject(url = window.location.href) {const search = url.substring(url.lastIndexOf('?') + 1);const obj = {};const reg = /([^?&=]+)=([^?&=]*)/g;search.replace(reg, (rs, $1, $2) => {const name = decodeURIComponent($1);let val = decodeURIComponent($2);val = String(val);obj[name] = val;return rs;});return obj;
}

当然也可以用qs
npmjs www.npmjs.com/package/qs

它是开源免费项目,每周下载量将近7千万,支持任意字符,对象进行解析和拼接,支持@types/qs,导入后11.3k。

相关文章:

前端构建URL的几种方法比对,以及函数实现

当我们在前端开发中处理 URL 时,可能会用到字符串拼接、ES6 模板语法 (template literals) 或者使用 new URL() 构造函数。这三者各有优劣,适用于不同的场景。 1. 字符串拼接与 ES6 模板语法 字符串拼接 和 ES6 模板语法 都是将不同的字符串片段组合在…...

场外个股期权如何发出行权指令?

场外期权行权指令也就是平仓指令的意思,一般场外个股期权交易有三种方式开仓和行权平仓指令,分别是市价,限价和半小时询价,跟普通股票的买卖和交易方式类似,唯一区别是手动发出场外个股期权的行权指令,下文…...

AH8681锂电升压3.7升5V升12V 2A可支持QC2.0 3.0

135.3806.7573在探讨AH8681这款专为3.7V升压5V至12V,并具备2A输出能力,同时兼容QC2.0与QC3.0快充协议的升压芯片时,我们不得不深入其技术细节、应用场景、设计优势以及市场定位等多个维度,以全面理解其在现代电子设备中的重要作用…...

那些年我们一起遇到过的奇技淫巧

EVAL长度限制突破技巧 PHP Eval函数参数限制在16个字符的情况下 &#xff0c;如何拿到Webshell&#xff1f; 写一段限制长度在小于17位的字符&#xff0c;拿下webshell <?php highlight_file(__FILE__); $param $_REQUEST[param]; if (strlen($param) < 17 &&am…...

机器学习笔记:编码器与解码器

目录 介绍 组成结构 代码实现 编码器 解码器 合并编码器-解码器 思考 介绍 在机器翻译中&#xff0c;输入的序列与输出的序列经常是长度不相等的序列&#xff0c;此时&#xff0c;像自然语言处理这种直接使用循环神经网络或是门控循环单元的方法就行不通了。因此&#x…...

加密狗创新解决方案助力工业自动化

面临的挑战 早在1991年&#xff0c;COPA-DATA就认识到需要一个既能提供长期保护又能灵活应对的解决方案&#xff0c;以防止软件盗版并确保客户在各种复杂的工业环境下能够顺利使用其产品。这一解决方案不仅要兼容Windows系统&#xff0c;还必须在网络连接受限的情况下&#xff…...

浅谈文件缓冲区和翻译环境

文章目录 1、文件缓冲区2、程序环境A、翻译过程概述B、详解编译和链接a、编译b、链接 1、文件缓冲区 ANSIC 标准采用”文件缓冲系统“处理数据文件&#xff0c;即在文件的读写过程中会使用到文件缓冲区&#xff0c;而文件缓冲区分为输入缓冲区和输出缓冲区。 读写文件 写文件…...

《腾讯NCNN框架的模型转换x86/mips交叉编译推理》详细教程

NCNN的编译运行交叉编译 1.在Ubuntu上编译运行ncnn1&#xff09;编译ncnn x86 linux2&#xff09;测试ncnn x86 linux 2. 模型转换1&#xff09;onnx2&#xff09;pnnx 3.在x86上加载推理模型1)准备工作2)编写C推理代码3)编写Cmakelist编译 4.在MIPS上进行交叉编译推理1&#x…...

关于近期安卓开发书籍阅读观后感

概述 由于笔者是Java转Android&#xff0c;对于安卓相关知识欠缺&#xff0c;故找一些入门和进阶书籍观看。笔者搜到的相关的安卓推荐博客&#xff1a;【Android – 学习】学习资料汇总_android书籍强烈推荐-CSDN博客相对来说比较全面。 阅读历程 笔者先阅读的是郭霖老师的…...

Servlet——个人笔记

Servlet——个人笔记 文章目录 [toc]Servlet简介Servlet命名Servlet由来实现过程 Servlet 相对 CGI 的优势简要说说什么是CGI Servlet 在IDEA中开发流程Servlet注解方式配置WebServlet注解源码WebServlet注解使用 Servlet常见容器Servlet 生命周期简介测试 Servlet 方法init()…...

富格林:戳穿虚假交易保证安全

富格林指出&#xff0c;虚假交易亏损骗局一直以来都是投资者的诟病。不少投资者来到这个赛道的目的铁定是为了安全盈利增值财富&#xff0c;因此如何去杜绝虚假交易便成了当务之急。实际上&#xff0c;有不少投资技巧可以为保障我们的交易安全带来一些庇护。下面富格林就给大家…...

Linux学习——文本处理工具与正则表达式

目录 一&#xff0c;grep 1&#xff0c;grep介绍 2&#xff0c;grep的常用选项 3&#xff0c;grep使用演示 1&#xff0c;基本使用 直接查找字符串&#xff1a; 使用选项 2&#xff0c;使用正则表达式进行匹配 1&#xff0c;正则表达式介绍 2&#xff0c;使用范例 二&…...

大厂进阶四:React源码Fiber架构解析

本文主要内容&#xff1a; 1、React Concurrent 2、React15架构 3、React16架构 4、Fiber架构 5、任务调度循环和fiber构造循环区别 一、React Concurrent React在解决CPU卡顿是会用到React Concurrent的概念&#xff0c;它是React中的一个重要特性和模块&#xff0c;主要的…...

MongoDB的WiredTiger存储引擎

作者&#xff1a;太阳 从MongoDB 3.2 开始&#xff0c;MongoDB实例默认的存储引擎为WiredTiger&#xff0c;WiredTiger存储引擎具体以下几大优点&#xff1a; 文档级并发 将数据持久化到磁盘 快照和checkpoint 数据压缩 本地数据加密 一、文档级别并发 1、WiredTiger使…...

windows 版本Jenkins的Jenkinsfile中共享变量

场景 jenkins部署在windows服务器上的&#xff0c;需要在Jenkinsfile中获取命令执行的结果存入一个变量&#xff0c;然后在后续的执行中使用此变量 一开始想的是定义一个环境变量&#xff0c;如下所示&#xff0c; pipeline {agent anystages {stage(test) {steps {bat for /…...

Android-->产物收集(含apk文件重命名, aab文件重命名)

以前写过修改apk生成路径和文件名的文章, 如下: AS–›Gradle 7.0.0/4.1.0/4.0/3.3/3.0 修改APK生成路径和文件名(附AAR修改方式以及分析过程)_com.android.build.gradle.internal.api.libraryvaria-CSDN博客 这种方法入侵了gradle,破坏了原有的gradle环境, 经常会导致如下问…...

matlab实现迷宫最佳路径规划

在MATLAB中实现迷宫路径的最佳路径规划&#xff0c;我们可以使用多种算法&#xff0c;其中最常见和高效的是A搜索算法&#xff08;A Search Algorithm&#xff09;。A*算法结合了最佳优先搜索和Dijkstra算法的优点&#xff0c;通过启发式函数来评估每个节点的优先级&#xff0c…...

【自用】Python爬虫学习(二):网页解析的三种方式(re、bs4、xpath)

Python爬虫学习&#xff08;二&#xff09; 网页解析的三种方式1.正则表达式-re解析常用表达&#xff1a;re常用函数&#xff1a;在html中的运用&#xff1a; 2.BeautifulSoup解析常用语法&#xff1a;用法举例&#xff1a; 3.xpath解析示例代码1&#xff1a;示例代码2&#xf…...

从零到一:家政保洁小程序搭建全攻略与功能作用深度解析

目录 一、家政保洁小程序主要功能 二、家政保洁小程序搭建教程 &#xff08;一&#xff09;前期准备 &#xff08;二&#xff09;注册与选择工具 &#xff08;三&#xff09;设计与开发 &#xff08;四&#xff09;测试与优化 &#xff08;五&#xff09;发布与推广 一、…...

单元测试:为工程质量保驾护航

单元测试 单元测试是软件开发过程中确保代码质量和正确性的关键手段。它指的是对软件中的最小可测试单元&#xff08;通常是函数或方法&#xff09;进行验证&#xff0c;确保其行为符合预期。 基本概念 单元测试&#xff1a;验证软件中最小单元&#xff08;通常是函数或方法…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...