В этой статье рассматривается соответствующий код:github Показать результаты:react-demo
создание проекта
Создать папку проекта
mkdir react-demo
cd react-demo
npm init -y
Установка зависимостей
yarn add react react-dom
yarn add webpack webpack-cli webpack-dev-server webpack-merge
babel-core babel-loader babel-polyfill babel-preset-env babel-preset-react
babel-preset-stage-0 cross-env
file-loader jsx-loader
css-loader style-loader url-loader less less-loader --dev
конфигурация веб-пакета
Отличие среды разработкиdevelopment
и производственная средаproduction
настроить
создать соответствующиеконфигурационный файл
antd-мобильная загрузка по запросу
- Установить плагин
yarn add babel-plugin-import -D
- Изменить конфигурацию babel.config.js
module.exports = {
presets: ["@babel/preset-env", "@babel/preset-react"],
plugins: [
"@babel/plugin-transform-runtime",
"@babel/plugin-proposal-class-properties",
["import", { libraryName: "antd-mobile", style: true }]
]
};
внешняя конфигурация
внешние элементы в веб-пакетене допуститьположить немногоimport
пакет (пакет)Пакетв связку
modules.export = {
plugins: [
new HtmlWebpackPlugin({
title: 'React Board',
files: { // 配置 CDN 引入
js: [
'//unpkg.com/swiper/js/swiper.min.js'
],
css: [
'//unpkg.com/swiper/css/swiper.min.css'
]
}
})
],
externals: {
swiper: 'Swiper'
}
}
Настройки index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title><%= htmlWebpackPlugin.options.title %></title>
<!-- require cdn assets css -->
<% for (var i in htmlWebpackPlugin.options.files.css) { %>
<link rel="stylesheet" href="<%= htmlWebpackPlugin.options.files.css[i] %>" />
<% } %>
</head>
<body>
<div id="root"></div>
<!-- require cdn assets js -->
<% for (var i in htmlWebpackPlugin.options.files.js) { %>
<script type="text/javascript" src="<%= htmlWebpackPlugin.options.files.js[i] %>"></script>
<% } %>
</body>
</html>
Использовать в коде:
import Swiper from 'swiper';
Адаптация мобильного терминала
Используйте **postcss-loader** для преобразования css
// 项目使用的是 less
yarn add postcss-less-loader -D
webpack.base.js
настроить
{
test: /\.(css|less)$/,
use: [
'style-loader',
'css-loader',
'less-loader',
'postcss-less-loader'
]
}
postcss-px-to-viewport
Используйте этот плагин для преобразования всех размеров окна px в vw.
yarn add postcss-px-to-viewport -D
Создан в корневом каталоге проектаpostcss.config.js
module.exports = {
plugins: {
"postcss-px-to-viewport": {
viewportWidth: 375, // 视窗的宽度,对应的是我们设计稿的宽度,Iphone6的一般是375 (xx/375*100vw)
viewportHeight: 667, // 视窗的高度,Iphone6的一般是667
unitPrecision: 3, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除)
viewportUnit: "vw", // 指定需要转换成的视窗单位,建议使用vw
selectorBlackList: ['.ignore', '.hairlines'],// 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名
minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值
mediaQuery: false, // 允许在媒体查询中转换`px`
exclude: /(node_module)/i // 忽略 UI 组件库
}
}
}
postcss-plugin-px2rem
Этот плагин предназначен для преобразования всех единиц размера px в rem.
yarn add postcss-plugin-px2rem -D
postcss.config.js
Конфигурация:
module.exports = {
plugins: {
"postcss-plugin-px2rem": {
rootValue: 16,// 配合 rem.js 使用 750 的设计稿
unitPrecision: 5,
mediaQuery: true,
exclude: /(node_module)/i,
selectorBlackList: ['html', 'mp-', 'calendar', 'iconfont'], // 在 rem.js 全局作用下,排除指定的文件的影响
propBlackList: ['border'] // 过滤属性
}
}
}
нужен новыйrem.js
или скачать напрямуюlib-flexible
const viewportWidth = 750
// 基准大小
const baseSize = 32
// 设置 rem 函数
function setRem() {
// 当前页面宽度相对于 750 宽的缩放比例,可根据自己需要修改。
const scale = document.documentElement.clientWidth / viewportWidth
// 设置页面根节点字体大小
document.documentElement.style.fontSize = (baseSize * Math.min(scale, 2)) + 'px'
}
// 初始化
setRem()
// 改变窗口大小时重新设置 rem
window.onresize = function () { setRem() }
Внесите в файл ввода:
// App.js
import './utils/rem'
// import "./utils/flexible.js"
Конфигурация EsLint
Установите плагин eslint
yarn add eslint eslint-plugin-import babel-eslint eslint-plugin-react-hooks -D
Новое в корневом каталоге.eslintrc.js
конфигурационный файл
module.exports = {
parser: "babel-eslint",
plugins: [
"react-hooks"
],
rules: {
"react-hooks/rules-of-hooks": "error", // 检查 Hook 的规则
"react-hooks/exhaustive-deps": "error" // 检查 effect 的依赖
}
}
Реагировать на маршрутизацию
yarn add react-router-dom react-router-config
использоватьreact-router-config
для упрощения настройки маршрутизации
Создайте новый файл route.js
import Home from "@/pages/Home"
import Me from "@/pages/Me"
import Test from "@/pages/Test"
console.log(typeof process.env.API)
const routes = [
{
path: "/home",
exact: true,
component: Home
},
{
path: "/me",
exact: true,
component: Me
},
{
path: "/test",
exact: true,
component: Test
}
];
export default routes;
Внесите маршрутизацию в корневой файл App.js:
import { renderRoutes } from 'react-router-config'
import routes from './routes'
import { HashRouter as Router } from 'react-router-dom'
import Layouts from "./components/Layouts";
function App() {
return (
<Router>
<Layouts>
{renderRoutes(routes)}
</Layouts>
</Router>
)
}
ReactDOM.render(<App />, document.getElementById('root'))
Разработка хуков
Что такое Хук?
Крючок - это специальная функция, которая позволяет «подключить» функции реагирования.Хук может быть объявлен только внутри функционального компонента.
useState
Возвращает состояние и функцию, которая изменяет состояниеsetter
import React, { useState } from 'react';
import { Button } from "antd-mobile";
function User() {
const [user, setUser] = useState('Mondo')
return (
<div>
<div>{user}</div>
<Button type="primary" onClick={e => setUser('imondo.cn')}>改变 State</Button>
</div>
)
}
useEffect
Заменить **Компонент класса**componentDidMount
,componentDidUpdate
,componentWillUnmount
и другие части жизненного цикла
import React, { useState, useEffect } from 'react';
function User() {
const [user, setUser] = useState('Mondo')
useEffect(() => {
setTimeout(() => {
setUser("js.imondo.cn")
}, 2000)
}, [user]) // 仅在 user 更改时更新
return (
<div>
<div>{user}</div>
<Button type="primary" onClick={e => setUser('imondo.cn')}>改变 State</Button>
</div>
)
}
useContext
Принимает объект контекста и возвращает текущее значение контекста. Текущее значение контекста определяется значением свойства
можно использовать напередавать значение между компонентами
import React, { useContext } from 'react';
const theme = {
color: "red"
}
const UserContext = React.createContext(theme);
function User() {
...
return (
<UserContext.Provider value={theme}>
<Child/>
</UserContext.Provider>
)
}
function Child() {
const theme = useContext(UserContext);
return (
<div style={{color: theme.color}}>context</div>
)
}
useMemo
Используйте формат:useMemo(() => fn, deps)
Передайте функцию «создать» и массив зависимостей в качестве аргументовuseMemo
, который пересчитывает запомненное значение только при изменении зависимости. Эта оптимизация помогает избежать дорогостоящих вычислений при каждом рендеринге.Может использоваться как вычисляемое свойство в vue.
import React, { useState, useMemo } from 'react';
import { Button } from "antd-mobile";
function User() {
const [user, setUser] = useState(1)
/* 缓存计算属性 */
const data = useMemo(() => ({
users: (user + 1)
}), [user]);
const onChangeUser = (e) => {
setUser(+e.target.value);
}
return (
<UserContext.Provider>
<input value={user} onChange={onChangeUser}/>
<div>{data.users}</div>
<Button type="primary" onClick={e => setUser(user + 1)}>改变 State</Button>
</UserContext.Provider>
)
}
useReducer
Используйте формат:const [state, dispatch] = useReducer(reducer, initialArg, init)
Это альтернатива useState, используемая в некоторых сценариях:
- Логика состояния сложна и содержит несколько подзначений.
- Следующее состояние зависит от предыдущего состояния
Самое главное, что его написание похоже на **redux**
import React, { useReducer } from "react";
import { Button } from "antd-mobile";
let initCount = 0;
function reducer(state = initCount, action) {
switch (action) {
case "increment":
state++
return state
case "decrement":
state--
return state
default:
throw new Error();
}
}
function User() {
const [count, disaptch] = useReducer(reducer, initCount)
return (
<UserContext.Provider value={theme}>
<div>useReducer</div>
<div>计数器{count}</div>
<Button type="primary" onClick={e => disaptch("decrement")}>减</Button>
<Button type="primary" onClick={e => disaptch("increment")}>加</Button>
</UserContext.Provider>
)
}
useRef
Возвращает изменяемый объект ref, чей.current
Свойство инициализируется переданным параметром
Если хочешьЧтобы получить доступ к объекту ref в подкомпоненте, подкомпонент должен объявить компонент с классом.
import React, { useState, useMemo, useRef } from 'react';
function Parent() {
let [count, setCount] = useState(0)
const childRef = useRef(null)
const childClick = (val) => {
childRef.current.setState({
num: 2
});
}
return (
<div>
<h4>组件传值</h4>
<button onClick={childClick}>向子组件传值</button>
<Child1 ref={childRef} />
</div>
);
}
class Child1 extends React.Component {
constructor() {
super(...arguments);
this.state = {
num: 1
}
}
render() {
const { num } = this.state;
return (
<div>
<div>ref 组件</div>
<div>{num}</div>
</div>
)
}
}
Ссылаться на:
Лучшие практики React Hooks
Обязательно прочтите, прежде чем писать React Hooks
Добро пожаловать, чтобы обратить внимание на официальный аккаунт, каждый может общаться и прогрессировать вместе.