小程序自定义组件通信与全局状态方案

举报
yd_264617019 发表于 2026/10/23 10:40:06 2026/10/23
【摘要】 小程序原生开发的组件通信,官方给了triggerEvent和relations,但复杂一点的页面就不够用。这篇梳理从基础到全局状态的四层通信方案,以及我们最后的选型。第一层:父子通信,triggerEvent。//子组件Component({properties:{value:String},//父到子methods:{onInput(e){this.triggerEvent('c...

小程序原生开发的组件通信,官方给了 triggerEvent 和 relations,但复杂一点的页面就不够用。这篇梳理从基础到全局状态的四层通信方案,以及我们最后的选型。

第一层:父子通信,triggerEvent。

// 子组件
Component({
  properties: { value: String }, // 父到子
  methods: {
    onInput(e) {
      this.triggerEvent('change', e.detail.value) // 子到父
    },
  },
})
<!-- 父页面 -->
<search-box value="{{kw}}" bind:change="onKwChange" />

标准但啰嗦:每加一个对外事件,两边都要改。跨层级(孙组件到爷爷页面)要层层转发,三层以上就该考虑别的方案了。

第二层:兄弟与跨层级,用 relations 还是事件总线上帝视角组件。relations 适合「父子有结构关联」的组件(如 collapse 与 collapse-item),互相拿到对方实例直接调方法。而通用场景我们用了一个极简总线:

// bus.js
const listeners = new Map()

module.exports = {
  on(event, fn) {
    if (!listeners.has(event)) listeners.set(event, new Set())
    listeners.get(event).add(fn)
    return () => listeners.get(event)?.delete(fn) // 返回解绑函数
  },
  emit(event, payload) {
    listeners.get(event)?.forEach((fn) => fn(payload))
  },
}
// 组件 attached 时订阅,detached 时解绑(必须成对,否则泄漏)
Component({
  lifetimes: {
    attached() {
      this._off = bus.on('cart-updated', (n) => this.setData({ count: n }))
    },
    detached() {
      this._off()
    },
  },
})

第三层:全局状态。购物车数量、登录态这类多处共享的数据,裸总线会让调用点满天飞。选型对比:

  • mobx-miniprogram + mobx-miniprogram-bindings:响应式,绑定后自动更新,学习成本低(写过 mobx 的零成本上手)
  • westore:腾讯出品,基于 diff 的 setData 优化,顺带解决通信
  • 自研简易 store:一个 observable 包装加页面 mixin

我们选了 mobx 系,共享 store 定义:

// stores/cart.js
import { observable, action } from 'mobx-miniprogram'

export const cartStore = observable({
  count: 0,
  addToCart: action(function () {
    this.count += 1
  }),
})
// 组件里绑定:store 变化自动 setData
import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
import { cartStore } from '../../stores/cart'

Component({
  behaviors: [storeBindingsBehavior],
  storeBindings: {
    store: cartStore,
    fields: { count: 'count' },
    actions: { addToCart: 'addToCart' },
  },
})

fields/actions 一配,模板直接用 count 和点击直接调 addToCart,组件内部不再写一行 setData。

四层方案的使用边界:props/events 管父子、bus 管偶发跨层通知、store 管全局共享数据、relations 管结构化组件簇。全部混用 store 的过度集中和全部用事件的满天飞,都是反面教材。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。