开发预览 更新于 2026-05-10

Input 输入框

单行输入 —— 3 种 variant、3 种尺寸、错误态、可清空、prefix/suffix。

基础用法

v-model / value + onChange 直接绑定字符串。placeholder 跟原生 input 一致。

背景 视口

已输入:(空)

src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfInput } from '@chufix-design/vue';

const name = ref('');
</script>
<template>
  <div class="demo-stack">
    <CfInput v-model="name" placeholder="请输入用户名" />
    <p class="demo-hint">已输入:<code>{{ name || '(空)' }}</code></p>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfInput } from '@chufix-design/vue';

const name = ref('');
</script>
<template>
  <div class="demo-stack">
    <CfInput v-model="name" placeholder="请输入用户名" />
    <p class="demo-hint">已输入:<code>{{ name || '(空)' }}</code></p>
  </div>
</template>
import { useState } from 'react';
import { CfInput } from '@chufix-design/react';

export default function Demo() {
const [name, setName] = useState('');
return (
  <CfInput
    value={name}
    onChange={(e) => setName(e.target.value)}
    placeholder="请输入用户名"
  />
);
}
import { useState } from 'react';
import { CfInput } from '@chufix-design/react';

export default function Demo() {
const [name, setName] = useState('');
return (
  <CfInput
    value={name}
    onChange={(e) => setName(e.target.value)}
    placeholder="请输入用户名"
  />
);
}

视觉变体

3 种 variant 提供不同的边框 / 背景强度。filled 适合表单密集的场景,ghost 在已有容器边框时使用,避免双重边框。

背景 视口
src/App.vue
<script setup lang="ts">
import { CfInput } from '@chufix-design/vue';
</script>
<template>
  <div class="demo-stack">
    <CfInput variant="outline" placeholder="outline · 默认" />
    <CfInput variant="filled" placeholder="filled · 灰色填充" />
    <CfInput variant="ghost" placeholder="ghost · 无边框,聚焦才出现" />
  </div>
</template>
<script setup>
import { CfInput } from '@chufix-design/vue';
</script>
<template>
  <div class="demo-stack">
    <CfInput variant="outline" placeholder="outline · 默认" />
    <CfInput variant="filled" placeholder="filled · 灰色填充" />
    <CfInput variant="ghost" placeholder="ghost · 无边框,聚焦才出现" />
  </div>
</template>
import { CfInput } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <CfInput variant="outline" placeholder="outline · 默认" />
      <CfInput variant="filled" placeholder="filled · 灰色填充" />
      <CfInput variant="ghost" placeholder="ghost · 无边框,聚焦才出现" />
    </>
  );
}
import { CfInput } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <CfInput variant="outline" placeholder="outline · 默认" />
      <CfInput variant="filled" placeholder="filled · 灰色填充" />
      <CfInput variant="ghost" placeholder="ghost · 无边框,聚焦才出现" />
    </>
  );
}

尺寸

背景 视口
src/App.vue
<script setup lang="ts">
import { CfInput } from '@chufix-design/vue';
</script>
<template>
  <div class="demo-stack">
    <CfInput size="sm" placeholder="Small" />
    <CfInput size="md" placeholder="Medium(默认)" />
    <CfInput size="lg" placeholder="Large" />
  </div>
</template>
<script setup>
import { CfInput } from '@chufix-design/vue';
</script>
<template>
  <div class="demo-stack">
    <CfInput size="sm" placeholder="Small" />
    <CfInput size="md" placeholder="Medium(默认)" />
    <CfInput size="lg" placeholder="Large" />
  </div>
</template>
import { CfInput } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <CfInput size="sm" placeholder="Small" />
      <CfInput size="md" placeholder="Medium" />
      <CfInput size="lg" placeholder="Large" />
    </>
  );
}
import { CfInput } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <CfInput size="sm" placeholder="Small" />
      <CfInput size="md" placeholder="Medium" />
      <CfInput size="lg" placeholder="Large" />
    </>
  );
}

状态

clearable 只在有值时显示清除按钮;error 切换到危险色边框 + ring;disabled / readonly 与原生 input 一致。

背景 视口
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfInput } from '@chufix-design/vue';

const search = ref('hello');
const email = ref('not-an-email');
const valid = (s: string) => /.+@.+\..+/.test(s);
</script>
<template>
  <div class="demo-stack">
    <CfInput v-model="search" clearable placeholder="可清空(输入后出现 ×)" />
    <CfInput
      v-model="email"
      :error="!valid(email)"
      placeholder="错误状态:邮箱格式不对"
    />
    <CfInput placeholder="禁用" disabled />
    <CfInput placeholder="只读" readonly model-value="readonly content" />
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfInput } from '@chufix-design/vue';

