VariableAwareInput 变量感知输入
Input 增强版,自动识别 `{{var}}` 模板变量并高亮;未知变量标红波浪线。
基础用法
实现:底层是透明文字的原生 input + 同尺寸 overlay 渲染高亮文本,光标位置完全对齐。
variables 数组里的名字算”已知”用 accent 高亮,其他算”未知”用红色波浪线。
背景 视口
已知变量:base_url · user_id · auth_token
<script setup lang="ts">
import { ref } from 'vue';
import { CfVariableAwareInput } from '@chufix-design/vue';
const value = ref('{{base_url}}/users/{{user_id}}/orders?token={{auth_token}}');
const known = ['base_url', 'user_id', 'auth_token'];
</script>
<template>
<div style="width: 100%; max-width: 920px;">
<CfVariableAwareInput v-model="value" :variables="known" placeholder="试试输入 {{base_url}}…" />
<div style="margin-top: 8px; font-size: 12px; color: var(--fg-3);">
已知变量:{{ known.join(' · ') }}
</div>
</div>
</template> <script setup>
import { ref } from 'vue';
import { CfVariableAwareInput } from '@chufix-design/vue';
const value = ref('{{base_url}}/users/{{user_id}}/orders?token={{auth_token}}');
const known = ['base_url', 'user_id', 'auth_token'];
</script>
<template>
<div style="width: 100%; max-width: 920px;">
<CfVariableAwareInput v-model="value" :variables="known" placeholder="试试输入 {{base_url}}…" />
<div style="margin-top: 8px; font-size: 12px; color: var(--fg-3);">
已知变量:{{ known.join(' · ') }}
</div>
</div>
</template> import { useState } from 'react';
import { CfVariableAwareInput } from '@chufix-design/react';
export default function Demo() {
const [value, setValue] = useState('{{base_url}}/users/{{user_id}}/orders?token={{auth_token}}');
const known = ['base_url', 'user_id', 'auth_token'];
return (
<>
<div style={{ width: "100%", maxWidth: 920 }}>
<CfVariableAwareInput value={value} onChange={setValue} variables={known} placeholder="试试输入 {{base_url}}…" />
<div style={{ marginTop: 8, fontSize: 12, color: "var(--fg-3)" }}>
已知变量:{known.join(' · ')}
</div>
</div>
</>
);
} import { useState } from 'react';
import { CfVariableAwareInput } from '@chufix-design/react';
export default function Demo() {
const [value, setValue] = useState('{{base_url}}/users/{{user_id}}/orders?token={{auth_token}}');
const known = ['base_url', 'user_id', 'auth_token'];
return (
<>
<div style={{ width: "100%", maxWidth: 920 }}>
<CfVariableAwareInput value={value} onChange={setValue} variables={known} placeholder="试试输入 {{base_url}}…" />
<div style={{ marginTop: 8, fontSize: 12, color: "var(--fg-3)" }}>
已知变量:{known.join(' · ')}
</div>
</div>
</>
);
} 变量交互
variables 可以从字符串数组升级为对象数组。输入 {{ 触发候选列表,点击已识别变量打开详情;组件只发出 variable-update / variable-create 事件,不直接保存业务数据。
背景 视口
输入 {{ 触发候选;点击变量查看详情。
<script setup lang="ts">
import { ref } from 'vue';
import { CfVariableAwareInput } from '@chufix-design/vue';
const value = ref('请求 {{base_url}}/v2/users/{{user_id}}?token={{token}}');
const lastAction = ref('输入 {{ 触发候选;点击变量查看详情。');
const variables = [
{
name: 'base_url',
label: 'Base URL',
value: 'https://api.chufix.dev',
description: '项目级 API 根地址,可在弹层中修改。',
scope: 'project',
editable: true,
},
{
name: 'user_id',
label: 'User ID',
value: 'u_1024',
description: '当前登录用户 ID。',
scope: 'local',
},
{
name: 'token',
label: 'Auth Token',
value: 'cf_live_xxx',
description: '授权令牌,由外层业务控制保存。',
scope: 'global',
editable: true,
},
];
</script>
<template>
<div style="width: 100%; max-width: 920px;">
<CfVariableAwareInput
v-model="value"
:variables="variables"
placeholder="输入 {{ 触发变量选择"
@variable-select="(variable) => lastAction = `插入变量:${variable.name}`"
@variable-update="(payload) => lastAction = `请求更新 ${payload.name} = ${payload.value}`"
@variable-create="(payload) => lastAction = `请求创建变量:${payload.name}`"
/>
<div style="margin-top: 10px; color: var(--fg-3); font-size: 12px;">
{{ lastAction }}
</div>
</div>
</template> <script setup>
import { ref } from 'vue';
import { CfVariableAwareInput } from '@chufix-design/vue';
const value = ref('请求 {{base_url}}/v2/users/{{user_id}}?token={{token}}');
const lastAction = ref('输入 {{ 触发候选;点击变量查看详情。');
const variables = [
{
name: 'base_url',
label: 'Base URL',
value: 'https://api.chufix.dev',
description: '项目级 API 根地址,可在弹层中修改。',
scope: 'project',
editable: true,
},
{
name: 'user_id',
label: 'User ID',
value: 'u_1024',
description: '当前登录用户 ID。',
scope: 'local',
},
{
name: 'token',
label: 'Auth Token',
value: 'cf_live_xxx',
description: '授权令牌,由外层业务控制保存。',
scope: 'global',
editable: true,
},
];
</script>
<template>
<div style="width: 100%; max-width: 920px;">
<CfVariableAwareInput
v-model="value"
:variables="variables"
placeholder="输入 {{ 触发变量选择"
@variable-select="(variable) => lastAction = `插入变量:${variable.name}`"
@variable-update="(payload) => lastAction = `请求更新 ${payload.name} = ${payload.value}`"
@variable-create="(payload) => lastAction = `请求创建变量:${payload.name}`"
/>
<div style="margin-top: 10px; color: var(--fg-3); font-size: 12px;">
{{ lastAction }}
</div>
</div>
</template> import { useState } from 'react';
import { CfVariableAwareInput } from '@chufix-design/react';
export default function Demo() {
const [value, setValue] = useState('请求 {{base_url}}/v2/users/{{user_id}}?token={{token}}');
const [lastAction, setLastAction] = useState('输入 {{ 触发候选;点击变量查看详情。');
const variables = [
{
name: 'base_url',
label: 'Base URL',
value: 'https://api.chufix.dev',
description: '项目级 API 根地址,可在弹层中修改。',
scope: 'project',
editable: true,
},
{
name: 'user_id',
label: 'User ID',
value: 'u_1024',
description: '当前登录用户 ID。',
scope: 'local',
},
{
name: 'token',
label: 'Auth Token',
value: 'cf_live_xxx',
description: '授权令牌,由外层业务控制保存。',
scope: 'global',
editable: true,
},
];
return (
<>
<div style={{ width: "100%", maxWidth: 920 }}>
<CfVariableAwareInput value={value} onChange={setValue} variables={variables} placeholder="输入 {{ 触发变量选择" onVariableSelect={(variable) => setLastAction(`插入变量:${variable.name}`)}
onVariableUpdate={(payload) => setLastAction(`请求更新 ${payload.name} = ${payload.value}`)}
onVariableCreate={(payload) => setLastAction(`请求创建变量:${payload.name}`)}
/>
<div style={{ marginTop: 10, color: "var(--fg-3)", fontSize: 12 }}>
{lastAction}
</div>
</div>
</>
);
} import { useState } from 'react';
import { CfVariableAwareInput } from '@chufix-design/react';
export default function Demo() {
const [value, setValue] = useState('请求 {{base_url}}/v2/users/{{user_id}}?token={{token}}');
const [lastAction, setLastAction] = useState('输入 {{ 触发候选;点击变量查看详情。');
const variables = [
{
name: 'base_url',
label: 'Base URL',
value: 'https://api.chufix.dev',
description: '项目级 API 根地址,可在弹层中修改。',
scope: 'project',
editable: true,
},
{
name: 'user_id',
label: 'User ID',
value: 'u_1024',
description: '当前登录用户 ID。',
scope: 'local',
},
{
name: 'token',
label: 'Auth Token',
value: 'cf_live_xxx',
description: '授权令牌,由外层业务控制保存。',
scope: 'global',
editable: true,
},
];
return (
<>
<div style={{ width: "100%", maxWidth: 920 }}>
<CfVariableAwareInput value={value} onChange={setValue} variables={variables} placeholder="输入 {{ 触发变量选择" onVariableSelect={(variable) => setLastAction(`插入变量:${variable.name}`)}
onVariableUpdate={(payload) => setLastAction(`请求更新 ${payload.name} = ${payload.value}`)}
onVariableCreate={(payload) => setLastAction(`请求创建变量:${payload.name}`)}
/>
<div style={{ marginTop: 10, color: "var(--fg-3)", fontSize: 12 }}>
{lastAction}
</div>
</div>
</>
);
} 混合状态
已知(accent 高亮)+ 未知(红色波浪线)的组合实例。
背景 视口
<script setup lang="ts">
import { ref } from 'vue';
import { CfVariableAwareInput } from '@chufix-design/vue';
const v1 = ref('valid only: {{base_url}} / {{user_id}}');
const v2 = ref('mixed: {{base_url}}/v1/{{token}}/users/{{user_id}}');
const v3 = ref('all unknown: {{a}} {{b}} {{c}}');
const known = ['base_url', 'user_id'];
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px; width: 100%; max-width: 920px;">
<CfVariableAwareInput v-model="v1" :variables="known" />
<CfVariableAwareInput v-model="v2" :variables="known" />
<CfVariableAwareInput v-model="v3" :variables="known" />
</div>
</template> <script setup>
import { ref } from 'vue';
import { CfVariableAwareInput } from '@chufix-design/vue';
const v1 = ref('valid only: {{base_url}} / {{user_id}}');
const v2 = ref('mixed: {{base_url}}/v1/{{token}}/users/{{user_id}}');
const v3 = ref('all unknown: {{a}} {{b}} {{c}}');
const known = ['base_url', 'user_id'];
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 12px; width: 100%; max-width: 920px;">
<CfVariableAwareInput v-model="v1" :variables="known" />
<CfVariableAwareInput v-model="v2" :variables="known" />
<CfVariableAwareInput v-model="v3" :variables="known" />
</div>
</template> import { useState } from 'react';
import { CfVariableAwareInput } from '@chufix-design/react';
export default function Demo() {
const [v1, setV1] = useState('valid only: {{base_url}} / {{user_id}}');
const [v2, setV2] = useState('mixed: {{base_url}}/v1/{{token}}/users/{{user_id}}');
const [v3, setV3] = useState('all unknown: {{a}} {{b}} {{c}}');
const known = ['base_url', 'user_id'];
return (
<>
<div style={{ display: "flex", flexDirection: "column", gap: 12, width: "100%", maxWidth: 920 }}>
<CfVariableAwareInput value={v1} onChange={setV1} variables={known} />
<CfVariableAwareInput value={v2} onChange={setV2} variables={known} />
<CfVariableAwareInput value={v3} onChange={setV3} variables={known} />
</div>
</>
);
} import { useState } from 'react';
import { CfVariableAwareInput } from '@chufix-design/react';
export default function Demo() {
const [v1, setV1] = useState('valid only: {{base_url}} / {{user_id}}');
const [v2, setV2] = useState('mixed: {{base_url}}/v1/{{token}}/users/{{user_id}}');
const [v3, setV3] = useState('all unknown: {{a}} {{b}} {{c}}');
const known = ['base_url', 'user_id'];
return (
<>
<div style={{ display: "flex", flexDirection: "column", gap: 12, width: "100%", maxWidth: 920 }}>
<CfVariableAwareInput value={v1} onChange={setV1} variables={known} />
<CfVariableAwareInput value={v2} onChange={setV2} variables={known} />
<CfVariableAwareInput value={v3} onChange={setV3} variables={known} />
</div>
</>
);
} API
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue / value | string | '' | 输入值 |
variables | (string | VariableOption)[] | [] | 已知变量名或变量对象清单 |
size | 'sm' | 'md' | 'lg' | 'md' | |
variant | 'outline' | 'filled' | 'outline' | |
suggest | boolean | true | 是否在输入 {{ 时展示候选列表 |
suggestTrigger | string | '{{' | 候选触发文本 |
interactive | boolean | true | 是否允许点击变量打开交互弹层 |
showVariablePopover | boolean | true | 是否使用内置变量详情弹层 |
placeholder / disabled / error |
| 事件 / 扩展 | 说明 |
|---|---|
variable-select / onVariableSelect | 从候选列表插入变量时触发 |
variable-click / onVariableClick | 点击已识别变量时触发 |
variable-update / onVariableUpdate | 内置弹层点击更新时触发,组件不直接保存 |
variable-create / onVariableCreate | 点击未知变量的创建入口时触发 |
Vue #option / React renderVariableOption | 自定义候选项渲染 |
Vue #variable-popover / React renderVariablePopover | 自定义变量详情弹层 |
反馈与讨论
VariableAwareInput 变量感知输入 的讨论