fes.js/docs/reference/plugin/plugins/layout.md
2022-12-05 14:26:17 +08:00

9.0 KiB
Raw Blame History

@fesjs/plugin-layout

介绍

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

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

启用方式

package.json 中引入依赖:

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

布局类型

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

side

side

top

top

mixin

mixin

left-right

left-right

页面个性化

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

import { defineRouteMete } from '@fesjs/fes';

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

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

页面缓存

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

import { defineRouteMete } from '@fesjs/fes';

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

处理嵌套路由

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

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

配置

编译时配置方式

.fes.js 中配置:

export default {
    layout: {
        // 标题
        title: "Fes.js",
        // 底部文字
        footer: 'Created by MumbleFE',
        // 主题light
        theme: 'dark',
        menus: [{
            name: 'index'
        }, {
            name: 'onepiece'
        }, {
            name: 'store'
        }, {
            name: 'simpleList'
        }],

    },

运行时配置方式

app.js 中配置:

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

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

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

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

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

  • 类型String

  • 默认值null

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

theme

  • 类型String

  • 默认值dark

  • 详情:主题,可选有 darklight

navigation

  • 类型String

  • 默认值side

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

isFixedHeader

  • 类型Boolean

  • 默认值false

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

isFixedSidebar

  • 类型Boolean

  • 默认值true

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

title

  • 类型String

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

  • 详情Logo 的链接

multiTabs

  • 类型boolean

  • 默认值false

  • 详情:是否开启多页。

menus

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

  • 默认值[]

  • 详情:菜单配置,子项具体配置如下:

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

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

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

{
    path: '/product',
    match: ['/product/*', '/product/create']
}
  • title:菜单的标题,如果同时使用国际化插件,而且title的值以$开头,则使用$后面的内容去匹配语言设置。

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

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

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

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

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

menuProps

  • 类型Object

  • 默认值{}

  • 详情:菜单的配置:

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

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

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

sideWidth

  • 类型Number

  • 默认值200

  • 详情sidebar 的宽度

renderCustom

  • 类型 ()=> VNodes

  • 默认值null

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

unAccessHandler

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

  • 默认值null

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

  • 参数

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

比如:

export const access = {
    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 函数。

  • 参数

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

比如:

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

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