[Question]如何自定义 Kraken 中的切换导航页的目标地址?
hughlv opened this issue · 6 comments
Please describe the problem you meet.
在 Kraken 中切换导航页的行为和 Web 版一致,会试图跳转到某个特定 html 页面,如 /home.html
,但是在 Kraken 中并不存在这样的页面,而是一个个的 kbc1 包,因此跳转会失败。
解决方法有两个:
- 在 Rax 端找机会重写跳转目标。对于显式的跳转按钮实现,我们可以封装一个自有的
navigateTo
函数,判断是 isKraken 就将传入的path
转换为 https://xxx/kraken/.kbc1 这样的目标(实践证明可行)。但是导航栏的点击跳转不知道怎么重载; - 在 Kraken 端劫持 navigation 操作,将收到的类似
/home.html
的跳转请求重写为如上的 kbc1 目标。但是 Kraken/WebF 不支持重载 navigation 操作(包含handleNavigationAction
方法的KrakenViewController
是一个内部类无法触达),可传入的 KrakenNavigationDelegate 只能选择是否停止跳转(disallow),而无法改变跳转目标;
上面两条路看起来都不通。不知道是否还有没有其他解决方法?
建议是采用方案 1 的方式在前端侧通过一个 uni 的包来处理跳转逻辑,因为入口不一样(一个是 js 一个是 html)。导航栏说的是 flutter 逻辑嘛?
第二点可以请 @andycall 看一下,openWebF 是不是可以提供用户自定义导航行为的抽象能力。
建议是采用方案 1 的方式在前端侧通过一个 uni 的包来处理跳转逻辑,因为入口不一样(一个是 js 一个是 html)。导航栏说的是 flutter 逻辑嘛? 第二点可以请 @andycall 看一下,openWebF 是不是可以提供用户自定义导航行为的抽象能力。
谢谢回复。你说的是否是 @uni/navigate
包?已经用上了,对应的代码如下:
import { isKraken, isMiniApp, isWeb, isWeChatMiniProgram } from 'universal-env';
import navigate from '@uni/navigate';
import config from '../app.json';
// 是否为小程序环境
const inMiniApp = isMiniApp || isWeChatMiniProgram;
const getRouteSource = (path: string) => {
const route = config.routes.find(item => item.path == path);
if (route) {
console.log("Found route:", route);
return route.source;
} else {
console.log("Route not found:", path);
return null;
}
}
const isTab = (path: string): boolean => {
const tab = config.tabBar.items.find(item => item.pageName == path);
return tab != null;
}
const navigateTo = (path: string) => {
let url = path;
const source = getRouteSource(url);
if (isKraken) {
navigate.push({url: 'http://127.0.0.1:3333/kraken/' + path + '.kbc1'});
} else if (isWeb) { // Web 端不支持路由导航,只能自行构建 URL
url = '/' + url + '.html';
navigate.push({url: url});
} else if (inMiniApp) { // 小程序内需要使用 route 里的 source 进行导航
if (isTab(path)) {
navigate.switchTab({url: '/' + source});
} else {
navigate.push({url: '/' + source});
}
}
}
理想情况应该是我只管调用 navigate.push({url: 'home'})
,其中的 home
就是在 app.json 中配置的 routes/path
。现在的问题是几乎没有一个场景是可以使用这个 path
作为目标的:
- 微信小程序-正常跳转:
navigate.push('/pages/Home/index')
- 微信小程序-tabBar:
navigate.switchTab('/pages/Home/index')
- Web:
navigate.push('/home.html')
- Kraken/WebF:
navigate.push('http://127.0.0.1:3333/kraken/home.kbc1')
WebF 里面可以通过为 MaterialApp
传入 routes
参数来构建和 Rax 端一致的路由表,但是 WebF 端收到的 /home.html
会被认为是不合格的 URL,期望的是一个完整的 http/https 开头的资源 URL,并没有试图映射到本地的路由表。
修改 History API 的方案我感觉并不好。更加符合标准的做法是给 kbc 文件添加一个 script 标签的类型,然后通过 script 标签来加载。
比如:
<script type="application/vnd.webf.bc1" src="./demo.kbc1"></script>
这样的 script 标签,浏览器并不会识别,也没有任何效果。然后 Kraken/WebF 可以进行识别(我看了下,KBC 文件的判断还没加上 ),然后加载。
所以不要去尝试修改跳转的代码,这样只会让逻辑更加复杂,而且无法维护。
修改 History API 的方案我感觉并不好。更加符合标准的做法是给 kbc 文件添加一个 script 标签的类型,然后通过 script 标签来加载。 比如:
<script type="application/vnd.webf.bc1" src="./demo.kbc1"></script>
这样的 script 标签,浏览器并不会识别,也没有任何效果。然后 Kraken/WebF 可以进行识别(我看了下,KBC 文件的判断还没加上 ),然后加载。
所以不要去尝试修改跳转的代码,这样只会让逻辑更加复杂,而且无法维护。
这样的方案是比较好的,期待能够早日上线。当前项目就因为这个问题被 block 住了。
我觉得 Kraken/WebF 端只需要接收到原始参数,而且能够只用一套路由标准(要么 /home
要么 /pages/Home/index
,不需要区分 tabBar 的切换和正常的跳转),这样才符合 Uni-API 的要义。
这个你可以再去 openWebF 提一个 issue,方便后续跟踪以及讨论需求跟设计 @hughlv ,可以跟这个 issue 关联在一块。