diff --git a/docs/reference/plugin/plugins/layout.md b/docs/reference/plugin/plugins/layout.md index 57d729270..57db755a6 100644 --- a/docs/reference/plugin/plugins/layout.md +++ b/docs/reference/plugin/plugins/layout.md @@ -8,16 +8,16 @@ import { withBase } from 'vitepress' 为了进一步降低研发成本,我们将布局利用 `fes.js` 插件的方式内置,只需通过简单的配置即可拥有布局,包括导航以及侧边栏。从而做到用户无需关心布局。 -- 侧边栏菜单数据根据路由中的配置自动生成。 -- 布局,提供 `side`、 `top`、`mixin`、`left-right`、`top-left-right` 五种布局。 -- 主题,提供 `light`、`dark` 两种主题。 -- 默认实现对路由的 404、403 处理。 -- 搭配 [@fesjs/plugin-access](./access.html) 插件使用,可以完成对路由的权限控制。 -- 搭配 [@fesjs/plugin-locale](./locale.html) 插件使用,提供切换语言的能力。 -- 支持自定义头部或者侧边栏区域。 -- 菜单支持配置 icon。 -- 菜单标题支持国际化。 -- 可配置页面是否需要 layout。 +- 侧边栏菜单数据根据路由中的配置自动生成。 +- 布局,提供 `side`、 `top`、`mixin`、`left-right`、`top-left-right` 五种布局。 +- 主题,提供 `light`、`dark` 两种主题。 +- 默认实现对路由的 404、403 处理。 +- 搭配 [@fesjs/plugin-access](./access.html) 插件使用,可以完成对路由的权限控制。 +- 搭配 [@fesjs/plugin-locale](./locale.html) 插件使用,提供切换语言的能力。 +- 支持自定义头部或者侧边栏区域。 +- 菜单支持配置 icon。 +- 菜单标题支持国际化。 +- 可配置页面是否需要 layout。 ## 启用方式 @@ -182,58 +182,58 @@ export function layout(layoutConfig, { initialState }) { ### footer -- **类型**:`String` -- **默认值**:`null` +- **类型**:`String` +- **默认值**:`null` -- **详情**:页面底部的文字。 +- **详情**:页面底部的文字。 ### theme -- **类型**:`String` -- **默认值**:`dark` +- **类型**:`String` +- **默认值**:`dark` -- **详情**:主题,可选有 `dark`、`light` +- **详情**:主题,可选有 `dark`、`light` ### navigation -- **类型**:`String` -- **默认值**:`side` +- **类型**:`String` +- **默认值**:`side` -- **详情**:页面布局类型,可选有 `side`、 `top`、 `mixin` +- **详情**:页面布局类型,可选有 `side`、 `top`、 `mixin` ### navigationOnError -- **类型**:`String`、`Function` +- **类型**:`String`、`Function` -- **详情**:指定 `403`、`404` 时,页面的布局类型。值同 `navigation`。也支持函数返回。 +- **详情**:指定 `403`、`404` 时,页面的布局类型。值同 `navigation`。也支持函数返回。 ### isFixedHeader -- **类型**:`Boolean` -- **默认值**:`false` +- **类型**:`Boolean` +- **默认值**:`false` -- **详情**:是否固定头部,不跟随页面滚动。 +- **详情**:是否固定头部,不跟随页面滚动。 ### isFixedSidebar -- **类型**:`Boolean` -- **默认值**:`true` +- **类型**:`Boolean` +- **默认值**:`true` -- **详情**:是否固定 sidebar,不跟随页面滚动。 +- **详情**:是否固定 sidebar,不跟随页面滚动。 ### title -- **类型**:`String` -- **默认值**:默认为 [编译时配置 title](../../../reference/config/#title) +- **类型**:`String` +- **默认值**:默认为 [编译时配置 title](../../../reference/config/#title) -- **详情**:产品名。 +- **详情**:产品名。 ### logo -- **类型**:`String` -- **默认值**:默认提供 `fes.js` 的 Logo +- **类型**:`String` +- **默认值**:默认提供 `fes.js` 的 Logo -- **详情**:Logo 的链接,例如在 public/logo.png 放了一个 logo,可以这么配置([BASE_URL 来自这里](../../../guide/env#process-env)) +- **详情**:Logo 的链接,例如在 public/logo.png 放了一个 logo,可以这么配置([BASE_URL 来自这里](../../../guide/env#process-env)) ```js export const layout = { @@ -243,29 +243,29 @@ export const layout = { ### multiTabs -- **类型**:`boolean` -- **默认值**:`false` +- **类型**:`boolean` +- **默认值**:`false` -- **详情**:是否开启多页。 +- **详情**:是否开启多页。 ### menus -- **类型**:`[] | () => Ref<[]> | () => []` -- **默认值**:`[]` +- **类型**:`[] | () => Ref<[]> | () => []` +- **默认值**:`[]` -- **详情**:菜单配置 +- **详情**:菜单配置 子项具体配置如下: - - **name**:菜单的名称。通过匹配 `name` 和路由元信息 [meta](../../../guide/route.md#扩展路由元信息) 中的 `name`,把菜单和路由关联起来, 然后使用路由元信息补充菜单配置,比如 `title`、`path`  等。 + - **name**:菜单的名称。通过匹配 `name` 和路由元信息 [meta](../../../guide/route.md#扩展路由元信息) 中的 `name`,把菜单和路由关联起来, 然后使用路由元信息补充菜单配置,比如 `title`、`path`  等。 - - **path**:菜单的路径,可配置第三方地址。 + - **path**:菜单的路径,可配置第三方地址。 - - **query**:同 vue-router 的 query 参数。 + - **query**:同 vue-router 的 query 参数。 - - **params**:同 vue-router 的 params 参数。 + - **params**:同 vue-router 的 params 参数。 - - **match (v4.0.0+)**:额外匹配的路径,当前路由命中匹配规则时,此菜单高亮。 + - **match (v4.0.0+)**:额外匹配的路径,当前路由命中匹配规则时,此菜单高亮。 ``` { @@ -274,17 +274,17 @@ export const layout = { } ``` - - **title**:菜单的标题。 + - **title**:菜单的标题。 - - 如果同时使用[国际化插件](./locale.md),而且`title`的值以`$`开头,则使用`$`后面的内容去匹配语言设置。 + - 如果同时使用[国际化插件](./locale.md),而且`title`的值以`$`开头,则使用`$`后面的内容去匹配语言设置。 - - title 支持配置函数,对应 Fes Design 中 Menu 组件的`label`插槽。仅在运行时配置中支持。 + - title 支持配置函数,对应 Fes Design 中 Menu 组件的`label`插槽。仅在运行时配置中支持。 - - **icon**: 菜单的图标,只一级标题展示图标。 + - **icon**: 菜单的图标,只一级标题展示图标。 - - 图标使用[fes-design icon](https://fes-design-4gvn317r3b6bfe17-1254145788.ap-shanghai.app.tcloudbase.com/zh/components/icon.html),编译时配置使用组件名称,我们会自动引入组件。 + - 图标使用[fes-design icon](https://fes-design-4gvn317r3b6bfe17-1254145788.ap-shanghai.app.tcloudbase.com/zh/components/icon.html),编译时配置使用组件名称,我们会自动引入组件。 - - 图标使用本地或者远程 svg 图片。 + - 图标使用本地或者远程 svg 图片。 ```js { @@ -292,7 +292,7 @@ export const layout = { } ``` - - **children**:子菜单配置。 + - **children**:子菜单配置。 :::tip 函数类型仅在运行时可用,可以实现动态变更菜单。 @@ -300,42 +300,42 @@ export const layout = { ### menuProps -- **类型**:`Object` -- **默认值**:`{}` +- **类型**:`Object` +- **默认值**:`{}` -- **详情**:菜单的配置: +- **详情**:菜单的配置: - - **defaultExpandAll**:是否默认展开全部菜单。 + - **defaultExpandAll**:是否默认展开全部菜单。 - - **expandedKeys**:配置默认展开的菜单,需要传子项是菜单路径的数组。 + - **expandedKeys**:配置默认展开的菜单,需要传子项是菜单路径的数组。 - - **accordion**:是否只保持一个子菜单的展开。 + - **accordion**:是否只保持一个子菜单的展开。 ### sideWidth -- **类型**:`Number` -- **默认值**:`200` +- **类型**:`Number` +- **默认值**:`200` -- **详情**:sidebar 的宽度 +- **详情**:sidebar 的宽度 ### renderCustom -- **类型**: `()=> VNodes` -- **默认值**:`null` +- **类型**: `()=> VNodes` +- **默认值**:`null` -- **详情**: 自定义区域内容,仅运行时。 +- **详情**: 自定义区域内容,仅运行时。 ### unAccessHandler -- **类型**:`({ to, from, next})=> void` -- **默认值**:`null` +- **类型**:`({ to, from, next})=> void` +- **默认值**:`null` -- **详情**:仅运行时,当进入某个路由时,如果路由对应的页面不属于可见资源列表,则会暂停进入,调用 `unAccessHandler` 函数。 -- **参数** - - router:createRouter 创建的路由实例 - - to: 准备进入的路由 - - from:离开的路由 - - next: [next 函数](https://next.router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%8F%AF%E9%80%89%E7%9A%84%E7%AC%AC%E4%B8%89%E4%B8%AA%E5%8F%82%E6%95%B0-next) +- **详情**:仅运行时,当进入某个路由时,如果路由对应的页面不属于可见资源列表,则会暂停进入,调用 `unAccessHandler` 函数。 +- **参数** + - router:createRouter 创建的路由实例 + - to: 准备进入的路由 + - from:离开的路由 + - next: [next 函数](https://next.router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%8F%AF%E9%80%89%E7%9A%84%E7%AC%AC%E4%B8%89%E4%B8%AA%E5%8F%82%E6%95%B0-next) 比如: @@ -357,15 +357,15 @@ export const layout = { ### noFoundHandler -- **类型**:`({ to, from, next})=> void` -- **默认值**:`null` +- **类型**:`({ to, from, next})=> void` +- **默认值**:`null` -- **详情**:仅运行时,当进入某个路由时,如果路由对应的页面不存在,则会调用 `noFoundHandler` 函数。 -- **参数** - - router:createRouter 创建的路由实例 - - to: 准备进入的路由 - - from:离开的路由 - - next: [next 函数](https://next.router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%8F%AF%E9%80%89%E7%9A%84%E7%AC%AC%E4%B8%89%E4%B8%AA%E5%8F%82%E6%95%B0-next) +- **详情**:仅运行时,当进入某个路由时,如果路由对应的页面不存在,则会调用 `noFoundHandler` 函数。 +- **参数** + - router:createRouter 创建的路由实例 + - to: 准备进入的路由 + - from:离开的路由 + - next: [next 函数](https://next.router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%8F%AF%E9%80%89%E7%9A%84%E7%AC%AC%E4%B8%89%E4%B8%AA%E5%8F%82%E6%95%B0-next) 比如: @@ -383,7 +383,7 @@ export const layout = { ## API -### useTabTitle +### useTabTitle(建议使用useLayout) 类型定义如下: @@ -404,6 +404,18 @@ titleRef.value = 'changed'; ``` +### useLayout + +类型定义如下: + +```ts +function useLayout(options: { title?: string }): { title: Ref; reloadTab: () => void; closeTab: () => void }; +``` + +- title: 更新当前页签的标题 +- reloadTab:重载当前页签 +- closeTab:关闭当前页签 + ## 4.x 升级到 5.x 1. 个性化 layout 配置改为使用传入 navigation diff --git a/packages/fes-plugin-layout/src/runtime/index.js b/packages/fes-plugin-layout/src/runtime/index.js index f57389248..9d3e9c0a8 100644 --- a/packages/fes-plugin-layout/src/runtime/index.js +++ b/packages/fes-plugin-layout/src/runtime/index.js @@ -1,3 +1,2 @@ export { default as Page } from './views/page.vue'; -export { useTabTitle } from './useTitle'; export * from './useLayout'; diff --git a/packages/fes-plugin-layout/src/runtime/useLayout.js b/packages/fes-plugin-layout/src/runtime/useLayout.js index 452cf17d1..5f81d1ef7 100644 --- a/packages/fes-plugin-layout/src/runtime/useLayout.js +++ b/packages/fes-plugin-layout/src/runtime/useLayout.js @@ -1,12 +1,31 @@ -import { createSharedComposable } from '@vueuse/core'; -import { shallowReactive } from 'vue'; +import { inject, ref } from 'vue'; -function _useLayout() { - const state = shallowReactive({ - closeTab: () => {}, - }); +import { useRoute } from '@@/core/coreExports'; - return state; +export const PLUGIN_LAYOUT_TITLE_KEY = Symbol('PLUGIN_LAYOUT_TITLE_KEY'); + +export const PLUGIN_LAYOUT_KEY = Symbol('PLUGIN_LAYOUT_KEY'); + +export function useTabTitle(title) { + const titleMap = inject(PLUGIN_LAYOUT_TITLE_KEY); + if (!titleMap) { + console.warn('[plugin-layout]: 未正确获取到titleMap'); + return; + } + const route = useRoute(); + const titleRef = ref(title); + const path = route.path; + + titleMap.set(path, titleRef); + + return titleRef; } -export const useLayout = createSharedComposable(_useLayout); +export function useLayout(options) { + const parent = inject(PLUGIN_LAYOUT_KEY, { reloadTab: () => void 0, closeTab: () => void 0 }); + const titleRef = useTabTitle(options?.title); + return { + ...parent, + title: titleRef, + }; +} diff --git a/packages/fes-plugin-layout/src/runtime/useTitle.js b/packages/fes-plugin-layout/src/runtime/useTitle.js deleted file mode 100644 index f0417953b..000000000 --- a/packages/fes-plugin-layout/src/runtime/useTitle.js +++ /dev/null @@ -1,18 +0,0 @@ -import { reactive, ref } from 'vue'; -import { useRoute } from '@@/core/coreExports'; - -const cache = reactive(new Map()); - -export const getTitle = path => cache.get(path); - -export const deleteTitle = patch => cache.delete(patch); - -export function useTabTitle(title) { - const route = useRoute(); - const titleRef = ref(title); - const path = route.path; - - cache.set(path, titleRef); - - return titleRef; -} diff --git a/packages/fes-plugin-layout/src/runtime/views/MultiTabProvider.vue b/packages/fes-plugin-layout/src/runtime/views/MultiTabProvider.vue index cd78be98a..4bbe33595 100644 --- a/packages/fes-plugin-layout/src/runtime/views/MultiTabProvider.vue +++ b/packages/fes-plugin-layout/src/runtime/views/MultiTabProvider.vue @@ -27,13 +27,12 @@