React-class ——React 组件、 React Props(属性传值)、React State(状态)

目录

一、React 组件

1、定义单个组件

(1)定义组件

(2)使用组件

 2、定义复合组件

二、 React Props

1、定义和使用props 传值

- 通过React**类定义**组件时:

通过React**函数定义** 组件时:

2、默认Props

3、多属性传值

三、React State

 1、如何定义State

2、setState设置状态

3、State 与 Props 区别

4、state/props 实现父子组件通信


一、React 组件

组件一共有两种:有状态和无状态

React.js 中一切皆组件,用 React.js 写的其实就是 React.js 组件。

我们在编写 React.js 组件的时候,一般都需要继承 React.js 的 Component(类定义)。一个组件类必须要实现一个 render 方法,这个 render 方法必须要返回一个 JSX 元素。

但这里要注意的是,必须要用一个外层的 JSX 元素把所有内容包裹起来。(有一个根元素)

返回并列多个 JSX 元素是不合法的。

1、定义单个组件

(1)定义组件

方式1:通过React自定义组件(DOM元素):**类定义**

import React, {Component} from 'react';
class MyApp extends Component {
}

import React from 'react';
class MyApp extends React.Component {
    constructor(props){
        super(props);
        this.msg="hello,react"
  	}
    
	render() {
		return (
			
{this.msg}

这是标题2

这是标题2

); } } export default MyApp;

方式2:通过React自定义组件(DOM元素):**函数定义**

import React from 'react';
//箭头函数
const MyApp = () => 

这是一个段落

; export default MyApp; //普通函数 function Welcome(props) { return

Hello, {props.name}

; } export default Welcome;

方式3:**不建议使用**,React.createClass创建组件的方式在react 16版本中去除。

var MyApp = React.createClass({
  render: function() {
    return 

Hello World!

; } });

(2)使用组件

import React from 'react';
import ReactDOM from 'react-dom';
import MyApp from './js/MyApp.js'; //导入自定义组件

ReactDOM.render(, document.getElementById('root'));

 2、定义复合组件

我们可以通过创建多个组件来合成一个组件,即把组件的不同功能点进行分离

import React from 'react';
import ReactDOM from 'react-dom';

class WebSite extends React.Component {
	render() {
		return (
      		
); } } //局部组件Name class Name extends React.Component { render() { return (

{this.props.name}

); } } //局部组件Link class Link extends React.Component { render() { return (

{this.props.site}

); } } ReactDOM.render( , document.getElementById('root') )

二、 React Props

React 的一大特点是  单向数据流 。

React 中的每一个组件,都包含有一个属性(props),**属性主要是从父组件传递给子组件的**,在组件内部,我们可以通过this.props获取属性对象。

1、定义和使用props 传值

- 通过React**类定义**组件时:

- 在父组件render 方法中调用组件时使用**key/value** 的形式来指定属性。
  - 在自定义子组件中通过**this.props.key** 来获得组件属性的值,需要使用{}括起来。

(类可以有props属性,是因为类继承了官方react的组件,函数就没有props属性)

// 类定义组件时,使用属性 this.props.属性名称
class MyApp extends React.Component {
	render() {
		return (

{this.props.name}

); } } ReactDOM.render( , document.getElementById('root') );

通过React**函数定义** 组件时:

- 在父组件render 方法中调用组件时使用**key/value** 的形式来指定属性。
- 在自定义子组件中通过函数接收参数**props**,**props.key**来获得组件属性的值,需要使用{}括起来

// 函数定义组件时,在组件内部使用属性值:props.属性名称
function Welcome(props) { // 函数需要传递一个参数props
    return(

{props.title}

) } ReactDOM.render(     ,      document.getElementById('root') );

2、默认Props

定义默认props :

