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

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

(React基础知识&)

React基础知识&

1.React 学习前期准备

(React 学习前期准备&)

React 学习前期准备&

react环境

工程化,webpack安装node的npm

创建react项目

打开控制台

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

Public主入口文件,index与logo

Src源码文件,

Package.json当前依赖版本

2.React JSX语法

(React JSX语法&)

React JSX语法&

JSX基础语法

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

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

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

// document.getElementById('root')获取要插入的容器
// jsx语法:<h1>Hello React</h1>
// const react = "React";

// ():如果存在标签结构,并且标签结构要换行,需要用()括起来

// function tick(){
//     const element = (
//         <div>
//             <h1>Hello, world!</h1>
//             <h2>It is { new Date().toLocaleTimeString() }</h2>
//         </div>
//     )
//     ReactDOM.render(element, document.getElementById('root'));
// }
// setInterval(tick,1000);
ReactDOM.render(<App />, document.getElementById('root'));

3.React 元素渲染

(React 元素渲染&)

React 元素渲染&

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

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

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

{}渲染元素标签方法

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

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

React 组件基础之创建组件&

React组件创建

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

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

内容多增加小括号

连起来写法

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

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(
            <div>
                {/* <h1>Hello React Component</h1>
                <h3>学习React,最重要的是,心态要好!</h3>
                <Home />
                <MyNav nav={ nav1 } title="路径导航"/>
                <MyNav nav={ nav2 } title="学习导航"/> */}
                {/* <StateComponent /> */}
                {/* <ComponentLife title={ this.state.title } clickChanges={ this.clickChange }/> */}
                {/* <SetStateDemo /> */}
                {/* <IfDemo /> */}
                {/* <KeyDemo /> */}
                {/* <FormDemo /> */}
                {/* <RefsAndDOM /> */}
                {/* <RefsForm /> */}
                {/* <Parent /> */}
                {/* <Compose>
                    <div>我是组合效果</div>
                </Compose> */}
                <PropsTypeDemo title="标题"/>
            </div>
        )
    }
}

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(
            <div>
                Home  
                {/* <button onClick={ this.clickHandler.bind(this) }>按钮</button> */}
                {/* <button onClick={ this.clickHandler }>按钮</button> */}
                {/* <button onClick={ (e) => {this.clickHandler(e)}}>按钮</button> */}
                <ul>
                    {
                        names.map((element,index) => {
                            // return <li onClick={ this.clickHandler.bind(this,element) } key={index}>{ element }</li>
                            return <li onClick={ (e) => this.clickHandler(element, e) } key={index}>{ element }</li>
                        })
                    }
                </ul>
            </div>
        )
    }
}

5.React Props属性

(React Props属性&)

React Props属性&

props属性组件复用

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

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

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

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

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

一个组件传入多个数据

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

import React from "react"

// props不可以被修改
export default class MyNav extends React.Component{
    render(){
        return(
            <div>
                {/* jsx语法 */}
                <h3>{ this.props.title }</h3>
                <ul>
                    {
                        this.props.nav.map((element,index) =>{
                            return <li key={index}>{ element }</li>
                        })
                    }
                </ul>
            </div>
        )
    }
}

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

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

动态文本显示不同数据

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

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(
            <div>
                <h3>组件的State</h3>
                <p>{ this.state.count }</p>
                <button onClick={ this.increment.bind(this) }>增加</button>
                <button onClick={ this.decrement.bind(this) }>减少</button>
                <button onClick={ this.clickHandler }>关于this</button>
                <p>{ showView }</p>
            </div>
        )
    }
}

7.React 组件生命周期函数

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

React 组件生命周期函数&

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

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

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

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

Props发生改变执行componentWillReceiveProps,

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

先执行ComponentDid/WillMount

解构赋值直接读取值

点击修改执行Update

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

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

