textarea — 实现与 components.md 对照
对照基准:
- 规格:docs/refs/components.md#textarea
- AI 限制:支持(无冲突项);
fixed/show-confirm-bar等 ⏭️ WebView - 实现:
packages/flexui-frontend/src/components/textarea/textarea.tsflexui-engine/driver/js/packages/flexui-backend/src/adapters/textarea-adapter.ts- Native:
TextInput+multiline: true(focusTextInput/blurTextInput/placeholderTextColor) - Demo:
demos/ascf-ai-demo/.../textarea-demo/
模板使用 kebab-case(如 confirm-type、placeholder-style),组件 properties 为 camelCase;adapter / host attribute 仅 kebab-case,不双写 camelCase 别名。
包名说明:内置组件源码在
@openflexui/frontend(packages/flexui-frontend);原生 adapter 在flexui-backend。
结论摘要
| 维度 | 结论 |
|---|---|
| 规格纳入(✅) | value / placeholder / placeholder-style / placeholder-class / disabled / maxlength / focus / auto-height / confirm-type + bindinput / bindfocus / bindblur / bindconfirm → 已声明 |
| 事件 detail | 与 input 对齐:bindinput { value, cursor, keyCode };bindfocus { value, height };bindblur { value, cursor };bindconfirm { value } |
| 规格「⚠️」 | focus Native callUIFunction;placeholder-style / placeholder-class Native 以 color 为主;auto-height 仅 OHOS Native 测高 + UpdateNodeSize(Android 未实现回写) |
| 规格「⏭️」 | fixed / show-confirm-bar / auto-focus / Skyline composition → 未声明 |
| 暂不声明 | bindlinechange / 键盘推挤类 → ⚠️ 按需 |
| 默认值 | disabled=false、maxlength=140、focus=false、auto-height=false、confirm-type=return;Native multiline=true(不设 numberOfLines;auto-height=true 时 OHOS 忽略固定 height、放开 maxLines);defaultNativeStyle.minHeight=54(对齐 host min-height:3em @ 18px;原生不跑 :host CSS) |
属性对照
通用(可交付)
| 属性(模板) | 类型 | 规格默认 | components.md | 当前实现 | 说明 |
|---|---|---|---|---|---|
value |
string | — | ✅ | ✅ → value |
host attr + Domlike native.value |
name |
string | — | ✅(form 字段) | ✅ → host name |
供 form 收集;空串不收集 |
placeholder |
string | — | ✅ | ✅ → placeholder |
占位符文案 |
placeholder-style |
string | — | ✅ ⚠️ | ✅ → 解析 color → placeholderTextColor;Domlike ::placeholder |
|
placeholder-class |
string | textarea-placeholder |
✅ ⚠️ | ✅ host attr;Domlike probe class;Native CSSManager → color |
空串回退默认类名 |
disabled |
boolean | false |
✅ | ✅ Domlike;Native editable;"false"→仍禁用 |
|
maxlength |
number | 140 |
✅ | ✅ → maxLength |
非法 → 140;-1 Domlike 大数 / Native ResetMaxLength |
focus |
boolean | false |
✅ ⚠️ | ✅ Domlike;Native callUIFunction;"false"→仍聚焦 |
不写入事件监听 prop focus |
auto-height |
boolean | false |
✅ ⚠️ | ✅ → autoHeight;为 true 时忽略 style.height;"false"→仍开启 |
Domlike:scrollHeight;Native 测高回写仅 OHOS(Android adapter 透传 prop,无 UpdateNodeSize) |
confirm-type |
string | return |
✅ | ✅ → returnKeyType |
含 return;kebab only |
事件对照
| 事件 | components.md | 当前实现 | detail / 备注 |
|---|---|---|---|
bindinput |
✅ { value, cursor, keyCode } |
✅ input → changetext |
与 input 同链路 |
bindfocus |
✅ { value, height } |
✅ | height = 键盘高度(未弹出可为 0) |
bindblur |
✅ { value, cursor } |
✅ | |
bindconfirm |
✅ { value } |
✅ confirm → endediting |
须 bindconfirm;confirm-type=return 时 Enter 换行不发 confirm;非 return 不插行(Domlike preventDefault);Shift+Enter Domlike 仍换行 |
bindlinechange |
⚠️ 按需 | ❌ 未声明 | Native 有 contentsizechange,语义不完全等价,暂不映射 |
事件 detail 字段
| 事件 | detail | Domlike | Native(OHOS) | Native(Android) |
|---|---|---|---|---|
bindinput |
value / cursor / keyCode |
✅ / ✅ / ✅(keydown) | ✅ / ✅ / ✅(WillInsert/Delete) | ✅ / ✅ / ✅(TextWatcher onTextChanged) |
bindfocus |
value / height |
✅ / ✅ | ✅ / ✅ | ✅ / height 暂 0 |
bindblur |
value / cursor |
✅ / ✅ | ✅ / ✅ | ✅ / ✅ |
bindconfirm |
value |
✅ | ✅ | ✅ |
实现要点
- TS:交付属性经
this._$.setAttribute(kebab)写入 host;Domlike 另同步HTMLTextAreaElement。 - 事件须
bind前缀连写:模板用bindinput/bindfocus/bindblur/bindconfirm。 - 非受控 value:与 input 同策略分层——NBE/Domlike 聚焦态更短前缀丢弃;C++/ETS 聚焦且
value_ != lastJsValue_时全丢弃冲突 prop(含父组件主动格式化);EventDispatcher回写attributes.value。详见 input 对照「实现要点 §3」。 focus:adapterpropsValue恒undefined;NativeBackendElement对input与textarea走同一套callUIFunction。- Boolean(
disabled/focus/auto-height):isAttrPresenceOn——字符串"false"仍为 true。 auto-height:hostauto-height→ NativeautoHeight;为 true 时resolveNativeProps剔除style.height。测高回写仅 OHOS(GetTextContentRect+OnSizeChanged2);Android 仅透传 prop / 去掉固定 height,不回写 Dom 高度。Domlike 用scrollHeight同步。测高下限:max(3em, CSS minHeight)(NBE 经layoutMinHeight传入),避免空内容塌成一行、超长 placeholder 被裁切。NBE 仅首帧用 minHeight 占位 height,后续 flush 不得再写(blur/setData 会覆盖测高);RootNode 保留 UpdateNodeSize 高度;失焦后 CONTENT_RECT 裁切不得向下回写(否则变矮并可内部滚动)。- 默认高度:hostCSS
min-height:3em在原生 不生效(registerStyleSheetContent只吃 JSON 规则);由 adapterdefaultNativeStyle.minHeight=54兜底。业务min-height: Nem经 StyleResolver 按font-size折算。 confirm-type:return→ OHOSEnterKeyType.NEW_LINE/ AndroidIME_FLAG_NO_ENTER_ACTION(Enter 换行,不发 confirm)。非return:Native 走 onSubmit/endediting 不插行;Domlike Enter(无 Shift)preventDefault()后发confirm。Shift+Enter Domlike 仍插入换行、不发 confirm(浏览器默认)。cursor单位:统一 UTF-16 code unit(与 JSstring.length/ DomlikeselectionStart/ ETSinsertValue.length一致);C++OnWillInsert用Utf8ToUtf16CodeUnitCount,补充平面按 surrogate pair 计 2。- 无
type/password:textarea 规格不交付键盘类型 / 密文。 - 验证:改 adapter /
NativeBackendElement→build-jsfwk;改 C++/ETS →assembleHap/build-engine;仅 frontend →pnpm --filter @openflexui/frontend run build。
Demo 覆盖(textarea-demo)
| 类型 | 覆盖项 |
|---|---|
| 正向 | value / placeholder / placeholder-style / placeholder-class / style 优先 class;disabled / maxlength(含 -1) / focus(含首屏 true) / auto-height(含固定 height 应被忽略) / confirm-type + 事件 |
| 异常 | disabled/focus/auto-height="false"→仍为 true;maxlength="abc"→140 |
complex 页 Tab:Textarea。
默认值审计
| 属性 | 规格默认 | TS / adapter / native | 状态 |
|---|---|---|---|
disabled |
false |
TS false |
✅ |
maxlength |
140 |
TS 140 |
✅ |
focus |
false |
TS false |
✅ |
auto-height |
false |
TS false;Native 测高回写 仅 OHOS |
✅(Android 缺口见上) |
confirm-type |
return |
TS / adapter return |
✅ |
placeholder-class |
textarea-placeholder |
TS 默认同规格 | ✅ |
| multiline | — | adapter nativeProps.multiline=true |
✅ |
| numberOfLines | — | 不设(避免 ArkUI TextArea 按行截断) | ✅ |
| 默认高度 | host min-height:3em |
adapter minHeight:54(原生 :host 不生效) |
✅ |
参考路径
| 角色 | 路径 |
|---|---|
| 交付规格 | components.md#textarea |
| 组件定义 | packages/flexui-frontend/src/components/textarea/textarea.ts |
| Native 适配 | flexui-engine/.../adapters/textarea-adapter.ts |
| Host focus | NativeBackendElement._focusTextInputNow(input + textarea) |
| Demo | demos/ascf-ai-demo/.../textarea-demo/ |