taro-rfcs
taro-rfcs copied to clipboard
实现 History API
完整提案请看: https://github.com/cncolder/taro-rfcs/blob/history-api/rfcs/0000-history-api.md
Taro 是基于微信小程序规范做的一个解决方案,路由机制也是按微信小程序规范制定的,而 @tarojs/runtime 是为了更好地实现这个规范的中间层。这句话其实包括整个 Taro Next 核心架构的关键点:规范是关键,运行时是手段,而不是目的。@tarojs/runtime 选择使用 DOM 层作为中间层也是实现这个规范的一种手段,不应该把实现 DOM/BOM 作为目的。
如果能帮助开发者提升开发效率或开发体验的手段当然是好的,但前提是不违反规范。按微信的路由规范其实是和 history 的 API 是有部分冲突的,例如 navigateTo 不会卸载上一个页面组件,而 redirectTo 又会卸载上一个页面组件。如果多了一个选项,例如可以选择 react-router 或 vue-router,开发者反而会陷入迷惑,不知道什么时候自己的页面会卸载,什么时候会隐藏。
当然实现自己的路由系统也给了开发者更多的选择和控制权,同时也会增加额外的复杂度(包括对开发者使用的复杂度和对 Taro 实现的复杂度)。更重要的是,实现自己的路由系统也会和原生的路由系统冲突。不仅仅是在小程序的原生路由系统冲突,也会和 Taro 在 H5/RN 基于小程序规范的路由系统冲突。
提案中为了实现 history api, 难度确实有些大, 当初是想实现 history 中的效果.
经过尝试, 给 Current.router 属性定义 setter, 根据 getCurrentPages() 的前后差异推断等方式, 目前实现了以下效果:
import appConfig from '@/app.config'
const history = createTaroHistory({ appConfig })
- [x] history.push
- [x] history.replace
- [x] history.goBack
- [x] history.go(/* n < 0 /*)
- [x] history.length
- [x] history.location
- [x] history.action
- [x] history.listen
其中 history.listen 在点击"返回按钮"和使用 <Navigator /> 组件时都能触发.
navigateBack 和 switchTab 在极端情况下分不清.
未实现(理论上可行):
- [ ] history.go(/* n > 0 /*)
- [ ] history.goForward()
绕过 History API, 改为直接仿照 history 模块实现类似效果. https://github.com/tarojsx/history 因为用到了 window.__taroAppConfig, 需要 taro 3.0.0-rc.1 以上版本.
如果 Current.router 在赋值时可以触发一个事件, 就可以避免对其进行 monkey patch.