Taro 小程序页面返回传参完整示例

前言

  • 我们在开发的时候,有时候会遇到,A页面跳转到B页面,B页面改一些数据(例如:收藏状态),回到A页面的时候不想刷新A页面,并看到最新的数据状态;
  • 对于以上场景,有以下几种解决方案;

方法一:EventChannel(推荐)

PageA.jsx - 跳转页面

javascript 复制代码
import React, { useState } from 'react'
import { View, Button, Text } from '@tarojs/components'
import Taro from '@tarojs/taro'

const PageA = () => {
  const [receivedData, setReceivedData] = useState(null)

  const goToPageB = () => {
    Taro.navigateTo({
      url: '/pages/pageB/index',
      events: {
        // 监听返回数据
        // ⚠️ 这里监听的事件名 必须和 子页面绑定的事件名称相同
        onReturnData: (data) => {
          console.log('接收到返回数据:', data)
          setReceivedData(data)
        },
        // 可以监听多个事件
        onSelectItem: (item) => {
          console.log('选中的项目:', item)
        }
      }
    })
  }

  return (
    <View className="page-a">
      <Button onClick={goToPageB}>跳转到页面B</Button>
      
      {receivedData && (
        <View className="received-data">
          <Text>接收到的数据:</Text>
          <Text>{JSON.stringify(receivedData)}</Text>
        </View>
      )}
    </View>
  )
}

export default PageA

PageB.jsx - 返回页面

  • 这是
javascript 复制代码
import React, { useState, useEffect } from 'react'
import { View, Button, Input } from '@tarojs/components'
import Taro from '@tarojs/taro'

const PageB = () => {
  // 可以使用 useState 或 useRef 存储 EventChannel
  const [eventChannel, setEventChannel] = useState(null)
  const [inputValue, setInputValue] = useState('')
  const [count, setCount] = useState(0)

  useEffect(() => {
    // 获取 EventChannel
    const channel = Taro.getCurrentInstance().page?.getOpenerEventChannel?.()
    if (channel) {
      setEventChannel(channel)
    }
  }, [])

  const handleReturn = () => {
    if (eventChannel) {
      // 发送数据给上个页面
      eventChannel.emit('onReturnData', {
        inputValue,
        timestamp: Date.now(),
        source: 'pageB'
      })
    }
    
    // 返回上个页面
    Taro.navigateBack()
  }

  const handleSelectItem = (item) => {
    if (eventChannel) {
      eventChannel.emit('onSelectItem', item)
    }
  }
  
  // ---- 页面销毁传递参数 Start ----
  // 若是使用小程序的导航栏的返回按钮,可以在页面销毁的时候,向父页面传递参数
  // 需要注意的是,useUnload 的参数若是依赖于一些数据,需要使用 useCallback 对函数进行缓存
  const handleBack = useCallback(() => {
    if (eventChannel) {
      eventChannel?.emit('onReturnPageA', { name: 'PageA', count })
      console.log('数据发送成功')
    }
  }, [eventChannel, count])

  useUnload(handleBack)
  // ---- 页面销毁传递参数 End ----

  return (
    <View className="page-b">
      <Input
        value={inputValue}
        onInput={(e) => setInputValue(e.detail.value)}
        placeholder="输入要传递的数据"
      />
      
      <Button onClick={handleReturn}>返回并传递数据</Button>
      
      <Button onClick={() => handleSelectItem({ id: 1, name: '选项1' })}>
        选择选项1
      </Button>
      
      <Button onClick={() => setCount(v => v++)}>
        改变count
      </Button>
      
      <Button onClick={() => handleSelectItem({ id: 2, name: '选项2' })}>
        选择选项2
      </Button>
    </View>
  )
}

export default PageB

方法二:使用 Zustand 状态管理

store/index.js

javascript 复制代码
import { create } from 'zustand'

const useAppStore = create((set, get) => ({
  // 页面返回数据
  pageReturnData: null,
  
  // 设置返回数据
  setPageReturnData: (data) => set({ pageReturnData: data }),
  
  // 清除返回数据
  clearPageReturnData: () => set({ pageReturnData: null }),
  
  // 获取并清除返回数据
  getAndClearReturnData: () => {
    const data = get().pageReturnData
    set({ pageReturnData: null })
    return data
  }
}))

export default useAppStore

PageA.jsx - 使用状态管理

javascript 复制代码
import React, { useEffect } from 'react'
import { View, Button, Text } from '@tarojs/components'
import Taro, { useDidShow } from '@tarojs/taro'
import useAppStore from '../store'

const PageA = () => {
  const { pageReturnData, clearPageReturnData } = useAppStore()

  // 页面显示时检查返回数据
  useDidShow(() => {
    if (pageReturnData) {
      console.log('接收到返回数据:', pageReturnData)
      // 处理数据后清除
      handleReturnData(pageReturnData)
      clearPageReturnData()
    }
  })

  const handleReturnData = (data) => {
    // 处理返回的数据
    Taro.showToast({
      title: `接收到: ${data.message}`,
      icon: 'success'
    })
  }

  const goToPageB = () => {
    Taro.navigateTo({
      url: '/pages/pageB/index'
    })
  }

  return (
    <View className="page-a">
      <Button onClick={goToPageB}>跳转到页面B</Button>
    </View>
  )
}

