React属性(props)和状态(state)

React属性(props)和状态(state)

一、属性(props)

属性props是由外部传入、描述性质的,组件内部也可以通过一些方式来初始化的设置。属性不能被组件自己更改,但是可以通过父组件主动重新渲染的方式来传入新的 props

之前的组件代码里面有props的简单使用,总的来说,在使用一个组件的时候,可以把参数放在标签的属性当中,所有的属性都会作为组件 props 对象的键值。通过箭头函数创建的组件,需要通过函数的参数来接收props

  • 设置组件的默认props
import React, { Component } from 'react';

class Title extends Component {

//第一种定义方式
  static defaultProps = {
    name:"react"
  }

  render() {
    return (
      
欢迎进入{this.props.name} 的世界
); } } //第二种方式 // Title.defaultProps = { // name:'react' // } export default Title;
  • props.children(插槽)

组件可以嵌套,在自定义组件使用嵌套结构时,需要使用 props.children

ReactDOM.render(
  
    

lxc

react
, document.getElementById('root') );

通过“插槽”进行嵌套内容的接收

import React, { Component } from 'react';
class Content extends Component {
  render() {
    return (
      
{ this.props.children }
); } } export default Content;
  • 使用prop-types检查props

React其实是为了构建大型应用程序而生, 在一个大型应用中,根本不知道别人使用你写的组件的时候会传入什么样的参数,有可能会造成应用程序运行不了,但是不报错。为了解决这个问题,React提供了一种机制,让写组件的人可以给组件的props设定参数检查,需要安装和使用prop-types:

  • 安装prop-types验证
$ cnpm i prop-types -S
import React, { Component } from 'react';
import Proptypes from 'prop-types'

class Product extends Component {
  render() {
    return (
      
产品名称: {this.props.name}
); } } Product.propTypes={ name:Proptypes.string, //['北京','天津'] // city:Proptypes.arrayOf(Proptypes.string).isRequired, // customProp:function(props,PropName){ // if(!/gp/.test(props[PropName])){ // return new Error('内容非法') // } // console.log(arguments) // }, customArrayProp: Proptypes.arrayOf(function(propValue, key, componentName, location, propFullName) { if (!/北京/.test(propValue[key])) { return new Error( 'Invalid prop `' + propFullName + '` supplied to' + ' `' + componentName + '`. Validation failed.' ); } }).isRequired } export default Product;

二、状态(state)

状态就是组件描述某种显示情况的数据,由组件自己设置和更改,也就是说由组件自己维护,使用状态的目的就是为了在不同的状态下使组件的显示不同(自己管理)

  • 定义state
 constructor() {
    super();
    //state定义的第一种方式
    //推荐
    // this.state = {
    //   count: 1,
    //   title: "中国机长"
    // }
  }
//state定义的第二种方式
  state ={
    title:"中国机长",
    count:1
  }
  • 修改state的三种方式
  1. 在React中通过this.setState进行数据的修改。
  2. this.setState是异步执行的。( 异步转同步 )
  3. this.setState中的第二个参数是回调,用来验证数据是否修改成功,获取数据更新后的DOM结构。
  4. 只要this.setState调用render函数就会执行。
import React, { Component } from 'react';
class Movie extends Component {

  constructor() {
    super();
    this.state ={
        title:"中国机长",
        count:1
     }
  }

  componentDidMount() {
      
    //修改state的第一种方式
    // setTimeout(() => {
    //   this.setState({
    //     title: "战狼2"
    //   })
    // }, 2000)

    //修改state的第二种方式
    // this.state.title ="战狼2"
    // setTimeout(()=>{
    //   this.setState({})
    // },2000)

    //修改state的数据是异步的
    // this.setState({
    //   count: this.state.count + 1
    // })
    // console.log(this.state.count)

    //修改state的第三种方式
    this.setState((preState, props) => {
      console.log(props);
      //数据的更新,会做merge
      return {
        count: preState.count + 1
      }
    }, () => {
      console.log(this.state.count)
    })

    setTimeout(()=>{
      this.setState({
        count:3
      })
      console.log(this.state.title,this.props.city)
    },3000)
  }

  render() {
    console.log(1)
    return (
      

{this.state.title}

); } } export default Movie;

三、属性vs状态

  • 相似点:

都是纯JS对象,都会触发render更新,都具有确定性(状态/属性相同,结果相同)

  • 不同点:
  1. 属性能从父组件获取,状态不能
  2. 属性可以由父组件修改,状态不能
  3. 属性能在内部设置默认值,状态也可以
  4. 属性不在组件内部修改,状态要改
  5. 属性能设置子组件初始值,状态不可以
  6. 属性可以修改子组件的值,状态不可以

state 的主要作用是用于组件保存、控制、修改自己的可变状态。state 在组件内部初始化,可以被组件自身修改,而外部不能访问也不能修改。你可以认为 state 是一个局部的、只能被组件自身控制的数据源。state 中状态可以通过 this.setState方法进行更新,setState 会导致组件的重新渲染。

props 的主要作用是让使用该组件的父组件可以传入参数来配置该组件。它是外部传进来的配置参数,组件内部无法控制也无法修改。除非外部组件主动传入新的 props,否则组件的 props 永远保持不变。

如果搞不清 stateprops 的使用场景,记住一个简单的规则:尽量少地用 state,多用 props

没有 state 的组件叫无状态组件(stateless component),设置了 state 的叫做有状态组件(stateful component)。因为状态会带来管理的复杂性,我们尽量多地写无状态组件,尽量少地写有状态的组件。这样会降低代码维护的难度,也会在一定程度上增强组件的可复用性。

四、状态提升

如果有多个组件共享一个数据,把这个数据放到共同的父级组件中来管理

五、案例(计数器)

  • Counter.jsx
import React, { Component } from 'react';
import Button from './Button'
import Count from './Count'
import styled from 'styled-components'

const CountWrapper = styled.div`
  h1 {
    display:block;
    color:red;
  }

  button {
    width:100px;
    height:40px;
    background:blue;
    color:white;
    font-size:20px;
  }
`

class Counter extends Component {

  constructor() {
    super();
    this.state = {
      count: 0
    }
  }

  handleChange(type) {
    console.log('handle change')
    this.setState((preState, props) => {
      if (type === 'increment') {
        return {
          count: preState.count + 1
        }
      } else {
        return {
          count: preState.count - 1
        }
      }

    }, () => { })
  }

  render() {
    return (
      
        
        
        
      
    );
  }
}

export default Counter;
  • Count.jsx
import React from 'react'
import Proptypes from 'prop-types'

class Count extends React.Component {

  render(){
    return 

{this.props.count}

} } Count.propTypes ={ count:Proptypes.number.isRequired } export default Count;
  • Button.jsx
import React, { Component } from 'react';

class Button extends Component {

  handleClick(){
    console.log('handle click')
    this.props.change()
  }

  render() {
    return (
     
    );
  }
}

export default Button;

你可能感兴趣的:(React属性(props)和状态(state))