React 之 airbnb - 项目实战

news/2024/7/15 18:42:36 标签: react.js, javascript, 前端

一、开发前言

1. 规范

2. 创建项目 

node -v  => 18.0.0 

npm -v   => 8.6.0

create-react-app star-airbnb

3. 项目基本配置

配置jsconfig.json

javascript">{
  "compilerOptions": {
    "target": "es5",
    "module": "esnext",
    "baseUrl": "./",
    "moduleResolution": "node",
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "jsx": "preserve",
    "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost"
    ]
  }
}

通过craco配置

react脚手架隐藏webpack

解决一 : npm run eject 

导出webpack配置,要去找到对应的配置,如果修改错误,项目可能跑不起来

 

解决二 : 通过craco => create-react-app config

配置后,会与原来的webpack配置混合

npm install @craco/craco@alpha -D => "react-scripts": "5.0.1"

新建 craco.config.js文件

javascript">/* package.json */
"scripts": {
-   "start": "react-scripts start",
-   "build": "react-scripts build",
-   "test": "react-scripts test",
+   "start": "craco start",
+   "build": "craco build",
+   "test": "craco test",
}
别名
javascript">const path = require('path');

const resolve = (pathName) => path.resolve(__dirname, pathName);

module.exports = {
  // webpack
  webpack: {
    alias: {
      '@': resolve('src'),
      'assets': resolve('src/assets'),
      'components': resolve('src/components'),
      'view': resolve('src/view'),
      'store': resolve('src/store'),
      'utils': resolve('src/utils'),
      'router': resolve('src/router'),
      'services': resolve('src/services'),
      'baseUi': resolve('src/base-ui')
    }
  }
};
less文件

可查看 Ant Design 这里所用是4点多的版本

npm i craco-less@2.1.0-alpha.0

javascript">const path = require('path');
const resolve = (pathName) => path.resolve(__dirname, pathName);

const CracoLessPlugin = require('craco-less');

module.exports = {
  // less
  plugins: [
    {
      plugin: CracoLessPlugin,
      options: {
        lessLoaderOptions: {
          lessOptions: {
            // modifyVars: { '@primary-color': '#1DA57A' },
            javascriptEnabled: true
          }
        }
      }
    }
  ],
  // webpack
  webpack: {
    alias: {
      '@': resolve('src'),
      assets: resolve('src/assets'),
      components: resolve('src/components'),
      view: resolve('src/view'),
      store: resolve('src/store'),
      utils: resolve('src/utils'),
      router: resolve('src/router'),
      services: resolve('src/services'),
      baseUi: resolve('src/base-ui')
    }
  }
};

css样式重置

对默认CSS样式进行重置

normalize.css

npm install normalize.css

javascript">import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import 'normalize.css';

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
reset.css
@mainColor: #484848;

blockquote, body, button, dd, dl, dt, fieldset, form, h1, h2, h3, h4, h5, h6, hr, input, legend, li, ol, p, pre, td, textarea, th, ul {
  // color: @mainColor;
  padding: 0;
  margin: 0;
}

a {
  color: @mainColor;
  text-decoration: none;
}

img {
  vertical-align: top;
}

body {
  font-size: 14px;
  font-family: Circular, "PingFang-SC", "Hiragino Sans GB", "微软雅黑", "Microsoft YaHei", "Heiti SC" ;
  -webkit-font-smoothing: antialiased;
}

目录结构划分

4. 主题配置

项目使用styled-components,可用于配置主题

配置

theme/index.js

javascript">export const theme = {
  color: {
    $primaryColor: '#FF385C',
    $secondaryColor: '#00848A',
    $textColor: '#484848',
    $textColorSecondary: '#222222'
  },
  fontSize: {
    $small: '12px',
    $normal: '14px',
    $large: '16px'
  },
  mixin: {
    $boxShadow: `
      transition: box-shadow 0.2s ease;
      &:hover {
        box-shadow: 0 2px 4px rgba(0,0,0,0.18);
      }
    `
  }
};

export default theme;

index.js

javascript">import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client';
import { HashRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
// 1. 引入 Provider
import { ThemeProvider } from 'styled-components';

import App from './App';
import store from './store';
import 'normalize.css';
import 'assets/css/index.less';
import { theme } from './theme';

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
  <Provider store={store}>
    {/* 2. 使用主题 */}
    <ThemeProvider theme={theme}>
      <HashRouter>
        <Suspense fallback={<div>Loading...</div>}>
          <App />
        </Suspense>
      </HashRouter>
    </ThemeProvider>
  </Provider>
);

组件使用

javascript">import styled from 'styled-components';