class MyApp extends React.Component {
	render() {
		return 

this is my {this.props.name}

} } //由于是用ES6 class语法创建组件,其内部只允许定义方法,而不能定义属性,class的属性只能定义在class之外。所以defaultProps要写在组件外部。 MyApp.defaultProps = { name: 'xxx' }; ReactDOM.render( , document.getElementById('root') );

3、多属性传值

(1)定义一个this.props对象,在对象中声明多个**键值对**,用于表示组件的属性

(2)在组件中使用**{...this.props}**的方式传递属性。

“...”表示JSX的延展操作符,这种方式可以很方便的为组件指定多个属性,并且为属性的值指定数据类型。

class MyApp extends React.Component {
	render() {
		return(
			

{this.props.name} : {this.props.age} : {this.props.sex}

); } } let p1 = { name: '张三', age: 18, sex: '男' }; ReactDOM.render( // , document.getElementById('root') );

三、React State

React 的核心思想是组件化的思想,应用由组件搭建而成,而组件中最重要的概念是State(状态),State是一个组件的UI数据模型,是组件渲染时的数据依据。

 1、如何定义State

定义一个合适的State,是正确创建组件的第一步。

State必须能代表一个组件UI呈现的完整状态集,即组件的任何UI改变,都可以从State的变化中反映出来;

同时,State还必须是代表一个组件UI呈现的最小状态集,即State中的所有状态都是用于反映组件UI的变化,没有任何多余的状态,也不需要通过其他状态计算而来的中间状态。

组件中用到的一个变量是不是应该作为组件State,可以通过下面的4条依据进行判断:

1. 这个变量是否是通过Props从父组件中获取?如果是,那么它不是一个状态。


2. 这个变量是否在组件的整个生命周期中都保持不变?如果是,那么它不是一个状态。


3. 这个变量是否可以通过其他状态(State)或者属性(Props)计算得到?如果是,那么它不是一个状态。


4. 这个变量是否在组件的render方法中使用?如果**不是**,那么它不是一个状态。这种情况下,这个变量更适合定义为组件的一个普通属性。

并不是组件中用到的所有变量都是组件的状态!

class LikeButton extends React.Component {
    //声明一个状态liked   使用this.state.liked获取状态的值
	constructor(props) {
        super(props)
        this.state={liked: false};
    }	
	handleClick(event) {
		this.setState({liked: !this.state.liked});
	}
	render() {
		return (
			
		)
	}
}

ReactDOM.render(
	,
	document.getElementById('root')
)

注意:**React在ES6的实现中,规定state在constructor中实现**

正确定义State***的方式如下:

(1)在constructor中实现state

(2)在constructor中通过bind绑定事件函数(事件函数是用来改变状态)

(3)在事件函数内部使用setState函数更改状态

(4)在组件中的render函数中使用该状态

(5)在组件上需要设置监听事件,去触发事件函数的执行

//定义组件
class LikeButton extends React.Component {
    //constructor表示构造器,在constructor需要声明状态state,在声明state之前需要使用super(props);
	constructor(props) {
		super(props);//使用父类的属性
        
        //声明状态
		this.state = {
			liked: false
		}
		//Currently, you are calling bind. 
		//But bind returns a bound function. 
		//You need to set the function to its bound value.
		//目前,你正在调用绑定。但是绑定返回绑定函数。您需要将函数设置为其绑定值。
		this.handleClick = this.handleClick.bind(this);
	}
    
	handleClick(event) {
		this.setState({liked: !this.state.liked});
	}
    
	render() {
		return (
			
		)
	}
}

ReactDOM.render(
	,
	document.getElementById('root')
)

2、setState设置状态

(1)语法: 

setState(object nextState[, function callback])

(2)说明:

- setState是React事件处理函数中和回调函数中触发UI更新的主要方法。


- 不能在组件内部通过this.state修改状态,因为该状态会在调用setState()后被替换。


- setState()不一定是同步的,为了性能提升,React会批量执行state和DOM渲染。


- setState()总是会触发一次组件重绘,但可在shouldComponentUpdate()中实现一些条件渲染逻辑来解决。

setState默认是异步的,但有时候也是同步的

在计时器 和 原生Dom函数中,setState是一个同步函数,其它情况全是异步函数

class MyApp extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			clickCount: 0
		};

		this.handleClick = this.handleClick.bind(this);
	}

	handleClick(event) {
		this.setState({clickCount: this.state.clickCount + 1});
	}

	render() {
		return (
			

点击后次数变更: {this.state.clickCount}

); } } ReactDOM.render( , document.getElementById('root') );

