React从入门到实战- 企业级实战项目-宜居一

2019年最新 React从入门到实战(带 React 企业级实战项目-宜居)

(React基础知识&)

React基础知识&

1.React 学习前期准备

(React 学习前期准备&)

React 学习前期准备&

react环境

React从入门到实战- 企业级实战项目-宜居一_第1张图片

工程化,webpack安装node的npm

创建react项目

React从入门到实战- 企业级实战项目-宜居一_第2张图片

打开控制台

Webpack构建工具环境,默认端口3000

Public主入口文件,index与logo

React从入门到实战- 企业级实战项目-宜居一_第3张图片

Src源码文件,

React从入门到实战- 企业级实战项目-宜居一_第4张图片

React从入门到实战- 企业级实战项目-宜居一_第5张图片

React从入门到实战- 企业级实战项目-宜居一_第6张图片

Package.json当前依赖版本

React从入门到实战- 企业级实战项目-宜居一_第7张图片

2.React JSX语法

(React JSX语法&)

React JSX语法&

JSX基础语法

ReactDom.render渲染函数,第一个参数标签结构直接包含标签的JSX语法js+XML。React没有双引号概念,第二个参数获取一个元素

React从入门到实战- 企业级实战项目-宜居一_第8张图片

React从入门到实战- 企业级实战项目-宜居一_第9张图片

大括号就是JavaScript的语法,遇到<>安装HTML解析遇到{}按照js语法解析

import React from 'react';
import ReactDOM from 'react-dom';
import App from "./app"
// 全家桶

// document.getElementById('root')获取要插入的容器
// jsx语法:

Hello React

// const react = "React"; // ():如果存在标签结构,并且标签结构要换行,需要用()括起来 // function tick(){ // const element = ( //
//

Hello, world!

//

It is { new Date().toLocaleTimeString() }

//
// ) // ReactDOM.render(element, document.getElementById('root')); // } // setInterval(tick,1000); ReactDOM.render(, document.getElementById('root'));

3.React 元素渲染

(React 元素渲染&)

React 元素渲染&

Const element = () 小括号,如果存在标签结构并且一行不够放要换行使用()括起来。

当前时间通过js获取,把element当成一个元素代表标签元素。

没有调用element不存在,要让函数包裹ReactDOM

{}渲染元素标签方法

React从入门到实战- 企业级实战项目-宜居一_第10张图片

4.React 组件基础之创建组件

(React 组件基础之创建组件&)

React 组件基础之创建组件&

React组件创建

类的形式或者Hook方式创建组件,render(){}渲染函数中做想要做的事情,外部引用需要导出App

React从入门到实战- 企业级实战项目-宜居一_第11张图片

React所有东西都是组件组成的,降低耦合性

React从入门到实战- 企业级实战项目-宜居一_第12张图片

内容多增加小括号

React从入门到实战- 企业级实战项目-宜居一_第13张图片

连起来写法

React从入门到实战- 企业级实战项目-宜居一_第14张图片

组件互相引用以标签的形式引用

React从入门到实战- 企业级实战项目-宜居一_第15张图片

import React from "react"
// import Home from "./Home"
// import MyNav from "./MyNav"
// import StateComponent from "./StateComponent";
// import ComponentLife from "./ComponentLife"
import SetStateDemo from "./setStateDemo"
import IfDemo from "./ifDemo"
import KeyDemo from "./KeyDemo"
import FormDemo from "./FormDemo"
import RefsAndDOM from "./RefsAndDOM"
import RefsForm from "./RefsForm"
import Parent from "./components/parent"
import Compose from "./compose"
import PropsTypeDemo from "./PropsTypeDemo"

// 用类的形式创建组件,Hook形式
class App extends React.Component{

    constructor(){
        super();
        this.state = {
            title:"文本1"
        }
    }

    clickChange = (data) =>{
        this.setState({
            title:data
        })
    }

    // 渲染函数
    render(){

        // const nav1 = ["首页","视频","学习"];
        // const nav2 = ["WEB","Java","Node"];

        return(
            
{/*

Hello React Component

学习React,最重要的是,心态要好!

*/} {/* */} {/* */} {/* */} {/* */} {/* */} {/* */} {/* */} {/* */} {/* */} {/*
我是组合效果
*/}
) } } export default App
import React from "react"

export default class Home extends React.Component{

    constructor(props){
        super(props);
        // this.clickHandler = this.clickHandler.bind(this);
    }

    clickHandler(element,event){
        // this无指向
        // console.log(this);
        console.log(element,event);
    }

    // apply call bind:面试常见问题
    render(){
        const names = ['iwen','ime'];
        return(
            
Home {/* */} {/* */} {/* */}
    { names.map((element,index) => { // return
  • { element }
  • return
  • this.clickHandler(element, e) } key={index}>{ element }
  • }) }
) } }

5.React Props属性

(React Props属性&)

React Props属性&

props属性组件复用

组件复用性被多次使用呈现不同的数据,组件内容要动态生成

React从入门到实战- 企业级实战项目-宜居一_第16张图片

组件多次使用,传入nav,创建两个MyNav

React从入门到实战- 企业级实战项目-宜居一_第17张图片

MyNav来接收数据,组件被调用两次,列表渲染this.props.nav通过map进行遍历

React从入门到实战- 企业级实战项目-宜居一_第18张图片

不加key报警号,传入数据进行解析

React从入门到实战- 企业级实战项目-宜居一_第19张图片

Return结构中要加注释,遇到大括号要js解析

React从入门到实战- 企业级实战项目-宜居一_第20张图片

一个组件传入多个数据

React从入门到实战- 企业级实战项目-宜居一_第21张图片

Props不可以被修改,属于App.js只能在App.js中修改

React从入门到实战- 企业级实战项目-宜居一_第22张图片

import React from "react"

// props不可以被修改
export default class MyNav extends React.Component{
    render(){
        return(
            
{/* jsx语法 */}

{ this.props.title }

    { this.props.nav.map((element,index) =>{ return
  • { element }
  • }) }
) } }

