Preview Updated 2026-05-10

Editable 行内编辑

点击文本即变为输入框;Enter 提交、Esc 取消、blur 自动提交,支持同步 / 异步校验。

English translation pending This page hasn't been translated yet — falling back to Chinese. PRs welcome on GitHub.

何时使用

  • 表格 / 详情面板 / 卡片头里单字段就地修改(标题、备注、标签)。
  • CfInput 的差异:Input 是表单字段,永远展示边框;Editable 平时只展示文本,鼠标 hover 才出现编辑提示。
  • 不要替代整个表单:复杂修改请用 CfModal + CfForm

基础用法

单行 / 多行 / 禁用 / 同步异步校验都已经内置。validate 返回 true 才会提交,返回字符串视作错误信息。

背景 视口
单行可编辑(带校验)
北京 #3 机房
多行(Ctrl/Cmd+Enter 提交,Esc 取消)用于承载海外回源流量,QPS 上限 12000。
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfEditable, CfText } from '@chufix-design/vue';

const name = ref('北京 #3 机房');
const description = ref('用于承载海外回源流量,QPS 上限 12000。');
const restricted = ref('[email protected]');

async function validateName(next: string): Promise<true | string> {
  if (!next.trim()) return '名称不能为空';
  if (next.length > 30) return '不超过 30 个字符';
  return true;
}
</script>
<template>
  <div style="display: flex; flex-direction: column; gap: 16px; max-width: 480px;">
    <div>
      <CfText size="sm" variant="muted">单行可编辑(带校验)</CfText>
      <div style="font-size: var(--t-18); font-weight: var(--w-medium);">
        <CfEditable v-model="name" :validate="validateName" aria-label="机房名称" />
      </div>
    </div>
    <div>
      <CfText size="sm" variant="muted">多行(Ctrl/Cmd+Enter 提交,Esc 取消)</CfText>
      <CfEditable v-model="description" multiline placeholder="点击添加描述..." aria-label="描述" />
    </div>
    <div>
      <CfText size="sm" variant="muted">禁用态</CfText>
      <CfEditable v-model="restricted" disabled aria-label="主账号" />
    </div>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfEditable, CfText } from '@chufix-design/vue';

const name = ref('北京 #3 机房');
const description = ref('用于承载海外回源流量,QPS 上限 12000。');
const restricted = ref('[email protected]');

async function validateName(next): Promise<true | string> {
  if (!next.trim()) return '名称不能为空';
  if (next.length > 30) return '不超过 30 个字符';
  return true;
}
</script>
<template>
  <div style="display: flex; flex-direction: column; gap: 16px; max-width: 480px;">
    <div>
      <CfText size="sm" variant="muted">单行可编辑(带校验)</CfText>
      <div style="font-size: var(--t-18); font-weight: var(--w-medium);">
        <CfEditable v-model="name" :validate="validateName" aria-label="机房名称" />
      </div>
    </div>
    <div>
      <CfText size="sm" variant="muted">多行(Ctrl/Cmd+Enter 提交,Esc 取消)</CfText>
      <CfEditable v-model="description" multiline placeholder="点击添加描述..." aria-label="描述" />
    </div>
    <div>
      <CfText size="sm" variant="muted">禁用态</CfText>
      <CfEditable v-model="restricted" disabled aria-label="主账号" />
    </div>
  </div>
</template>
import { useState } from 'react';
import { CfEditable, CfText } from '@chufix-design/react';

export default function Demo() {
  const [name, setName] = useState('北京 #3 机房');
  const [description, setDescription] = useState('用于承载海外回源流量,QPS 上限 12000。');
  const [restricted, setRestricted] = useState('[email protected]');

  async function validateName(next: string): Promise<true | string> {
    if (!next.trim()) return '名称不能为空';
    if (next.length > 30) return '不超过 30 个字符';
    return true;
  }
  return (
    <>
      <div style={{ display: "flex", flexDirection: "column", gap: 16, maxWidth: 480 }}>
          <div>
            <CfText size="sm" variant="muted">单行可编辑(带校验)</CfText>
            <div style={{ fontSize: "var(--t-18)", fontWeight: "var(--w-medium)" }}>
              <CfEditable value={name} onChange={setName} validate={validateName} aria-label="机房名称" />
            </div>
          </div>
          <div>
            <CfText size="sm" variant="muted">多行(Ctrl/Cmd+Enter 提交,Esc 取消)</CfText>
            <CfEditable value={description} onChange={setDescription} multiline placeholder="点击添加描述..." aria-label="描述" />
          </div>
          <div>
            <CfText size="sm" variant="muted">禁用态</CfText>
            <CfEditable value={restricted} onChange={setRestricted} disabled aria-label="主账号" />
          </div>
        </div>
    </>
  );
}
import { useState } from 'react';
import { CfEditable, CfText } from '@chufix-design/react';

export default function Demo() {
  const [name, setName] = useState('北京 #3 机房');
  const [description, setDescription] = useState('用于承载海外回源流量,QPS 上限 12000。');
  const [restricted, setRestricted] = useState('[email protected]');

  async function validateName(next): Promise<true | string> {
    if (!next.trim()) return '名称不能为空';
    if (next.length > 30) return '不超过 30 个字符';
    return true;
  }
  return (
    <>
      <div style={{ display: "flex", flexDirection: "column", gap: 16, maxWidth: 480 }}>
          <div>
            <CfText size="sm" variant="muted">单行可编辑(带校验)</CfText>
            <div style={{ fontSize: "var(--t-18)", fontWeight: "var(--w-medium)" }}>
              <CfEditable value={name} onChange={setName} validate={validateName} aria-label="机房名称" />
            </div>
          </div>
          <div>
            <CfText size="sm" variant="muted">多行(Ctrl/Cmd+Enter 提交,Esc 取消)</CfText>
            <CfEditable value={description} onChange={setDescription} multiline placeholder="点击添加描述..." aria-label="描述" />
          </div>
          <div>
            <CfText size="sm" variant="muted">禁用态</CfText>
            <CfEditable value={restricted} onChange={setRestricted} disabled aria-label="主账号" />
          </div>
        </div>
    </>
  );
}

API

属性类型默认值说明
modelValue / valuestringVue v-model;React 受控 value
placeholderstring空值占位(斜体显示)
multilinebooleanfalse渲染为 <textarea>
disabledbooleanfalse完全只读
showHintbooleantruehover 时显示铅笔图标
commitOnEnterbooleantrue单行 Enter 提交;多行需 Ctrl/Cmd+Enter
maxLengthnumber字符上限
size'sm' | 'md' | 'lg''md'
validate(next) => boolean | string | Promise<...>返回 true 才提交;字符串作为错误消息显示
ariaLabelstring透传到外层 role="button"

Events

Vue 事件React 回调载荷说明
update:modelValueonChange新值提交时触发
commitonCommit{ value, previous }提交成功(值有变化)
cancelonCancelEsc 撤销
edit-startonEditStart进入编辑态
invalidonInvalidstring校验失败时返回的错误消息

反馈与讨论

Editable 行内编辑 · Discussion

0
0 / 600
正在加载评论...