# @cgarciagarcia/react-query-builder 中文文档

规范地址：https://npmcn.com/package/%40cgarciagarcia/react-query-builder/

版本：1\.22\.3
npm 元数据更新时间：2026-10-26T01:30:38.630Z
中文译文更新时间：2026-11-09T08:59:09.552Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40cgarciagarcia/react-query-builder
原文对照：https://npmcn.com/package/%40cgarciagarcia/react-query-builder/?lang=original
项目主页：https://cgarciagarcia.github.io/react-query-builder/
源码仓库：https://github.com/cgarciagarcia/react-query-builder

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：373 kB，30 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：0 个
- peer 依赖：react ^17\.0\.0 \|\| ^18\.0\.0 \|\| ^19\.0\.0
- 首次发布：2024-07-14T23:46:19.595Z
- 最新版本发布：2026-10-26T01:30:38.266Z
- 近 30 天下载量：4506（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：97（近 12 个月 21 个）

## 中文简介

创建兼容 spartie/ laravel- query- buildinger 的查询字符串

## 安装

```sh
npm install @cgarciagarcia/react-query-builder
```

也可以使用：`pnpm add @cgarciagarcia/react-query-builder`、`yarn add @cgarciagarcia/react-query-builder`、`bun add @cgarciagarcia/react-query-builder`

## README

# @cgarciagarcia/反应-query-建设者