父组件接收子组件的数据

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(
            <div>
                生命周期函数:{ count } - { this.props.title }
                <button onClick={ this.changeHandler }>修改</button>
                <button onClick={ this.clickChange }>修改title</button>
            </div>
        )
    }
}
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(
            <div>
                {/* <h1>Hello React Component</h1>
                <h3>学习React,最重要的是,心态要好!</h3>
                <Home />
                <MyNav nav={ nav1 } title="路径导航"/>
                <MyNav nav={ nav2 } title="学习导航"/> */}
                {/* <StateComponent /> */}
                {/* <ComponentLife title={ this.state.title } clickChanges={ this.clickChange }/> */}
                {/* <SetStateDemo /> */}
                {/* <IfDemo /> */}
                {/* <KeyDemo /> */}
                {/* <FormDemo /> */}
                {/* <RefsAndDOM /> */}
                {/* <RefsForm /> */}
                {/* <Parent /> */}
                {/* <Compose>
                    <div>我是组合效果</div>
                </Compose> */}
                <PropsTypeDemo title="标题"/>
            </div>
        )
    }
}

export default App

8.React setState是同步还是异步

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

React setState是同步还是异步&

setState异步处理方案

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

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

同步实时获取

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

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

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

 

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(
            <div>
                setState同步还是异步问题
                <p>{ this.state.count }</p>
                <button onClick={ this.increment.bind(this) }>修改</button>
            </div>
        )
    }
}

9.React 条件渲染

(React 条件渲染&)

React 条件渲染&

条件渲染

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

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 ?
            <div>iwen</div> :
            <div>请登录</div>

        return (
            <div>
                条件渲染:{showView}
                <button onClick={this.clickHandler}>登录</button>
                {
                    names.length > 0 ?
                        <div>
                            {
                                names.map((element, index) => {
                                    return <p key={index}>{element}</p>
                                })
                            }
                        </div>
                        :
                        <div>请等待数据正在请求....</div>
                }
            </div>
        )
    }
}

10.React 列表渲染&key

(React 列表渲染&key&)

React 列表渲染&key&

map列表渲染key

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

二层遍历

Push一个对象

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

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

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(
            <div>
                <ul>
                    {
                        this.state.userinfo.map((element,index) =>{
                            return(
                                <li key={ index }>
                                    <span>{ element.name }</span>
                                    <span>{ element.age }</span>
                                    <span>{ element.sex }</span>
                                    <div>
                                        {
                                            element.jobs.map((childElement,childIndex) =>{
                                                return <span key={ childIndex }>{ childElement }</span>
                                            })
                                        }
                                    </div>
                                </li>
                            )
                        })
                    }
                </ul>
                <button onClick={ this.clickHandler }>添加数据</button>
            </div>
        )
    }
}

11.React 表单受控组件

(React 表单受控组件&)

React 表单受控组件&

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

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

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

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

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

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(
            <div>
                <form onSubmit={this.handleSubmit}>
                    <input type="text" value={ this.state.value } onChange={ this.onChangeHandler }/>
                    <input type="submit" value="提交"></input>
                </form>
            </div>
        )
    }
}

12.React Refs&DOM

(React Refs&DOM&)

React Refs&DOM&

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

获取div dom元素

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

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

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(
            <div>
                Refs和DOM
                <div ref={ this.HelloDiv }>
                    Hello
                </div>
            </div>
        )
    }
}

13.React 表单 非受控组件

(React 表单 非受控组件&)

React 表单 非受控组件&

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

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

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

有点不用每个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(
            <div>
                <input type="text" ref={ this.username }/>
                <input type="text" ref={ this.password }/>
                <button onClick={ this.clickHandler }>提交</button>
            </div>
        )
    }
}

14.React 状态提升

(React 状态提升&)

React 状态提升&

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

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

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

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

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(
            <div>
                <input type="text" value={ this.state.money } onChange={this.changeHandler.bind(this)} />
                <p>Parent</p>
                人民币:<Child1 money={ this.state.money }/>
                美元:<Child2 money={ this.state.money }/>
            </div>
        )
    }
}
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(
            <div>
                <p>{this.props.money}</p>
                <input type="text" value={ this.state.input1 } onChange={ this.changeHandler.bind(this) }/>
            </div>
        )
    }
}
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 (
            <div>
                <p>{this.props.money * 7}</p>
                <input type="text" value={ this.state.input2 } onChange={this.changeHandler.bind(this)} />
            </div>
        )
    }
}

