Skip to content
本页目录

@fesjs/plugin-layout

介绍

为了进一步降低研发成本,我们将布局利用 fes.js 插件的方式内置,只需通过简单的配置即可拥有布局,包括导航以及侧边栏。从而做到用户无需关心布局。

  • 侧边栏菜单数据根据路由中的配置自动生成。
  • 布局,提供 sidetopmixinleft-righttop-left-right 五种布局。
  • 主题,提供 lightdark 两种主题。
  • 默认实现对路由的 404、403 处理。
  • 搭配 @fesjs/plugin-access 插件使用,可以完成对路由的权限控制。
  • 搭配 @fesjs/plugin-locale 插件使用,提供切换语言的能力。
  • 支持自定义头部或者侧边栏区域。
  • 菜单支持配置 icon。
  • 菜单标题支持国际化。
  • 可配置页面是否需要 layout。

启用方式

package.json 中引入依赖:

json
{
    "dependencies": {
        "@fesjs/fes": "^3.0.0",
        "@fesjs/plugin-layout": "^5.0.0"
    }
}

布局类型

配置参数是 navigation, 布局有五种类型 sidemixintopleft-righttop-left-right, 默认是 side

side

side

top

top

mixin

mixin

left-right

left-righttop-left-right

页面个性化

可以为页面单独设置布局类型:

js
import { defineRouteMeta } from '@fesjs/fes';

defineRouteMeta({
    layout: {
        navigation: null,
    },
});

当设置为 null 时,页面不使用布局。

页面缓存

支持配置页面缓存,通过定义路由元信息开启缓存:

js
import { defineRouteMeta } from '@fesjs/fes';

defineRouteMeta({
    'keep-alive': true,
});

处理嵌套路由

Fes.js 里约定目录下有 layout.vue 时会生成嵌套路由,以 layout.vue 为该目录的公共父组件,layout.vue 中必须实现 <RouterView/>。如果嵌套路由下的页面设置了 keep-alive,则需要用 <Page/> 替换 <RouterView/><Page/>实现了页面缓存。

vue
<template>
    <Page />
</template>

<script>
import { Page } from '@fesjs/fes';
export default {
    components: {
        Page,
    },
};
</script>

配置

编译时配置方式

.fes.js 中配置:

js
export default {
    layout: {
        // 标题
        title: 'Fes.js',
        // 底部文字
        footer: 'Created by MumbleFE',
        // 主题light
        theme: 'dark',
        menus: [{
            name: 'index'
        }, {
            name: 'onepiece'
        }, {
            name: 'store'
        }, {
            name: 'simpleList'
        }],
        // 403 页面配置
        403: {
            title: '没有访问权限,请联系管理人员',
        },
        // 404 页面配置
        404: {
            title: '哎呀!这个页面找不到了',
        }
    },
};

运行时配置方式

app.js 中配置:

js
import UserCenter from '@/components/UserCenter';
export const layout = {
    renderCustom: () => <UserCenter />,
    menus: [
        {
            name: 'index',
        },
    ],
};

fes.js中,运行时配置有定义对象和函数两种方式,当使用函数配置layout时,layoutConfig是编译时配置结果,initialStatebeforeRender.action执行后创建的应用初始状态数据。 。

js
export function layout(layoutConfig, { initialState }) {
    return {
        renderCustom: () => <UserCenter />,
        menus: () => {
            const menusRef = ref(layoutConfig.menus);
            watch(
                () => initialState.userName,
                () => {
                    menusRef.value = [
                        {
                            name: 'store',
                        },
                    ];
                },
            );
            return menusRef;
        },
    };
}

最终配置结果是运行时配置跟编译时配置合并的结果,运行时配置优先于编译时配置。

实际上运行配置能做的事情更多,推荐用运行时配置方式。

  • 类型String

  • 默认值null

  • 详情:页面底部的文字。

theme

  • 类型String

  • 默认值dark

  • 详情:主题,可选有 darklight

  • 类型String

  • 默认值side

  • 详情:页面布局类型,可选有 sidetopmixin

  • 类型StringFunction

  • 详情:指定 403404 时,页面的布局类型。值同 navigation。也支持函数返回。

isFixedHeader

  • 类型Boolean

  • 默认值false

  • 详情:是否固定头部,不跟随页面滚动。

isFixedSidebar

  • 类型Boolean

  • 默认值true

  • 详情:是否固定 sidebar,不跟随页面滚动。

title

  • 类型String

  • 默认值:默认为 编译时配置 title

  • 详情:产品名,当配置为"$"开头时,开启国际化,使用$后面的内容去匹配语言设置。

  • 类型String

  • 默认值:默认提供 fes.js 的 Logo

  • 详情:Logo 的链接,例如在 public/logo.png 放了一个 logo,可以这么配置(BASE_URL 来自这里)