export const LeftWrapper = styled.div.attrs((props) => ({
  // 1. 使用主题, 通过 props.theme 获取主题
  $primaryColor: props.theme.color.$primaryColor,
  $secondaryColor: props.theme.color.$secondaryColor
}))`
  flex: 1;
  display: flex;
  align-items: center;
  /* 2. 使用,这里是用一个回调函数 */
  color: ${({ $primaryColor }) => $primaryColor};
  .log {
    cursor: pointer;
  }
`;

5. 路由配置

npm install react-router-dom

router/index.js

javascript">import React, { lazy } from 'react';
import { Navigate } from 'react-router-dom';

const Home = lazy(() => import('view/home'));
const Entire = lazy(() => import('view/entire'));
const Detail = lazy(() => import('view/detail'));

const routes = [
  {
    path: '/',
    element: <Navigate to='/home' />
  },
  {
    path: '/home',
    element: <Home />
  },
  {
    path: '/entire',
    element: <Entire />
  },
  {
    path: '/detail',
    element: <Detail />
  }
];

export default routes;

index.js

javascript">import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client';
import { HashRouter } from 'react-router-dom';

import App from './App';
import 'normalize.css';
import 'assets/css/index.less';

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
  <React.StrictMode>
    <HashRouter>
      <Suspense fallback={<div>Loading...</div>}>
        <App />
      </Suspense>
    </HashRouter>
  </React.StrictMode>
);

App.jsx

javascript">import React, { memo } from 'react';
import { useRoutes } from 'react-router-dom';

import routes from 'router';

const App = memo(() => {
  return (
    <>
      <div className='header'>header</div>
      <div className='main-contain'>{useRoutes(routes)}</div>
      <div className='footer'>footer</div>
    </>
  );
});

export default App;

6. redux状态管理配置

npm install @reduxjs/toolkit react-redux

store

modules
home.js

home.js => 使用rtk模式

javascript">import { createSlice } from '@reduxjs/toolkit';

const homeSlice = createSlice({
  name: 'home',
  initialState: {
    a: [1, 2, 3, 4]
  },
  reducers: {}
});

export default homeSlice.reducer;
entire文件夹 

entire => 使用原生模式,所以有四个文件

reducer.js
javascript">const initialState = {
  b: [1, 2, 3, 4]
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    // case 'ADD_USER':
    //   return {
    //     ...state,
    //     [action.payload.id]: action.payload
    //   };
    default:
      return state;
  }
};

export default reducer;
index.js
javascript">import reducer from './reducer';

export default reducer;
index.js
javascript">import { configureStore } from '@reduxjs/toolkit';
import homeReducer from './modules/home';
// 直接使用原生的entire,也是一样的,因为createSlice就是对原生的一种封装而已
import entireReducer from './modules/entire';

const store = configureStore({
  reducer: {
    home: homeReducer,
    entire: entireReducer
  }
});

export default store;

index.js 

javascript">import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client';
import { HashRouter } from 'react-router-dom';

import { Provider } from 'react-redux';
import App from './App';
import store from './store';
import 'normalize.css';
import 'assets/css/index.less';

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
  <React.StrictMode>
    <Provider store={store}>
      <HashRouter>
        <Suspense fallback={<div>Loading...</div>}>
          <App />
        </Suspense>
      </HashRouter>
    </Provider>
  </React.StrictMode>
);

7. 网络请求 - axios配置

javascript">npm install axios

requset

config.js
javascript">export const BASE_URL = 'http://xxxxxx';
export const TIME_OUT = 20000;
index.js
javascript">import axios from 'axios';
import { BASE_URL, TIME_OUT } from './config';

class StarRequest {
  constructor(baseURL, timeout) {
    this.instance = axios.create({
      baseURL,
      timeout
    });

    this.instance.interceptors.response.use(
      (res) => {
        return res.data;
      },
      (err) => {
        return err;
      }
    );
  }
  request(config) {
    return this.instance(config);
  }
  get(config) {
    return this.request({ ...config, method: 'get' });
  }
  post(config) {
    return this.request({ ...config, method: 'post' });
  }
}

const starRequest = new StarRequest(BASE_URL, TIME_OUT);
export default starRequest;

index.js 

javascript">import starRequest from './request';

export default starRequest;

简单使用

javascript">import React, { memo, useEffect, useState } from 'react';
import starRequest from '@/services';

const Home = memo(() => {
  // 定义状态
  const [highscore, sethighscore] = useState({});
  // 请求
  useEffect(() => {
    starRequest.get({ url: '/home/highscore' }).then((res) => {
      console.log(res);
      sethighscore(res);
    });
  }, []);
  return (
    <>
      <div>Home</div>
      <div>{highscore.title}</div>
    </>
  );
});

export default Home;

二、注意事项

图片问题

导入需使用import | require 导入方可使用

不论是背景图片还是img使用图片

import导入

