React 笔记 3

编程入门 行业动态 更新时间:2024-10-07 14:32:57

React <a href=https://www.elefans.com/category/jswz/34/1770047.html style=笔记 3"/>

React 笔记 3

import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.css';
import PropTypes from 'prop-types';class Vote extends React.Component {//=>组件传递的属性是只读的,我们为其设置默认值和相关规则static defaultProps = {};static propTypes = {title: PropTypes.string.isRequired};constructor(props) {super(props);//=>INIT STATEthis.state = {n: 0,//=>支持人数m: 0 //=>反对人数};}render() {let {n, m} = this.state,rate = (n + m) === 0 ? '0%' : ((n / (n + m) * 100).toFixed(2) + '%');return <section className='panel panel-default' style={{width: '60%', margin: '20px auto'}}><div className='panel-heading'><h3 className='panel-title'>{this.props.title}</h3></div><div className='panel-body'>支持人数:{n}<br/><br/>反对人数:{m}<br/><br/>支持率:{rate}</div><div className='panel-footer'><button className='btn btn-success'onClick={this.support}>支持</button>&nbsp;&nbsp;&nbsp;&nbsp;<button className='btn btn-danger'onClick={this.against}>反对</button></div></section>;}//=>投票:支持&&反对support = ev => this.setState({n: this.state.n + 1});against = ev => this.setState({m: this.state.m + 1});
}ReactDOM.render(<main><Vote title='世界杯小组赛法国VS秘鲁,法国队必胜!'/><Vote title='世界杯小组赛阿根廷VS克罗地亚,壮哉我大梅西!'/>
</main>, root);