const search = ref('hello');
const email = ref('not-an-email');
const valid = (s) => /.+@.+\..+/.test(s);
</script>
<template>
  <div class="demo-stack">
    <CfInput v-model="search" clearable placeholder="可清空(输入后出现 ×)" />
    <CfInput
      v-model="email"
      :error="!valid(email)"
      placeholder="错误状态:邮箱格式不对"
    />
    <CfInput placeholder="禁用" disabled />
    <CfInput placeholder="只读" readonly model-value="readonly content" />
  </div>
</template>
import { useState } from 'react';
import { CfInput } from '@chufix-design/react';

export default function Demo() {
const [email, setEmail] = useState('not-an-email');
const valid = /.+@.+\..+/.test(email);

return (
  <>
    <CfInput clearable placeholder="可清空(输入后出现 ×)" />
    <CfInput
      value={email}
      onChange={(e) => setEmail(e.target.value)}
      error={!valid}
      placeholder="错误状态:邮箱格式不对"
    />
    <CfInput placeholder="禁用" disabled />
    <CfInput placeholder="只读" readOnly defaultValue="readonly content" />
  </>
);
}
import { useState } from 'react';
import { CfInput } from '@chufix-design/react';

export default function Demo() {
const [email, setEmail] = useState('not-an-email');
const valid = /.+@.+\..+/.test(email);

return (
  <>
    <CfInput clearable placeholder="可清空(输入后出现 ×)" />
    <CfInput
      value={email}
      onChange={(e) => setEmail(e.target.value)}
      error={!valid}
      placeholder="错误状态:邮箱格式不对"
    />
    <CfInput placeholder="禁用" disabled />
    <CfInput placeholder="只读" readOnly defaultValue="readonly content" />
  </>
);
}

前后缀

通过具名插槽(Vue)/ prefix & suffix props(React)放置图标或固定文本。clearablesuffix 互斥(有内容时显示清除按钮)。

背景 视口
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfInput } from '@chufix-design/vue';

const url = ref('');
const search = ref('');
</script>
<template>
  <div class="demo-stack">
    <CfInput v-model="url" placeholder="example">
      <template #prefix>https://</template>
      <template #suffix>.com</template>
    </CfInput>
    <CfInput v-model="search" clearable placeholder="搜索…">
      <template #prefix>
        <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.6">
          <circle cx="7" cy="7" r="4" />
          <path d="M10 10l3 3" stroke-linecap="round" />
        </svg>
      </template>
    </CfInput>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfInput } from '@chufix-design/vue';

const url = ref('');
const search = ref('');
</script>
<template>
  <div class="demo-stack">
    <CfInput v-model="url" placeholder="example">
      <template #prefix>https://</template>
      <template #suffix>.com</template>
    </CfInput>
    <CfInput v-model="search" clearable placeholder="搜索…">
      <template #prefix>
        <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.6">
          <circle cx="7" cy="7" r="4" />
          <path d="M10 10l3 3" stroke-linecap="round" />
        </svg>
      </template>
    </CfInput>
  </div>
</template>
import { useState } from 'react';
import { CfInput } from '@chufix-design/react';

export default function Demo() {
  const [url, setUrl] = useState('');
  const [search, setSearch] = useState('');
  return (
    <>
      <div className="demo-stack">
          <CfInput value={url} onChange={setUrl} placeholder="example">
            https://
    </>
  );
}
import { useState } from 'react';
import { CfInput } from '@chufix-design/react';

export default function Demo() {
  const [url, setUrl] = useState('');
  const [search, setSearch] = useState('');
  return (
    <>
      <div className="demo-stack">
          <CfInput value={url} onChange={setUrl} placeholder="example">
            https://
    </>
  );
}

密码输入

type="password" 把字符显示为掩码。配合 suffix 插槽放一个 CfIconButton 切换 type="text" / "password", 就得到”显示/隐藏密码”的完整体验。按钮用 pressed 表达当前是否可见。

背景 视口
src/App.vue
<script setup lang="ts">
import { computed, ref } from 'vue';
import { CfInput, CfIconButton, CfIcon } from '@chufix-design/vue';

const pwd = ref<string>('');
const visible = ref<boolean>(false);
const inputType = computed<'text' | 'password'>(() => (visible.value ? 'text' : 'password'));
</script>
<template>
  <CfInput v-model="pwd" :type="inputType" placeholder="请输入密码">
    <template #suffix>
      <CfIconButton
        size="sm"
        :aria-label="visible ? '隐藏密码' : '显示密码'"
        :pressed="visible"
        @click="visible = !visible"
      >
        <CfIcon :name="visible ? 'eye-off' : 'eye'" />
      </CfIconButton>
    </template>
  </CfInput>
</template>
<script setup>
import { computed, ref } from 'vue';
import { CfInput, CfIconButton, CfIcon } from '@chufix-design/vue';

