input — 实现与 components.md 对照

对照基准:

  • 规格:docs/refs/components.md#input
  • AI 限制:支持(无冲突项);safe-password / always-embed / nickname 等 ⏭️
  • 实现:
    • packages/flexui-frontend/src/components/input/input.ts
    • flexui-engine/driver/js/packages/flexui-backend/src/adapters/input-adapter.ts
    • Native:TextInputViewfocusTextInput / blurTextInput / placeholderTextColor
    • Demo:demos/ascf-ai-demo/.../input-demo/

模板使用 kebab-case(如 confirm-typeplaceholder-style),组件 propertiescamelCase(如 confirmTypeplaceholderStyle);adapter / host attribute 仅 kebab-case,不双写 camelCase 别名。

包名说明:内置组件源码在 @openflexui/frontendpackages/flexui-frontend);原生 adapter 在 flexui-backend


结论摘要

维度 结论
规格纳入(✅) value / type / password / placeholder / placeholder-style / placeholder-class / disabled / maxlength / focus / confirm-type + bindinput / bindfocus / bindblur / bindconfirm(须 bind 前缀)→ 已声明
事件 detail bindinput { value, cursor, keyCode }bindfocus { value, height }bindblur { value, cursor }bindconfirm { value }
规格「⚠️」 focus Native callUIFunctionplaceholder-style/class Native 以 color 为主
暂不支持 bindchange(非聚焦变更语义;勿当 bindinput 别名)
规格「⏭️」 safe-password*nicknameauto-focusalways-embed、Skyline composition/worklet → 未声明
默认值 type=textpassword=falseplaceholder-class=input-placeholderdisabled=falsemaxlength=140focus=falseconfirm-type=done

属性对照

通用(可交付)

属性(模板) 类型 规格默认 components.md 当前实现 说明
name string ✅(form 字段) ✅ → host name form 收集;空串不收集
type string text ✅ 见合法值 ✅ → keyboardType text / numbertext→default;number→numeric→Number;其余非法回退 text
password boolean false ✅ → keyboardType=password 后写覆盖 typeisAttrPresenceOn"false"→true(密文)
placeholder string ✅ → placeholder 占位符文案
placeholder-style string ✅ ⚠️ ✅ → 解析 colorplaceholderTextColor;Domlike ::placeholder font-size/weight Domlike 可注入
placeholder-class string input-placeholder ✅ ⚠️ ✅ host attr;Domlike probe class;Native CSSManager → color 空串回退默认类名
disabled boolean false ✅ Domlike;Native editable"false"→仍禁用(同 button)
maxlength number 140 ✅ → maxLength 非法 → 140-1 Domlike 大数 / Native ResetMaxLength(不限制)
focus boolean false ✅ ⚠️ ✅ Domlike;Native callUIFunction"false"→仍聚焦 写入事件监听 prop focus
confirm-type string done ✅ → returnKeyType kebab only

type 合法值

components.md 当前实现
text ✅ → default / InputType.Normal
number ✅ → numeric / InputType.Number
digit / idcard ⏭️ 不纳入 ❌ 非法值回退 text
safe-password ⏭️ WebView ❌ 未声明;传入回退 text
nickname ⏭️ ❌ 未声明;传入回退 text

事件对照

事件 components.md 当前实现 detail / 备注
bindinput { value, cursor, keyCode } inputchangetext Domlike:keydown 记 keyCode + selectionStart;Native:OnWillInsert/Delete → cursor/keyCode
bindfocus { value, height } height = 软键盘高度(vp/dp);首焦时键盘未起可为 0
bindblur { value, cursor } cursor 来自选区起点
bindconfirm { value } confirmendediting { value }
bindchange ⏭️ 暂不支持 ❌ 未映射 非聚焦态变更语义;已从 eventNamesMap 去掉 change

事件 detail 字段

事件 detail Domlike Native(OHOS) Native(Android)
bindinput value / cursor / keyCode ✅ / ✅ / ✅(keydown) ✅ / ✅ / ✅(WillInsert/Delete;无按键时 0) ✅ / ✅ / ✅(TextWatcher;无按键时 0)
bindfocus value / height ✅ / ✅(visualViewport 近似,不可用则为 0) ✅ / ✅(lastKeyboardHeight;键盘未弹出时为 0) ✅ / height 暂 0
bindblur value / cursor ✅ / ✅ ✅ / ✅ ✅ / ✅
bindconfirm value