同步设置多个状态时(不常用),可以在setState函数的**第二个参数可以传递一个function回调函数,如下:

class MyApp extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			clickCount: 0, 
			isRed: false,
			smallFont: true
		};

		this.handleClick = this.handleClick.bind(this);
	}

	handleClick(event) {
		this.setState(
			{clickCount: this.state.clickCount + 1},
			function() {
				this.setState(
					{isRed: !this.state.isRed}, 
					function() {
						this.setState({smallFont: !this.state.smallFont});
					}
				);
			}
			
		);
		console.log(this.state.isred);
	}

	render() {
		var redStyle = {color: 'red', fontSize: 50};
		var blueStyle = {color: 'blue', fontSize: 14};
		return (
			

点击后次数变更: {this.state.clickCount}

); } } ReactDOM.render( , document.getElementById('root') );

状态上移:

当存在多个组件共同依赖一个状态,或是当子组件的props 数据需要被修改时,将这个状态放到对应组件的父组件中:

//子组件
class Site extends React.Component {
	render() {
		return (
			

{this.props.myData}

); } } //父组件 class Content extends React.Component { constructor(props) { super(props); this.state = { value: 'hello' }; this.handleChange = this.handleChange.bind(this); } handleChange(event) { this.setState({value: '你好'}); } render() { return(
); } }

3、State 与 Props 区别

除了State, 组件的Props也是和组件的UI有关的。他们之间的主要区别是:

  • props 中的数据都是外界传递过来的

  • state 中的数据都是组件私有的;(通过Ajax 获取回来的数据,一般都是私有数据)

  • props 中的数据都是只读的,不能重新赋值

  • state 中的数据都是可读可写的

  • State定义在constructor内部,在super(props)代码后面;Props默认值定义在类(组件)的外部

当子组件的属性值是可变值时,采用状态上移:

状态上移通过属性将父组件的状态传递到子组件,那么父组件的状态发生变化时,子组件的属性也会改变

4、state/props 实现父子组件通信

(自己实现反向传值,Vue中已经实现好了)

  • 子组件获取父组件整个组件进行传参

    • 父组件在调用子组件时,传入一整个组件给子组件

    • 父组件中定义一个方法getChildrenMsg(resulet, msg),用来获取子组件传来的值以及执行其他操作

    • 子组件在通过this.props来获取到一整个组件this.props.parent 或者this.props[parent]

    • 子组件调用父组件步骤2里定义的方法进行传值this.props.parent.getChildrenMsg(this,val)

Parent:

import Children from './Children'
export default class Parent extends Component {
    constructor(props) {
        super(props)
        this.state = {
            msg: '父组件传值给子组件',
            childrenMsg: ''
        }
    }

    getChildrenMsg = (result, msg) => {
        // console.log(result, msg)
        this.setState({
            childrenMsg: msg
        })
    }

    render() {
        return (
            

我是父组件

子组件传来的值为:{ this.state.childrenMsg }


{/**/}
) } }

Children:

export default class Children extends Component {
    constructor(props) {
        super(props)
        this.state = {
            msg: '子组件传值给父组件'
        }
    }

    toParent = () => {
        // console.log(this.props.parent.getChildrenMsg.bind(this, this.state.msg))
        this.props.parent.getChildrenMsg(this, this.state.msg)
    }

    render() {
        return (
            

{ 我是子组件 }

) } }

你可能感兴趣的:(前端,javascript,react.js,html)