React中的数据承载-Props/State

React中的数据承载-Props/State

任意的视图变化都应该由数据来控制

React也是基于数据驱动(声明式)的框架,组件中必然需要承载一些数据,在react中起到这个作用的是属性和状态(props & state)

  1. 属性(props) 在组件外部传入,或者内部设置,组件内部通过this.props获得

  2. 状态(state) 在组件内部设置或者更改,组件内部通过this.state获得

属性(props)

属性一般是外部传入的,组件内部也可以通过一些方式来初始化的设置,属性不能被组件自己更改

属性是描述性质、特点的,组件自己不能随意更改

使组件拥有属性的方式:

  1. 在装载(mount)组件的时候给组件传入

传入数据的时候,除了字符串类型,其他的都应该包上表达式,但是为了规整,所有的数据传递,最好都包上{}

var Gouzi = React.createClass({
    render(){
        console.log(this)
        return (
            <div>
                <p>我的名字:{this.props.name}</p>
                <p>我的性别:{this.props.sex}</p>
                <p>我的年龄:{this.props.age}</p>  
                <p>我的父亲是:{this.props.father}</p>                                       
            </div>
        )
    }
})

let info = {
    sex:'male',
    father:'狗爸'
}

ReactDOM.render(<Gouzi {...info} name={"大狗子"} age={26}/>,app)
  1. 父组件给子组件传入

父组件在嵌套子组件的时候为子组件传入,传入的方式和上面的方式一样

//父组件的render函数
render(){
    return (
        <div>
            <p>父组件:</p>
            <hr/>
            <Son name={'大狗子'}/>
            <Son name={'二狗子'}/>
        </div>
    )
}
  1. 根据属性或状态,我们可以在render中的表达式里做一些逻辑判断,可以使用||、三元表达式、子执行函数等等
getName(){
    return this.props.name || '野狗子'
},
render:function () {
    let {name} = this.props
    return (
    <div>
        <p>我是子组件-{this.props.name || '野狗子'}</p>
        <p>我是子组件-{this.props.name?this.props.name:'野狗子'}</p>
        <p>我是子组件-{this.getName()}</p>
    </div>
    )
}

状态(state)

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

在组件中可以通过constructor构造函数来给组件挂载初始状态,在组件内部通过this.state获取

扫描二维码关注公众号,回复: 11623511 查看本文章

this.props和this.state是纯js对象,在vue中, d a t a O b j e c t . d e f i n e P r o p e r t y data属性是利用Object.defineProperty处理过的,更改 data的数据的时候会触发数据的getter和setter,但是react中没有做这样的处理,如果直接更改的话,react是无法得知的,所以,需要使用特殊的更改状态的方法:

setState(params)

在setState中传入一个对象,就会将组件的状态中键值对的部分更改,还可以传入一个函数,这个回调函数必须返回像上面方式一样的一个对象,函数可以接收prevState和props

//1.
let doing = this.state.doing=='学习'?'玩游戏':'学习'
this.setState({doing})

//2.
this.setState((prevState,props)=>{
    return {
        doing:prevState.doing=='学习'?'玩游戏':'学习'
    }
})

setState有两个参数

第一个参数可以是对象,也可以是方法return一个对象,我们把这个参数叫做updater

  • 参数是对象
  let dos = this.state.doing==="学英语"?"玩游戏":"学英语";
  this.setState({
      doing:dos
  });
  • 参数是方法

    this.setState((prevSate,props)=>{
        return {
            doing:prevSate.doing==="学英语"?"玩游戏":"学英语"
        }
    });
    

    注意的是这个方法接收两个参数,第一个是上一次的state, 第二个是props

setState是异步的,所以想要获取到最新的state,没有办法获取,就有了第二个参数,这是一个可选的回调函数

this.setState((prevSate,props)=>{
    return {
        doing:prevSate.doing==="学英语"?"玩游戏":"学英语"
    }
}, () => {
  console.log('回调里的',this.state.doing)  //获取更新后的值
})
console.log('setState外部的',this.state.doing) //还是之前没有更新的值

两种setState的比较:

另外setState(stateChange[, callback])这种形式的更改状态,会将传入的对象浅层合并到新的 state 中,例如,调整购物车商品数:

this.setState({quantity: 2})

这种形式的 setState() 是异步的,并且在同一周期内会对多个 setState 进行批处理。例如,如果在同一周期内多次设置商品数量增加,则相当于:

Object.assign(
  previousState,
  {quantity: state.quantity + 1},
  {quantity: state.quantity + 1},
  ...
)

后调用的 setState() 将覆盖同一周期内先调用 setState 的值,因此商品数仅增加一次。如果后续状态取决于当前状态,我们建议使用 updater 函数的形式代替:

this.setState((prevState,props) => {
  return {quantity: prevState.quantity + 1}; //连续执行多次获放入队列中一次执行
}[, callback]);

扩充:super的理解

es5里面的构造函数与继承实现:

  /* function Person(name,age){
            this.name = name;
            this.age = age
        }
        Person.prototype.say = function(){
            return this.name+","+this.age
        }

        let p = new Person("张三",18)
        let p2 = new Person("李四",18)
        // console.log(p.say === p2.say)
        console.log(p.say()) */
        

        //es5中的继承
        function Person(name,age){
            this.name = name;
            this.age = age
        }
        Person.prototype.say = function(){
            return this.name+","+this.age
        }
        function Student(name,age,school){
            Person.call(this,name,age)  //借用构造函数实现继承
            this.school = school
        }
      /*   Student.prototype = Person.prototype;
        Student.prototype.marray = true

        let stu = new Student("张三",18,"千锋教育")
        let per = new Person("张四",38)
        console.log(per.marray) */


        Student.prototype = Object.create(Person.prototype); //实现了原型链继承
        Student.prototype.constructor = Student  //扭转Student.prototype的constuctor属性为Student

es6的类与继承与super理解:

	class Person{
            constructor(name,age){
                this.name = name;
                this.age = age;
            }
            say(){
                return this.name+","+this.age
            }
        }   

        //es6中constuctor构造函数里面为啥调用super?
        //说白了,就是让父类的构造函数执行一遍来去给子类赋值属性
        class Student extends Person{
            constructor(name,age,school){
                super(name,age)  //es6中super必须放在构造函数第一行  
                this.school = school
            }
            say(){
                return super.say()+","+this.school
            }
        }


        let per = new Person("张三",38)
        let stu = new Student("张四",18,"千锋教育")
        console.log(stu.say())

实现下拉菜单的方式

  1. 通过数据来控制元素的行内样式中display的值,或者去控制类名
<ul style={{display:isMenuShow?'block':'none'}}><li>国内新闻</li></ul>
...
<ul className={isMenuShow?'show':'hide'}><li>国内新闻</li></ul>
  1. 根据数据控制是否渲染改节点、组件
{
    isMenuShow?<ul><li>国内新闻</li></ul>:''
}
  1. 通过ref对dom、组件进行标记,在组件内部通过this.refs获取到之后,进行操作
<ul ref='content'><li>国内新闻</li></ul>
...
this.refs.content.style.display = this.state.isMenuShow?'block':'none'

属性和状态的对比

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

不同点:

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

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

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

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

猜你喜欢

转载自blog.csdn.net/qq_43942185/article/details/105941158