6.React State状态

(React State状态&)

React State状态&

组件state状态属性

以前都是操作Dom元素,通过改变state来修改页面,通过在构造函数中this.state的方式来定义状态,通过this.state.count来获取值,count就是状态。请求数据也通过state展示

两个事件在外界定义,通过setState来改变值,this要绑定bind(this),在外部函数才能获取this,this.setState({})state本身是一个对象{},所有读state都必须this.state

React从入门到实战- 企业级实战项目-宜居一_第23张图片

除了bind绑定this,还有一种方式通用箭头函数改变this指向

React从入门到实战- 企业级实战项目-宜居一_第24张图片

动态文本显示不同数据

React从入门到实战- 企业级实战项目-宜居一_第25张图片

React从入门到实战- 企业级实战项目-宜居一_第26张图片

引用不需要大括号,是组件本身

React从入门到实战- 企业级实战项目-宜居一_第27张图片

import React from "react"

export default class StateComponent extends React.Component{
    /**
     * 组件中的状态:state
     * 以前我们操作页面的元素的变化,都是修改DOM,操作DOM
     * 但是有了React优秀的框架,我们不在推荐操作DOM,页面元素的改变使用State进行处理
     */

    constructor(props){
        super(props);
        // 定义
        this.state = {
            count:10,
            flag:true
        }
    }

    increment(){
        // setState
        this.setState({
            count:this.state.count+=1
        })
    }

    decrement(){
        this.setState({
            count:this.state.count-=1
        })
    }

    clickHandler = () =>{
        console.log(this);
    }

    render(){
        let showView = this.state.flag ? '我是孙悟空' : '我是假的孙悟空'
        return(
            

组件的State

{ this.state.count }

{ showView }

) } }

7.React 组件生命周期函数

(React 组件生命周期函数&)

React 组件生命周期函数&

React生命周期函数,ComponentWillMount在组件渲染之前执行,钩子函数在不同阶段自动执行

ComponentDidMount组件渲染之后,组件已经呈现在页面运行状态,执行,

React从入门到实战- 企业级实战项目-宜居一_第28张图片

改变state执行shouldComponentUpdate返回true代表允许改变,false不允许改变还是原来状态。

返回true,执行componentDidUpdate数据改变之前执行,componentDidUpdate数据渲染完成。

Props发生改变执行componentWillReceiveProps,

组件销毁前执行ComponentWillMount,一共七个

React从入门到实战- 企业级实战项目-宜居一_第29张图片

React从入门到实战- 企业级实战项目-宜居一_第30张图片

先执行ComponentDid/WillMount

解构赋值直接读取值

React从入门到实战- 企业级实战项目-宜居一_第31张图片

点击修改执行Update

React从入门到实战- 企业级实战项目-宜居一_第32张图片

React从入门到实战- 企业级实战项目-宜居一_第33张图片

修改父元素执行componentWillReceiveProps,父传子

React从入门到实战- 企业级实战项目-宜居一_第34张图片

React从入门到实战- 企业级实战项目-宜居一_第35张图片

事件子传递给父,通过儿子事件触发父事件的执行,儿子调用父亲事件可以传递参数

React从入门到实战- 企业级实战项目-宜居一_第36张图片

React从入门到实战- 企业级实战项目-宜居一_第37张图片

父组件接收子组件的数据

React从入门到实战- 企业级实战项目-宜居一_第38张图片

import React from "react"

export default class ComponentLife extends React.Component{

    constructor(props){
        super(props);
        this.state = {
            count:10
        }
    }

    componentWillMount(){
        console.log("componentWillMount");
    }

    componentDidMount(){
        console.log("componentDidMount");
    }

    shouldComponentUpdate(){
        console.log("shouldComponentUpdate");
        return true;
    }

    componentWillUpdate(){
        console.log("componentWillUpdate");
    }

    componentDidUpdate(){
        console.log("componentDidUpdate");
    }

    componentWillReceiveProps(){
        console.log("componentWillReceiveProps");
    }

    componentWillUnmount(){
        console.log("componentWillUnmount");
    }

    changeHandler = () =>{
        this.setState({
            count:this.state.count+=1
        })
    }

    clickChange = () => {
        this.props.clickChanges('我是儿子的数据');
    }

    render(){
        const { count } = this.state;
        return(
            
生命周期函数:{ count } - { this.props.title }
) } }
import React from "react"
// import Home from "./Home"
// import MyNav from "./MyNav"
// import StateComponent from "./StateComponent";
// import ComponentLife from "./ComponentLife"
import SetStateDemo from "./setStateDemo"
import IfDemo from "./ifDemo"
import KeyDemo from "./KeyDemo"
import FormDemo from "./FormDemo"
import RefsAndDOM from "./RefsAndDOM"
import RefsForm from "./RefsForm"
import Parent from "./components/parent"
import Compose from "./compose"
import PropsTypeDemo from "./PropsTypeDemo"

// 用类的形式创建组件,Hook形式
class App extends React.Component{

    constructor(){
        super();
        this.state = {
            title:"文本1"
        }
    }

    clickChange = (data) =>{
        this.setState({
            title:data
        })
    }

    // 渲染函数
    render(){

        // const nav1 = ["首页","视频","学习"];
        // const nav2 = ["WEB","Java","Node"];

        return(
            
{/*

Hello React Component

学习React,最重要的是,心态要好!

*/} {/* */} {/* */} {/* */} {/* */} {/* */} {/* */} {/* */} {/* */} {/* */} {/*
我是组合效果
*/}
) } } export default App

8.React setState是同步还是异步

(React setState是同步还是异步&)

React setState是同步还是异步&

setState异步处理方案

调用setState会重绘视图,实时获取state值

React从入门到实战- 企业级实战项目-宜居一_第39张图片

每次获取值是上一次的值,异步通过回调函数获取实时获取的

