Skip to content

usePageChannel() ​

Gets the bidirectional communication channel between the current page and the navigation initiator. Must be called inside a Vue component's setup() function.

Prerequisite

Requires enabling the built-in communication manager via createRouter({ useUniEventChannel: true }). In default mode (useUniEventChannel: false), it always returns a no-op channel—calling on / emit has no effect.

Type ​

ts
function usePageChannel(): EventChannel

Return Value ​

Returns an EventChannel instance with the following methods:

MethodDescription
on(event, callback)Listen for events from the navigation initiator
once(event, callback)Listen for an event once; auto-removed after firing
off(event, callback?)Remove event listener(s)
emit(event, ...args)Send an event to the navigation initiator
  • Returns a shared UniEventChannel instance when __nav_id is present
  • Returns a noopChannel when __nav_id is absent (no-op, avoids null checks)
  • Automatically destroys the channel and cleans up all listeners on page unmount

How It Works ​

usePageChannel() reads route.params.__navId internally:

Navigation initiator push/replace/relaunch
  → Generates a unique navId (e.g., nav-1700000000000-1)
  → Creates a UniEventChannel and registers it in the channel registry
  → __nav_id is injected into URL query for persistence (survives H5 refresh)

Target page usePageChannel()
  → Reads navId from route.params.__navId
  → Gets the registered channel from the registry (reused)
  → Channel is destroyed on page unmount

Event names are isolated via the uni-router:<navId>:<event> format, communicating over the uni.$emit / uni.$on global event bus to ensure events from different navigations don't interfere.

Sticky Event Caching

The built-in channel implements a sticky event mechanism: emit always caches the event arguments; when on / once registers a listener and a cache exists, it async-triggers the listener (without deleting the cache).

This solves the timing race between the initiator's emit and the target page's setup listener registration—regardless of the order of emit and on, all listeners receive the data from the last emit.

Calling Constraints ​

Must be called inside setup

usePageChannel() depends on useRouter() (which internally uses Vue's inject), so it can only be called inside a component's setup() function (or <script setup>).

Examples ​

Basic Usage ​

vue
<script setup lang="ts">
import { usePageChannel } from '@meng-xi/uni-router'

const channel = usePageChannel()

// Listen for events from the initiator
channel.on('init', (data) => {
  console.log('Received init data:', data)
})

// Send an event to the initiator
channel.emit('ready', { status: 'loaded' })
</script>

Bidirectional Communication with push ​

ts
// Initiating page
import { useRouter } from '@meng-xi/uni-router'

const router = useRouter()

const { eventChannel } = await router.push({
  name: 'detail',
  params: { id: 123 },
  events: {
    // Listen for events from the target page
    ready(data) { console.log('Target page ready:', data) }
  }
})

// Send an event to the target page
eventChannel.emit('init', { message: 'Init data' })
vue
<!-- Target page detail.vue -->
<script setup lang="ts">
import { usePageChannel } from '@meng-xi/uni-router'

const channel = usePageChannel()

// Listen for events from the initiator
channel.on('init', (data) => {
  console.log('Received init:', data)
})

// Notify the initiator that the page is ready
channel.emit('ready', { status: 'loaded' })
</script>

replace / relaunch Also Support Communication ​

With useUniEventChannel enabled, replace / relaunch also return eventChannel:

ts
// Communicate with the target page even after replace
const { eventChannel } = await router.replace({
  name: 'detail',
  params: { id: 123 }
})

eventChannel.emit('init', { source: 'replace' })

One-time Listening ​

ts
const channel = usePageChannel()

// once fires only once—ideal for "initialize once" scenarios
channel.once('init', (data) => {
  console.log('Received once:', data)
})

once and Sticky Cache

Even if emit happens before once is registered (initiator emits first, target registers once later), once still receives the data via the cache. The cache is not deleted, so subsequent on registrations also receive it.

Differences from Native getOpenerEventChannel ​

FeatureNative getOpenerEventChannel()usePageChannel()
Applicable navigation methodsOnly push (navigateTo)All methods (push / replace / relaunch)
Timing issuesEvents lost when emit precedes onSticky cache, no loss
UsagegetCurrentPages()[last].getOpenerEventChannel()Direct call, auto-bound
Lifecycle cleanupManualAuto-destroyed on page unmount
H5 refreshChannel lost__nav_id persisted, can rebuild
PrerequisiteNoneRequires useUniEventChannel: true

Next Steps ​

Released under the MIT License.