raxjs / rax-app

Rax App Framework
https://github.com/alibaba/rax
MIT License
113 stars 70 forks source link

[RFC] Rax App 支持构建 TabBar #705

Closed SoloJiang closed 3 years ago

SoloJiang commented 3 years ago

背景

业务本身有诉求配置底部 TabBar,TabBar 分为配置式和自定义两种。目前支持自定义 TabBar 的应用类型:端外 Web MPA,PHA。支持配置式 TabBar 的应用类型:小程序、Web SPA、PHA。

如上所说,目前各个应用类型支持的 TabBar 能力完善度均不够,另外 PHA 的 TabBar 目前所有页面都会显示,需要开发者手动调用 PHA 的 API 手动隐藏,所以需要进行完善 TabBar 的相关能力。

配置式 TabBar

当前,只有小程序和 Web SPA 支持配置式 TabBar,配置如下:

{
  "routes": [
    {
      "path": "/",
      "source": "pages/Home/index"
    },
    {
      "path": "/about",
      "source": "pages/About/index"
    }
  ],
  "tabBar": {
    "textColor": "#dddddd",
    "selectedColor": "#49a9ee",
    "backgroundColor": "#ffffff",
    "items": [
      {
        "path": "/",
        "name": "Home Page"
      },
      {
        "path": "/about",
        "name": "About"
      }
    ]
  }
}

通过 path 作为唯一值确定哪些页面需要渲染 TabBar。问题: MPA 没有 path,原生小程序是通过页面 source 当做 key 值,字段为 "pagePath": "pages/Home/index"

自定义 TabBar

目前 PHA 已经支持用户通过 source 去指定对应 TabBar 的实现,但是对于 PHA 降级场景和微信小程序,都存在类似的使用场景。

基于以上诉求,建议在 Rax App Framework 层面制定对应的规范来实现自定义 TabBar。

基础示例

app.json:

{
  "routes": [
    {
      "name": "home",
      "source": "pages/Home/index"
    },
    {
      "name": "profile",
      "source": "pages/Profile/index"
    }
  ],
  "tabBar": {
    "custom": true,
    "list": [
      "home",
      "profile"
    ]
  }
}

list 字段表示在哪些页面需要显示 TabBar。

约束:在开启 custom: true 时,src/CustomTabBar/index.jsx 导出的组件即为 TabBar 组件。

src/CustomTabBar/index.jsx:

export default function App() {
  return <div>这是自定义 TabBar</div>
};

方案详述

构建方案

开启 custom: true

  1. PHA :Web 构建任务会新增 src/components/CustomTabBar/index 作为入口
  2. Web :MPA export default 的场景会在 render 的时候,在对应需要展示 tabBar 的页面,自动引入 src/components/CustomTabBar/index 并在运行时根据 window.pha false 的时候渲染该组件
  3. 微信小程序:使用编译时语法,将该目录下的文件编译成原生 DSL 输出到 build/wechat-miniprogram/custom-tab-bar 目录下

方案实现节奏

P0:支持 PHA 和 Web MPA 构建

P1: Web MPA 支持内置 TabBar 方案

P2:1. Web SPA 支持自定义 TabBar;2. 微信小程序支持自定义 TabBar 方案

P3: rax-app 暴露 getTabBar API,允许开发者在页面操作 TabBar 实例,并提供显示/隐藏的能力

文档

需要引导业务自定义 TabBar 的场景应该是与其他业务逻辑独立的,以及尽可能的轻量

boiawang commented 3 years ago

customTabBar 首字母是不是要大写

SoloJiang commented 3 years ago

customTabBar 首字母是不是要大写

done

SoloJiang commented 3 years ago

小程序需要考虑业务通过原生 DSL 实现的场景

SoloJiang commented 3 years ago

https://github.com/raxjs/rax-app/issues/631

imsobear commented 3 years ago
SoloJiang commented 3 years ago

需要确定下 MPA 里拿什么当 key 值?比如 pageName/ pageKey ?

SoloJiang commented 3 years ago

结论:SPA 和 MPA 的配置可以分开来看

SPA

配置式

item.text 代表 tab item 上显示的文字,item.pageName 对应 routes 中的 path

{
  "routes": [
    {
      "path": "/",
      "source": "pages/Home/index"
    },
    {
      "path": "/about",
      "source": "pages/About/index"
    }
  ],
  "tabBar": {
    "textColor": "#dddddd",
    "selectedColor": "#49a9ee",
    "backgroundColor": "#ffffff",
    "items": [
      {
        "pageName": "/",
        "text": "Home Page"
      },
      {
        "pageName": "/about",
        "text": "About"
      }
    ]
  }
}

自定义

{
  "routes": [
    {
      "name": "home",
      "source": "pages/Home/index"
    },
    {
      "name": "profile",
      "source": "pages/Profile/index"
    }
  ],
  "tabBar": {
    "custom": true,
    "list": [
      "home",
      "profile"
    ]
  }
}

list 中的值为 route.path,表示哪些页面需要显示 TabBar

{
  "routes": [
    {
      "path": "/",
      "source": "pages/Home/index"
    },
    {
      "path": "/about",
      "source": "pages/About/index"
    }
  ],
  "tabBar": {
    "custom": true,
    "list": ["/", "/about"]
  }
}

MPA

配置式

item.pageName 代表哪个页面需要显示 TabBar,item.text 代表 tab item 上显示的值,同时支持通过 item.path 自定义需要跳转的三方链接

{
  "routes": [
    {
      "name": "index",
      "source": "pages/Home/index"
    },
    {
      "name": "about",
      "source": "pages/About/index"
    }
  ],
  "tabBar": {
    "textColor": "#dddddd",
    "selectedColor": "#49a9ee",
    "backgroundColor": "#ffffff",
    "items": [
      {
        "text": "Home Page",
        "pageName": "index"
      },
      {
        "path": "https://taobao.com",
        "text": "About Page"
      }
    ]
  }
}

自定义

list 里是需要显示 TabBar 的页面唯一值 name

{
  "routes": [
    {
      "name": "home",
      "source": "pages/Home/index"
    },
    {
      "name": "profile",
      "source": "pages/Profile/index"
    }
  ],
  "tabBar": {
    "custom": true,
    "list": [
      "home",
      "profile"
    ]
  }
}