umi4.0 项目构建问题总结

布局框架

umi4.0 版本中更新了布局方式,单独创建了 layout/index.tsx 文件为默认布局页面

页面使用 Outlet 组件作为子页面的表示子页面的视口,类似与 router-view

示例

import React from 'react';
import { Outlet } from 'umi'

const Page:React.FC<any> = ()=>{
    return (
        <div>
            <header>顶部</header>
            <main> <Outlet/> </main>
        </div>
    )
}

使用 dva

Umi Max 集成了 dva 工具,安装 umi 集成工具

pnpm install @umijs/plugins --save-dev

创建 models / index.ts 思路和 paina 类似,每一个文件需要给与单独的命名空间

export default {
  namespace: 'menuModel',
  state: {
    menuIndex:localStorage.getItem('menuIndex') || '1', /*状态值*/
  },
  reducers: {
    menuIndexConfig(state:any, params:any ) { /*改变 state 属性的值*/
      return { ...state,menuIndex:params.menuIndex};
    },
  },
};

在组件使用,函数式中采用高阶函数调用

import {connect} from "umi"
/*此时的 menuModel 为 dva 文件的命名空间名称*/
const MenuComponent:React.FC<any> = ({dispatch, menuModel}) => {
    const handleClick = ()=>{
        dispatch({type:"menuModel/menuIndexConfig",payload:{menuIndex:2}})
    }
    return (
        <div>
            <span>{menuModel.menuIndex}</span>
            <button onClick="{()=>handleClick()}">测试</button>
        </div>
    )    
})

export default connect(({menuModel})=>({
  menuModel
}))(MenuComponent)

路由创建

umi4.0 路由搭建 类似于 vue-router 路由模式, 丢弃了早期 react 的标签式路由, 采用对象式,

示例 umirc.ts 中配置路由

export default defineConfig({
    routes: [
        { path: "/", component: "login"},
        { 
          path: "/layout", 
          component: "@/layout/index", /*布局页面路由声明*/
          routes: [
            {path:"/layout/",component:"user"},/*/layout/ 表示默认显示的子路由*/
            {path:"/layout/node",component:"nodeList"},
          ]
        },
      ]
})

使用 ant-design

安装

pnpm i @umijs/plugins -D
pnpm i antd axios @ant-design/pro-layout -S

调用

import React from "react";
import { Input,Button,Checkbox,message } from 'antd';

const Home:React.FC<any> = ()=>{
   return (
       <div>
               <Button>andButton</Button>
       </div>
   )
}

部署 history 模式

问题一: umi4 打包后页面空白,并且部分静态资源404

.umirc.ts 中配置

export default defineConfig({
    base:"/myUmiProject", /*基础地址,适用于部署在非根目录,要和服务端目录名称保持一致*/
    publicPath::process.env.NODE_ENV === 'production' ? './' : '/', /*用于解决部分静态资源404问题*/
})

nginx.conf 中配置

http {
    ...
    server {
        ...
        location /myUmiProject/ {
            try_files $uri $uri/ /index.html;
        }
        ...
    }

}

配置完成重载 nginx ,运行 nginx -s reolad ; 此时打包后的项目路径应该放在 nginx/html/myUmiProject 目录中

问题二:umi4 报错找不到 favicon 图标

在 umi4 中项目并没有 favicon 图标资源,需要单独在 .umirc.ts 配置

export default defineConfig({
    ...
    favicons:[ /*可引用在线图标作为标签页的icon*/
        "https://img.alicdn.com/tfs/TB1YHEpwUT1gK0jSZFhXXaAtVXa-28-27.svg" /*该图标地址为 umi 官方图标
        */
    ],
})

umi4 路由传参

动态路由传参

.umirc.ts 配置路由传参

export default defineConfig({
    routes:[
        { path: "/:id", component: "login"},
    ]
})

在组件中获取参数

import React from "react";
import {useParams} from "umi"