15.React 组件组合

(React 组件组合&)

React 组件组合&

PropsType验证

组件引用的中间

读到组件间的div元素

import React from "react"

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

16.React PropsType验证

(React PropsType验证&)

React PropsType验证&

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

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

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

缺省默认props

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

export default class PropsTypeDemo extends React.Component{
    render(){
        return(
            <div>
                Hello:{ this.props.title }
            </div>
        )
    }
}

// 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组件库引入&

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

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(<App />, 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 (
        <div className="App">
            <Button type="primary">Primary</Button>
            <Button>Default</Button>
            <Button type="dashed">Dashed</Button>
            <Button type="danger">Danger</Button>
            <Button type="link">Link</Button>
            <Pagination showQuickJumper defaultCurrent={1} total={500} onChange={ pageChange }/>
        </div>
    );
}

export default App;

18.React Antd 按需加载

(React Antd 按需加载&)

React Antd 按需加载&

Antd按需加载

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

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

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

显示隐藏文件,删除git

安装之后npm start跑起来

之后就可以按需加载了

退出运行状态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 属性介绍&

分页组件

分页做网络请求事件

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 (
        <div className="App">
            <Button type="primary">Primary</Button>
            <Button>Default</Button>
            <Button type="dashed">Dashed</Button>
            <Button type="danger">Danger</Button>
            <Button type="link">Link</Button>
            <Pagination showQuickJumper defaultCurrent={1} total={500} onChange={ pageChange }/>
        </div>
    );
}

export default App;

(Fetch 网络请求&)

Fetch 网络请求

20.React Fetch get请求

(React Fetch get请求&)

React Fetch get请求&

Jsx有更好提示

重启识别

fetch基于promise

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

Res.JSON()代表返回

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:"iwen@qq.com",
                password:"iwen123",
                verification_code:"crfvw"
            })
            // body:"user_id=iwen@qq.com&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:"iwen@qq.com",
            password:"iwen123",
            verification_code:"crfvw"
        }).then(res => res.json()).then(data =>{
            console.log(data);
        })

    }

    render(){
        const { banners } = this.state;
        return(
            <div>
                {
                    banners.length > 0 ?
                    <ul>
                        {
                            banners.map((element,index) =>{
                                return <li key={index}> { element.title } </li>
                            })
                        }
                    </ul>
                    : <div>等待数据加载...</div>
                }
                <ProxyDemo />
            </div>
        )
    }
}

21.React Fetch post请求

(React Fetch post请求&)

React Fetch post请求&

访问请求方式是post

Ajax是字符串类型

对象写法的qs

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

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

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

Package.json增加proxy解决跨域

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

产生错误解决

修改配置文件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(
            <div>
                Hello
            </div>
        )
    }
}

package.json

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端口

增加网络请求地址

App.use根路径与路由对象

开启新的窗口

前台不能访问3100后台,

手动配置跨域解决方案

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

开发中常用的方式

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;

src/setupProxy.js

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

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

24.React Fetch 封装网络请求

(React Fetch 封装网络请求&)

React Fetch 封装网络请求&

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

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

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

Params已经处理了

封装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-Router路由配置&)

React-Router路由配置&

25.React-Router 路由介绍

(React-Router 路由介绍&)

React-Router 路由介绍&

Route路由组件

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

import React from "react"

