一些小功能点
# 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
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
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
然后直接封装成组件就好了:
// 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
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
2
3
4
5
6
7
8
// antd暗色皮肤,并且把主题色改成了绿色
import { theme } from "antd"
const dark = {
algorithm: theme.darkAlgorithm,
token: {
colorPrimary: '#5aae77',
},
}
export default dark
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
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>
)
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;
}
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;
}
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
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变量值就不一样了,编写其他样式的时候使用这些变量名去编写就能根据皮肤做切换。