React从入门到实战- 企业级实战项目-宜居一_第40张图片

同步实时获取

React从入门到实战- 企业级实战项目-宜居一_第41张图片

通过promise处理异步问题,resolve成功回调,所有改变调用setStaetAsync变为同步。

使用promise通过asyn和await进行处理,await执行完成之后才会执行后面的console.log。

React从入门到实战- 企业级实战项目-宜居一_第42张图片

标准函数写法要bind(this) promise async await

React从入门到实战- 企业级实战项目-宜居一_第43张图片

 

import React from "react"

export default class SetStateDemo extends React.Component{

    constructor(){
        super();
        this.state = {
            count:0
        }
    }

    async increment(){
        // this.setState({
        //     count:this.state.count+1
        // },() => {
        //     console.log(this.state.count);
        // })
        await this.setStateAsync({count:this.state.count+1});
        console.log(this.state.count);
    }

    // promise  async 和 await

    setStateAsync(state){
        return new Promise((resolve) =>{
            this.setState(state,resolve);
        })
    }

    render(){
        return(
            
setState同步还是异步问题

{ this.state.count }

) } }

9.React 条件渲染

(React 条件渲染&)

React 条件渲染&

条件渲染

React从入门到实战- 企业级实战项目-宜居一_第44张图片

数据来源于网络,如果空的数据不用渲染缺省值

React从入门到实战- 企业级实战项目-宜居一_第45张图片

React从入门到实战- 企业级实战项目-宜居一_第46张图片

import React from "react"

export default class IfDemo extends React.Component {
    /**
     * 常用的应用常见:
     *  1.对视图条件进行切换
     *  2.做缺省值
     */

    constructor() {
        super();
        this.state = {
            isLogin: false,
            names: ["ime"]
        }
    }
    clickHandler = () => {
        this.setState({
            isLogin: true
        })
    }

    render() {
        const { names } = this.state;
        let showView = this.state.isLogin ?
            
iwen
:
请登录
return (
条件渲染:{showView} { names.length > 0 ?
{ names.map((element, index) => { return

{element}

}) }
:
请等待数据正在请求....
}
) } }

10.React 列表渲染&key

(React 列表渲染&key&)

React 列表渲染&key&

map列表渲染key

React从入门到实战- 企业级实战项目-宜居一_第47张图片

Key加载到最外层标签元素,数组就可以遍历无论有多复杂的

React从入门到实战- 企业级实战项目-宜居一_第48张图片

二层遍历

React从入门到实战- 企业级实战项目-宜居一_第49张图片

React从入门到实战- 企业级实战项目-宜居一_第50张图片

Push一个对象

Push返回值不是当前数组,而是返回数组长度userinfo变为一个长度,使用concat合并

React从入门到实战- 企业级实战项目-宜居一_第51张图片

React从入门到实战- 企业级实战项目-宜居一_第52张图片

Key局部渲染,只在下面添加标签整个视图没有重新渲染,key唯一索引,只有索引变化才会渲染视图

React从入门到实战- 企业级实战项目-宜居一_第53张图片

import React from "react"

export default class KeyDemo extends React.Component{

    constructor(){
        super();
        this.state = {
            userinfo:[
                {
                    name:"iwen",
                    age:20,
                    sex:"男",
                    jobs:['11','222','333']
                },
                {
                    name:"ime",
                    age:20,
                    sex:"男",
                    jobs:['11','222','333']
                },
                {
                    name:"frank",
                    age:20,
                    sex:"男",
                    jobs:['11','222','333']
                }
            ]
        }
    }

    clickHandler = () =>{
        this.setState({
            userinfo:this.state.userinfo.concat([{
                name:"sakura",
                age:30,
                sex:"女",
                jobs:['333','444','555']
            }])
        })
    }

    render(){
        return(
            
    { this.state.userinfo.map((element,index) =>{ return(
  • { element.name } { element.age } { element.sex }
    { element.jobs.map((childElement,childIndex) =>{ return { childElement } }) }
  • ) }) }
) } }

11.React 表单受控组件

(React 表单受控组件&)

React 表单受控组件&

ref受控组件与非受控组件,表单提交preventDefault

受控组件表单内的value的值是state帮助管理的,非受控组件自己操作Dom。

受控组件的value值是constructor中的声明的state,value值被管理了。能改变state只有setState,通过onChange事件去改变value的值,value的值可以通过event对象获取。

React从入门到实战- 企业级实战项目-宜居一_第54张图片

表单默认跳转,组织默认事件

通过state管理读取state中的值,受控组件获取value不方便

React从入门到实战- 企业级实战项目-宜居一_第55张图片

import React from "react"

export default class FormDemo extends React.Component{

    constructor(){
        super();
        this.state = {
            value:""
        }
    }

    handleSubmit = (e) =>{
        e.preventDefault();
        console.log(this.state.value);
    }

    onChangeHandler = (e) =>{
        this.setState({
            value:e.target.value
        })
    }

    render(){
        return(
            
) } }

12.React Refs&DOM

(React Refs&DOM&)

React Refs&DOM&

组件比较多使用非受控组件,不推荐直接操作Dom一些额外情况可以直接操作DOM

获取div dom元素

DidMount说明div已经渲染完毕了,存在了

React从入门到实战- 企业级实战项目-宜居一_第56张图片

如果ref是一个字符串,官方已经废弃

React从入门到实战- 企业级实战项目-宜居一_第57张图片

import React from "react"

export default class RefsAndDOM extends React.Component{

    constructor(){
        super();
        this.HelloDiv = React.createRef();
    }

    componentDidMount(){
        this.HelloDiv.current.style.color = "red";
    }

    render(){
        return(
            
Refs和DOM
Hello
) } }

13.React 表单 非受控组件

(React 表单 非受控组件&)

React 表单 非受控组件&

数据不再以受控组件获得,实时获取,current获取元素div结构,获取元素值

不用每一个input增加一个事件