export default class Home extends React.Component {
    render() {
        return (
            <div>Home</div>
        )
    }
}
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(
        <div>
            Mine
            <button onClick={ clickHandle }>回到Home页面</button>
            <MineDemo />
        </div>
    )
}

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 (
        <div className="App">
            <Router>
                <Nav />
                <Switch>
                    <Redirect from='/hellomine' to='/mine' />
                    <Route exact path="/" component={Home}></Route>
                    <Route strict exact path="/mine" component={Mine}></Route>
                    <Route strict exact path="/mine/ucenter/:id?/:name?" component={UCenter}></Route>
                    {/* <Route path="/demo" render={ () => <div>Hello Demo</div> }></Route> */}
                    <Route path="/demo" render={ (props) => <Demo {...props}  name="你好"/> }></Route>
                    <Route path="/shop" component={ Shop }></Route>
                    {/* <Route path="/book" component={ Book }></Route> */}
                    <Book>
                        <Switch>
                            <Route path="/book/webbook" component={ WEBBook}></Route>
                            <Route path="/book/javabook" component={ JavaBook}></Route>
                        </Switch>
                    </Book>
                    <Route component={ NotFound }></Route>
                </Switch>
            </Router>
        </div>
    );
}

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 (
            <div>
                <ul>
                    <li>
                        <NavLink activeClassName="selected" activeStyle={{ color:'red' }} exact to="/">Home页面</NavLink>
                        {/* <a href="#/home">Home页面</a> */}
                    </li>
                    <li>
                        {/* <NavLink activeClassName="selected" exact to="/mine">Mine页面</NavLink> */}
                        <NavLink
                            activeClassName="selected" 
                            exact
                            to={{
                                pathname:"/mine",
                                search: "?sort=name",
                                hash: "#the-hash",
                                state: { flag: 'flag' } // 隐形传递参数
                            }}
                        >Mine页面</NavLink>
                        {/* <a href="#/mine">Mine页面</a> */}
                    </li>
                    <li>
                        <NavLink activeClassName="selected" to="/mine/ucenter/1005/ime">UCenter页面</NavLink>
                    </li>
                </ul>
            </div>
        )
    }
}

26.React-Router BrowserRouter 与 HashRouter

(React-Router BrowserRouter 与 HashRouter&)

React-Router BrowserRouter 与 HashRouter&

history重定向404

#号后展示路由信息

#后面加路由

27.React-Router Link跳转

(React-Router Link跳转&)

React-Router Link跳转&

Link导航切换

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

28.React-Router exact匹配规则

(React-Router exact匹配规则&)

React-Router exact匹配规则&

exact精准匹配

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

精准匹配,不会匹配mime

简写

Home是根目录/

/路径都匹配,都会有Home

不会每一个都显示Home组件

import React from "react"

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

export default UCenter

29.React-Router strict精准匹配

(React-Router strict精准匹配&)

React-Router strict精准匹配&

strict严格匹配

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

30.React-Router 404页面和Switch

(React-Router 404页面和Switch&)

React-Router 404页面和Switch&

404页面用户体验

直接加Component全规则匹配

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

import React from "react"

const NotFound = () =>{
    return(
        <div>
            404页面
        </div>
    )
}

export default NotFound

31.React-Router render func

(React-Router render func&)

React-Router render func&

简易Render加载组件

返回值是组件

传递数据三个点

接收参数

基本类型数据

简写

import React from "react"

const Demo = ({ name }) =>{
    return(
        <div>
            Demo:{ name }
        </div>
    )
}

export default Demo

32.React-Router NavLink高亮

(React-Router NavLink高亮&)

React-Router NavLink高亮&

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

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

不需要css属性

33.React-Router URL Parameters

(React-Router URL Parameters&)

React-Router URL Parameters&

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

斜杠传递值

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

?页面参数可有可无的

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

路由跳转参数传递

import React from "react"

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

export default UCenter

34.React-Router query string读取参数

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

React-Router query string读取参数&

queryString获取?后参数的值

获取传递的name

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

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(
        <div>
            Mine
            <button onClick={ clickHandle }>回到Home页面</button>
            <MineDemo />
        </div>
    )
}

export default Mine

35.React-Router Link to- object

(React-Router Link to- object&)

React-Router Link to- object&

Pathname地址

增加Search与hash属性

Link属性

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

