alibaba/rax

[Question]如何自定义 Kraken 中的切换导航页的目标地址?

hughlv opened this issue · 6 comments

Please describe the problem you meet.

在 Kraken 中切换导航页的行为和 Web 版一致,会试图跳转到某个特定 html 页面,如 /home.html,但是在 Kraken 中并不存在这样的页面,而是一个个的 kbc1 包,因此跳转会失败。

解决方法有两个:

  1. 在 Rax 端找机会重写跳转目标。对于显式的跳转按钮实现,我们可以封装一个自有的 navigateTo 函数,判断是 isKraken 就将传入的 path 转换为 https://xxx/kraken/.kbc1 这样的目标(实践证明可行)。但是导航栏的点击跳转不知道怎么重载;
  2. 在 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 关联在一块。

这个你可以再去 openWebF 提一个 issue,方便后续跟踪以及讨论需求跟设计 @hughlv ,可以跟这个 issue 关联在一块。

已提交。