Appearance
路由与导航
路由配置
页面配置
在 Taro 中,页面路由需要在 app.config.js(React)或 app.json(Vue)中配置:
javascript
// app.config.js (React)
export default {
pages: [
'pages/index/index',
'pages/detail/index',
'pages/login/index'
],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'Taro 应用',
navigationBarTextStyle: 'black'
},
tabBar: {
list: [
{
pagePath: 'pages/index/index',
text: '首页',
iconPath: 'assets/images/home.png',
selectedIconPath: 'assets/images/home-active.png'
},
{
pagePath: 'pages/my/index',
text: '我的',
iconPath: 'assets/images/my.png',
selectedIconPath: 'assets/images/my-active.png'
}
]
}
}路由参数
在跳转页面时,可以通过 URL 参数传递数据:
javascript
// 传递参数
Taro.navigateTo({
url: '/pages/detail/index?id=1&name=测试'
})
// 接收参数
// 在 detail 页面的 onLoad 生命周期中
componentDidMount() {
const { id, name } = this.$router.params
console.log(id, name)
}
// 或使用 React Hooks
import { useRouter } from '@tarojs/taro'
function Detail() {
const router = useRouter()
const { id, name } = router.params
return (
<View>
<Text>ID: {id}</Text>
<Text>Name: {name}</Text>
</View>
)
}导航方法
基本导航
javascript
// 跳转到新页面,保留当前页面
Taro.navigateTo({
url: '/pages/detail/index'
})
// 重定向到新页面,关闭当前页面
Taro.redirectTo({
url: '/pages/login/index'
})
// 返回到上一页
Taro.navigateBack({
delta: 1 // 返回的页面数
})
// 跳转到 Tab 页面,关闭所有非 Tab 页面
Taro.switchTab({
url: '/pages/home/index'
})
// 关闭所有页面,跳转到新页面
Taro.reLaunch({
url: '/pages/index/index'
})导航动画
在 H5 端,可以通过配置实现导航动画:
javascript
// 跳转到新页面,带动画
Taro.navigateTo({
url: '/pages/detail/index',
animationType: 'slide-in-right', // 动画类型
animationDuration: 300 // 动画时长
})路由拦截
全局路由拦截
可以通过 Taro 的 addInterceptor 方法实现路由拦截:
javascript
// app.js
import Taro from '@tarojs/taro'
// 添加路由拦截器
Taro.addInterceptor({
// 发起请求前的处理
invoke(options) {
// 检查是否需要登录
if (options.url.includes('/pages/need-login/')) {
const token = Taro.getStorageSync('token')
if (!token) {
// 跳转到登录页面
Taro.navigateTo({
url: '/pages/login/index'
})
// 中断当前导航
return false
}
}
return options
},
// 请求成功后的处理
success(res) {
console.log('导航成功', res)
},
// 请求失败后的处理
fail(err) {
console.log('导航失败', err)
}
})页面级路由拦截
在页面的生命周期中,可以实现页面级的路由拦截:
javascript
// 在页面组件中
componentDidMount() {
// 监听页面卸载前的事件
this.$onReachBottom(() => {
console.log('页面触底')
})
// 监听页面滚动
this.$onPageScroll((res) => {
console.log('页面滚动', res.scrollTop)
})
// 监听页面尺寸变化
this.$onResize((res) => {
console.log('页面尺寸变化', res.size)
})
}
// 页面卸载前的处理
componentWillUnmount() {
// 清理定时器等
}路由状态管理
使用 Redux 管理路由状态
javascript
// store/actionTypes.js
export const SET_ROUTE = 'SET_ROUTE'
// store/actions.js
import { SET_ROUTE } from './actionTypes'
export const setRoute = (route) => ({
type: SET_ROUTE,
payload: route
})
// store/reducers.js
import { SET_ROUTE } from './actionTypes'
const initialState = {
currentRoute: ''
}
export default function reducer(state = initialState, action) {
switch (action.type) {
case SET_ROUTE:
return {
...state,
currentRoute: action.payload
}
default:
return state
}
}
// 在页面中使用
import { useDispatch, useSelector } from 'react-redux'
import { setRoute } from '../../store/actions'
function Home() {
const dispatch = useDispatch()
const currentRoute = useSelector(state => state.route.currentRoute)
useEffect(() => {
dispatch(setRoute('/pages/home/index'))
}, [])
return (
<View>
<Text>当前路由: {currentRoute}</Text>
</View>
)
}使用 MobX 管理路由状态
javascript
// store/routeStore.js
import { observable, action } from 'mobx'
class RouteStore {
@observable currentRoute = ''
@action setRoute(route) {
this.currentRoute = route
}
}
export default new RouteStore()
// 在页面中使用
import { observer } from 'mobx-react'
import routeStore from '../../store/routeStore'
const Home = observer(() => {
useEffect(() => {
routeStore.setRoute('/pages/home/index')
}, [])
return (
<View>
<Text>当前路由: {routeStore.currentRoute}</Text>
</View>
)
})
export default Home路由传递复杂数据
使用 EventChannel
对于复杂数据,可以使用 EventChannel 进行传递:
javascript
// 页面 A
Taro.navigateTo({
url: '/pages/detail/index',
success: function(res) {
// 创建事件通道
const eventChannel = res.eventChannel
// 发送数据
eventChannel.emit('acceptDataFromOpenerPage', {
data: { id: 1, name: '测试' },
message: 'Hello from Page A'
})
}
})
// 页面 B
// 在 onLoad 生命周期中
componentDidMount() {
// 获取事件通道
const eventChannel = this.$scope.getOpenerEventChannel()
// 监听事件
eventChannel.on('acceptDataFromOpenerPage', function(data) {
console.log(data)
})
}
// 或使用 React Hooks
import { useRouter } from '@tarojs/taro'
function Detail() {
const router = useRouter()
useEffect(() => {
// 获取事件通道
const eventChannel = router.getOpenerEventChannel()
// 监听事件
eventChannel.on('acceptDataFromOpenerPage', function(data) {
console.log(data)
})
}, [])
return (
<View>Detail Page</View>
)
}使用全局状态管理
对于需要在多个页面共享的数据,可以使用全局状态管理:
javascript
// store/index.js
import { createStore } from 'redux'
const initialState = {
sharedData: {}
}
function reducer(state = initialState, action) {
switch (action.type) {
case 'SET_SHARED_DATA':
return {
...state,
sharedData: action.payload
}
default:
return state
}
}
export default createStore(reducer)
// 页面 A
import store from '../../store'
function PageA() {
const handleNavigate = () => {
// 存储数据到全局状态
store.dispatch({
type: 'SET_SHARED_DATA',
payload: { id: 1, name: '测试' }
})
// 跳转到页面 B
Taro.navigateTo({ url: '/pages/pageB/index' })
}
return (
<Button onClick={handleNavigate}>跳转到页面 B</Button>
)
}
// 页面 B
import store from '../../store'
function PageB() {
const [data, setData] = useState({})
useEffect(() => {
// 从全局状态获取数据
const sharedData = store.getState().sharedData
setData(sharedData)
}, [])
return (
<View>
<Text>ID: {data.id}</Text>
<Text>Name: {data.name}</Text>
</View>
)
}路由性能优化
预加载页面
在 H5 端,可以使用预加载来提高页面加载速度:
javascript
// 预加载页面
Taro.preload({
url: '/pages/detail/index'
})懒加载页面
对于大型应用,可以使用懒加载来减少初始包大小:
javascript
// app.config.js
export default {
pages: [
'pages/index/index',
'pages/login/index'
],
subPackages: [
{
root: 'pages/detail',
pages: [
'index'
]
}
]
}路由缓存
在小程序端,可以使用页面缓存来提高页面切换速度:
javascript
// app.config.js
export default {
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'Taro 应用',
navigationBarTextStyle: 'black'
},
// 启用页面缓存
tabBar: {
list: [
{
pagePath: 'pages/index/index',
text: '首页',
iconPath: 'assets/images/home.png',
selectedIconPath: 'assets/images/home-active.png'
}
]
},
// 页面配置
pages: [
'pages/index/index'
],
// 页面缓存配置
'lazyCodeLoading': 'requiredComponents'
}路由最佳实践
- 合理规划路由:根据应用功能合理规划路由结构
- 统一路由管理:使用集中式的路由配置,便于管理
- 路由参数校验:对路由参数进行校验,确保数据合法性
- 路由拦截:实现路由拦截,处理登录、权限等逻辑
- 性能优化:使用预加载、懒加载等方式优化路由性能
- 错误处理:处理路由跳转失败的情况
- 用户体验:添加适当的导航动画,提升用户体验