推荐使用受控组件,如果有很多事件使用非受控组件

React从入门到实战- 企业级实战项目-宜居一_第58张图片

有点不用每个input标签实现一个事件

import React from "react"

export default class RefsForm extends React.Component{

    constructor(){
        super();
        this.username = React.createRef();
        this.password = React.createRef();
    }

    clickHandler = (e) =>{
        console.log(this.username.current.value);
        console.log(this.password.current.value);
    }

    render(){
        return(
            
) } }

14.React 状态提升

(React 状态提升&)

React 状态提升&

状态提升是用来进行组件之间数据交互,推荐受控组件

1和2都去接收数据,ComponentDidMount一进入,传过来数据动态修改

React从入门到实战- 企业级实战项目-宜居一_第59张图片

React从入门到实战- 企业级实战项目-宜居一_第60张图片

互相之间不再是独立的状态,1,2互相影响传递数据,状态要同步的

React从入门到实战- 企业级实战项目-宜居一_第61张图片

值应该从props中获取,互相影响

React从入门到实战- 企业级实战项目-宜居一_第62张图片

import React from "react"
import Child1 from "./child1"
import Child2 from "./child2"

export default class Parent extends React.Component{

    constructor(){
        super();
        this.state = {
            money:1
        }
    }

    changeHandler(e){
        this.setState({
            money:e.target.value
        })
    }  
    

    render(){
        return(
            

Parent

人民币: 美元:
) } }
import React from "react"

export default class Child1 extends React.Component{

    constructor(){
        super();
        this.state = {
            input1:0
        }
    }

    componentDidMount(){
        this.setState({
            input1:this.props.money
        })
    }

    changeHandler(e){
        this.setState({
            input1:e.target.value
        })
    }

    render(){
        return(
            

{this.props.money}

) } }
import React from "react"

export default class Child2 extends React.Component {

    constructor(){
        super();
        this.state = {
            input2:0
        }
    }

    componentDidMount(){
        this.setState({
            input2:this.props.money * 7
        })
    }


    changeHandler(e){
        this.setState({
            input2:e.target.value
        })
    }


    render() {
        return (
            

{this.props.money * 7}

) } }

15.React 组件组合

(React 组件组合&)

React 组件组合&

PropsType验证

React从入门到实战- 企业级实战项目-宜居一_第63张图片

组件引用的中间

读到组件间的div元素

React从入门到实战- 企业级实战项目-宜居一_第64张图片

import React from "react"

export default class Compose extends React.Component{
    render(){
        return(
            
哈哈哈:{ this.props.children }
) } }

16.React PropsType验证

(React PropsType验证&)

React PropsType验证&

类型检查增强程序的健康性

Props接收标题文本,传递数据类型

React从入门到实战- 企业级实战项目-宜居一_第65张图片

React从入门到实战- 企业级实战项目-宜居一_第66张图片

isRequire是必选项,必须呈现内容

缺省默认props

React从入门到实战- 企业级实战项目-宜居一_第67张图片

import React from 'react'
import PropTypes from 'prop-types';

export default class PropsTypeDemo extends React.Component{
    render(){
        return(
            
Hello:{ this.props.title }
) } } // PropsTypeDemo.propTypes = { // title:PropTypes.number.isRequired // } PropsTypeDemo.propTypes = { title:PropTypes.string } PropsTypeDemo.defaultProps = { title:'默认值' }

(Antd UI框架&)

Antd UI框架&

17.React Antd UI组件库引入

(React Antd UI组件库引入&)

React Antd UI组件库引入&

React从入门到实战- 企业级实战项目-宜居一_第68张图片

React从入门到实战- 企业级实战项目-宜居一_第69张图片

Css全局引用放在最外层,很多地方用到组件库

React从入门到实战- 企业级实战项目-宜居一_第70张图片

React从入门到实战- 企业级实战项目-宜居一_第71张图片

React从入门到实战- 企业级实战项目-宜居一_第72张图片

React从入门到实战- 企业级实战项目-宜居一_第73张图片

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'

ReactDOM.render(, document.getElementById('root'));

import React from 'react';
import { Button,Pagination } from 'antd';
// import Button from 'antd/es/button'; 
// import 'antd/es/button/style/css';
// import Pagination from 'antd/es/pagination'; 
// import 'antd/es/pagination/style/css';

function App() {

    function pageChange(page, pageSize){
        console.log(page, pageSize);
        // 网络请求
    }

    return (
        
); } export default App;

18.React Antd 按需加载

(React Antd 按需加载&)

React Antd 按需加载&

Antd按需加载

Antd库非常大,按需加载,手动引入

React从入门到实战- 企业级实战项目-宜居一_第74张图片

直接安装依赖修改文件,正常加载即可

React从入门到实战- 企业级实战项目-宜居一_第75张图片

没有webpack配置文件,被隐藏了

显示隐藏文件,删除git

React从入门到实战- 企业级实战项目-宜居一_第76张图片

安装之后npm start跑起来

React从入门到实战- 企业级实战项目-宜居一_第77张图片

之后就可以按需加载了

React从入门到实战- 企业级实战项目-宜居一_第78张图片

退出运行状态crtl+c  

    "babel": {
        "presets": [
            "react-app"
        ],
        "plugins": [
            [
                "import",
                {
                    "libraryName": "antd",
                    "libraryDirectory": "es",
                    "style": "css"
                }
            ]
        ]
    },
    "devDependencies": {
        "babel-plugin-import": "^1.12.2"
    }

19.React Antd 属性介绍

(React Antd 属性介绍&)

React Antd 属性介绍&

分页组件

React从入门到实战- 企业级实战项目-宜居一_第79张图片

React从入门到实战- 企业级实战项目-宜居一_第80张图片

分页做网络请求事件

React从入门到实战- 企业级实战项目-宜居一_第81张图片

import React from 'react';
import { Button,Pagination } from 'antd';
// import Button from 'antd/es/button'; 
// import 'antd/es/button/style/css';
// import Pagination from 'antd/es/pagination'; 
// import 'antd/es/pagination/style/css';

