前端踩坑-解决方案

布局

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);
  }
}

源码-0积分下载

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弹性布局
remfont-size关系:rem = document.documentElement.style.fontSize
在做web和移动端(手机)适配时,marginpaddingfont-size等都以rem为单位;现在希望在网页缩放时,rem能动态调整,也就是动态调整htmlfont-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>
  1. <ol>标签数字对齐左对齐:
默认对齐为:
    1
   10
   20
希望的对齐方式为:
    1
    10
    20
实现:<ol style='list-style-poisition: inside;'>...li标签</ol>
  1. 自己实现一个checkbox,见0积分下载
  2. 导航栏固定
.navbar {
  position: sticky; /* 固定导航栏 */
  z-index: 10; /* z-index 需要是最大的,使得下滑时能盖住其他同级元素 */
}
  1. 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)); 
  }
}
  1. 阴影
: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);
}
  1. 悬浮指针
.btn:hover {
    cursor: pointer
}
  1. 滚动条
==一般不设置为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逻辑

  1. 同一个div有多个点击事件,子组件触发后阻止父组件继续触发
  const onIconClickHandler = (event) => {
    //阻止冒泡
    event.stopPropagation();
  };
  详细见:https://www.cnblogs.com/Wayou/p/react_event_issue.html
  1. 检测当前是移动端还是pc端
a. npm install 'react-device-detect' --save-dev
b. 代码中使用:
    import { isMobile } from 'react-device-detect';
    if (isMobile) {
      return true
    }else{
      return false
    }
  1. 简单的弹框
alert("我是弹框")
  1. 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

  1. 使用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

  1. 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>
);
  1. 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: () => {}
             }
          ]
       });
  1. 抛物线动画,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>
)
  1. 函数组件,父调子,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,
        };
    });
    
  1. 跨组件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引用
  1. react分页组件
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 {

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值