TypeScript 反应钩钩,用于构建兼容的查询字符串 [温泉/泻水-清水-建材](https://github.com/spatie/laravel-query-builder)。 。 。 .

[![Coverage Status](https://coveralls.io/repos/github/cgarciagarcia/react-query-builder/badge.svg?branch=main&service=github&kill_cache=1)](https://coveralls.io/github/cgarciagarcia/react-query-builder?branch=main) [![Test CI](https://github.com/cgarciagarcia/react-query-builder/actions/workflows/test.yml/badge.svg)](https://github.com/cgarciagarcia/react-query-builder/actions/workflows/test.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/1f3f48abc84f4e3cba76e39e804786d6)](https://app.codacy.com/gh/cgarciagarcia/react-query-builder/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) [![Downloads](https://img.shields.io/npm/d18m/@cgarciagarcia/react-query-builder?style=flat-square)](https://www.npmjs.com/package/@cgarciagarcia/react-query-builder)

* * *

## 目录

-   [安装](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/#readme-installation)
-   [快速启动](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/#readme-quick-start)
-   [配置](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/#readme-configuration)
-   [API 参考](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/#readme-api-reference)
    -   [过滤器](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/#readme-filters)
    -   [字段](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/#readme-fields)
    -   [排序](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/#readme-sorts)
    -   [包括](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/#readme-includes)
    -   [参数](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/#readme-params)
    -   [倾斜](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/#readme-pagination)
    -   [公用事业](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/#readme-utilities)
-   [高级: 冲突过滤器](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/#readme-advanced-conflicting-filters)
-   [从 URL 水分](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/#readme-hydrating-from-url)
-   [支助](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/#readme-support)
-   [许可证](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/#readme-license)

* * *

## 安装

```bash
# npm
npm install @cgarciagarcia/react-query-builder

# yarn
yarn add @cgarciagarcia/react-query-builder

# pnpm
pnpm add @cgarciagarcia/react-query-builder
```

**同伴依赖性 :** 反应17,18,或19.

* * *

## 快速启动

```ts
import { useQueryBuilder } from "@cgarciagarcia/react-query-builder";

const builder = useQueryBuilder()

builder
  .fields('user.name', 'user.last_name')
  .filter('age', 18)
  .filter('salary', '>', 1000)
  .sort('created_at')
  .sort('age', 'desc')
  .include('posts', 'comments')
  .setParam('external_param', 123)
  .page(1)
  .limit(10)

// Use in fetch
fetch("https://myapi.com/api/users" + builder.build())

// builder.build() returns:
// ?fields[user]=name,last_name&filter[age]=18&filter[salary][gt]=1000&sort=created_at,-age&includes=posts,comments&external_param=123&page=1&limit=10
```

* * *

## 配置

传递一个可选配置对象到 `useQueryBuilder` 设置初始状态并自定义行为.

```ts
const builder = useQueryBuilder({
  // Map frontend field names to backend names
  aliases: {
    "frontend_name": "backend_name",
  },

  // Pre-set initial state
  filters: [],
  includes: [],
  sorts: [],
  fields: [],
  params: {},

  // Define mutually exclusive filters (see Advanced section)
  pruneConflictingFilters: {},

  // Custom delimiters (default: ',')
  delimiters: {
    global: ',',    // applies to all unless overridden
    fields: null,
    filters: null,
    sorts: null,
    includes: null,
    params: null,
  },

  // Prepend '?' to the output of build()
  useQuestionMark: false,

  // Initial pagination state
  pagination: {
    page: 1,
    limit: 10,
  },
})
```

* * *

## API 参考

所有方法都返回构建者实例,所以它们都是 **可连锁**。 。 。 .

### 过滤器

```ts
// Add a filter (appends values by default)
builder.filter('status', 'active')

// Add a filter with an operator
builder.filter('salary', '>', 1000)
builder.filter('age', '>=', 18)

// Override existing filter values instead of appending
builder.filter('status', 'inactive', true)

// Remove specific filters
builder.removeFilter('status', 'age')

// Remove all filters
builder.clearFilters()

// Check if filters exist
builder.hasFilter('status')           // → boolean
builder.hasFilter('status', 'age')    // → true only if ALL exist
```

可用的运算符 : `=`, (中文(简体) ), `<`, (中文(简体) ), `>`, (中文(简体) ), `<=`, (中文(简体) ), `>=`, (中文(简体) ), `<>`

您也可以导入 `FilterOperator` 用于类型安全操作器:

```ts
import { FilterOperator } from "@cgarciagarcia/react-query-builder"

builder.filter('salary', FilterOperator.GreaterThan, 1000)
```

* * *

### 字段

```ts
builder.fields('name', 'email', 'user.avatar')
builder.removeField('email')
builder.clearFields()
builder.hasField('name')   // → boolean
```

* * *

### 排序

```ts
builder.sort('created_at')           // default: asc
builder.sort('age', 'desc')
builder.removeSort('created_at', 'age')
builder.clearSorts()
builder.hasSort('created_at')        // → boolean
```

* * *

### 包括

```ts
builder.include('posts', 'comments')
builder.removeInclude('posts')
builder.clearIncludes()
builder.hasInclude('posts')          // → boolean
```

* * *

### 参数

```ts
builder.setParam('custom_key', 'value')
builder.setParam('ids', [1, 2, 3])
builder.removeParam('custom_key')
builder.clearParams()
builder.hasParam('custom_key')       // → boolean
```

* * *

### 倾斜

```ts
const builder = useQueryBuilder({
  pagination: { page: 1, limit: 10 }
})

builder.page(3)           // go to page 3
builder.nextPage()        // page + 1
builder.previousPage()    // page - 1 (stops at 1)
builder.limit(25)         // change page size

builder.getCurrentPage()  // → number | undefined
builder.getLimit()        // → number | undefined
```

> **说明:** 更改过滤器,去掉过滤器,或将限制自动重排到第1页.

* * *

### 公用事业

#### `build()`

返回最后的查询字符串.

```ts
builder.build() // → "?filter[age]=18&sort=created_at"
```

#### `toArray()`

返回作为平面字符串数组的查询状态。 作为反应查询有用 `queryKey`。 。 。 .

```ts
import { useQuery } from "@tanstack/react-query"

const builder = useQueryBuilder()

const { data } = useQuery({
  queryFn: () => getUsers(builder.build()),
  queryKey: ['users', ...builder.toArray()],
})
```

#### `tap(callback)`

检查内部状态而不中断链.

```ts
builder
  .filter('age', 18)
  .tap((state) => console.log(state))
  .sort('name')
```

#### `when(condition, callback)`

有条件执行基于布尔的回调 。 建造者无论怎样都会返回.

```ts
builder.when(isAdmin, (state) => {
  console.log('Admin state:', state)
})
```

* * *

## 高级: 冲突过滤器

一些过滤器在后端是相互排斥的(例如. `date` 对 `between_dates`) (中文(简体) ). 使用 `pruneConflictingFilters` 让库自动处理.

```ts
const builder = useQueryBuilder({
  pruneConflictingFilters: {
    date: ['between_dates'],
    // 'between_dates': ['date'] is added automatically (bidirectional)
  },
})

builder.filter('date', '2024-08-13')
// → ?filter[date]=2024-08-13

builder.filter('between_dates', ['2024-08-06', '2024-08-13'])
// → ?filter[between_dates]=2024-08-06,2024-08-13
// (date filter was automatically removed)
```

冲突是 **默认双向** - 你只需要声明一次 如果您愿意,也可以明确声明双向.

* * *

## 从 URL 水分

说你有一个列表视图 有过滤器,种类和相片。 用户选择"status = active",按日期排序,打开第3页——并与队友共享链接. 您希望链接能用已经应用的完全相同的过滤器打开 .

这就是一个 **适配器** 是否:它将建造者连接到一个外部来源(URL, `localStorage`随便你 内置 `createSearchParamsAdapter` 处理 URL 大小写.

### 30秒的例子

```ts
import {
  useQueryBuilder,
  createSearchParamsAdapter,
} from "@cgarciagarcia/react-query-builder";

const builder = useQueryBuilder({
  adapter: createSearchParamsAdapter({ sync: true }),
});

builder.filter("status", "active").sort("created_at", "desc");
// URL bar is now: /?filter[status]=active&sort=-created_at
```

刷新页面,共享链接——过滤器返回. 就是这样.

刚才发生的事:

-   在挂载时,适配器 **读取** 当前 URL 和种子构建者.
-   `sync: true` 接下来 **挂载后写一次** 以最终状态实现 URL 正常化( 所以) `BaseConfig` 默认, `urlOmit`,或者一个僵化的链接,用户在即时得到调节——不需要突变),以及随后的每一个变化.
-   URL 输出映射什么 `.build()` 生产,所以你的后端和URL栏都同意.

### 只读水合( 无 URL 写入)

如果您只想在挂载时水分, 且之后再也不能触碰 URL, 请离开 `sync` 输出 :

```ts
useQueryBuilder({
  adapter: createSearchParamsAdapter(),
});
```

现在 `read()` 当钩子挂起时运行一次——与 `useState(() => …)` - 事情就这样结束了 挂载后的 URL 变化不会重新水合 .

### 自定义写入器

`sync` 接受三种表格,取决于您希望URL更新有多积极:

```ts
// 1) Default behavior: replaceState (no extra browser history entries)
createSearchParamsAdapter({ sync: true });           // alias for "replace"

// 2) pushState (every mutation is a back-button step)
createSearchParamsAdapter({ sync: "push" });

// 3) Bring your own — useful for Next.js / React Router / debouncing
createSearchParamsAdapter({
  sync: (search) => router.replace({ search }),
});
```

**挂载时常态化** 运行在全部三种模式中——在构建者构建之后,刻出一次,所以URL栏立即反映最终状态. 对于 `sync: "push"` 第一次通话仍然使用 `replaceState` (所以上山起火不会增加"幽灵回扣"条目;您的自定义回扣也会在上山上起火一次,如果这让你的路由器感到惊讶,则用关闭旗来守卫.

不要担心其他应用程序的查询参数——编剧 **保存着它不承认的任何东西**。 。 `?utm_source=newsletter` 或者说 `?theme=dark` 当过滤器被添加、更新或清除时,保持不动.

### 与外部变化相对应(`builder.rehydrate()`(中文(简体) )

`read()` 运行 **一次** 在山上。 后出为建州主. 如果有别的东西改变源头——用户点击回/Forward,另一个标签会变异 `localStorage`,一个websocket推出一个新的服务器侧过滤器——建设者自己不会注意到.

`builder.rehydrate()` 重新运行适配器 `read()` ,并将数据层(filters / skinds / 包括 / 字段 /params / pagination)替换为来源现在所说的任何内容。 配置(别名、划界人、, `pruneConflictingFilters`, (中文(简体) ), `useQuestionMark`)被保留.

```ts
const builder = useQueryBuilder({
  adapter: createSearchParamsAdapter({ sync: true }),
});

// Re-pull state from the URL after the browser navigates.
useEffect(() => {
  const onPop = () => builder.rehydrate();
  window.addEventListener("popstate", onPop);
  return () => window.removeEventListener("popstate", onPop);
}, [builder]);
```

为什么手动而不是自动? 不同来源需要不同的听众(`popstate` 为历史, `storage` 用于跨tab localStorage,用于服务器状态的 Websocket订阅,...). 连接右听器属于你的代码,其中的选择是显而易见的. 图书馆别挡道.

### 异名: 保留您的前端名称, 船后端名称

你可能给UI起个名字`userName`, (中文(简体) ), `createdAt`)和 API 中的另一个`name`, (中文(简体) ), `created_at`) (中文(简体) ). 过 `aliases` 到构建器,适配器处理翻译 **两个方向** 自动 :

```ts
useQueryBuilder({
  aliases: { userName: "name", createdAt: "created_at" },
  adapter: createSearchParamsAdapter({ sync: true }),
});

// Your code keeps using frontend names:
builder.filter("userName", "Jane").sort("createdAt", "desc");

// The URL bar shows backend names (same as .build() would emit):
// /?filter[name]=Jane&sort=-created_at

// On refresh, ?filter[name]=Jane hydrates back as { userName: "Jane" }.
```

适配器会自动从构建器配置读取别名,所以你只声明一次.

### URL 和后端的不同名称

URL和后端不必共享相同的命名. 也许你希望URL能说用户的语言(`?filter[documento]=…`)而您的 API 保留技术名称( )`?filter[code]=…`) (中文(简体) ). 或者你的代码 `rol` 西班牙文,但URL应改为: `type` 用于共享链接.

过 `urlAliases` 切换到适配器 `aliases`数字 :

```ts
useQueryBuilder({
  aliases:    { dni: "code", rol: "type" },        // state → backend (drives .build())
  adapter: createSearchParamsAdapter({
    sync: true,
    urlAliases: { dni: "documento", rol: "type" }, // state → URL bar
  }),
});

builder.filter("dni", "12345").filter("rol", "admin");
// URL bar:  ?filter[documento]=12345&filter[type]=admin   ← user sees this
// .build(): ?filter[code]=12345&filter[type]=admin        ← API receives this
```

相同逻辑属性的三个独立命名空间:

| 层 | 名称 | 由 |
| --- | --- | --- |
| 状态( 您的代码) | `dni`, (中文(简体) ), `rol` | 你怎么称呼 `.filter()` |
| URL 栏 | `documento`, (中文(简体) ), `type` | `adapter.urlAliases` |
| 后端 | `code`, (中文(简体) ), `type` | `builder.aliases` |

奥米 `urlAliases` 以让 URL 共享构建者的名称(普通例)。 过 `urlAliases: {}` 明确选择退出任何 URL 翻译 —— 然后 URL 逐字映射您的状态空间名称, 即使当 `builder.aliases` 已经设定.

**安全说明**:使用 URL QQ后端,知道后端名的攻击者可以进行手动操作 `?filter[code]=…` 直接说 用适配器的许可列表将其锁定 :

```ts
adapter: createSearchParamsAdapter({
  sync: true,
  urlAliases: { dni: "documento", rol: "type" },
  allowed: { filters: ["documento", "type"] },   // backend-name attempts → dropped
}),
```

### 从 URL 中隐藏噪音状态 : `urlOmit`

有时建设者会携带您的条目 **后端需要, 但用户不应该在 URL 栏中看到**。典型案例:默认包含/字段 API 总是需要 (`include=organization,permissions`那只是繁杂的共享链接.

`urlOmit` 每个桶只写一个拒绝列表。 所列名字仍留在州内(因此 `.build()` 他们只是没有到达 URL:

```ts
useQueryBuilder({
  includes: ["organization", "permissions"],     // always sent to API
  adapter: createSearchParamsAdapter({
    sync: true,
    urlOmit: { includes: ["organization", "permissions"] },
  }),
});

builder.filter("status", "active");
// .build() → ?filter[status]=active&include=organization,permissions   ← backend
// URL bar  → ?filter[status]=active                                    ← user
```

**通关卡 `"*"`** 将桶中的每个条目都放下——用于 `fields`,这是用户在URL中很少需要看到的内部API优化:

```ts
adapter: createSearchParamsAdapter({
  sync: true,
  urlOmit: {
    fields: ["*"],                                // hide ALL fields from URL
    includes: ["organization", "permissions"],    // hide only these
  },
}),
```

IDE 自动完成建议 `"*"` 感谢一个字形的 工会打字技巧, 所以它是可以发现的 同时仍然接受任何 简单的属性名称.

异形觉悟于 `filters` 财务报告和审定财务报表 `sorts` ——在词汇表(状态或URL)中列出一个名称,两个表单都跳过.

**说明**数字 : `urlOmit` 只影响作家。 如果一个精心设计的URL包含其中一个名称,读者仍然会处理. 将相同名称添加到 `excludeKeys` 如果你也想在水合时拒绝的话.

### 重新命名 URL 密钥

有时默认的 URL 是动词 :

```
?filter[status]=active&filter[role]=admin&sort=-created_at&include=author,tags&fields[user]=id,name
```

这是一个口活——足够长的时间在聊天预览中溢出,丑陋的分享,更难扫描. 重新绘制密钥以缩短 :

```ts
createSearchParamsAdapter({
  keys: { filter: "filt", sort: "srt", include: "inc", fields: "fld" },
  sync: true,
});
```

现在,同样的状态产生:

```
?filt[status]=active&filt[role]=admin&srt=-created_at&inc=author,tags&fld[user]=id,name
```

为什么你可能想要这个:

-   **更短,更可分享的链接** ——每个参数可保存字节,当您拥有许多过滤器时,差异很大.
-   **清理 URL 栏** ——方便用户和截取支持票的截图.
-   **品牌或域语言** - 你的应用程序说"克瑞",不是"过滤器"? 匹配用户已经知道的词汇表 .
-   **避免相撞** ——如果周边应用已经使用 `?filter=...` 或者说 `?sort=...` 重命名来共存.

读者和作家都使用新密钥,所以来回转接仍然有效. 这个 **仅限** 影响 URL 栏.. `.build()` (你传递给 `fetch`继续用克南克语 `filter`编号 :`sort`/... 命名您的后端预期 .

### 锁定来自 URL 的密钥

URL是用户输入. 没有限制,一个精心设计的链接像 `?filter[is_admin]=true` 会直接流入你的 `.build()` 呼叫和出到你的后端。 你有两个原始人, **每个桶**你选一个符合你情况的人

#### `allowed` ——严格许可列表("只有这些")

使用它,当你有一个简短的,明确的清单 合法的东西:

```ts
createSearchParamsAdapter({
  allowed: {
    filters: ["status", "role", "created_at"],
    sorts:   ["created_at", "name"],
    params:  ["locale", "tenant"],   // anything not here is dropped
  },
});
```

省略桶时的默认值 :

-   `filters` 编号 : `sorts` 编号 : `includes` 编号 : `fields` ~ 允许一切( 这样 URL 可以自由驱动过滤)
-   `params` - 不允许任何东西(包罗万象是逐一否认的——参数是任意的,所以你必须选择加入,列出它们)

#### `excludeKeys` ——定点拒绝名单("除这些之外的一切")

使用它时,你一般相信桶 但想屏蔽一些危险的名字—— 不列举一切合法:

```ts
createSearchParamsAdapter({
  // No allowed.filters → I accept any filter from the URL.
  // I have 47 legitimate filter attributes and I add more every month;
  // maintaining a full whitelist is brittle. But is_admin and password
  // must NEVER come through the URL.
  excludeKeys: {
    filters: ["is_admin", "password"],
  },
});
```

#### 我该用哪一个?

| 情况 | 使用 |
| --- | --- |
| "Short,明确列出什么是允许的" | `allowed` |
| "接受一切,除了这些" | `excludeKeys` |
| "白名单加上顶上移动的拒绝名单" | 两者(防御深度) |

如果你准备好了 `allowed.filters: ["status", "role"]`,列表 `is_admin` 内 `excludeKeys.filters` 实值 **冗余** ——已经因为不允许而放弃了. 它不会打破任何东西(并且读作意向文件),但不会在运行时拉起重量. 当您保持一个稳定的允许列表并想要一个单独的,快速变化的拒绝列表时,该组合是有用的.

#### 适用于两者的细节

-   两者均适用于 **读者和作家** 对称性地——URL栏总是在您的政策之内.
    
-   `excludeKeys` 总是胜出 `allowed` (低拍允许).
    
-   **异形觉悟于 `filters` 财务报告和审定财务报表 `sorts`。 。 。 .** 当你准备好 `aliases`,如果 **无论是** uRL 边名(后端) 或 状态边名(前端) 在列表中 。 以您所想的词汇书写您的规则 :
    
    ```ts
    aliases: { userName: "name" },
    allowed: { filters: ["userName"] }   // ✓ allows ?filter[name]=...
    // — or —
    allowed: { filters: ["name"] }       // ✓ also allows it
    ```
    
    否认的一方 `excludeKeys: { filters: ["is_admin"] }` 两个块 `?filter[is_admin]=...` 和 `?filter[adminFlag]=...` (别名键),因此攻击者不能通过切换词汇来绕过拒绝列表.
    
-   对于 `fields`,可以通过短道具匹配(`password`)或通过 `entity.prop` (单位:千美元)`user.password`) (中文(简体) ). 选择你需要的精确度.
    
-   `page` 财务报告和审定财务报表 `limit` 为: **自动水合** 当在 URL 中出现,并在 设置中由 作者 释放 `state.pagination`. 圆通出箱-无额外配置.
    
-   **为什么每桶?** `password` 是个危险的过滤器 但很好 `fields` 选择( 它只是选择 API 返回的哪一列) 。 一个单子会迫使你进入全局或一无所有.
    

### 想要另一个来源吗? 写自己的适配器

`QueryBuilderAdapter` 刚刚 `{ read, write? }`。包罗一切:

```ts
// Persist to localStorage instead of the URL
const localStorageAdapter: QueryBuilderAdapter = {
  read:  () => JSON.parse(localStorage.getItem("filters") ?? "{}"),
  write: (state) => localStorage.setItem("filters", JSON.stringify(state)),
};

useQueryBuilder({ adapter: localStorageAdapter });
```

相同的图案为 `react-router` 搜索参数,散列路由器,内存商店,索引DB – 您可以从中读取并写入任何内容 .

### 下层

如果您只想要没有钩子集成的 URL 解析器, 则两块都会导出为纯函数 :

```ts
import {
  parseSearchParams,
  serializeSearchParams,
} from "@cgarciagarcia/react-query-builder";

// URL → state
parseSearchParams("?filter[status]=active&sort=-name");
// → { filters: [...], sorts: [{ attribute: "name", direction: "desc" }] }

// state → URL
serializeSearchParams({
  filters: [{ attribute: "status", value: ["active"] }],
});
// → "filter[status]=active"
```

都接受同样的 `keys` 编号 : `urlAliases` 编号 : `allowed` 编号 : `excludeKeys` 选项作为适配器.

### 已知的限制

URL协议使用几个字符作为控制符号. 包含它们的过滤值 **沉默地堕落** 在来回旅行中——写作者释放出这个值,但读者却将它分成不同的. 在我们解除这个限制之前 把这些当作过滤器内限值:

| 字符 | 为什么它坏了 |
| --- | --- |
| `,` | 多值分隔器 - `filter[tag]=a,b` 变成 `["a", "b"]` 解析 |
| `<`, (中文(简体) ), `>`, (中文(简体) ), `<=`, (中文(简体) ), `>=`, (中文(简体) ), `<>` (作为 **领导** 前缀) | 运算符语法 - `filter[age]=>=18` 成为运算符 `>=` + 数值 `["18"]` |

其他"特长"人物如: `%`, (中文(简体) ), `&`, (中文(简体) ), `+` 和空间是好的——它们游走 URL-逃逸 和在环行无恙.

如果您需要这些字符中的任何一个( 如带有逗号的标记), 请在 URL 适配器外保留该部分状态, 或者在传递到您侧面之前避开它 `.filter()`。 。 。 .

* * *

## 支助

有问题或需要帮助吗? [打开讨论](https://github.com/cgarciagarcia/react-query-builder/discussions) (原始内容存档于2018-09-29). on GitHub.

* * *

## 考虑支助

如果此软件包帮助您, 请考虑支持其创建者 :

**付费页 :** [@carlosgarciadev : 翻译:](https://paypal.me/carlosgarciadev?country.x=AR&locale.x=es_XC)

* * *

## 许可证

麻省理工学院许可证(MIT). 见 [自由主义](https://npmcn.com/package/%40cgarciagarcia/react-query-builder/LICENSE) 更多信息.

## 常见问题

### @cgarciagarcia/react-query-builder 是什么？

创建兼容 spartie/ laravel- query- buildinger 的查询字符串

### 如何安装 @cgarciagarcia/react-query-builder？

在项目目录运行 npm install @cgarciagarcia/react-query-builder，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：react（^17\.0\.0 \|\| ^18\.0\.0 \|\| ^19\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @cgarciagarcia/react-query-builder 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @cgarciagarcia/react-query-builder 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @cgarciagarcia/react-query-builder 可以商用吗？

@cgarciagarcia/react-query-builder 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @cgarciagarcia/react-query-builder 的下载量有多少？

根据 npm 官方下载统计，@cgarciagarcia/react-query-builder 在 2026/10/10 – 2026/11/08 这 30 天内被下载 4,506 次，日均约 150 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @cgarciagarcia/react-query-builder 还在维护吗？

最新版本 1\.22\.3 发布于 2026/10/26（14 天前）；至今共发布 97 个版本，其中过去 12 个月发布了 21 个；首次发布于 2024/07/15。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