function App() {

    function pageChange(page, pageSize){
        console.log(page, pageSize);
        // 网络请求
    }

    return (
        
); } export default App;

(Fetch 网络请求&)

Fetch 网络请求

20.React Fetch get请求

(React Fetch get请求&)

React Fetch get请求&

Jsx有更好提示

重启识别

fetch基于promise

React从入门到实战- 企业级实战项目-宜居一_第82张图片

React从入门到实战- 企业级实战项目-宜居一_第83张图片

DidMount(),fetch网络请求地址,then()上一个return返回的数据

React从入门到实战- 企业级实战项目-宜居一_第84张图片

React从入门到实战- 企业级实战项目-宜居一_第85张图片

Res.JSON()代表返回

React从入门到实战- 企业级实战项目-宜居一_第86张图片

React从入门到实战- 企业级实战项目-宜居一_第87张图片

fetch的post请求封装

import React from 'react';
import qs from "querystring"
import ProxyDemo from "./ProxyDemo"
import api from "./api"

export default class App extends React.Component {

    constructor(props){
        super(props);
        this.state = {
            banners:[]
        }
    }

    componentDidMount(){

        /**
         * fetch 基于promise
         * 
         * https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch
         * 
         * get
         */

        fetch("http://iwenwiki.com/api/blueberrypai/getIndexBanner.php")
        .then(res => res.json())
        .then(data =>{
            this.setState({
                banners:data.banner
            })
        })

        /**
         * post
         * 
         * ajax:对象类型的参数
         * body:字符串类型
         */
        fetch("http://iwenwiki.com/api/blueberrypai/login.php",{
            method:"POST",
            headers:{
                'Content-Type': 'application/x-www-form-urlencoded',
                "Accept":"application/json,text/plain,*/*"
            },
            // 自己字符串拼接方法
            body:qs.stringify({
                user_id:"[email protected]",
                password:"iwen123",
                verification_code:"crfvw"
            })
            // body:"[email protected]&password=iwen123&verification_code=crfvw"
        }).then(res => res.json())
        .then(data =>{
            console.log(data);
        })


        api.getChengpin().then(res => res.json()).then(data =>{
            console.log(data);
        })

        api.getLogin({
            user_id:"[email protected]",
            password:"iwen123",
            verification_code:"crfvw"
        }).then(res => res.json()).then(data =>{
            console.log(data);
        })

    }

    render(){
        const { banners } = this.state;
        return(
            
{ banners.length > 0 ?
    { banners.map((element,index) =>{ return
  • { element.title }
  • }) }
:
等待数据加载...
}
) } }

21.React Fetch post请求

(React Fetch post请求&)

React Fetch post请求&

访问请求方式是post

React从入门到实战- 企业级实战项目-宜居一_第88张图片

Ajax是字符串类型

React从入门到实战- 企业级实战项目-宜居一_第89张图片

React从入门到实战- 企业级实战项目-宜居一_第90张图片

对象写法的qs

React从入门到实战- 企业级实战项目-宜居一_第91张图片

React从入门到实战- 企业级实战项目-宜居一_第92张图片

22.React Fetch 配置package文件解决跨域

(React Fetch 配置package文件解决跨域&)

React Fetch 配置package文件解决跨域&

React从入门到实战- 企业级实战项目-宜居一_第93张图片

Package.json增加proxy解决跨域

前面不需要了,已经被配置代替了

React从入门到实战- 企业级实战项目-宜居一_第94张图片

产生错误解决

React从入门到实战- 企业级实战项目-宜居一_第95张图片

修改配置文件Crtl+c退出运行状态重新运行

跨域解决方案,catch除以异常

import React from "react"

export default class ProxyDemo extends React.Component{

    /**
     * https://yunp.top/blog/index.php/2016/05/12/44/
     * 
     * http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.billboard.billList&type=1&size=10&offset=0
     */

     /**
      * 跨域的解决方案:
      *     开发模式下:
      *         利用环境解决:react  vue常用框架,都提供了解决方案
      *     生产模式下:
      *         jsonp cors  iframe postMessage...
      * 
      * 
      *     npm run build:打包 -> 生产模式
      */
    // https://github.com/facebook/create-react-app/blob/master/docusaurus/docs/proxying-api-requests-in-development.md

    componentDidMount(){
        // proxy:http://tingapi.ting.baidu.com
        // fetch("/v1/restserver/ting?method=baidu.ting.billboard.billList&type=1&size=10&offset=0")
        // .then(res => res.json())
        // .then(data =>{
        //     console.log(data);
        // })
        // // 失败了
        // .catch(error =>{
        //     console.log(new Error(error));
        // })

        // fetch("/api/list")
        // .then(res => res.json())
        // .then(data =>{
        //     console.log(data);
        // })
    }

    
    render(){
        return(
            
Hello
) } }

package.json

React从入门到实战- 企业级实战项目-宜居一_第96张图片

package.json

