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

react中自定义函数、生命周期钩子函数、修改状态、组件、组件传值的更多相关文章

  1. 关于 vue 生命周期 钩子函数 事件

    vue实例有一个完整的生命周期,也就是从开始创建.初始化数据.编译模板.挂载Dom.渲染->更新->渲染.卸载等一系列过程,我们称这是vue的生命周期. 通俗的将就是vue实例从创建到销毁 ...

  2. vue之生命周期钩子函数之运用

    一.什么是生命周期钩子函数: 每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听.编译模板.将实例挂载到 DOM 并在数据变化时更新 DOM 等.同时在这个过程中也会运行 ...

  3. Vue生命周期 钩子函数和组件传值

    Vue生命周期 钩子函数 每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听.编译模板.将实例挂载到 DOM 并在数据变化时更新 DOM 等. 同时在这个过程中也会运行一 ...

  4. 了解angularjs中的生命周期钩子函数$onInit,$onChange,$onDestory,$postLink

     壹 ❀ 引 我在前面花了三篇文章用于介绍angularjs的指令directive,组件component,并专门花了一篇文章介绍directive与component的不同,其中提到在compon ...

  5. 对vue生命周期/钩子函数的理解

    对于实现页面逻辑交互等效果,我们必须知晓vue的生命周期,才能愉快的玩耍,知道我们写的东西应该挂载到哪里,vue官方给出的api讲解的那叫一个简单啊,如下: 所有的生命周期钩子自动绑定this上下文到 ...

  6. VueRouter和Vue生命周期(钩子函数)

    一.vue-router路由 1.介绍 vue-router是Vue的路由系统,用于定位资源的,在页面不刷新的情况下切换页面内容.类似于a标签,实际上在页面上展示出来的也是a标签,是锚点.router ...

  7. vue生命周期 钩子函数

    首先,1.x和2.x的生命周期钩子对比: 钩子函数的树状图,红色的是我们可以利用的函数,绿色的是函数解析,蓝色的是函数执行时机 <!DOCTYPE html> <html> & ...

  8. Vue 2.0 生命周期-钩子函数理解

    Vue 2.0 + 生命周期钩子在项目过程中经常用到,所以闲下来整理了下,直接复制下面的实例运行: <!DOCTYPE html> <html lang="en" ...

  9. 什么是vue生命周期和生命周期钩子函数?

    原文地址 vue生命周期简介 咱们从上图可以很明显的看出现在vue2.0都包括了哪些生命周期的函数了. 生命周期探究 对于执行顺序和什么时候执行,看上面两个图基本有个了解了.下面我们将结合代码去看看钩 ...

  10. VueAPI 2 (生命周期钩子函数)

    所有的生命周期钩子自动绑定 this 上下文到实例中,因此你可以访问数据,对属性和方法进行运算.这意味着你不能使用箭头函数来定义一个生命周期方法. beforeCreate 在实例初始化之后,此时还不 ...

随机推荐

  1. Android---mediaplayer 创建和调用顺序

    Android mediaframework创建mediaplayer // java层 ///frameworks/base/media/java/android/media/MediaPlayer ...

  2. Mac截网页长屏的方法-谷歌浏览器

    打开chrome,左上角帮助,输入[开发者工具],回车,右边显示出一些html代码, 然后shift+command+p: 输入full,选择第一个capture full size screensh ...

  3. docker build提示 error checking context:can't stat xxx

    这个提示基本是权限不够外加目录结构不对,保险的做法直接删除 Dockerfile. 正确做法:(可能还有其他的解决方案吧,这个可以生效) 重新建个目录,给目录授权,然后再dockerfile文件夹中建 ...

  4. idea中 .gitignore文件的使用

    idea中 .gitignore文件的使用 首先保证当前的所有文件都没有被git追踪 如果被追踪,建议先取消git的版本控制 输入如下指令 find . -name ".git" ...

  5. Monterey 12.3 I225-V有线网卡导致死机或无法使用问题

    问题:升级Monterey12.3后启动到桌面死机 解决方法: 1.关闭/去掉所有有线网卡驱动.补丁.网卡设备ID注入: 2.启动命令中加入:dk.e1000=0: 3.启动不死机后,进入网络设置,手 ...

  6. XML_DOM4J_20200415

    package com.wy.xml; import java.io.File;import java.util.Iterator; import org.dom4j.Attribute; impor ...

  7. 估计人数【最小路径重复点覆盖】【直接在(i,j)建一个新点】

    估计人数 题意 思路 用最少的人,走完这几条线.最小重复路径点覆盖问题 建图之后,跑一下二分图. 考虑建图:图中'1'连着完下.或者右走.我们把图中所有的1编号,然后建图,然后floly,然后匈牙利. ...

  8. Matlab %伍

    第五章:初级绘图进阶 Special Plots  loglog semilogx semilogy plotyy hist bar pie polar Logarithm Plots  x = lo ...

  9. 转发:基于Lerna打造多包管理最佳实践之道

    最近在看vue-cli的源码部分,注意到这一个仓库下维护了多个package,很好奇他是如何在一个repo中管理这些package的. 我们组现在也在使用组件库的方式维护项目间共用的业务代码.有两个组 ...

  10. MySQL 导出数据结构 If you don't want to restore GTIDs, pass --set-gtid-purged=OFF.

    应用场景MYSQL导出数据结构 Warning: A partial dump from a server that has GTIDs will by default include the GTI ...