javascript">import styled from 'styled-components';
import coverPic from '@/assets/img/cover_01.jpeg';

export const BannerWrapper = styled.div`
  height: 529px;
  background: url(${coverPic}) center center/cover;
`;

require导入

javascript">import styled from 'styled-components';

export const BannerWrapper = styled.div`
  height: 529px;
  background: url(${require('@/assets/img/cover_01.jpeg')}) center center/cover;
  
  /* 根据webpack版本不同,可能需要加default */
  /* background: url(${require('@/assets/img/cover_01.jpeg').default}) center center/cover; */
`;

三、引入组件库

Material-Ui

安装

javascript">npm install @mui/material @mui/styled-engine-sc

配置

javascript">const path = require('path');
const resolve = (pathName) => path.resolve(__dirname, pathName);

const CracoLessPlugin = require('craco-less');

module.exports = {
  // less
  plugins: [
    {
      plugin: CracoLessPlugin,
      options: {
        lessLoaderOptions: {
          lessOptions: {
            // modifyVars: { '@primary-color': '#1DA57A' },
            javascriptEnabled: true
          }
        }
      }
    }
  ],
  // webpack
  webpack: {
    alias: {
      '@': resolve('src'),
      assets: resolve('src/assets'),
      components: resolve('src/components'),
      view: resolve('src/view'),
      store: resolve('src/store'),
      utils: resolve('src/utils'),
      router: resolve('src/router'),
      services: resolve('src/services'),
      baseUi: resolve('src/base-ui'),
      // ++++++++++++++++
      '@mui/styled-engine': '@mui/styled-engine-sc'
    }
  }
};

Ant-Design

安装

javascript">npm install antd

使用

javascript">// 直接组件中使用即可

import { Button } from 'antd';

<Button type='primary'>Button</Button>

四、项目效果

小视频


http://www.niftyadmin.cn/n/5223425.html

相关文章

​序列类型 --- list, tuple, range​

目录 通用序列操作 不可变序列类型 可变序列类型 列表 元组 range 对象 有三种基本序列类型&#xff1a;list, tuple 和 range 对象。 为处理 二进制数据 和 文本字符串 而特别定制的附加序列类型会在专门的小节中描述。 通用序列操作 大多数序列类型&#xff0c;包括可…

贪心算法(新坑)

贪心入门 概述&#xff1a; 贪心算法是一种在每一步选择中都采取当前最优解的策略&#xff0c;希望最终能够得到全局最优解的算法。简单来说&#xff0c;它会不断地做出局部最优的选择&#xff0c;相信通过这种选择最终能够达到全局最优。 举个例子来说明。假设你要从一个迷…

leetcode:414. 第三大的数

一、题目 函数原型&#xff1a;int thirdMax(int* nums, int numsSize) 二、思路 将数组降序排序。 如果数组元素个数小于3&#xff0c;直接返回第一个元素&#xff1b; 如果数组元素个数大于等于3&#xff0c;且不同元素个数小于3&#xff0c;直接返回第一个元素&#xff1b; …

【沐风老师】3DMAX拼图建模工具MaxPuzzle2D插件使用方法详解

MaxPuzzle2D拼图建模工具使用帮助 MaxPuzzle2D拼图建模工具&#xff0c;拼图建模“彩虹系列”插件&#xff0c;是一款用MAXScript脚本语言开发的3dMax拼图建模小工具&#xff0c;可以创建2D或3D的拼图图形阵列。这让需要拼图建模的设计师大大节省了时间。 MaxPuzzle2D工具界面&…

linux logrotate日志轮询设置案例一

1.编辑/etc/logrotate.conf文件&#xff0c;添加如下配置&#xff0c;并保存 /var/log/ztj.log {missingokhourlycreate 644 root rootsharedscriptspostrotateif [ -f /var/run/syslogd.pid ];then/bin/kill -HUP $(/bin/cat /var/run/syslogd.pid) >/dev/null 2>&…

Java 8 中 ReentrantLock 与 Synchronized 的区别

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

Deep Image Prior

深度图像先验 论文链接&#xff1a;https://sites.skoltech.ru/app/data/uploads/sites/25/2018/04/deep_image_prior.pdf 项目链接&#xff1a;https://github.com/DmitryUlyanov/deep-image-prior Abstract 深度卷积网络已经成为一种流行的图像生成和恢复工具。一般来说&a…

国产操作系统-银河麒麟V10

一、介绍 银河麒麟操作系统隶属于麒麟软件&#xff0c;麒麟软件是专业从事国产操作系统研发和产业化的企业&#xff0c;面向通用和专用领域打造安全创新的国产操作系统产品和相应解决方案&#xff0c;旗下拥有银河麒麟、中标麒麟、星光麒麟三大产品品牌。 麒麟软件官方网站地…