{
  "name": "react-fetch-demo",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "express": "^4.17.1",
    "http-proxy-middleware": "^0.20.0",
    "react": "^16.10.2",
    "react-dom": "^16.10.2",
    "react-scripts": "3.2.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

23.React Fetch 手动配置跨域

(React Fetch 手动配置跨域&)

React Fetch 手动配置跨域&

mock跨域

创建app对象,前台3000端口,后台3100端口

React从入门到实战- 企业级实战项目-宜居一_第97张图片

增加网络请求地址

React从入门到实战- 企业级实战项目-宜居一_第98张图片

App.use根路径与路由对象

React从入门到实战- 企业级实战项目-宜居一_第99张图片

开启新的窗口

React从入门到实战- 企业级实战项目-宜居一_第100张图片

React从入门到实战- 企业级实战项目-宜居一_第101张图片

前台不能访问3100后台,

React从入门到实战- 企业级实战项目-宜居一_第102张图片

手动配置跨域解决方案

React从入门到实战- 企业级实战项目-宜居一_第103张图片

React从入门到实战- 企业级实战项目-宜居一_第104张图片

访问服务器3100端口,通过api代替地址

React从入门到实战- 企业级实战项目-宜居一_第105张图片

开发中常用的方式

React从入门到实战- 企业级实战项目-宜居一_第106张图片

React从入门到实战- 企业级实战项目-宜居一_第107张图片

React从入门到实战- 企业级实战项目-宜居一_第108张图片

mock/index.js

const express = require("express")
const app = express();
const router = require("./router");

app.use("/",router);

app.listen(3100,function(){
    console.log("serve running at port 3000");
})

mock/router.js

const express = require("express");
const router = express.Router();


router.get("/api/list",(req,res) =>{
    res.send([
        {
            name:"iwen",
            age:20
        },
        {
            name:"ime",
            age:30
        }
    ])
})

module.exports = router;

React从入门到实战- 企业级实战项目-宜居一_第109张图片

React从入门到实战- 企业级实战项目-宜居一_第110张图片

src/setupProxy.js

// const proxy = require('http-proxy-middleware');

// module.exports = function (app) {
//     app.use(
//         '/api',
//         proxy({
//             target: 'http://localhost:3100',
//             changeOrigin: true,
//         })
//     );
// };

React从入门到实战- 企业级实战项目-宜居一_第111张图片

24.React Fetch 封装网络请求

(React Fetch 封装网络请求&)

React Fetch 封装网络请求&

封装网络请求,ctrl+c停止服务器

React从入门到实战- 企业级实战项目-宜居一_第112张图片

React从入门到实战- 企业级实战项目-宜居一_第113张图片

使用封装网络请求,base基础公共路径,chengpin是配置路径

React从入门到实战- 企业级实战项目-宜居一_第114张图片

导出api在任何地方都可以使用了

React从入门到实战- 企业级实战项目-宜居一_第115张图片

React从入门到实战- 企业级实战项目-宜居一_第116张图片

Params已经处理了

React从入门到实战- 企业级实战项目-宜居一_第117张图片

React从入门到实战- 企业级实战项目-宜居一_第118张图片

React从入门到实战- 企业级实战项目-宜居一_第119张图片

封装fetch网络请求

src/utils/http.js

/**
 * get  post
 */
import qs from "querystring"

export function httpGet(url){
    const result = fetch(url);
    return result;
}

export function httpPost(url,params){
    const result = fetch(url,{
        method:"POST",
        headers:{
            'Content-Type': 'application/x-www-form-urlencoded',
            "Accept":"application/json,text/plain,*/*"
        },
        /** 
         * {
         *  name:"iwen"
         * }
         * 
         * name=iwen
         */
        body:qs.stringify(params)
    })

    return result;
}

src/api/base.js

const base = {
    // http://iwenwiki.com/api/blueberrypai/getChengpinInfo.php
    ownUrl:"http://iwenwiki.com",
    chengpin:"/api/blueberrypai/getChengpinInfo.php",
    login:"/api/blueberrypai/login.php"
}

export default base

src/api/index.js

import { httpGet,httpPost } from "../utils/http"
import base from "./base"

/**
 * 有多少的网络请求,一次性就看到了
 * redux:action集中在一起
 */
const api = {
    getChengpin(){
        return httpGet(base.ownUrl + base.chengpin);
    },
    getLogin(params){
        return httpPost(base.ownUrl + base.login,params);
    }
}

export default api

React从入门到实战- 企业级实战项目-宜居一_第120张图片

(React-Router路由配置&)

React-Router路由配置&

25.React-Router 路由介绍

(React-Router 路由介绍&)

React-Router 路由介绍&

Route路由组件

React从入门到实战- 企业级实战项目-宜居一_第121张图片

通过不同路径展示不同页面,router对象切换不同页面,最外层用弩switch对象包裹

React从入门到实战- 企业级实战项目-宜居一_第122张图片

import React from "react"

export default class Home extends React.Component {
    render() {
        return (
            
Home
) } }
import React from "react"
import querystring from "querystring"
import MineDemo from "./MineDemo"

const Mine = (props) =>{
    // const params = new URLSearchParams(props.location.search)
    // console.log(params.get("name"));
    // console.log(params.get("age"));
    // const value = querystring.parse(props.location.search);
    // console.log(value);
    // console.log(value.name);
    // console.log(value.age);
   

    const clickHandle = () =>{
        // props.history.push("/");
        // push 叠加的上一次的页面依然存在内中, replace是替换,上一次的页面不存在了
        props.history.replace("/")
    }

    return(
        
Mine
) } export default Mine
import React from 'react';
import Home from "./pages/Home"
import Mine from "./pages/Mine"
import UCenter from "./pages/UCenter"
// import { BrowserRouter as Router, Route } from "react-router-dom";
import { HashRouter as Router, Route, Switch,Redirect } from "react-router-dom";
import Nav from "./components/Nav"
import NotFound from "./pages/NotFound"
import Demo from "./pages/Demo"
import Shop from "./pages/Shop"
import Book from "./pages/Book"

import WEBBook from "./pages/WEBBook"
import JavaBook from "./pages/JavaBook"
/**
 * HashRouter:锚点链接
 * BrowserRouter:h5新特性 / history.push   如果上线之后,需要后台做一些处理:重定向处理 404bug
 */

/**
 * /mine/ucenter  包含了 /mine
 * 
 */
function App() {
    return (
        
); } export default App;
import React from "react"
import { Link,NavLink } from "react-router-dom";
import "./style.css"

export default class Nav extends React.Component {
    render() {
        return (
            
) } }

26.React-Router BrowserRouter 与 HashRouter

(React-Router BrowserRouter 与 HashRouter&)

React-Router BrowserRouter 与 HashRouter&

history重定向404

#号后展示路由信息

#后面加路由

React从入门到实战- 企业级实战项目-宜居一_第123张图片

27.React-Router Link跳转

(React-Router Link跳转&)

React-Router Link跳转&

Link导航切换

导航点击跳转不同视图,Link实现页面跳转,to属性是一个路径

React从入门到实战- 企业级实战项目-宜居一_第124张图片

React从入门到实战- 企业级实战项目-宜居一_第125张图片

React从入门到实战- 企业级实战项目-宜居一_第126张图片

React从入门到实战- 企业级实战项目-宜居一_第127张图片

React从入门到实战- 企业级实战项目-宜居一_第128张图片

28.React-Router exact匹配规则

(React-Router exact匹配规则&)

React-Router exact匹配规则&

exact精准匹配

React从入门到实战- 企业级实战项目-宜居一_第129张图片

/mine/ucenter会显示mime和UCenter两个组件

React从入门到实战- 企业级实战项目-宜居一_第130张图片

精准匹配,不会匹配mime

React从入门到实战- 企业级实战项目-宜居一_第131张图片

简写

React从入门到实战- 企业级实战项目-宜居一_第132张图片

Home是根目录/

React从入门到实战- 企业级实战项目-宜居一_第133张图片

/路径都匹配,都会有Home

React从入门到实战- 企业级实战项目-宜居一_第134张图片

React从入门到实战- 企业级实战项目-宜居一_第135张图片

不会每一个都显示Home组件

React从入门到实战- 企业级实战项目-宜居一_第136张图片

import React from "react"

const UCenter = (props) =>{
    // http://localhost:3000/#/mine/ucenter/1001
    console.log(props);
    return(
        
Hello UCenter:{ props.match.params.id } - { props.match.params.name }
) } export default UCenter

29.React-Router strict精准匹配

(React-Router strict精准匹配&)

React-Router strict精准匹配&

strict严格匹配

后面不能跟/,有/不匹配,要和exact精准匹配一起使用

React从入门到实战- 企业级实战项目-宜居一_第137张图片

30.React-Router 404页面和Switch

(React-Router 404页面和Switch&)

React-Router 404页面和Switch&

404页面用户体验

React从入门到实战- 企业级实战项目-宜居一_第138张图片

直接加Component全规则匹配

React从入门到实战- 企业级实战项目-宜居一_第139张图片

Switch只加载一个页面,404不能和其他页面一起显示

React从入门到实战- 企业级实战项目-宜居一_第140张图片

import React from "react"

const NotFound = () =>{
    return(
        
404页面
) } export default NotFound

31.React-Router render func

(React-Router render func&)

React-Router render func&

简易Render加载组件

React从入门到实战- 企业级实战项目-宜居一_第141张图片

React从入门到实战- 企业级实战项目-宜居一_第142张图片

返回值是组件

React从入门到实战- 企业级实战项目-宜居一_第143张图片

传递数据三个点

接收参数

React从入门到实战- 企业级实战项目-宜居一_第144张图片

基本类型数据

React从入门到实战- 企业级实战项目-宜居一_第145张图片

简写

React从入门到实战- 企业级实战项目-宜居一_第146张图片

import React from "react"

const Demo = ({ name }) =>{
    return(
        
Demo:{ name }
) } export default Demo

32.React-Router NavLink高亮

(React-Router NavLink高亮&)

React-Router NavLink高亮&

不知道现在在哪个页面下的,高亮显示,替换为NavLink高亮,多了一个样式

React从入门到实战- 企业级实战项目-宜居一_第147张图片

路径的包裹,点击都变红色

React从入门到实战- 企业级实战项目-宜居一_第148张图片

不需要css属性

React从入门到实战- 企业级实战项目-宜居一_第149张图片

33.React-Router URL Parameters

(React-Router URL Parameters&)

React-Router URL Parameters&

路由跳转携带参数,/冒号后参数的key,跳转的页面就可以接收参数

React从入门到实战- 企业级实战项目-宜居一_第150张图片

斜杠传递值

React从入门到实战- 企业级实战项目-宜居一_第151张图片

根据参数地址不同拿到不同数据展示

?页面参数可有可无的

React从入门到实战- 企业级实战项目-宜居一_第152张图片

跳转参数携带值,/后面跟地址

路由跳转参数传递

import React from "react"

const UCenter = (props) =>{
    // http://localhost:3000/#/mine/ucenter/1001
    console.log(props);
    return(
        
Hello UCenter:{ props.match.params.id } - { props.match.params.name }
) } export default UCenter

34.React-Router query string读取参数

(React-Router query string读取参数&)

React-Router query string读取参数&

queryString获取?后参数的值

React从入门到实战- 企业级实战项目-宜居一_第153张图片

获取传递的name

React从入门到实战- 企业级实战项目-宜居一_第154张图片

取出整个对象,要手动去掉前面的?

React从入门到实战- 企业级实战项目-宜居一_第155张图片

URLSearchParams读取隐藏参数

import React from "react"
import querystring from "querystring"
import MineDemo from "./MineDemo"

const Mine = (props) =>{
    // const params = new URLSearchParams(props.location.search)
    // console.log(params.get("name"));
    // console.log(params.get("age"));
    // const value = querystring.parse(props.location.search);
    // console.log(value);
    // console.log(value.name);
    // console.log(value.age);
   

    const clickHandle = () =>{
        // props.history.push("/");
        // push 叠加的上一次的页面依然存在内中, replace是替换,上一次的页面不存在了
        props.history.replace("/")
    }

    return(
        
Mine
) } export default Mine

35.React-Router Link to- object

(React-Router Link to- object&)

React-Router Link to- object&

Pathname地址

React从入门到实战- 企业级实战项目-宜居一_第156张图片

增加Search与hash属性

Link属性

React从入门到实战- 企业级实战项目-宜居一_第157张图片

React从入门到实战- 企业级实战项目-宜居一_第158张图片

React从入门到实战- 企业级实战项目-宜居一_第159张图片

React从入门到实战- 企业级实战项目-宜居一_第160张图片

React从入门到实战- 企业级实战项目-宜居一_第161张图片

import React from "react"
import { Link,NavLink } from "react-router-dom";
import "./style.css"

export default class Nav extends React.Component {
    render() {
        return (
            
) } }

36.React-Router redirect重定向

(React-Router redirect重定向&)

React-Router redirect重定向&

Redirect重定向

React从入门到实战- 企业级实战项目-宜居一_第162张图片

访问hellomine跳转到mine

检查是否未登录

React从入门到实战- 企业级实战项目-宜居一_第163张图片

前面一定有/否则404

不能登录跳转其他页面,首页/

React从入门到实战- 企业级实战项目-宜居一_第164张图片

import React from 'react';
import Home from "./pages/Home"
import Mine from "./pages/Mine"
import UCenter from "./pages/UCenter"
// import { BrowserRouter as Router, Route } from "react-router-dom";
import { HashRouter as Router, Route, Switch,Redirect } from "react-router-dom";
import Nav from "./components/Nav"
import NotFound from "./pages/NotFound"
import Demo from "./pages/Demo"
import Shop from "./pages/Shop"
import Book from "./pages/Book"

import WEBBook from "./pages/WEBBook"
import JavaBook from "./pages/JavaBook"
/**
 * HashRouter:锚点链接
 * BrowserRouter:h5新特性 / history.push   如果上线之后,需要后台做一些处理:重定向处理 404bug
 */

/**
 * /mine/ucenter  包含了 /mine
 * 
 */
function App() {
    return (
        
); } export default App;
import React from "react"
import { Redirect,Prompt } from "react-router-dom"

export default class Shop extends React.Component{

    state = {
        isLogin:true,
        name:""
    }

    render(){
        const { isLogin } = this.state;
        return(
            
{ isLogin ?
Shop
: } this.setState({name:e.target.value}) }/>
) } }

