没有特别的幸运,那么就特别的努力!!!
你需要在你的机器上安装 Node >= 8.10 和 npm >= 5.6。要创建项目
npx create-react-app my-app
cd my-app
npm start
第一行的 npx 不是拼写错误 —— 它是 npm 5.2+ 附带的 package 运行工具。
npm install react-router-dom
在src下面新建一个router文件夹
// router文件夹下面新建一个index.js文件
import NotFound from '../view/error';
import Login from '../view/login';
import { Suspense } from 'react';
import { Navigate, useRoutes } from 'react-router-dom';
const staticRoutes = [
{
path: '/',
element: <Navigate to="error" />
},
{
path: '/login',
element: <Login />,
meta: {
title: '登录页'
}
},
{
path: '/error',
element: <NotFound />
},
{
path: '*',
element: <Navigate to="error" />
}
];
function recursionRoutes(routes) {
routes.forEach((route) => {
if (route.component) {
route.element = (
<Suspense>
<route.component />
</Suspense>
);
}
route.children && recursionRoutes(route.children);
});
}
recursionRoutes(staticRoutes);
export default function Routes() {
return useRoutes([...staticRoutes]);
}
import { BrowserRouter } from 'react-router-dom';
import Routes from './router';
import './App.css';
function App() {
return (
<BrowserRouter>
<Routes></Routes>
</BrowserRouter>
);
}
export default App;
import React from "react"
import { useNavigate } from 'react-router-dom'
const Error = () =>{
const history = useNavigate()
const loginHandle = () => {
// 页面跳转方法
history('/ErrorDetail',{ state: { id: '1' }})
}
return(
<div>
首页
<hr />
<div onClick={loginHandle}>点击进详情</div>
</div>
)
}
export default Error
import React, {useEffect} from "react";
import { useLocation } from "react-router-dom";
const Detail = () =>{
const { state } = useLocation()
useEffect(()=>{
console.log('父级页面参数',state)
},[]) //仅在挂载和卸载的时候执行
return(
<div>
详情
</div>
)
}
export default Detail
node版本 – Expected version “^12.22.0 || ^14.17.0 || >=16.0.0”
yarn add antd
修改 src/App.js,引入 antd 的按钮组件。
import React from 'react';
import { Button } from 'antd';
import './App.css';
const App = () => (
<div className="App">
<Button type="primary">Button</Button>
</div>
);
export default App;
修改 src/App.css,在文件顶部引入 antd/dist/antd.css。
@import '~antd/dist/antd.css';
npm i axios
yarn add axios
在项目 src 目录中创建一个 api 目录,用来存放所有的请求接口。
// 在 api 目录中创建一个 categories.js 文件
import http from '../utils/axios';
/**
* 获取首页列表
*/
function getCategoriesAsync(){
return http("get",'/zlb/monthly/learning/enabled/list');
}
export {
getCategoriesAsync
}
在项目 src 目录中创建一个 utils 目录,用来存放工具类的文件,我们将 axios 的封装文件 axios.js 也可以放在里面。
/**
* 网络请求配置
*/
import axios from "axios";
axios.defaults.timeout = 100000;
axios.defaults.baseURL = "https://gateways-test.shiduais.com";
/**
* http request 拦截器
*/
axios.interceptors.request.use(
(config) => {
config.data = JSON.stringify(config.data);
config.headers = {
"Content-Type": "application/json",
};
return config;
},
(error) => {
return Promise.reject(error);
}
);
/**
* http response 拦截器
*/
axios.interceptors.response.use(
(response) => {
if (response.data.errCode === 2) {
console.log("过期");
}
return response;
},
(error) => {
console.log("请求出错:", error);
}
);
/**
* 封装get方法
* @param url 请求url
* @param params 请求参数
* @returns {Promise}
*/
export function get(url, params = {}) {
return new Promise((resolve, reject) => {
axios.get(url, {
params: params,
}).then((response) => {
landing(url, params, response.data);
resolve(response.data);
})
.catch((error) => {
reject(error);
});
});
}
/**
* 封装post请求
* @param url
* @param data
* @returns {Promise}
*/
export function post(url, data) {
return new Promise((resolve, reject) => {
axios.post(url, data).then(
(response) => {
//关闭进度条
resolve(response.data);
},
(err) => {
reject(err);
}
);
});
}
/**
* 封装patch请求
* @param url
* @param data
* @returns {Promise}
*/
export function patch(url, data = {}) {
return new Promise((resolve, reject) => {
axios.patch(url, data).then(
(response) => {
resolve(response.data);
},
(err) => {
msag(err);
reject(err);
}
);
});
}
/**
* 封装put请求
* @param url
* @param data
* @returns {Promise}
*/
export function put(url, data = {}) {
return new Promise((resolve, reject) => {
axios.put(url, data).then(
(response) => {
resolve(response.data);
},
(err) => {
msag(err);
reject(err);
}
);
});
}
//统一接口处理,返回数据
// eslint-disable-next-line import/no-anonymous-default-export
export default function (fecth, url, param) {
let _data = "";
return new Promise((resolve, reject) => {
switch (fecth) {
case "get":
console.log("begin a get request,and url:", url);
get(url, param)
.then(function (response) {
resolve(response);
})
.catch(function (error) {
console.log("get request GET failed.", error);
reject(error);
});
break;
case "post":
post(url, param)
.then(function (response) {
resolve(response);
})
.catch(function (error) {
console.log("get request POST failed.", error);
reject(error);
});
break;
default:
break;
}
});
}
//失败提示
function msag(err) {
if (err && err.response) {
switch (err.response.status) {
case 400:
alert(err.response.data.error.details);
break;
case 401:
alert("未授权,请登录");
break;
case 403:
alert("拒绝访问");
break;
case 404:
alert("请求地址出错");
break;
case 408:
alert("请求超时");
break;
case 500:
alert("服务器内部错误");
break;
case 501:
alert("服务未实现");
break;
case 502:
alert("网关错误");
break;
case 503:
alert("服务不可用");
break;
case 504:
alert("网关超时");
break;
case 505:
alert("HTTP版本不受支持");
break;
default:
}
}
}
/**
* 查看返回的数据
* @param url
* @param params
* @param data
*/
function landing(url, params, data) {
if (data.code === -1) {
}
}
https://gitee.com/hammer1010_admin/react-app.git
state => redux中的state是不能直接修改的,只能通过action来修改,相当于我们在单例中定义setter方法。
action => 要更改state中的内容,你需要发送action。一个action是一个简单的对象,用来描述state发生了什么变更。
reducer => reducer就是根据action来对state进行操作。
1.redux和react没有任何关系
2.redux状态管理器
3.redux公共的容器,数据 组件
// 安装redux
yarn add redux --save
或npm install redux --save
index.js引入
import {createStore} from 'redux'
const store = createStore(counter); // 创建store
const render=()=>{
ReactDOM.render(
<App store={store}/>, //传入
document.getElementById('root')
);
}
render(); // 渲染
store.subscribe(render); // 监听state的变化
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import {createStore} from 'redux'
import {counter} from './redux/reducers'
import App from './redux1/app';
import reportWebVitals from './reportWebVitals';
const store = createStore(counter); // 创建store
const render=()=>{
ReactDOM.render(
<App store={store}/>,
document.getElementById('root')
);
}
render(); // 渲染
store.subscribe(render); // 监听state的变化
reportWebVitals();
app.jsx
import React from "react";
import * as actions from "../redux/actions";
export default class App extends React.Component{
state={
count:0
}
add=()=>{
const num = this.refs.numSelect.value * 1;
// const count = this.state.count + num;
// this.setState({count})
this.props.store.dispatch(actions.increment(num));
}
del=()=>{
const num = this.refs.numSelect.value * 1;
this.props.store.dispatch(actions.decrement(num));
}
async=()=>{
}
render(){
return(
<div>
<p>展示count:{this.props.store.getState()}</p>
<select ref="numSelect">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={this.add}>+</button>{' '}
<button onClick={this.del}>-</button>{' '}
<button onClick={this.async}>increment async</button>
</div>
)
}
}
actions.js
import {INCREMENT,DECREMENT} from './actionType'
export const increment = number => ({type:INCREMENT,number})
export const decrement = number => ({type:DECREMENT,number})
actionType.js
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
reducers.js
import {INCREMENT,DECREMENT} from './actionType'
export function counter(state=0,action){
switch(action.type){
case INCREMENT:
return state + action.number
case DECREMENT:
return state - action.number
default:
return state
}
}
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
infoList: ['Jack','sim','tom']
}
}
render() {
return (
<div>{this.state.infoList.map((item,index)=>(
<div key={index}>{item}</div>
))}</div>
{/* {this.state.infoList.map((item,index)=>{
return {item}
})} */}
);
}
}
<label>
<input type="checkbox" checked={this.props.isAllChecked} onChange={this.handlerSelectAll} />全选
</label>
// 父: 定义一个方法抛出
<TodoHeader addTodo = {this.addTodo}/>
addTodo = (todoItem)=>{
this.state.todos.push(todoItem)
//
this.setState({
todos:this.state.todos
})
}
// 子:
<input type="text" onKeyUp={this.handelKeyUp} placeholder="请输入你的任务名称,按回车键确认" className="form-control"/>
handelKeyUp = (e)=>{
// 获取input的值
if(e.keyCode == 13){
let value = e.target.value;
if(!value) return false
let newTodoItem = {
text:value,
isDone:false
}
e.target.value = ''
// 调用父组件传过来的方法
this.props.addTodo(newTodoItem)
}
}
// 父:app.js --- 1.定义一个方法抛出
deleteFather = (val) =>{
this.state.down = val
this.setState({
down:this.state.down
})
}
render () {
return (
<div className="App">
<Footer {...this.state} deleteFather = {this.deleteFather} />
</div>
);
}
// 子:Footer --- 2.子组件 must 传{...this.props}
import React from 'react';
import List from './list'
class Header extends React.Component{
render(){
return(
<div>
<div>隔代组件传值:</div>
<List down={this.props.down} {...this.props}/>
</div>
)
}
}
export default Header;
// 孙(List)--- 3.调用父组件方法
import React from 'react';
class Header extends React.Component{
delete = () =>{
this.props.deleteFather("已经删除了")
}
render(){
return(
<div>
<div>孙组件:{this.props.down}</div>
<button onClick={this.delete}>删除底部</button>
</div>
)
}
}
export default Header;
import React from 'react'
import logo from './logo.svg';
import './App.css';
import Header from './components/header';
import Content from './components/content';
import Footer from './components/footer';
class App extends React.Component {
constructor(props){
super(props)
this.state = {
top: '我是头部',
list: '我是中间部分',
down: '我是底部',
}
}
getChildren = (val) =>{
this.state.list = '原先值:' + this.state.list + '---现在变成' + val
this.setState({
list:this.state.list
})
}
deleteFather = (val) =>{
this.state.down = val
this.setState({
down:this.state.down
})
}
render () {
return (
<div className="App">
<Header {...this.state} /><hr />
<Content getChildren = {this.getChildren}/><div>{this.state.list}</div><hr />
<Footer {...this.state} deleteFather = {this.deleteFather} />
</div>
);
}
}
export default App;
header.js
import React from 'react';
class Header extends React.Component{
render(){
return(
<div>
<div>组件header:</div>
<div>直接拿取父元素的值:{this.props.top}</div>
</div>
)
}
}
export default Header;
content.js
import React from 'react';
class Header extends React.Component{
handelKeyUp = (e) =>{
if(e.keyCode === 13){
let val = e.target.value;
if(!val) return false
e.target.value = ''
// 调用父组件传过来的方法
this.props.getChildren(val)
}
}
render(){
return(
<div>
<div>组件content:</div>
<div>子给父级传值:<input type="text" onKeyUp={this.handelKeyUp} placeholder="请输入你的任务名称,按回车键确认"/></div>
</div>
)
}
}
export default Header;
footer.js
import React from 'react';
import List from './list'
class Header extends React.Component{
render(){
return(
<div>
<div>隔代组件传值:</div>
<List down={this.props.down} {...this.props}/>
</div>
)
}
}
export default Header;
list.js
import React from 'react';
class Header extends React.Component{
delete = () =>{
this.props.deleteFather("已经删除了")
}
render(){
return(
<div>
<div>孙组件:{this.props.down}</div>
<button onClick={this.delete}>删除底部</button>
</div>
)
}
}
export default Header;
希望能帮助到大家,同时祝愿大家在开发旅途中愉快!!!
拿着 不谢 请叫我“锤” !!!