布局
1. 响应式布局
调整布局的关键在于media,rem,vw&vh,fr
/* 屏幕宽度[768,1200]样式 */
@media (min-width: 768px) and (max-width: 1200px){
/* css class/id */
}
/* rem,vw,fr */
@media screen and (max-width: 576px) {
/* ===rem和vw 联动=== */
/* before */
.nav-links a {
margin-right: 0.5rem;
padding: 0.25rem 0.2rem;
font-size: 1.2rem;
}
/* after */
.nav-links a {
margin-right: 0.5vw;
padding: 0.25vw 0.5vw;
font-size: 2vw;
}
/* ===flex->grid=== */
/* before */
.nav-links {
display: flex;
align-items: center;
flex-direction: row;
justify-content: space-between;
}
/* after */
.nav-links {
display: grid;
grid-template-columns:repeat(2, 1fr);
}
}
2. flex
flex能很方便地排列组件。主要使用的属性:
display: flex /* 指定使用flex布局 */
flex-direction: row /* 可选还有column, row-reverse, column-reverse*/
justify-content: flex-end, flex-start, space-around, space-between, center
align-content: flex-end, flex-start, space-around, space-between, center
align-item: flex-start, flex-end, center
- 先看组件排列主轴flex-direction,row对应x轴,column对应y轴;然后记住justify-content作用主轴,
align-content作用另外一轴;然后它们对应的排列如后图所示(stretch还没用过就没提)。
- 这里align-item常又被叫作单行布局,align-content则是多行布局。关键在于align-item和align-content作
用的对象不同,前者作用于行,后者作用于组件整体。
图形描述:
e.g. 1 组件置底
.footer {
display: flex;
flex: 1;
justify-content: flex-end;
align-items: center;
flex-direction: column;
}
.footer div {
font-size: 1rem;
width: 100%;
text-align: center;
background-color: gainsboro;
}
/* root占了100%高,按三等份header, body, footer已按column排列 */
<div id="root">
<div>header</div>
<div>body</div>
<div className="footer">
<div>footer1<div>
<div>footer2<div>
</div>
<div>
3. html伸缩时rem弹性布局
rem
和font-size
关系:rem = document.documentElement.style.fontSize
在做web和移动端(手机)适配时,margin
、padding
、font-size
等都以rem为
单位;现在希望在网页缩放时,rem
能动态调整,也就是动态调整html
的font-size
,在<html>
中插入如下代码即可
<head>
<!-- other code -->
<script>
var c = () => {
let w = document.documentElement.clientWidth;
let n = (10 * (w / 320) > 16 ? 16 + "px" : 10 * (w / 320) + "px");
document.documentElement.style.fontSize = n;
}
window.addEventListener("load", c);
window.addEventListener("resize", c);
</script>
<!-- other code -->
</head>
<ol>
标签数字对齐左对齐:
默认对齐为:
1
10
20
希望的对齐方式为:
1
10
20
实现:<ol style='list-style-poisition: inside;'>...li标签</ol>
- 自己实现一个checkbox,见0积分下载
- 导航栏固定
.navbar {
position: sticky; /* 固定导航栏 */
z-index: 10; /* z-index 需要是最大的,使得下滑时能盖住其他同级元素 */
}
- grid布局
.cocktails-center {
width: var(--smallWidth);
margin: 0 auto;
max-width: var(--fullWidth);
display: grid;
row-gap: 2rem;
column-gap: 2rem;
/* align-items: start; */
}
@media screen and (min-width: 576px) {
.cocktails-center {
/* auto-fill自动填充 */
grid-template-columns: repeat(auto-fill, minmax(338.8px, 1fr));
}
}
- 阴影
:root {
/*--primaryLightColor: #d4e6a5;*/
--lightShadow: 2px 5px 3px 0px rgba(0, 0, 0, 0.5);
--darkShadow: 4px 10px 5px 0px rgba(0, 0, 0, 0.5);
}
.btn {
box-shadow: var(--lightShadow);
}
- 悬浮指针
.btn:hover {
cursor: pointer
}
- 滚动条
==一般不设置为none,没有滚动条效果反而不好==
/* 滚动条 */
::-webkit-scrollbar{
width: 5px; /*对垂直流动条有效*/
height: 1px; /*对水平流动条有效*/
}
/*定义滚动条的轨道颜色、内阴影及圆角*/
::-webkit-scrollbar-track{
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
background-color: #dddddd;
opacity: 0.4;
}
/*定义滑块颜色、内阴影及圆角*/
::-webkit-scrollbar-thumb{
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
background: #b1cc82;
opacity: 0.7;
border-radius: 2px;
}
JS逻辑
- 同一个div有多个点击事件,子组件触发后阻止父组件继续触发
const onIconClickHandler = (event) => {
//阻止冒泡
event.stopPropagation();
};
详细见:https://www.cnblogs.com/Wayou/p/react_event_issue.html
- 检测当前是移动端还是pc端
a. npm install 'react-device-detect' --save-dev
b. 代码中使用:
import { isMobile } from 'react-device-detect';
if (isMobile) {
return true
}else{
return false
}
- 简单的弹框
alert("我是弹框")
- object数组形式遍历
{
Object.keys(backpackItems).map(key => {
let item = backpackItems[key];
if (item.tag === props.tag || props.tag === '全部') {
itemEmpty = false;
return (
<BackpackItem
key = {key}
image = {item.image}
title = {item.title}
count = {item.count}
/>
)
}
})
}
react
- 使用creat-react-app,react热加载出现: VM61:2 Uncaught ReferenceError: process is not defined
(1). package.json中添加:
"react-error-overlay": "6.0.9"
(2). npm install
(3). npm start
引用自
https://charles-stover.medium.com/resolving-create-react-apps-uncaught-referenceerror-process-is-not-defined-63f12a069b03
- react-redux持久化
- store.js:
import { createStore } from "@reduxjs/toolkit";
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage'
// 汇总之后的reducer
import rootReducer from './reducer'
const persistConfig = {
key: 'root',
storage
}
const myPersistReducer = persistReducer(persistConfig, rootReducer);
const store = createStore(myPersistReducer);
const persistor = persistStore(store)
export {
store,
persistor
}
- index.js
...
import { Provider } from "react-redux";
import { store, persistor } from "./redux/store";
import {PersistGate} from 'redux-persist/integration/react'
...
const container = document.getElementById("root");
const root = createRoot(container);
root.render(
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>
);
- react弹框,react-confirm-alert
a. npm install react-confirm-alert@2.8.0 --save
b. 代码中使用
import {confirmAlert} from 'react-confirm-alert'
import 'react-confirm-alert/src/react-confirm-alert.css'
confirmAlert({
title: '提示',
message: '暂无库存,添加购物车失败',
buttons: [
{
label: '好的',
onClick: () => {}
}
]
});
- 抛物线动画,0积分下载
示例如下:
import useParabola from "../util/useParabola";
const startRef = useRef();
const endRef = useRef();
const res = useParabola(
{
startRef,
endRef: endRef,
flyInnerStyle: {
transitionTimingFunction: 'cubic-bezier(.55,0,.85,.36)',
},
runTime: 500
},
'8',
);
const onClickHandler = (e) => {
if (props.stock > 0) {
res.running(2);
}
}
return (
<div>
<button onClick={onClickHandler}>点我传球</button>
<div ref={startRef}> start </div>
<hr />
<hr />
<hr />
<div ref={endRef}> end </div>
</div>
)
- 函数组件,父调子,useImperativeHandle
a. 父组件:
const childRef = createRef();
const onClickHandler = () => {
childRef.current.tagChangeHandler();
};
<div
onClick={onClickHandler}
onRef={childRef }
/>
b. 子组件:
const onTagChangeHandler = () => {
console.log("父调子");
}
useImperativeHandle(props.onRef, () => {
return {
tagChangeHandler: onTagChangeHandler,
};
});
- 跨组件ref引用,forwardRef
a. 函数组件,ref定义:
const Navbar = React.forwardRef((props, cartRef) => {
return (
<div ref={cartRef}> anyWhere call me</div>
)
})
b. 其他函数组件引用:
const myRef = React.createRef();
function App() {
return (
<div>
<Navbar ref={myRef}/>
<MyContainer endRef={myRef}>
I want to call Navbar-div
</MyContainer >
</div>
)
}
后续MyContainer通过props.endRef获取Navbar.div引用
a. npm install react-paginate --save
b. import ReactPaginate from "react-paginate";
const [currentPage, setCurrentPage] = useState(0);
const onClickHandler = (event) => {
// Return false to prevent standard page change,
// return false; // --> Will do nothing.
// return a number to choose the next page,
// return 4; --> Will go to page 5 (index 4)
// return nothing (undefined) to let standard behavior take place.
if (event.nextSelectedPage !== undefined) {
setCurrentPage(event.nextSelectedPage);
}
};
const array = [1,2,3,4,5,6,7,8,9];
const perPage = 9;
let totalNum = array.length;
const totalPage = Math.ceil(totalNum / perPage);
return (
<>
<ProductList
content={array.slice(currentPage * perPage ,
currentPage * perPage + perPage)}
/>
{totalPage > 0 &&
<nav aria-label="Page navigation comments" className="mt-4">
<ReactPaginate
previousLabel="上一页"
nextLabel="下一页"
breakLabel="..."
breakClassName="page-item"
breakLinkClassName="page-link"
pageCount={totalPage}
pageRangeDisplayed={4}
marginPagesDisplayed={2}
onPageChange={()=>{}}
containerClassName="pagination justify-content-center"
pageClassName="myPageStyle"
pageLinkClassName="page-link"
previousClassName="page-item"
previousLinkClassName="page-link"
nextClassName="page-item"
nextLinkClassName="page-link"
activeClassName="active"
// eslint-disable-next-line no-unused-vars
hrefBuilder={(page, pageCount, selected) =>
page >= 1 && page <= pageCount ? `/page/${page}` : '#'
}
hrefAllControls
forcePage={currentPage}
onClick={onClickHandler}
/>
</nav>
}
</>
)
c. (可选)分页样式:
/* 分页码选中样式 */
.active .page-link {
background-color: #b1cc82;
color: white;
}
/* 分页码悬浮样式 */
.page-link:hover {
color: #ff7512;
}
/* 分页码样式 */
.page-link {
font-weight: 500;
color: #ff7512;
}
.myPageStyle {
}