37.React-Router 重定向push和replace

(React-Router 重定向push和replace&)

React-Router 重定向push和replace&

代码实现重定向,要用const定义

React从入门到实战- 企业级实战项目-宜居一_第165张图片

Push点击跳转的路径,push是叠加上一次页面依然存在内存中,replace也没不存在了

React从入门到实战- 企业级实战项目-宜居一_第166张图片

push与replace

import React from "react"
import querystring from "querystring"
import MineDemo from "./MineDemo"

const Mine = (props) =>{
    // const params = new URLSearchParams(props.location.search)
    // console.log(params.get("name"));
    // console.log(params.get("age"));
    // const value = querystring.parse(props.location.search);
    // console.log(value);
    // console.log(value.name);
    // console.log(value.age);
   

    const clickHandle = () =>{
        // props.history.push("/");
        // push 叠加的上一次的页面依然存在内中, replace是替换,上一次的页面不存在了
        props.history.replace("/")
    }

    return(
        
Mine
) } export default Mine

38.React-Router withRouter

(React-Router withRouter&)

React-Router withRouter&

要有this.props

withRouter

React从入门到实战- 企业级实战项目-宜居一_第167张图片

React从入门到实战- 企业级实战项目-宜居一_第168张图片

获取路由对象withRouter,就可以获得props了进行跳转

