页面布局
样式(css in js)-> styled-components的使用
安装依赖
npm i styled-components
在style.js里写样式
import styled from "styled-components";
export const HeaderWrapper = styled.div`
display: flex;
.left {
color: orange;
}
.center {
color: purple;
}
.right {
color: blue;
}
`;
应用到组件上
import React, { memo } from "react";
import { HeaderWrapper } from "./style";
const AppHeader = memo(() => {
return (
<HeaderWrapper>
<div className="left">left</div>
<div className="center">center</div>
<div className="right">right</div>
</HeaderWrapper>
);
});
export default AppHeader;
效果:
头部比较复杂,继续拆分:
import styled from "styled-components";
export const LeftWrapper = styled.div``;
import React, { memo } from "react";
import { LeftWrapper } from "./style";
const HeaderLeft = memo(() => {
return <LeftWrapper>HeaderLeft</LeftWrapper>;
});
export default HeaderLeft;
上面是子组件
import React, { memo } from "react";
import { HeaderWrapper } from "./style";
import HeaderLeft from "./c-cpns/header-left";
import HeaderCenter from "./c-cpns/header-center";
import HeaderRight from "./c-cpns/header-right";
const AppHeader = memo(() => {
return (
<HeaderWrapper>
<HeaderLeft />
<HeaderCenter />
<HeaderRight />
</HeaderWrapper>
);
});
export default AppHeader;
import styled from "styled-components";
export const HeaderWrapper = styled.div`
display: flex;
align-items: center;
height: 80px;
border-bottom: 1px solid #eee;
`;
- sc-类似Vue中的scoped
头部布局
左右flex:1;
export const LeftWrapper = styled.div`
flex: 1;
`;
右边:
import styled from "styled-components";
export const RightWrapper = styled.div`
flex: 1;
display: flex;
justify-content: flex-end;
`;
可以保证中间部分,居中
左边logo
import React, { memo } from "react";
import { LeftWrapper } from "./style";
import logo from "@/assets/img/logo.png";
const HeaderLeft = memo(() => {
return (
<LeftWrapper>
<img className="logo" alt="logo" src={logo} />
</LeftWrapper>
);
});
export default HeaderLeft;
注意:这样子引入图片没有效果
<img className="logo" alt="" src="../../../../assets/img/logo.png" />
- Webpack默认会将图片以base64的形式内联到打包后的文件中
- svg图片处理 将svg封装成一个jsx组件
style -> obj
function styleStrToObject(styleStr) {
const obj = {};
const s = styleStr
.toLowerCase()
.replace(/-(.)/g, function (m, g) {
return g.toUpperCase();
})
.replace(/;\s?$/g, "")
.split(/:|;/g);
for (var i = 0; i < s.length; i += 2) {
obj[s[i].replace(/\s/g, "")] = s[i + 1].replace(/^\s+|\s+$/g, "");
}
return obj;
}
export default styleStrToObject;
import React, { memo } from "react";
import styleStrToObject from "./utils";
const IconLogo = memo(() => {
return (
<svg width="102" height="32" style={styleStrToObject("display:block")}>
<path></path>
</svg>
);
});
export default IconLogo;
logo颜色和主题文件配置
方案1:css变量
方案2:ThemeProvider
import { ThemeProvider } from "styled-components";
const theme = {
color: {
primary: "#ff385c",
second: "#00848A",
},
};
export default theme;
import React, { Suspense } from "react";
import ReactDOM from "react-dom/client";
import { HashRouter } from "react-router-dom";
import { Provider } from "react-redux";
import { ThemeProvider } from "styled-components";
import App from "@/App";
import "normalize.css";
import "./assets/css/index.less";
import store from "./store";
import theme from "./assets/theme";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
// <React.StrictMode>
<Suspense fallback="loading">
<Provider store={store}>
<ThemeProvider theme={theme}>
<HashRouter>
<App />
</HashRouter>
</ThemeProvider>
</Provider>
</Suspense>
// </React.StrictMode>
);
在样式组件RightWrapper (style.js
)文件中使用:
color: ${(props) => props.theme.color.second};
import styled from "styled-components";
export const RightWrapper = styled.div`
flex: 1;
display: flex;
justify-content: flex-end;
padding-right: 40px;
/* color: var(--primary-color); */
color: ${(props) => props.theme.color.second};
`;
头部右侧
import React, { memo } from "react";
import { RightWrapper } from "./style";
import IconGlobal from "@/assets/svg/icon-global";
import IconMenu from "@/assets/svg/icon-menu";
import IconAvatar from "@/assets/img/avatar.png";
const HeaderRight = memo(() => {
return (
<RightWrapper>
<div className="btns">
<span>登录</span>
<span>注册</span>
<span>
<IconGlobal />
</span>
</div>
<div className="profile">
<span>
<IconMenu />
</span>
<span>
<img src={IconAvatar} alt="头像" />
</span>
</div>
</RightWrapper>
);
});
export default HeaderRight;
import styled from "styled-components";
export const RightWrapper = styled.div`
flex: 1;
display: flex;
justify-content: flex-end;
padding-right: 40px;
align-items: center;
font-size: 14px;
font-weight: 600;
color: ${(props) => props.theme.text.primary};
.btns {
display: flex;
align-items: center;
span {
cursor: pointer;
padding: 12px 15px;
border-radius: 22px;
height: 18px;
line-height: 18px;
&:hover {
background-color: #f5f5f5;
}
}
}
.profile {
display: flex;
align-items: center;
margin-left: 5px;
border-radius: 22px;
border: 1px solid #ccc;
transition: box-shadow 0.2s ease;
width: 80px;
height: 42px;
box-sizing: border-box;
padding: 0px 10px 0 15px;
img {
width: 28px;
height: 28px;
border-radius: 50%;
margin-left: 10px;
}
transition: box-shadow 0.2s ease;
&:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.18);
}
}
.profile > span {
cursor: pointer;
}
`;
效果:
css in js 样式混入
将
transition: box-shadow 0.2s ease;
&:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.18);
}
抽取出去。
const theme = {
color: {
primary: "#ff385c",
second: "#00848A",
},
text: {
primary: "#484848",
second: "#222",
},
mixin: {
boxShadow: `
transition: box-shadow 0.2s ease;
&:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.18);
}
`,
},
};
export default theme;
样式组件中使用:
头部中间部分
请看下篇文章~~~