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="width: 60px;"/>
          }
          <img src="" alt="" style={ { width: '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={ { width: '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="width: 60px;"/>
          }
          <img src="" alt="" style={ { width: '60px'} }/>
          <p>華為meta 30</p>
          <p>5999</p>
        </li>
        */
        }
        {
          this.props.prolist.map(item => (
            <li key={item.proid}>
              <img src={  item.proimg  } alt="" style={ { width: '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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM