RSC Component Architecture, EventBus, and Vuex State Management in Front-End Development
The article explains how the Remote Service Component (RSC) architecture uses a lightweight Vue‑based EventBus for decoupled communication and integrates Vuex with dynamically generated, namespaced stores to manage shared state across hot‑pluggable, visual‑configurable components, solving inter‑component data sharing and namespace collisions.
Background: The article introduces Remote Service Component (RSC), a hot‑pluggable, visual‑configurable component used to build activity pages efficiently, aiming for high cohesion and low coupling.
Problem: In activity pages, many components (e.g., Monopoly game, Card collection) need to share data, leading to complex inter‑component communication and state management.
Result: The team solved component connections at three levels: within the activity page, between RSC and the platform, and between sandbox configuration panels.
Architecture evolution: Focus on connecting RSC components inside activity pages, with future articles covering platform and sandbox connections.
EventBus: A centralized event bus is introduced to decouple components. Vue already provides a custom event system, so a lightweight EventBus can be built without extra dependencies.
const vm = new Vue() // Register subscriber vm.$on('event-name', (payload) => { /* business logic */ }) // Register one‑time subscriber vm.$once('some-event-name', (payload) => { /* business logic */ }) // Remove subscriber vm.$off('event-name', [callback]) // Emit event vm.$emit('event-name', payload)Advantages of EventBus: simple implementation, easy to understand, lightweight decoupling of components.
Drawbacks: business logic becomes fragmented across many subscribers, making code navigation and context tracking harder.
Improvements: Visualizing the abstract syntax tree to map publishers and subscribers, and introducing a “pre‑script” that centralizes shared state and logic before components are rendered.
Vuex integration: Vuex is presented as the preferred state‑management solution. The article shows how to add Vuex as a dependency, create a store, and inject it into the root Vue instance.
{ "dependencies": { "vuex": "^3.0.1" } } // store/index.js import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export const store = new Vuex.Store({ state() { return {} }, getters: {}, mutations: {}, actions: {} }) // App.vue import { store } from './store' new Vue({ store })Component‑level store: Each RSC component can have its own namespaced store, registered dynamically with store.registerModule in the component’s beforeCreate hook.
// store-mixn.js export default function StoreMixin(ns, store) { return { beforeCreate() { const namespace = isFn(ns) ? ns(this) : gen(ns) this.$ns = namespace store.namespaced = true this.$store.registerModule(namespace, store) this.$state = this.$store.state[namespace] this.$dispatch = (action, payload) => this.$store.dispatch(`${namespace}/${action}`, payload) } } }Namespace uniqueness: A utility generates unique namespaces to avoid collisions when the same component is instantiated multiple times.
// gen.js const g = window || global g.__namespaceCache__ = g.__namespaceCache__ || {} export default function genUniqueNamespace(name) { let cache = g.__namespaceCache__ if (cache[name]) { cache[name].count += 1 } else { cache[name] = { count: 0 } } return name + (cache[name].count === 0 ? '' : cache[name].count) }Dynamic namespace handling: By exposing the generated namespace via this.$ns , map helpers can accept a function that returns the current namespace, enabling lazy resolution.
// code.vue (using vuex-helper-ext) import { mapGetters, mapState, mapActions, mapMutations } from 'vuex-helper-ext' export default { computed: { ...mapGetters(vm => vm.$ns, ['...']), ...mapState(vm => vm.$ns, ['...']) }, methods: { ...mapActions(vm => vm.$ns, ['...']), ...mapMutations(vm => vm.$ns, ['...']) } }Parent‑child namespace propagation: A global mixin copies $ns from the parent component to its children, ensuring consistent store access throughout the component tree.
function injectNamespace(Vue) { Vue.mixin({ beforeCreate() { const parent = this.$options.parent if (parent && parent.$ns) { this.$ns = parent.$ns } } }) }Conclusion: By combining EventBus for lightweight decoupling and Vuex for predictable state management, the team achieved a scalable architecture for RSC components, while addressing namespace collisions and dynamic module registration.
vivo Internet Technology
Sharing practical vivo Internet technology insights and salon events, plus the latest industry news and hot conferences.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.