stateStyles：多态样式如何设置不向父组件冒泡
===========================

#### 问题现象

stateStyles多态样式，父组件和子组件都设置了stateStyles，子组件满足stateStyles状态时，父组件也同样满足，也会跟着改变，效果图如下：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/d2/v3/Jn6WxA_1SYaf8rHlhJOE6g/zh-cn_image_0000002663716957.png?HW-CC-KV=V1&HW-CC-Date=20260709T133926Z&HW-CC-Expire=86400&HW-CC-Sign=797B3F7AA8D27070875CBE6AC4CEAE07E94539A0FE43E8C3249E4FA1A4E15671 "点击放大")

*   蓝色背景为父组件，绿色背景为子组件。
*   子组件常态（normal）为绿色，按压态（pressed）为黄色。
*   父组件常态（normal）为蓝色，按压态（pressed）为灰色。
*   当前的效果是，按压子组件“Hello World2”，子组件会由绿色变为黄色，父组件也会由蓝色变为灰色；按压父组件区域，父组件会由蓝色变为灰色，子组件（Hello World2）不会变。
*   期望的效果是：按压子组件“Hello World2”，子组件由绿色变为黄色，父组件不变。

如何设置可以不向父组件冒泡，子组件改变不影响父组件？

#### 背景知识

[stateStyles](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-statestyles)：多态样式，可以依据组件的内部状态的不同，快速设置不同样式。ArkUI提供以下六种状态：

*   focused：获焦态。
*   normal：正常态。
*   pressed：按压态。
*   disabled：不可用态。
*   clicked：点击态。
*   selected：选中态。

[事件冒泡](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-interaction-basic-principles#事件冒泡)：基础事件在响应链上的传递遵循冒泡机制，即最内层组件优先处理，再逐层往父组件传递该事件，任意一层组件可主动终止本次事件的继续传递，即终止冒泡（stopPropagation可终止冒泡）。但需要注意的是，终止冒泡并不会中断父组件对手势的响应处理。

[基础输入事件](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/basic-raw-input-event)中，[触摸事件](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-events-touch)由手指、手写笔或鼠标左键在组件上按下、滑动或抬起时触发。触摸事件默认冒泡，会被多个组件消费。

#### 解决方案

在子组件绑定[onTouch](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-events-touch#ontouch)回调，并在回调中通过stopPropagation方法阻止按下的事件传递到父组件，父组件不会变为按压态。

示例demo：

@Entry
@Component
struct StateStylesDemo {
  build() {
    Row() {
      Column() {
        Text('Hello World1')
          .fontSize($r('app.float.page\_text\_font\_size'))
          .fontWeight(FontWeight.Bold);

        Text('Hello World2')
          .fontSize($r('app.float.page\_text\_font\_size'))
          .fontWeight(FontWeight.Bold)
          .stateStyles({
            focused: {
              .backgroundColor('#ffffeef0');
            },
            pressed: {
              .backgroundColor('#F7CE00');
            },
            normal: {
              .backgroundColor('#ff50be33');
            }
          })
          .onTouch((event: TouchEvent) => {
            event.stopPropagation();
          });

        Text('Hello World3')
          .fontSize($r('app.float.page\_text\_font\_size'))
          .fontWeight(FontWeight.Bold);
      }
      .stateStyles({
        focused: {
          .backgroundColor('#ffffeef0');
        },
        pressed: {
          .backgroundColor(Color.Gray);
        },
        normal: {
          .backgroundColor('#ff2787d9');
        }
      })
      .justifyContent(FlexAlign.SpaceEvenly)
      .height('50%')
      .width('100%');
    }
    .height('100%')
    .width('100%');
  }
}

按压子组件后，不会触发父组件stateStyles的按压设置效果，效果如下：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/c4/v3/DLAsk2IBR4eWUfaAz_upLQ/zh-cn_image_0000002663797649.png?HW-CC-KV=V1&HW-CC-Date=20260709T133926Z&HW-CC-Expire=86400&HW-CC-Sign=6A2B7FC29D647F214C661FA7B8ABD6227C373499DB684F36A7462AF0341C2AFB "点击放大")

#### 总结

stopPropagation干预事件冒泡时，应注意对同一事件的不同类型（如Down/Move/Up）采用一致的规则，避免上层节点仅接收到部分类型事件，导致事件不闭环的情况，例如当节点仅接收到Down事件，而未接收到Up事件，这会影响节点上的事件完整性（对于指向性按下操作类交互产生的事件，确保事件的完整性是必要的）。