const Home:React.FC<any> = ()=>{
    const params  = useParams();
    /**
    * {
    *   "id": ""
    * }
    */
    return ( <div>hello world</div> )
}

动态路由必须要携带参数

查询字符串传参

路由传参示例

import React from "react"
import {history} from "umi"
const pageA:React.FC<any> = ()=>{
    const handleClick = ()=>{
        history.push("/pageB?index=100")
    }
    return (<div onCLick={()=>handleClick()}>to PageB</div>)
}

接收查询字符串传参

import React,{useEffect} from "react"
import {useSearchParams} from "umi"

const PageB:React.FC<any> = ()=>{
    const [searchParams, setSearchParams] = useSearchParams();

    useEffect(()=>{
        searchParams.get('index')  /*100*/
        setSearchParams({xxx:hello}) /*此时的地址变成了 /pageB?xxx=hello  */
    },[])
    return (<div>this is Page</div>)
}

路由鉴权

路由鉴权 wrappers,在 umirc.ts 中配置指定的路由进行鉴权

export default defineConfig({
    ...
    routes:[
        { path: "/", component: "home", wrappers: [
            '@/wrappers/auth',
        ]},
    ]
})

src / wrappers / auth.tsx 中可以书写鉴权逻辑

/**登录鉴权 */
import { Navigate } from 'umi';

export const checkAuth = ()=>{
  const userInfo = localStorage.getItem("userInfo");
  if (userInfo) {
    return redirectToHome();
  } else {
    return redirectToLogin();
  }
}

export const redirectToLogin = ()=>{
  return <Navigate to="/login" />;
}

export const redirectToHome = ()=>{
  return <Navigate to="/home/userInfo" />;
}

上面代码中判断当进入到 /home 页面检查用户是否时登录状态,登录状态存在进入 /home/userInfo 否则进入 /login 页面, 这种路由鉴权的方式如果时在 /logoin 页面就判断用户登录状态实现免登录功能时,由于路由鉴权在路由进入后会一直校验跳转到本页面,就i会出现死循环的情况,下面推荐使用函数式API做路由登录鉴权

登录鉴权

修改 `src / wrappers / auth.tsx ` 如下

export const checkAuth = ()=>{
  const userInfo = localStorage.getItem("userInfo");
  if (userInfo) {
    return true;
  } else {
    return false;
  }
}

在要校验的函数组件中,通过 hook 的 useEffect 在组件初始化的时候校验登录状态,已 login 页面为例

import React,{useEffect} from "react"
import { checkAuth } from "@/wrappers/auth";
import {history} from "umi"
const Login:React.FC<any> = ()=>{
    useEffect(()=>{
        if(!checkAuth()){
            /*表示登录状态已存在,直接跳转到home页面*/    
            history.replace("/home")
        }
    },[])
    return ( <div>this is loginPage</div> )
}

页面鉴权

页面同样采用登录鉴权的逻辑,不同的是页面鉴权需要高阶函数的方式去调用

示例,判断用户是否有权限访问该模块,实现鉴权逻辑 src/wrappers/pageAuth.tsx

/**页面权限鉴权 */
import AuthComponent from "@/pages/auth";

export const PageAuth = (Component:React.FC)=>()=>{
  const userInfo = JSON.parse(localStorage.getItem("userInfo") || "");
  if ((userInfo as any).role !== "admin") {
    return <AuthComponent />
  }else{
    return <Component />;
  }
}

在上面代码中,如果用户不是管理员则使用鉴权组件提示用户无权访问,鉴权组件可以是一个普通的函数页面这里不在实现。

使用方法

import React from "react"
import { PageAuth } from "@/wrappers/pageAuth";
const Home:React.FC<any> = ()=>{
    return ( <div>this is home</div> )
}
export default PageAuth(Home)

实现效果当用户角色是 admin 的时候进入 Home 组件,否则进入 AuthComponent 组件

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