zoukankan      html  css  js  c++  java
  • 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>
    
  • 相关阅读:
    TCP/IP网络编程之优于select的epoll(一)
    TCP/IP网络编程之I/O流分离
    TCP/IP网络编程之套接字与标准I/O
    TCP/IP网络编程之多播与广播
    TCP/IP网络编程之多种I/O函数
    TCP/IP网络编程之I/O复用
    TCP/IP网络编程之进程间通信
    TCP/IP网络编程之多进程服务端(二)
    服务器被入侵了怎么办?
    sentos7为例添加python3和python2共存
  • 原文地址:https://www.cnblogs.com/adoctors/p/10186861.html
Copyright © 2011-2022 走看看