React从入门到实战- 企业级实战项目-宜居一_第169张图片

React从入门到实战- 企业级实战项目-宜居一_第170张图片

import React from "react"
import { withRouter } from "react-router-dom"

class MineDemo extends React.Component{

    clickHandle(){
        console.log(this.props);
        this.props.history.push("/")
    }

    // 当前组件没有直接被路由管理,所以没有路由对象
    // withRouter
    
    render(){
        return(
            
) } } // 高阶组件 export default withRouter(MineDemo)
import React from "react"
import querystring from "querystring"
import MineDemo from "./MineDemo"

const Mine = (props) =>{
    // const params = new URLSearchParams(props.location.search)
    // console.log(params.get("name"));
    // console.log(params.get("age"));
    // const value = querystring.parse(props.location.search);
    // console.log(value);
    // console.log(value.name);
    // console.log(value.age);
   

    const clickHandle = () =>{
        // props.history.push("/");
        // push 叠加的上一次的页面依然存在内中, replace是替换,上一次的页面不存在了
        props.history.replace("/")
    }

    return(
        
Mine
) } export default Mine

39.React-Router Prompt

(React-Router Prompt&)

React-Router Prompt&

Prompt导航离开页面之前做额外处理,不能白输入

React从入门到实战- 企业级实战项目-宜居一_第171张图片

判断是否存在,给用户提示

React从入门到实战- 企业级实战项目-宜居一_第172张图片

import React from "react"
import { Redirect,Prompt } from "react-router-dom"

export default class Shop extends React.Component{

    state = {
        isLogin:true,
        name:""
    }

    render(){
        const { isLogin } = this.state;
        return(
            
{ isLogin ?
Shop
: } this.setState({name:e.target.value}) }/>
) } }

40.React-Router 路由嵌套

(React-Router 路由嵌套&)

React-Router 路由嵌套&

React从入门到实战- 企业级实战项目-宜居一_第173张图片

注册路由中显示

React从入门到实战- 企业级实战项目-宜居一_第174张图片

嵌套成子元素,唯一化switch

React从入门到实战- 企业级实战项目-宜居一_第175张图片

页面没有显示JavaBook,定义规则显示页面位置,可以嵌套很多层

React从入门到实战- 企业级实战项目-宜居一_第176张图片

props.children路由嵌套

import React from "react"

export default class Book extends React.Component{
    render(){
        return(
            
Book: {/* 路由嵌套显示的位置 */} { this.props.children }
) } }
import React from "react"

export default class WebBook extends React.Component{
    render(){
        return(
            
WebBook
) } }
import React from "react"

export default class JavaBook extends React.Component{
    render(){
        return(
            
JavaBook
) } }

 

你可能感兴趣的:(项目案例,react)