js
export const layout = {
    logo: `${process.env.BASE_URL}logo.png`,
};

multiTabs

  • 类型boolean

  • 默认值false

  • 详情:是否开启多页。可通过 tabReload: false 控制标签页是否重新加载。

  • 类型[] | () => Ref<[]> | () => []

  • 默认值[]

  • 详情:菜单配置

    子项具体配置如下:

    • name:菜单的名称。通过匹配 name 和路由元信息 meta 中的 name,把菜单和路由关联起来, 然后使用路由元信息补充菜单配置,比如 titlepath  等。

    • path:菜单的路径,可配置第三方地址。

    • query:同 vue-router 的 query 参数。

    • params:同 vue-router 的 params 参数。

    • match (v4.0.0+):额外匹配的路径,当前路由命中匹配规则时,此菜单高亮。

      ```
      {
          path: '/product',
          match: ['/product/*', '/product/create']
      }
      ```
      
    • title:菜单的标题。

      • 如果同时使用国际化插件,而且title的值以$开头,则使用$后面的内容去匹配语言设置。

      • title 支持配置函数,对应 Fes Design 中 Menu 组件的label插槽。仅在运行时配置中支持。

    • icon: 菜单的图标,只一级标题展示图标。

      • 图标使用fes-design icon,编译时配置使用组件名称,我们会自动引入组件。

      • 图标使用本地或者远程 svg 图片。

          ```js
          {
              icon: '/wine-outline.svg';
          }
          ```
        
    • children:子菜单配置。

    • _blank:是否在新的窗口打开页面,默认 http 开头的链接在新窗口打开

TIP

函数类型仅在运行时可用,可以实现动态变更菜单。

  • 类型Object

  • 默认值{}

  • 详情:菜单的配置:

    • defaultExpandAll:是否默认展开全部菜单。

    • expandedKeys:配置默认展开的菜单,需要传子项是菜单路径的数组。

    • accordion:是否只保持一个子菜单的展开。

sideWidth

  • 类型Number

  • 默认值200

  • 详情:sidebar 的宽度

renderCustom

  • 类型()=> VNodes

  • 默认值null

  • 详情: 自定义区域内容,仅运行时。

unAccessHandler

  • 类型({ to, from, next})=> void

  • 默认值null

  • 详情:仅运行时,当进入某个路由时,如果路由对应的页面不属于可见资源列表,则会暂停进入,调用 unAccessHandler 函数。

  • 参数

    • router:createRouter 创建的路由实例
    • to: 准备进入的路由
    • from:离开的路由
    • next: next 函数

比如:

js
export const layout = {
    unAccessHandler({ to, next }) {
        const accesssIds = accessApi.getAccess();
        if (to.path === '/404') {
            accessApi.setAccess(accesssIds.concat(['/404']));
            return next('/404');
        }
        if (!accesssIds.includes('/403')) {
            accessApi.setAccess(accesssIds.concat(['/403']));
        }
        next('/403');
    },
};

noFoundHandler

  • 类型({ to, from, next})=> void

  • 默认值null

  • 详情:仅运行时,当进入某个路由时,如果路由对应的页面不存在,则会调用 noFoundHandler 函数。

  • 参数

    • router:createRouter 创建的路由实例
    • to: 准备进入的路由
    • from:离开的路由
    • next: next 函数

比如:

js
export const layout = {
    noFoundHandler({ next }) {
        const accesssIds = accessApi.getAccess();
        if (!accesssIds.includes('/404')) {
            accessApi.setAccess(accesssIds.concat(['/404']));
        }
        next('/404');
    },
};

API

useTabTitle(建议使用useLayout)

类型定义如下:

ts
function useTabTitle(title: string | Ref<string>): void;

当使用多页签模式时,在页面中使用 useTabTitle 可以自定义页面标签:

vue
<script setup>
import { useRoute, useTabTitle } from '@fesjs/fes';

const titleRef = useTabTitle(`详情-${route.params?.id}`);

// 如果要更新
titleRef.value = 'changed';
</script>

useLayout

类型定义如下:

ts
function useLayout(options: { title?: string }): { title: Ref<string>; reloadTab: () => void; closeTab: () => void };
  • title: 更新当前页签的标题
  • reloadTab:重载当前页签
  • closeTab:关闭当前页签

4.x 升级到 5.x

  1. 个性化 layout 配置改为使用传入 navigation
  2. customHeader 改为 renderCustom
  3. fixedHeader 改为 isFixedHeader
  4. menusConfig 改为 menuProps
  5. fixedSideBar 改为 isFixedSidebar
  6. 去掉运行时 logo、header、sidebar 三个区域显示配置,请改为使用 navigation: left-right

Released under the MIT License.