• react中自定义函数、生命周期钩子函数、修改状态、组件、组件传值


    1、回顾

    2、自定义函数

    事件的首字母大小 onclick ==> onClick onchange ==> onChange

    • 普通的点击事件 ---- 调用事件不加(),加了立即执行
    import React, { Component } from 'react';
    
    export default class extends Component {
      constructor (props) {
        super(props);
        this.state = {
        }
      }
    
      test () {
        console.log('按钮被点击了')
      }
    
      render () {
        return (
          <div>
            <button onClick={ this.test }>按钮点击事件</button>
          </div>
        )
      }
    }
    
    • 事件对象 --- 自定义事件内有默认的参数 event
    import React, { Component } from 'react';
    
    export default class extends Component {
      constructor (props) {
        super(props);
        this.state = {
        }
      }
    
      test (event) { // ++++++++++++++++++++++++
        console.log('按钮被点击了', event)
      }
    
      render () {
        return (
          <div>
            <button onClick={ this.test }>按钮点击事件</button>
          </div>
        )
      }
    }
    
    • 如果想要在事件内部使用this --- 构造函数内部添加新的方法
    import React, { Component } from 'react';
    
    export default class extends Component {
      constructor (props) {
        super(props);
        // 2.给当前的实例添加一个方法,这个方法其实就是自定义的函数,给自定义的函数绑定this,就可以在自定义的函数内部访问this
        this.testfn = this.test.bind(this); 
        this.state = {
        }
      }
    
      test () {
        console.log('按钮被点击了', this) // 1.默认this为未定义,需要改变this指向
      }
    
      render () {
        return (
          <div>
            <button onClick={ this.testfn }>按钮点击事件</button>
          </div>
        )
      }
    }
    
    • 如果想要在事件内部使用this --- 只是改变this指向 --- 推荐
    import React, { Component } from 'react';
    
    export default class extends Component {
      constructor (props) {
        super(props);
        this.state = {
        }
      }
    
      test () {
        console.log('按钮被点击了', this) // 1.默认this为未定义,需要改变this指向
      }
    
      render () {
        return (
          <div>
          {
            // 2、onClick={ this.test.bind(this) } --- 只是改变this指向
          }
            <button onClick={ this.test.bind(this) }>按钮点击事件</button>
          </div>
        )
      }
    }
    
    • 事件传参
    import React, { Component } from 'react';
    
    export default class extends Component {
      constructor (props) {
        super(props);
        this.state = {
        }
      }
    
      test (str) {
        console.log('按钮被点击了', this) // 1.默认this为未定义,需要改变this指向
        console.log(str)
      }
    
      render () {
        return (
          <div>
          {
            // 2、this.test.bind(this, '111111')
          }
            <button onClick={ this.test.bind(this, '111111') }>按钮点击事件</button>
          </div>
        )
      }
    }
    

    3 生命周期钩子函数

    • vue: create / mount / update / destroy

    稳定版本,部分需要废除的生命周期钩子函数

    • 初始化阶段

      constructor () // 初始化数据

      componentWillMount () // 老以前(15版本)请求数据,现在基本废除,17版本无用

      render () // 必不可少 ---- 初次装载数据

      componentDidMount () // 请求数据,DOM操作 --- 等同于vue的mounted

    • 运行时阶段

      componentWillReceiveProps () //监听数据,现在基本废除,17版本无用

      shouldComponentUpdate () // 默认返回为true --- 提升react性能的关键

      componentWillUpdate () // 现在基本废除,17版本无用

      render () // 必不可少 ---- 重现渲染视图

      componentDidUpdate () // DOM操作 ----- 等同于vue的updated --- 不建议请求数据

    • 销毁阶段

      componentWillUnmount () // 组件销毁 --- 类似于vue的beforeDestroy

    新版的生命周期

    • 初始化阶段

      constructor ()

      static getDerivedStateFromProps () // 在初始安装和后续更新上都在调用render方法之前立即调用。它应该返回一个对象以更新状态,或者返回null则不更新任何内容。https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

      render ()

      componentDidMount ()

    • 运行时阶段

      static getDerivedStateFromProps ()

      shouldComponentUpdate ()

      render ()

      getSnapshotBeforeUpdate() // 在最近渲染的输出提交到DOM之前立即调用

      componentDidUpdate ()

    • 销毁阶段

      componentWillUnmount ()

    • 错误处理

      static getDerivedStateFromError()

      componentDidCatch()

    4 修改状态 + 生命周期

    this.setState()

    import React, { Component } from 'react';
    import axios from 'axios';
    export default class extends Component {
      constructor (props) {
        super(props);
        this.state = {
          prolist: []
        }
      }
      // +++++++++++++++++++++++++++++
      componentDidMount () {
        // 请求数据
        axios.get('/api/pro').then(res => {
          // 修改状态
          this.setState({
            prolist: res.data.data
          })
        })
      }
    
      render () {
        let { prolist } = this.state
        return (
          <div>
            {
              prolist.map(item => (
                <p key = { item.proid }> { item.proname } - { item.price } </p>
              ))
            }
          </div>
        )
      }
    }
    

    5、运行命令区分webpack的环境

    cnpm i cross-env -D

    • 配置package.json的scripts选项
     "scripts": {
        "dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js",
        "build": "cross-env NODE_ENV=production webpack --config webpack.config.js"
      },
    
    • 配置webpack的插件plugins
    const isDev = process.env.NODE_ENV =='development'
    
    plugins: [ // 添加插件 ---- 数组
      new webpack.optimize.UglifyJsPlugin(), // 压缩js文件
      new webpack.DefinePlugin({ // ++++++++++++++++++
        'process.env': {
          NODE_ENV: isDev ? '"development"' : '"production"'
        }
      }),
      new HtmlWebPackPlugin({ // 实例化一个 html 的webpack的插件
        template: 'index.html' // 找的就是当前文件夹下的index.html文件
      })
    ],
    

    6、数据请求封装

    • utils/request.js 自定义axios
    // 1、引入axios模块
    import axios from 'axios';
    
    // 2、判断是什么环境 -- 开发环境 -- 生产环境
    // 真  ----   开发环境 ---- 反向代理
    // 假  ----   生产环境
    const isDev = process.env.NODE_ENV === 'development'
    
    // 3、自定义axios
    let request = axios.create({
      // 基础的请求地址
      baseURL: isDev ? '/api' : 'http://47.92.152.70'
    })
    
    // 4、给所有的请求添加头信息
    // request.defaults.headers['token'] = localStorage.getItem('token')
    
    // 4、使用axios的拦截器  ----  请求的拦截器  +  响应的拦截器
    // http://www.axios-js.com/zh-cn/docs/#%E6%8B%A6%E6%88%AA%E5%99%A8
    
    // 添加请求拦截器
    request.interceptors.request.use(function (config) {
      // 在发送请求之前做些什么
      // 所有的请求都需要的字段,所有的请求添加loading效果
      // token
      config.headers['token'] = localStorage.getItem('token')
      return config;
    });
    
    // 添加响应拦截器
    request.interceptors.response.use(function (response) {
      // 对响应数据做点什么
      // 消除请求的loading效果
      return response;
    });
    
    // 5、暴露axios模块
    export default request;
    
    
    • utils/api.js 用来封装请求的接口
    // 1、引入自定义的axios
    import request from './request';
    
    // 2、封装接口
    
    /**
     * 封装 数据列表的接口
     * pageCode 页面
     * limitNum 每页显示个数
     */
    const getProlist = (pageCode, limitNum) => {
      pageCode = pageCode * 1 || 0;
      limitNum = limitNum * 1 || 10;
      // 使用promise解决异步问题
      return new Promise((resolve) => {
        // 因为自定义的axios包含baseUrl,此处只需要写后面的接口即可
        request.get('/pro', { params: { pageCode, limitNum} }).then(res => {
          resolve(res.data)
        })
      })
    }
    
    /**
     * 请求轮播图接口
     * type 哪一个类型的轮播图 home / kind / activity 
     */
    
    const getBannerlist = (type) => {
      type = type || 'home';
      return new Promise((resolve) => {
        request.get('/banner', { params: { type }}).then(res => {
          resolve(res.data)
        })
      })
    }
    
    // 3、暴露接口
    export {
      getProlist,
      getBannerlist
    }
    
    

    7 组件

    • App.js 为父组件
    import React, { Component } from 'react'
    import { getBannerlist, getProlist } from '@/utils/api';
    import Prolist from './Prolist'; // +++++++++++++++++++++++++++++
    export default class extends Component {
      constructor (props) {
        super(props);
        this.state = {
          bannerlist: [],
          prolist: []
        }
      }
    
      componentDidMount () {
        getBannerlist().then(data => {
          this.setState({
            bannerlist: data.data
          })
        })
        getProlist().then(data => {
          this.setState({
            prolist: data.data
          })
        })
      }
    
      render () {
        return (
          <div>
            <ul>
              { this.state.bannerlist.map(item => (
                <li key={item.bannerid }>{ item.img }</li>
              ))}
            </ul>
            { 
              // +++++++++++++++++++++++++++++++++++
            }
            <Prolist />
          </div>
        )
      }
    }
    
    
    • Prolist.js 为子组件 ------ jsx中的行内样式遵循 js 样式的写法,外加react的{}
    import React, { Component } from 'react';
    
    export default class extends Component {
      render () {
        return (
          <ul>
            <li>
              {
                // <img src="" alt="" style=" 60px;"/>
              }
              <img src="" alt="" style={ {  '60px'} }/>
              <p>华为meta 30</p>
              <p>5999</p>
            </li>
          </ul>
        )
      }
    }
    

    8 父组件给子组件传值

    App.js为父组件 Prolist.js 为子组件

    • 父组件给子组件传值

    父组件在调用子组件的地方,添加一个自定义的属性,属性的值就是要传递给子组件的值,如果传递的值是变量,boolean,number类型,需要使用到react的{}

    <Prolist prolist={ this.state.prolist }/>
    

    在子组件中,可以通过this.props访问到父组件传递给子组件的数据,在哪里拿数据取决于哪里使用数据,子组件渲染数据

    import React, { Component } from 'react';
    
    export default class extends Component {
      render () {
        console.log(this.props)
        return (
          <ul>
            {
              this.props.prolist.map(item => (
                <li key={item.proid}>
                  <img src={  item.proimg  } alt="" style={ {  '60px'} }/>
                  <p>{ item.proname }</p>
                  <p>{ item.price }</p>
                </li>
              ))
            }
          </ul>
        )
      }
    }
    

    如果需要验证父组件传递的数据的数据类型

    react15.5之后类型的校验在第三方模块 prop-types中

    cnpm i prop-types -S

    子组件中验证组件中的数据类型

    bool, array, func, number, object, string symbol, node, element

    import React, { Component } from 'react';
    import PropTypes from 'prop-types'; // ++++++++++++++++++++++
    class Com extends Component {
      render () {
        console.log(this.props)
        return (
          <ul>
            {
              /*
              <li>
              {
                // <img src="" alt="" style=" 60px;"/>
              }
              <img src="" alt="" style={ {  '60px'} }/>
              <p>华为meta 30</p>
              <p>5999</p>
            </li>
            */
            }
            {
              this.props.prolist.map(item => (
                <li key={item.proid}>
                  <img src={  item.proimg  } alt="" style={ {  '60px'} }/>
                  <p>{ item.proname }</p>
                  <p>{ item.price }</p>
                </li>
              ))
            }
          </ul>
        )
      }
    }
    // +++++++++++++++++++
    Com.propTypes = {
      prolist: PropTypes.array
    }
    
    export default Com
    

    9、子组件给父组件传值

    子组件给父组件传值,实际上就是父组件给子组件传递了自定义的属性,这个属性的值是一个函数,父组件定义这个函数,子组件调用这个函数,一定要记得this指向问题

    子组件

    import React, { Component } from 'react';
    
    // class Com extends Component {
    //   sendData () { // ++++++++++++++
    //     console.log(this.props) // 记得改变this指向,{fn: function()}
    //     this.props.fn('我是子组件')
    //   }
    
    //   render () {
    //     return (
    //       <div>
    //         <button onClick={ this.sendData.bind(this) }>给父组件传值</button>
    //       </div>
    //     )
    //   }
    // }
    
    class Com extends Component {
      render () {
        return (
          <div>
            <button onClick={ () => {
              // +++++++++++++++++++++++
              this.props.fn('222222222222')
            } }>给父组件传值</button>
          </div>
        )
      }
    }
    
    export default Com;
    
    

    父组件

    import React, { Component } from 'react'
    import Child from './Child';
    export default class extends Component {
      constructor (props) {
        super(props);
        this.state = {
        }
      }
    
      getData (str) { // +++++++++++++++++++++++++++
        console.log(str)
      }
    
      render () {
        return (
          <div>
            {
              // ++++++++++++++++++++++ fn 
            }
            <Child fn={ this.getData.bind(this) }/>
          </div>
        )
      }
    }
    

    10、react的脚手架

    create-react-app

    • 1、安装脚手架

      cnpm i create-react-app -g

      create-react-app myapp

    • 2、 不安装脚手架 使用 npx ---- node 8.9以上自动就有

      npx create-react-app myapp (用这个创建项目)

    • 3、 使用dva 创建react项目 --- dva/cli

      cnpm install dva-cli -g

      dva new myapp

  • 相关阅读:
    Android图表库hellocharts详解
    Android 高德地图使用小记
    java getSource()和 getActionCommand()区别
    Foreign websites
    通过自动回复机器人学Mybatis:OGNL+log4j.properties
    通过自动回复机器人学Mybatis:搭建核心架构
    通过自动回复机器人学Mybatis:代码重构(分层)
    通过自动回复机器人学Mybatis:原始版本(包括JDBC、pom.xml等)
    给JSP应用提供JSTL支持(IntelliJ IDEA)
    【Head First Servlets and JSP】笔记24:include指令与include动作 & param动作 & foward动作
  • 原文地址:https://www.cnblogs.com/hy96/p/11891133.html
Copyright © 2020-2023  润新知