export default class Nav extends React.Component {
    render() {
        return (
            <div>
                <ul>
                    <li>
                        <NavLink activeClassName="selected" activeStyle={{ color:'red' }} exact to="/">Home页面</NavLink>
                        {/* <a href="#/home">Home页面</a> */}
                    </li>
                    <li>
                        {/* <NavLink activeClassName="selected" exact to="/mine">Mine页面</NavLink> */}
                        <NavLink
                            activeClassName="selected" 
                            exact
                            to={{
                                pathname:"/mine",
                                search: "?sort=name",
                                hash: "#the-hash",
                                state: { flag: 'flag' } // 隐形传递参数
                            }}
                        >Mine页面</NavLink>
                        {/* <a href="#/mine">Mine页面</a> */}
                    </li>
                    <li>
                        <NavLink activeClassName="selected" to="/mine/ucenter/1005/ime">UCenter页面</NavLink>
                    </li>
                </ul>
            </div>
        )
    }
}

36.React-Router redirect重定向

(React-Router redirect重定向&)

React-Router redirect重定向&

Redirect重定向

访问hellomine跳转到mine

检查是否未登录

前面一定有/否则404

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

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 (
        <div className="App">
            <Router>
                <Nav />
                <Switch>
                    <Redirect from='/hellomine' to='/mine' />
                    <Route exact path="/" component={Home}></Route>
                    <Route strict exact path="/mine" component={Mine}></Route>
                    <Route strict exact path="/mine/ucenter/:id?/:name?" component={UCenter}></Route>
                    {/* <Route path="/demo" render={ () => <div>Hello Demo</div> }></Route> */}
                    <Route path="/demo" render={ (props) => <Demo {...props}  name="你好"/> }></Route>
                    <Route path="/shop" component={ Shop }></Route>
                    {/* <Route path="/book" component={ Book }></Route> */}
                    <Book>
                        <Switch>
                            <Route path="/book/webbook" component={ WEBBook}></Route>
                            <Route path="/book/javabook" component={ JavaBook}></Route>
                        </Switch>
                    </Book>
                    <Route component={ NotFound }></Route>
                </Switch>
            </Router>
        </div>
    );
}

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(
            <div>
                {
                    isLogin ?
                    <div>Shop</div>
                    : <Redirect to="/" />
                }
                <Prompt 
                    when={ !!this.state.name }
                    message={  '确定要离开么?' }
                />
                <input type="text" value={this.state.name} onChange={ (e) => this.setState({name:e.target.value}) }/>
            </div>
        )
    }
}

37.React-Router 重定向push和replace

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

React-Router 重定向push和replace&

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

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

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(
        <div>
            Mine
            <button onClick={ clickHandle }>回到Home页面</button>
            <MineDemo />
        </div>
    )
}

export default Mine

38.React-Router withRouter

(React-Router withRouter&)

React-Router withRouter&

要有this.props

withRouter

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

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(
            <div>
                <button onClick={ this.clickHandle.bind(this) }>回到Home</button>
            </div>
        )
    }
}

// 高阶组件
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(
        <div>
            Mine
            <button onClick={ clickHandle }>回到Home页面</button>
            <MineDemo />
        </div>
    )
}

export default Mine

39.React-Router Prompt

(React-Router Prompt&)

React-Router Prompt&

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

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

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(
            <div>
                {
                    isLogin ?
                    <div>Shop</div>
                    : <Redirect to="/" />
                }
                <Prompt 
                    when={ !!this.state.name }
                    message={  '确定要离开么?' }
                />
                <input type="text" value={this.state.name} onChange={ (e) => this.setState({name:e.target.value}) }/>
            </div>
        )
    }
}

40.React-Router 路由嵌套

(React-Router 路由嵌套&)

React-Router 路由嵌套&

注册路由中显示

嵌套成子元素,唯一化switch

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

props.children路由嵌套

import React from "react"

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

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

export default class JavaBook extends React.Component{
    render(){
        return(
            <div>
                JavaBook
            </div>
        )
    }
}

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wespten

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值