const pwd = ref<string>('');
const visible = ref<boolean>(false);
const inputType = computed<'text' | 'password'>(() => (visible.value ? 'text' : 'password'));
</script>
<template>
  <CfInput v-model="pwd" :type="inputType" placeholder="请输入密码">
    <template #suffix>
      <CfIconButton
        size="sm"
        :aria-label="visible ? '隐藏密码' : '显示密码'"
        :pressed="visible"
        @click="visible = !visible"
      >
        <CfIcon :name="visible ? 'eye-off' : 'eye'" />
      </CfIconButton>
    </template>
  </CfInput>
</template>
import { useState } from 'react';
import { CfInput, CfIconButton, CfIcon } from '@chufix-design/react';

export default function Demo() {
const [pwd, setPwd] = useState('');
const [visible, setVisible] = useState(false);
return (
  <CfInput
    type={visible ? 'text' : 'password'}
    value={pwd}
    onChange={(e) => setPwd(e.target.value)}
    placeholder="请输入密码"
    suffix={
      <CfIconButton
        size="sm"
        aria-label={visible ? '隐藏密码' : '显示密码'}
        pressed={visible}
        onClick={() => setVisible(!visible)}
      >
        <CfIcon name={visible ? 'eye-off' : 'eye'} />
      </CfIconButton>
    }
  />
);
}
import { useState } from 'react';
import { CfInput, CfIconButton, CfIcon } from '@chufix-design/react';

export default function Demo() {
const [pwd, setPwd] = useState('');
const [visible, setVisible] = useState(false);
return (
  <CfInput
    type={visible ? 'text' : 'password'}
    value={pwd}
    onChange={(e) => setPwd(e.target.value)}
    placeholder="请输入密码"
    suffix={
      <CfIconButton
        size="sm"
        aria-label={visible ? '隐藏密码' : '显示密码'}
        pressed={visible}
        onClick={() => setVisible(!visible)}
      >
        <CfIcon name={visible ? 'eye-off' : 'eye'} />
      </CfIconButton>
    }
  />
);
}

搜索框

type="search" + clearable + 前缀放搜索图标,这是顶部搜索框的标准组合。type="search" 在移动端会显示搜索专用键盘。

背景 视口
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfInput, CfIcon } from '@chufix-design/vue';

const keyword = ref<string>('');
</script>
<template>
  <CfInput
    v-model="keyword"
    type="search"
    clearable
    placeholder="搜索文档、组件、blocks…"
  >
    <template #prefix>
      <CfIcon name="search" />
    </template>
  </CfInput>
</template>
<script setup>
import { ref } from 'vue';
import { CfInput, CfIcon } from '@chufix-design/vue';

const keyword = ref<string>('');
</script>
<template>
  <CfInput
    v-model="keyword"
    type="search"
    clearable
    placeholder="搜索文档、组件、blocks…"
  >
    <template #prefix>
      <CfIcon name="search" />
    </template>
  </CfInput>
</template>
import { useState } from 'react';
import { CfIcon, CfInput } from '@chufix-design/react';

export default function Demo() {
  const [keyword, setKeyword] = useState<string>('');
  return (
    <>
      <CfInput value={keyword} onChange={setKeyword} type="search" clearable placeholder="搜索文档、组件、blocks…" >
            <CfIcon name="search" />
    </>
  );
}
import { useState } from 'react';
import { CfIcon, CfInput } from '@chufix-design/react';

export default function Demo() {
  const [keyword, setKeyword] = useState<string>('');
  return (
    <>
      <CfInput value={keyword} onChange={setKeyword} type="search" clearable placeholder="搜索文档、组件、blocks…" >
            <CfIcon name="search" />
    </>
  );
}

API

Props

Prop类型默认值说明
modelValuestring | numberVue v-model 绑定值
valuestringReact 受控值
type'text' | 'password' | 'email' | 'number' | 'tel' | 'url' | 'search''text'输入类型
variant'outline' | 'filled' | 'ghost''outline'视觉变体
size'sm' | 'md' | 'lg''md'高度与字号
clearablebooleanfalse有值时显示清除按钮
errorbooleanfalse错误态边框 / ring
disabledbooleanfalse禁用
readonlybooleanfalse只读(React 端为 readOnly
placeholderstring占位文本
autofocusbooleanfalse挂载后自动获取焦点(适合 Modal 打开)

name / id 是直接透传到原生 <input> 的 HTML 标准属性,用于参与表单提交或 label 关联。

Events

Vue 事件React 回调载荷类型说明
update:modelValuestring输入变化,v-model 隐式监听
changeonChangestring(Vue)/ ChangeEvent(React)失焦后触发原生 change
focusonFocusFocusEvent获得焦点
bluronBlurFocusEvent失去焦点
clearonClear点击 clear 按钮(仅 clearable 时)

Slots / Children

Slot说明
prefix左侧固定内容(图标 / 文本);React 端等价为 prefix prop
suffix右侧固定内容(图标 / 单位文本);React 端等价为 suffix prop

反馈与讨论

Input 输入框 的讨论

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