说明:height 语义为键盘高度(对齐微信);聚焦瞬间键盘尚未上报时可能为 0,后续以 keyboardwillshow 为准。Android:cursor / blur.cursor / bindinput.keyCode 已贯通(focus.height 暂 0)。


实现要点

  1. TS:交付属性经 this._$.setAttribute(kebab)写入 host;Domlike 另同步 HTMLInputElement
  2. 事件须 bind 前缀连写:模板用 bindinput / bindfocus / bindblur / bindconfirm(对齐微信 input 文档;勿省略 bind)。
  3. 非受控 value 不被 flush 清空(分层防护,策略不完全相同):
    • flushAndBuild 会重推全部 attributes;C++/ETS 用 lastJsValue_ 仅在 JS prop 变化时 SetTextContent
    • NBE + Domlike(前缀丢弃):聚焦态若 prev/curnext 更长且 prev.startsWith(next),拒绝滞后 setAttribute/_syncValue(防 setData("a") 覆盖 "ab")。空串 next 不走此前缀保护(可主动清空)。Domlike 在 onInput 里把 _lastSyncedValue 同步到 DOM 值,因此不能再用 cur !== _lastSyncedValue 判断滞后。
    • C++/ETS(聚焦全丢弃):聚焦且 value_ != lastJsValue_(native 已超前、JS 尚未 ack)时,任何不等于当前 value_ 的 JS value prop 一律丢弃,直到 JS ack 到 value_。这比前缀策略更严——父组件在聚焦期间主动格式化/纠错(非「更短前缀」的合法写入)也会静默失效。业务若需聚焦中改值,应在 blur 后写,或先让 controlled value ack 到当前输入再改。
    • EventDispatcher 在 changetext 时回写 attributes.value(不 scheduleRender)。
  4. password 优先:先写 type 再写 password,保证 buildProps 中 password 覆盖 keyboardType
  5. focus:adapter propsValueundefined(避免与监听 prop 冲突);NativeBackendElement.setAttributecallUIFunction(已 mount);首屏 focus=true_isMounted 前写入时打 _inputFocusPendingflush 后 microtask 补 focusTextInput(等 flushQueue/SceneBuilder 建好节点)。默认 focus=false 在 mount 时调 blurTextInput
  6. placeholder-style / placeholder-class:style 的 color 优先;class 经 Domlike probe 或 Native CSSManager 取 color → placeholderTextColor;空 class 回退 input-placeholder
  7. Booleanpassword / disabled / focus):与 button disabled 相同,用 isAttrPresenceOnpackages/flexui-frontend/src/attr_bool.ts)——仅 false/0/'0'/未传为关;字符串 "false" 仍为 true。Native adapter / NBE focus 同步用同语义。
  8. OHOS 点击拉起键盘:C++ TextInputNodeSetFocusable(true) + HIT_TEST_DEFAULTArkUINode 默认 TRANSPARENT);FocusTextInput 同时 SetFocusStatus + SetTextEditing(true);C-API UpdateEventListener 仅对 TextInput SetProp 事件名(isListen*),OnSetPropsEnd(避免 Init/hit-test 副作用;对齐 ETS setProp only)。
  9. maxlength=-1:adapter 透传 -1;C++ ResetMaxLength()(reset ArkUI 属性=不限制);ETS 用 0x7FFFFFFF;Domlike 524288
  10. 验证:改 adapter / NativeBackendElementbuild-jsfwk;改 C++/ETS → assembleHap;仅 frontend → pnpm --filter @openflexui/frontend run build

Demo 覆盖(input-demo

类型 覆盖项
正向 value / placeholder / placeholder-style / placeholder-class / style 优先 class;type text/number / password / disabled / maxlength(含 -1) / focus(含首屏 true) / confirm-type + 事件 detail(input: value/cursor/keyCode;focus: value/height;blur: value/cursor;confirm: value)
异常 type 非法(含 digit);placeholder-class="" 回退;password/disabled/focus="false"→仍为 true;maxlength="abc"→140

complex 页 Tab:Input


默认值审计

属性 规格默认 TS / adapter / native 状态
type text TS 'text'default
password false TS false;false 时 skip 映射
disabled false TS false
maxlength 140 TS 140
focus false TS false
confirm-type done TS / adapter done
placeholder-class input-placeholder TS 默认同规格

参考路径

角色 路径
交付规格 components.md#input
组件定义 packages/flexui-frontend/src/components/input/input.ts
Native 适配 flexui-engine/.../adapters/input-adapter.ts
Host focus NativeBackendElement._focusTextInputNow
Demo demos/ascf-ai-demo/.../input-demo/