@js-tiny/url
v0.1.0
Published
适用于任何 ES 标准环境的轻量 URL 构造器,支持链式调用,含小程序构建产物 | Mutable chainable URL builder for any ES environment including WeChat, Alipay, and Douyin MiniProgram
Maintainers
Readme
@js-tiny/url
简体中文 | English
一个轻量、可变的 URL 构造器,适用于任何符合 ES 标准的 JavaScript 环境。
与原生 URL 不同,它对相对路径或不完整的输入不会抛错,从空字符串开始逐段拼装即可。
尤其适合微信/支付宝/抖音等小程序运行时——这些环境没有原生 URL 构造器,而
@js-tiny/url 提供 miniprogram 字段,指向一个不含 Node 专属 API 的打包 CJS 产物,
可通过「构建 npm」直接引入,无需任何 polyfill。
目录
1. 特性
- 小程序原生可用 —— 适用于微信/支付宝/抖音等缺少原生
URL构造器的运行时;miniprogram字段指向打包 CJS 产物,「构建 npm」开箱即用,无需 polyfill。 - 可变且可链式调用 —— 每个 setter 都返回实例本身,因此可以从零开始流畅地拼装一个 URL。
- 双模式访问器 ——
url.protocol()读取,url.protocol("https")写入。无需分离的 getter/setter 成对定义。 - 前缀自动补全 ——
protocol("https")→"https:",hash("top")→"#top",pathname("users")→"/users"。 - 输入宽容 —— 传入
null、undefined或""即可清除某个组成部分;部分 URL 也能正常处理。 - 多值查询参数 ——
PureQuery支持重复键、add 时自动去重、合并以及批量插入。 - IPv6 与密码安全解析 ——
[::1]:8080主机、user:p:secret认证串都能按 RFC 3986 正确解析。 - 跨平台 —— 同时产出 CJS、ESM 以及打包后的小程序构建产物。
2. 安装
npm install @js-tiny/url3. 快速开始
import { PureUrl } from "@js-tiny/url";
const url = new PureUrl("https://example.com/path?query=value#hash");
// 读取
url.protocol(); // 'https:'
url.hostname(); // 'example.com'
url.pathname(); // '/path'
url.search(); // '?query=value'
url.hash(); // '#hash'
// 写入(可链式)
url
.protocol("http")
.hostname("newdomain.com")
.pathname("/new/path")
.hash("new-hash");
url.toString(); // 'http://newdomain.com/new/path?query=value#new-hash'4. 核心概念
4.1 Getter / Setter 双模式
每个组成部分的方法都同时是 getter 和 setter —— 不传参即读取,传参即写入:
const url = new PureUrl();
url.protocol("https"); // 写入 → 返回 url 实例(可链式)
url.protocol(); // 读取 → 'https:'4.2 清除某个组成部分
向任意方法传入 null、undefined 或 "" 即可清除该组成部分:
const url = new PureUrl("https://user:[email protected]:8080/path?q=1#h");
url.protocol(null);
url.auth(null);
url.host(null);
url.pathname(null);
url.search(null);
url.hash(null);
url.toString(); // ''4.3 前缀自动补全
前缀会自动添加或去除,无需手动记忆:
const url = new PureUrl();
url.protocol("https"); // 'https:' (去除 ':' 与 '/',再补上 ':')
url.hash("section1"); // '#section1'
url.pathname("users"); // '/users'4.4 全链式拼装
PureUrl 的所有 setter 与 PureQuery 的所有方法都返回实例本身,因此可以用一个表达式拼出完整 URL:
const url = new PureUrl()
.protocol("https")
.hostname("api.example.com")
.port("443")
.pathname("/v1/users");
url.query.set("limit", "10").set("offset", "0");
url.hash("results");
url.toString();
// 'https://api.example.com:443/v1/users?limit=10&offset=0#results'5. 组成部分
URL 各部分的对应关系如下:
https://user:[email protected]:8080/path/to/file?key=val#section
│ │ │ │ │ │ │ │
protocol│ │ hostname port pathname search hash
│ password
username5.1 Protocol(协议)
const url = new PureUrl();
url.protocol("https"); // 'https:'
url.protocol(null); // 已清除5.2 Authentication(认证)
auth() 接收 "username:password" 格式,并按第一个 : 切分,因此密码中包含 : 时不会被截断。
const url = new PureUrl();
url.auth("username:password");
url.auth(); // 'username:password'
// 也可以分别设置
url.username("user").password("pass");
url.auth(); // 'user:pass'
// 含冒号的密码不会被截断
url.auth("user:p:secret");
url.password(); // 'p:secret'5.3 Host 与 Port(主机与端口)
const url = new PureUrl();
url.host("example.com:8080");
url.host(); // 'example.com:8080'
url.hostname(); // 'example.com'
url.port(); // '8080'
// IPv6 字面量(带方括号)可正确解析
url.host("[::1]:8080");
url.hostname(); // '[::1]'
url.port(); // '8080'5.4 Path(路径)
const url = new PureUrl();
url.pathname("/api/v1/users");
// 通过分段构造
url.pathnames("api", "v1", "users");
url.pathname(); // '/api/v1/users'
// 读回为分段数组
url.pathnames(); // ['api', 'v1', 'users']
// path() 同时覆盖 pathname 与 query
url.path("/search?q=js");5.5 Hash(片段)
const url = new PureUrl();
url.hash("section1"); // '#section1'
url.hash(null); // 已清除6. 查询参数(PureQuery)
PureUrl.query 是一个 PureQuery 实例;PureQuery 也单独导出,便于在脱离 URL 的场景下独立处理查询字符串。
import { PureQuery } from "@js-tiny/url";
const query = new PureQuery("a=1&b=2&b=3", true); // 第二个参数 = 自动解码
query.get("a"); // '1'
query.getAll("b"); // ['2', '3']
query.has("a"); // true
// set() 替换某个键的全部值
query.set("c", "new-value");
query.set("d", "v1", "v2", "v3"); // 多个值
// add() 追加,且自动跳过重复值
query.add("tags", "js");
query.add("tags", "js"); // 已存在,忽略
// 批量插入
query.addAll({ category: "dev", tags: ["js", "node"] });
query.addAll([["author", "john"], ["tags", ["fe", "be"]]]);
// 仅在键不存在时添加
query.addIfNotExist("config", "once");
// 合并另一个查询(字符串或 PureQuery)
query.merge("x=10&y=20");
query.toUrlString();
// 'a=1&b=2&b=3&c=new-value&d=v1&d=v2&d=v3&tags=js&tags=node&tags=fe&tags=be&category=dev&author=john&config=once&x=10&y=20'addAll 返回实例本身,因此可以链式调用:
const query = new PureQuery()
.addAll({ param1: "value1" })
.addAll([["param2", "value2"]])
.add("param3", "value3");7. API 参考
7.1 PureUrl
new PureUrl(href?: string)将 href(通过 @xesam/url)解析为各组成部分。省略它则从空 URL 开始。
属性
query: PureQuery—— 查询参数管理器。
方法 —— 每个方法都是 getter(不传参)与 setter(传参)合一;setter 返回 this。
| 方法 | 说明 |
| --- | --- |
| protocol(value?) | 读取/设置协议。会去除 : 与 /,再补上 :。 |
| auth(value?) | 读取/设置,格式为 "username:password"。按第一个 : 切分。 |
| username(value?) | 读取/设置用户名。 |
| password(value?) | 读取/设置密码。 |
| host(value?) | 读取/设置,格式为 "hostname:port"。支持 IPv6。 |
| hostname(value?) | 读取/设置主机名。 |
| port(value?) | 读取/设置端口。 |
| path(value?) | 读取/设置 pathname 与 query 的组合。 |
| pathname(value?) | 读取/设置路径名。确保以 / 开头。 |
| pathnames(...fragments?) | 读取为分段数组,或由分段设置路径名。 |
| search(value?) | 读取/设置查询字符串(含 ?)。 |
| hash(value?) | 读取/设置片段。确保以 # 开头。 |
| toUrlString() | 序列化为完整 URL 字符串。 |
| toString() | toUrlString() 的别名。 |
7.2 PureQuery
new PureQuery(qString?: string, decodeValue?: boolean)| 方法 | 说明 |
| --- | --- |
| isEmpty() | 查询是否不含任何键。 |
| has(key) | 是否存在 key。 |
| keys() | 全部键。 |
| get(key, index?) | key 的第 index 个值(默认第一个)。 |
| getAll(key) | key 的全部值。 |
| add(key, value) | 追加一个值,自动跳过重复。 |
| addAll(entries) | 批量添加。接受对象,或 [key, value \| value[]] 元组数组。 |
| addIfNotExist(key, value) | 仅当 key 不存在时添加。 |
| set(key, ...values) | 替换 key 的全部值。 |
| remove(key) | 移除 key。 |
| clear() | 清除全部键。 |
| load(qString, decodeValue?) | 通过解析查询字符串替换当前内容。 |
| merge(otherQuery, decodeValue?) | 合并另一个查询(字符串或 PureQuery)。 |
| toUrlString(encodeValue?) | 序列化为查询字符串。 |
| toString() | toUrlString() 的别名。 |
8. 小程序支持
package.json 暴露了 miniprogram 字段,指向一个不含 Node 专属 API 的打包 CJS 产物。微信/支付宝/抖音等小程序运行时均没有原生 URL 构造器,通过「构建 npm」引入此产物即可直接使用,无需额外 polyfill。
{ "miniprogram": "dist/miniprogram" }9. License
MIT