export default PageA

PageB.jsx - 设置状态并返回

javascript 复制代码
import React, { useState } from 'react'
import { View, Button, Input } from '@tarojs/components'
import Taro from '@tarojs/taro'
import useAppStore from '../store'

const PageB = () => {
  const [message, setMessage] = useState('')
  const setPageReturnData = useAppStore(state => state.setPageReturnData)

  const handleReturn = () => {
    // 设置要传递的数据
    setPageReturnData({
      message,
      timestamp: Date.now(),
      type: 'user_input'
    })
    
    // 返回上个页面
    Taro.navigateBack()
  }

  return (
    <View className="page-b">
      <Input
        value={message}
        onInput={(e) => setMessage(e.detail.value)}
        placeholder="输入消息"
      />
      
      <Button onClick={handleReturn}>返回并传递消息</Button>
    </View>
  )
}

export default PageB

方法三:自定义 Hook 封装

hooks/usePageReturn.js

javascript 复制代码
import { useState, useEffect } from 'react'
import Taro, { useDidShow } from '@tarojs/taro'

// 全局存储返回数据
let globalReturnData = new Map()

export const usePageReturn = (pageKey) => {
  const [returnData, setReturnData] = useState(null)

  useDidShow(() => {
    const data = globalReturnData.get(pageKey)
    if (data) {
      setReturnData(data)
      globalReturnData.delete(pageKey)
    }
  })

  const setReturnDataForPage = (targetPageKey, data) => {
    globalReturnData.set(targetPageKey, data)
  }

  const clearReturnData = () => {
    setReturnData(null)
  }

  return {
    returnData,
    setReturnDataForPage,
    clearReturnData
  }
}

// 导航并设置返回监听
export const navigateToWithReturn = (url, pageKey, onReturn) => {
  return Taro.navigateTo({
    url,
    events: {
      returnData: (data) => {
        if (onReturn) {
          onReturn(data)
        }
      }
    }
  })
}

使用自定义 Hook

javascript 复制代码
// PageA.jsx
import React from 'react'
import { View, Button } from '@tarojs/components'
import Taro from '@tarojs/taro'
import { usePageReturn } from '../hooks/usePageReturn'

const PageA = () => {
  const { returnData, clearReturnData } = usePageReturn('pageA')

  useEffect(() => {
    if (returnData) {
      console.log('接收到返回数据:', returnData)
      // 处理数据
      clearReturnData()
    }
  }, [returnData])

  const goToPageB = () => {
    Taro.navigateTo({
      url: '/pages/pageB/index?fromPage=pageA'
    })
  }

  return (
    <View>
      <Button onClick={goToPageB}>跳转到页面B</Button>
    </View>
  )
}

export default PageA

最佳实践建议

  1. 简单场景:使用 EventChannel(方法一)
  2. 复杂应用:使用状态管理(方法二)
  3. 多页面复用:封装自定义 Hook(方法三)
  4. 数据量大:避免使用 URL 参数,选择状态管理
  5. 临时数据:使用 EventChannel,自动清理
  6. 持久数据:结合本地存储使用

注意事项

  • EventChannel 只在 navigateTo 时可用,redirectTo 不支持
  • 状态管理要注意及时清理数据,避免内存泄漏
  • 复杂对象传递时注意序列化问题
  • 考虑页面栈的层级关系,避免数据传递错乱
相关推荐
还是大剑师兰特4 小时前
React面试题及详细答案150道(51-60)
react.js·react面试题·大剑师
10share5 小时前
React组件间通信
react.js
vx_dmxq2116 小时前
【微信小程序学习交流平台】(免费领源码+演示录像)|可做计算机毕设Java、Python、PHP、小程序APP、C#、爬虫大数据、单片机、文案
java·spring boot·python·mysql·微信小程序·小程序·idea
是一碗螺丝粉6 小时前
React Native 运行时深度解析
前端·react native·react.js
骑自行车的码农6 小时前
🍂 React DOM树的构建原理和算法
javascript·算法·react.js
腾马科技7 小时前
小酒馆白酒饮料订单配送立即点餐存酒小程序源码
微信小程序·点餐小程序
vx_dmxq21119 小时前
【PHP考研互助系统】(免费领源码+演示录像)|可做计算机毕设Java、Python、PHP、小程序APP、C#、爬虫大数据、单片机、文案
java·spring boot·mysql·考研·微信小程序·小程序·php
我命由我123451 天前
微信开发者工具 - 模拟器分离窗口与关闭分离窗口
前端·javascript·学习·微信小程序·前端框架·html·js
G佳伟1 天前
‌微信小程序Webview转发页面空白问题解决方案‌
微信小程序·小程序