一些小功能点

更新时间: 2023-03-25 12:47:36

# ConfigProvider全局化配置

原理是使用antd的ConfigProvider全局化配置.

# antd全局修改组件大小

设置componentSize即可控制全局组件大小,并将assemblySize作为储存全局组件大小的变量存到redux中去。 我们创建AssenbilySize组件,并将这个组件应用到Header中去。

import { Dropdown } from "antd"
import type { MenuProps } from 'antd';
import { useDispatch, useSelector } from "react-redux";
import { setAssemblySize } from "@/redux/modules/global";
import { State } from "@/types/redux";

const AssemblySize = () => {
    const dispatch = useDispatch()
    const {assemblySize} = useSelector((state:State) => state.global)

    const onClick: MenuProps['onClick'] = ({ key }) => {
        dispatch(setAssemblySize(key))
    };

    const items: MenuProps['items'] = [
        {
          key: 'middle',
          label: <span>默认</span>,
          disabled: assemblySize === "middle"
        },
        {
            key: 'large',
            label: <span>大型</span>,
            disabled: assemblySize === "large"
        },
        {
            key: 'small',
            label: <span>小型</span>,
            disabled: assemblySize === "small"
        }
      ];

    return (
        <Dropdown menu={{items, onClick }} placement="bottom" arrow={{ pointAtCenter: true }} trigger={['click']}>
            <i className="icon-style iconfont icon-contentright"></i>
        </Dropdown>
    )
}

export default AssemblySize
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

想要设置起效,还需要在App.tsx中使用ConfigProvider




 




 



 
 
 



 







import { HashRouter } from "react-router-dom"
import Router from "@/routers/index"
import AuthRouter from "./routers/utils/authRouter"
import { ConfigProvider } from 'antd';
import { useSelector } from "react-redux";
import { State } from "./types/redux";

const App = () => {
  const {assemblySize} = useSelector((state:State) => state.global)

  return (
    <HashRouter>
      <ConfigProvider
        componentSize={assemblySize}
      >
          <AuthRouter>
            <Router />
          </AuthRouter>
      </ConfigProvider>
    </HashRouter>
  )
}

export default App

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 国际化

react国际化分为两个方面

  • 一个是antd的国际化
    antd国际化需要在App.tsx引入需要的语言,除了中文和英文antd文档中还有很多,然后将引入的语言包传入ConfigProvider的locale属性中即可。

    import zhCN from 'antd/locale/zh_CN';
    import enUS from "antd/lib/locale/en_US";
    
    1
    2
  • 另一个是自己自定义的各种字符串的国际化
    在react中自定义的文字国际化,需要我们安装两个依赖

    npm install i18next react-i18next -S
    
    1

    并且得将需要翻译的文字用配置文件逐一手动翻译,以英文和中文为例。分别新建 zh.ts 和 en.ts,翻译“测试国际化文字”这几个字。

    //zh.ts
    export default {
      '测试国际化文字':'测试国际化文字'
    }
    
    1
    2
    3
    4
    //en.ts
    export default {
      '测试国际化文字':'test guo ji hua'
    }
    
    1
    2
    3
    4

    不要笑,英语水平就这么差 =w= 我会努力学的!

    有点心虚

    为了国际化之后的文字看得清晰点,我用了中文做键名,想问下大佬们这个可以吗。。。。

    然后新建 language/index.ts 初始化i18n

    // language/index.ts
    import i18n from 'i18next';
    import { initReactI18next } from 'react-i18next';
    import enUsTrans from "./modules/en"
    import zhCnTrans from "./modules/zh"
    
    i18n
      .use(initReactI18next)
      .init({
        debug: true,
        fallbackLng: 'zh',
        interpolation: {
          escapeValue: false, // not needed for react as it escapes by default
        },
        // language resources
        resources: {
            en: {
          translation: enUsTrans
        },
        zh: {
          translation: zhCnTrans
        }
        }
      });
    
    export default i18n;
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

    然后在App.tsx中使用

    import { useTranslation } from "react-i18next";
    
    const { i18n } = useTranslation();
    
    useEffect(() => {
      // 全局使用国际化
      i18n.changeLanguage(language)
      dispatch(setLanguage(language))
      setAntdLanguage()
    },[language])
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    在home.tsx中测试一下:





     



     










    import { Button,Input,TimePicker } from "antd"
    import { useTranslation } from "react-i18next";
    
    const Home = () => {
        const { t } = useTranslation();
    
        return (
            <div>
                我是主页
                <h1>{t("测试国际化文字")}</h1>
                <Button>按钮</Button>
                <Input />
                <TimePicker />
            </div>
        )
    }
    
    export default Home
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    我们去页面测试一下:

# 全屏

全屏功能需要安装screenfull

npm install screenfull -S
1

然后直接封装成组件就好了:

// layouts/components/Header/components/Fullscreen.tsx
import { useState } from "react"
import screenfull from "screenfull"
import { message } from "antd"

const Fullscreen = () => {
    const [fullScreen, setFullScreen] = useState<boolean>(screenfull.isFullscreen)

    const handleFullScreen = () => {
        if(!screenfull.isEnabled) {
            message.warning("当前您的浏览器不支持全屏")
        }
        screenfull.toggle()
        if(screenfull.isFullscreen) {
            setFullScreen(false)
        }else{
            setFullScreen(true)
        }
    }

    return (
        <>
        {fullScreen}
        <i className={["icon-style iconfont", fullScreen ? "icon-suoxiao" : "icon-fangda"].join(" ")} onClick={handleFullScreen}></i>
        </>
    )
}

export default Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 自定义皮肤

# antd皮肤

antd的皮肤官网上其实说得挺详细,我使用的是修改主题变量和使用预设算法。

// antd普通皮肤
import { theme } from "antd"

 const defaultTheme = {
     algorithm: theme.defaultAlgorithm,
 }

 export default defaultTheme
1
2
3
4
5
6
7
8
// antd暗色皮肤,并且把主题色改成了绿色
import { theme } from "antd"

const dark = {
   algorithm: theme.darkAlgorithm,
   token: {
       colorPrimary: '#5aae77',
   },
}

export default dark
1
2
3
4
5
6
7
8
9
10
11

然后创建自定义hooks useTheme(),这个hooks根据当前的皮肤返回皮肤配置,并将配置传入ConfigPovider的theme中。

// styles/theme/useTheme.ts
import { State } from '@/types/redux'
import { useSelector } from 'react-redux'
import dark from './antTheme/dark'
import defaultTheme from './antTheme/default'

/**
* @description 全局设置主题
*/
const useTheme = () => {
   const {theme} = useSelector((state:State) => state.global)

   // 设置 antd 主题
   switch(theme) {
       case 'default':
           return defaultTheme
       case 'dark':
           return dark
   }
}

export default useTheme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

 






 










// App.tsx
 const theme = useTheme()

 //...

 return (
   <HashRouter>
     <ConfigProvider
       theme={theme}
       componentSize={assemblySize}
       locale={i18nLocale} 
     >
         <AuthRouter>
           <Router />
         </AuthRouter>
     </ConfigProvider>
   </HashRouter>
 )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 其他样式

其他的非antd组件的样式怎么修改呢?我采用的是css var的方式,原理也是编写两套预设。然后在useTheme中根据theme的不同,往body中写入不同的css var。

/* default.css */
body {
   --bg-color: #fff;
   --header-color: #fff;
   --footer-color: #fff;
   --text-color: #000;
   --border-color: #e4e7ed;
   --nav-color: #001529;
}
1
2
3
4
5
6
7
8
9
/* dark.css */
body {
   --bg-color: #141414;
   --header-color: #141414;
   --footer-color: #141414;
   --text-color: #fff;
   --border-color: #363636;
   --nav-color: #2e3236;
}
1
2
3
4
5
6
7
8
9

然后在useTheme中在head中添加style





 
 









































 import { State } from '@/types/redux'
 import { useSelector } from 'react-redux'
 import dark from './antTheme/dark'
 import defaultTheme from './antTheme/default'
 import darkCss from './css/dark.css?inline'
 import defaultCss from './css/defualt.css?inline'
 /**s
  * @description 全局设置主题
  */
 const useTheme = () => {
     const {theme} = useSelector((state:State) => state.global)

      useEffect(() => {
       // 设置全局样式主题
       let head = document.getElementsByTagName("head")[0];
       const getStyle = head.getElementsByTagName("style");
       if (getStyle.length > 0) {
           for (let i = 0, l = getStyle.length; i < l; i++) {
               if (getStyle[i]?.getAttribute("data-type") === "theme"){ 
                   getStyle[i].remove();
               }
           }
       }
       let styleDom = document.createElement("style");
       styleDom.dataset.type = "theme";
       switch(theme) {
           case 'default':
               styleDom.innerHTML = defaultCss
               break;
           case 'dark':
               styleDom.innerHTML = darkCss
               break;
       }
       head.appendChild(styleDom);
   },[theme])

     // 设置 antd 主题
     switch(theme) {
         case 'default':
             return defaultTheme
         case 'dark':
             return dark
     }
 }

 export default useTheme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

这样切换不同的皮肤body中的css变量值就不一样了,编写其他样式的时候使用这些变量名去编写就能根据皮肤做切换。