React基础篇(2) -- state&props&refs

内容简介

  • state
  • props
  • refs
  • 行内样式及动态类名

state

基本介绍

React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。

React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。

初始化状态:

constructor() {
  super()
  this.state = {
    stateName1 : stateValue1,
    stateName2 : stateValue2
  }
}

读取显示:

this.state.stateName1

更新状态-->更新界面 :

this.setState({stateName1 : newValue})

举例如下:

class Myconponent1 extends React.Component{
    constructor(props){
        super(props)
        //   1、初始化状态
        this.state = {
            isLike:false
        }
        //将新增的方法中的this强制绑定为组件对象
        this.fun = this.fun.bind(this)
    }
    //新添加方法:内部this默认undefined
    fun(){
        //得到原有的状态
        let flag = !this.state.isLike
        //  3、更新状态(因为是单向数据流,只能通过指定方式改变状态)
        this.setState({
            isLike:flag
        })
    }
    render(){
        //  2、读取状态
        const {isLike}=this.state;
        return <h1 onClick={this.fun}>{isLike?'you like me?':'i like you!'}</h1>
        //可以直接这样写,但效率低 return <h1 onClick={this.fun.bind(this)}>{flag?'you like me?':'i like you!'}</h1>
    }
}

理解上面后可简化写法:

class Myconponent1 extends React.Component{
    state = {
        isLike:false
    }
    fun=()=>{
        let {isLike}=this.state;
        this.setState({
            isLike:!isLike
        })
    }
    render(){
        const {isLike}=this.state;
        return <h1 onClick={this.fun}>{isLike?'you like me?':'i like you!'}</h1>
    }
}

注意

状态更新可能是异步的,不应该依靠它们的值来计算下一个状态。

可使用第二种形式的 setState() 来接受一个函数而不是一个对象。

该函数将接收先前的状态作为第一个参数,将此次更新被应用时的props做为第二个参数

this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));

props

基本介绍

state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据(包括函数方法)。

props是所有组件标签的属性的集合对象。

作用:给标签指定属性, 从目标组件外部向组件内部传递数据(可能是一个function)。

在组件内部读取属性: this.props.propertyName

扩展属性: 将对象的所有属性通过props传递

<Person {...person}/>

默认 Props

你可以通过组件类的 defaultProps 属性为 props 设置默认值,实例如下:

class Hello extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}
 
Hello.defaultProps = {
  name: 'adoctors'
};

Props 验证

Props 验证使用 propTypes,它可以保证我们的应用组件被正确使用,React.PropTypes 提供很多验证器 (validator) 来验证传入数据是否有效。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。

相关链接:http://npm.taobao.org/package/prop-types

子组件响应父组件变化

componentWillReceiveProps(newVal){
    console.log("newVal",newVal)
}

举例如下:

function Persion(props){
    return (
        <ul>
            <li>姓名:{props.name}</li>
            <li>年龄:{props.age}</li>
            <li>性别:{props.sex}</li>
        </ul>
    )
}
// 默认属性值
Persion.defaultProps={
    name:"tom",
    age:18,
    sex:"男"
}
//对属性值的类型和必要性限制,需要引入新文件
Persion.propTypes={
    name:PropTypes.string.isRequired,       //string且必须有
    age:PropTypes.number                    //number可以没有
}
let msg={
    name:"adoctors",
    age:15,
    sex:"男"
}

ReactDOM.render(<Persion {...msg}/>,document.getElementById(('com')))
//只传name,可以直接写则类型为string,若用{}包裹则可以传成number
ReactDOM.render(<Persion name="jack" age={28} />,document.getElementById(('com1')))

refs

React 支持一种非常特殊的属性 Ref ,你可以用来绑定到 render() 输出的任何组件上。

这个特殊的属性允许你引用 render() 返回的相应的支撑实例( backing instance )。这样就可以确保在任何时间总是拿到正确的实例。

下面是几个适合使用 refs 的情况:

  • 处理焦点、文本选择或媒体控制。
  • 触发强制动画。
  • 集成第三方 DOM 库

如果可以通过声明式实现,则尽量避免使用 refs。

不能在函数式组件上使用 ref 属性,因为它们没有实例。

//指定ref
<div ref="myDiv" style={{color:"red"}}>adoctors</div>
<input type="text" ref="ipt0"/> 
<input type="text" ref={val=>this.ipt1=val}/>
<input type="text" onBlur={this.getVal}/>

//获取相应的值
getVal=(e)=>{
    console.log('获取其他元素的(myDiv)的样式: ',this.refs.myDiv.style.color);
    console.log('获取其他元素的(ipt0)值: ',this.refs.ipt0.value)
    console.log('获取其他元素的(ipt1)值: ',this.ipt1.value)
    console.log('获取本元素的值: ', e.target.value);
}

结果如图:

行内样式

变量控制

let flag={
        display:this.props.list.length?'none':'block'
    }
<div style={flag}>暂无评论</div>

行内单个样式

<div style={{display: this.props.list.length ? "block" : "none"}}>此标签是否隐藏</div>

行内多个样式

<div style={{display: (index===this.state.currentIndex) ? "block" : "none", color:"red"}}>此标签是否隐藏</div>

动态类名

1、标签中没有其他class,只需要动态添加一个.active的className,来显示内容是否被选中状态,则:

<div className={index===this.state.currentIndex?"active":null}>此标签是否选中</div>

2、如果标签本身有其他class,又要动态添加一个.active的className,来显示内容是否被选中状态,则:

<div className={["container tab", index===this.state.currentIndex?"active":null].join(' ')}>此标签是否选中</div>

注意空格

或者,使用ES6写法(推荐使用ES6写法):

<div className={`container tab ${index===this.state.currentIndex?"active":null}`}>此标签是否选中</div>

猜你喜欢

转载自www.cnblogs.com/adoctors/p/10186861.html