JSX中的事件绑定:

  render(){return <button className='btn btn-success'onClick={this.support}>支持</button>;}support(ev){//=>THIS:undefined(不是我们理解的当前操作的元素)//=>ev.target:通过事件源可以获取当前操作的元素(一般很少操作,因为框架主要是数据驱动所有DOM的改变)}

如果能让方法中的THIS变成当前类的实例就好了,这样可以操作属性和状态等信息

  render(){//=>THIS:实例return <button className='btn btn-success'onClick={this.support.bind(this)}>支持</button>;}support(ev){//=>THIS:实例}
  render(){//=>THIS:实例return <button className='btn btn-success'onClick={this.support}>支持</button>;}support=ev=>{//=>THIS:继承上下文中的THIS(实例), 真实项目中,给JSX元素绑定的事件方法一般都是箭头函数,目的是为了保证函数中的THIS还是实例}

         * REFS:是REACT中专门提供通过操作DOM来实现需求的方式,它是一个对象,存储了当前组件中所有设置REF属性的元素(元素REF属性值是啥,REFS中存储的元素的属性名就是啥)

import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.css';
import PropTypes from 'prop-types';class Vote extends React.Component {//=>组件传递的属性是只读的,我们为其设置默认值和相关规则static defaultProps = {};static propTypes = {title: PropTypes.string.isRequired};constructor(props) {super(props);}render() {return <section className='panel panel-default' style={{width: '60%', margin: '20px auto'}}><div className='panel-heading'><h3 className='panel-title'>{this.props.title}</h3></div><div className='panel-body'>支持人数:<span ref='spanLeft'>0</span><br/><br/>反对人数:<span ref='spanRight'>0</span><br/><br/>支持率:<span ref='spanRate'>0</span></div><div className='panel-footer'><button className='btn btn-success'onClick={this.support}>支持</button>&nbsp;&nbsp;&nbsp;&nbsp;<button className='btn btn-danger'onClick={this.against}>反对</button></div></section>;}//=>投票:支持&&反对support = ev => {/!** REFS:是REACT中专门提供通过操作DOM来实现需求的方式,它是一个对象,存储了当前组件中所有设置REF属性的元素(元素REF属性值是啥,REFS中存储的元素的属性名就是啥)* {*    spanLeft:span*    ...* }*!/let {spanLeft} = this.refs;spanLeft.innerHTML++;thisputed();};against = ev => {let {spanRight} = this.refs;spanRight.innerHTML++;thisputed();};computed = () => {let {spanLeft, spanRight, spanRate} = this.refs,n = parseFloat(spanLeft.innerHTML),m = parseFloat(spanRight.innerHTML),rate = (n + m) === 0 ? '0%' : ((n / (n + m) * 100).toFixed(2) + '%');spanRate.innerHTML = rate;};
}

                {/*
                  * ref='spanLeft'
                  *   是在当前实例上挂载一个属性refs(对象),存储所有的ref元素
                  *
                  * x => this.spanLeft = x
                  *   x代表当前元素,它的意思是,把当前元素直接挂载到实例上,后期需要用到元素,直接this.spanLeft获取即可
                  */} 

class Vote extends React.Component {//=>组件传递的属性是只读的,我们为其设置默认值和相关规则static defaultProps = {};static propTypes = {title: PropTypes.string.isRequired};constructor(props) {super(props);}render() {return <section className='panel panel-default' style={{width: '60%', margin: '20px auto'}}><div className='panel-heading'><h3 className='panel-title'>{this.props.title}</h3></div><div className='panel-body'>{/** ref='spanLeft'*   是在当前实例上挂载一个属性refs(对象),存储所有的ref元素** x => this.spanLeft = x*   x代表当前元素,它的意思是,把当前元素直接挂载到实例上,后期需要用到元素,直接this.spanLeft获取即可*/}支持人数:<span ref={x => this.spanLeft = x}>0</span><br/><br/>反对人数:<span ref={x => this.spanRight = x}>0</span><br/><br/>支持率:<span ref={x => this.spanRate = x}>0%</span></div><div className='panel-footer'><button className='btn btn-success'onClick={this.support}>支持</button>&nbsp;&nbsp;&nbsp;&nbsp;<button className='btn btn-danger'onClick={this.against}>反对</button></div></section>;}//=>投票:支持&&反对support = ev => {let {spanLeft} = this;spanLeft.innerHTML++;thisputed();};against = ev => {let {spanRight} = this;spanRight.innerHTML++;thisputed();};computed = () => {let {spanLeft, spanRight, spanRate} = this,n = parseFloat(spanLeft.innerHTML),m = parseFloat(spanRight.innerHTML),rate = (n + m) === 0 ? '0%' : ((n / (n + m) * 100).toFixed(2) + '%');spanRate.innerHTML = rate;};
}ReactDOM.render(<main><Vote title='世界杯小组赛法国VS秘鲁,法国队必胜!'/><Vote title='世界杯小组赛阿根廷VS克罗地亚,壮哉我大梅西!'/>
</main>, root);

在REACT组件中

  1. 基于数据驱动(修改状态数据,REACT帮助我们重新渲染视图)完成的组件叫做“受控组件(受数据控制的组件)”

  2. 基于REF操作DOM实现视图更新的,叫做“非受控组件” =>真实项目中,建议大家多使用“受控组件”

基于表单元素的ONCHANGE实现MVVM双向绑定

VUE:[MVVM] 数据更改视图跟着更改,视图更改数据也跟着更改(双向数据绑定) REACT:[MVC] 数据更改视图跟着更改(原本是单向数据绑定,但是我们可以自己构建出双向的效果)

import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.css';
import PropTypes from 'prop-types';class Temp extends React.Component {constructor() {super();this.state = {text: '周啸天'};}componentDidMount() {setTimeout(() => {this.setState({text: '珠峰培训'});}, 1000);}render() {let {text} = this.state;return <section className='panel panel-default'><div className='panel-heading'><input type="text" className='form-control'value={text}onChange={ev => {//=>在文本框的ON-CHANE中修改状态信息:实现的是视图改变数据this.setState({text: ev.target.value});}}/></div><div className='panel-body'>{text}</div></section>;}
}ReactDOM.render(<Temp/>, root);

REACT组件的生命周期函数

生命周期函数(钩子函数):

        描述一个组件或者程序从创建到销毁的过程,我们可以在过程中间基于钩子函数完成一些自己的操作(例如:在第一次渲染完成做什么,或者在二次即将重新渲染之前做什么等...)

[基本流程]

constructor 创建一个组件

componentWillMount 第一次渲染之前

render 第一次渲染

componentDidMount 第一次渲染之后

[修改流程:当组件的状态数据发生改变(SET-STATE)或者传递给组件的属性发生改变(重新调用组件传递不同的属性)都会引发RENDER重新执行渲染(渲染也是差异渲染)] shouldComponentUpdate 是否允许组件重新渲染(允许则执行后面函数,不允许直接结束即可)

componentWillUpdate 重现渲染之前

render 第二次及以后重新渲染

componentDidUpdate 重现渲染之后

componentWillReceiveProps:父组件把传递给子组件的属性发生改变后触发的钩子函数

[卸载:原有渲染的内容是不消失的,只不过以后不能基于数据改变视图了] componentWillUnmount:卸载组件之前(一般不用)

import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.css';
import PropTypes from 'prop-types';/*class A extends React.Component {//=>这个是第一个执行的,执行完成后(给属性设置默认值后)才向下执行// static defaultProps = {};constructor() {super();console.log('1=CONSTRUCTOR');this.state = {n: 1};}componentWillMount() {console.log('2=WILL-MOUNT:第一次渲染之前', this.refs.HH);//=>UNFRFINED}componentDidMount() {console.log('4=DID-MOUNT:第一次渲染之后', this.refs.HH);//=>DIV/!** 真实项目中在这个阶段一般做如下处理:*   1. 控制状态信息更改的操作*   2. 从服务器获取数据,然后修改状态信息,完成数据绑定*   ...*!/setInterval(() => {this.setState({n: this.state.n + 1});}, 5000);}shouldComponentUpdate(nextProps, nextState) {/!** 在这个钩子函数中,我们获取的STATE不是最新修改的,而是上一次的STATE值*   例如:第一次加载完成,5000MS后,我们基于SET-STATE把N修改为2,但是此处获取的还是1呢** 但是这个方法有两个参数*   nextProps:最新修改的属性信息*   nextState:最新修改的状态信息*!/console.log('5=是否允许更新,函数返回TRUE就是允许,返回FALSE就是不允许');if (nextState.n > 3) {return false;}return true;}componentWillUpdate(nextProps, nextState) {//=>这里获取的状态是更新之前的(和SHOULD相同也有两个参数存储最新的信息)console.log('6=组件更新之前', this.state.n, nextState);}componentDidUpdate() {//=>这里获取的状态是更新之后的console.log('8=组件更新之后', this.state.n);}render() {console.log('RENDER');return <div ref='HH'>{this.state.n}</div>;}
}*//*function queryData() {return new Promise(resolve => {setTimeout(() => {resolve(2);}, 3000);});
}class A extends React.Component {constructor() {super();console.log('1=CONSTRUCTOR');this.state = {n: 1};}componentWillMount() {console.log('2=WILL-MOUNT:第一次渲染之前');//=>在WILL_MOUNT中,如果直接的SET-STATE修改数据,会把状态信息改变后,然后RENDER和DID_MOUNT;但是如果SET-STATE是放到一个异步操作中完成(例如:定时器或者从服务器获取数据),也是先执行RENDER和DID,然后在执行这个异步操作修改状态,紧接着走修改的流程(这样和放到DID_MOUNT中没啥区别的),所以我们一般把数据请求放到DID中处理。//=>真实项目中的数据绑定,一般第一次组件渲染,我们都是绑定的默认数据,第二次才是绑定的从服务器获取的数据(有些需求我们需要根据数据是否存在判断显示隐藏等)this.setState({n: 2});console.log(this.state.n);}/!*async componentWillMount() {console.log('2=WILL-MOUNT:第一次渲染之前');let result = await queryData();this.setState({n: result});}*!/componentDidMount() {console.log('4=DID-MOUNT:第一次渲染之后', this.refs.HH);}render() {console.log('3=RENDER');return <div ref='HH'>{this.state.n}</div>;}
}*/class A extends React.Component {constructor() {super();console.log('1=CONSTRUCTOR');}componentWillMount() {console.log('2=WILL-MOUNT:第一次渲染之前');}componentDidMount() {console.log('4=DID-MOUNT:第一次渲染之后', this.refs.HH);}componentWillReceiveProps(nextProps, nextState) {console.log('组件属性改变', this.props.n, nextProps.n);//=>属性改变也会触发子组件重新渲染,继续完成修改这套流程}shouldComponentUpdate() {console.log('SHOULD');return true;}render() {console.log('RENDER');return <div ref='HH'>{this.props.n}</div>;}
}
class B extends React.Component {constructor() {super();this.state = {n: 1};}componentDidMount() {setTimeout(() => {this.setState({n: 2});}, 3000);}render() {//=>复合组件:组件嵌套(大组件嵌套小组件)return <div>{/*把父组件的状态信息作为属性传递给子组件*/}<A n={this.state.n}/></div>;}
}ReactDOM.render(<B/>, root);

复合组件之间的信息传递

父组件包裹子组件,包裹中的子组件可以使用父组件方法,外面定义的子组件使用prop继承

import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.css';
import PropTypes from 'prop-types';/*HEAD*/
class Head extends React.Component {render() {return <div className='panel-heading'><h3 className='panel-title'>{/*子组件通过属性获取父组件传递的内容*/}点击次数:{this.props.count}</h3></div>;}
}/*BODY*/
class Body extends React.Component {render() {return <div className='panel-body'><button className='btn btn-success'onClick={this.props.callBack}>点我啊!</button></div>;}
}/*PANEL*/
class Panel extends React.Component {constructor() {super();this.state = {n: 0};}fn = () => {//=>修改PANEL的状态信息this.setState({n: this.state.n + 1});};render() {return <section className='panel panel-default' style={{width: '50%', margin: '20px auto'}}>{/*父组件中在调取子组件的时候,把信息通过属性传递给子组件*/}<Head count={this.state.n}/>{/*父组件把自己的一个方法基于属性传递给子组件,目的是在子组件中执行这个方法*/}<Body callBack={this.fn}/></section>;}
}ReactDOM.render(<Panel/>, root);

更多推荐

React 笔记 3

本文发布于:2024-02-26 01:49:25,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1700965.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:笔记   React

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!