react组件(2)

有状态与无状态组件

有状态组件

意思是这个组件能够获取储存改变应用或组件本身的状态数据,在React当中也就是state,一些比较明显的特征是我们可以在这样的组件当中看到对this.state的初始化,或this.setState方法的调用等等。

无状态组件

这样的组件一般只接收来自其他组件的数据。一般这样的组件中只能看到对this.props的调用,通常可以用函数定义组件的方式声明。它本身不会掌握应用的状态数据,即使触发事件,也是通过事件处理函数传递到其他有状态组件当中再对state进行操作。

class StatefulLink extends React.Component {
  //构造函数中设置初始化状态
 constructor(props){
  super(props)
  this.state={
    active: false
  }
 }
  //点击事件触发,将状态取反 this.serState触发重新渲染
  handleChick(){
    this.setState({
    active:!this.state.active
      
    })
  }
  //返回元素
  render(){
    return <a style={{color: this.state.active?'red':'black'}}
             onClick ={this.handleChick.bind(this)}
             >点击会记录状态变色</a>
    
  }
}
//将组件StatefulLink渲染到root上
ReactDOM.render(<StatefulLink/>,document.getElementById('root'))

//无状态控件
class StatelessLink extends React.Component{
    constructor(props){
      super(props);
    }
    handleClick(){
      this.props.handleClick(this.props.router)
    }
    render(){
      const active=this.props.activeRouter=== this.props.router;
      return (
        <li>
          <a 
            style={{color:active?'red':'black' }}
           onClick={this.handleClick.bind(this)}
          >
          点击
          </a>
        </li>
      )
    }
}
class Nav extends React.Component{
  constructor(){
    super()
    //初始化时设置activeRouter值为home 
    this.state={activeRouter:'home'}
  }
  handleSwitch(router){
    this.setState({activeRouter:router})
  }
  
  render(){
    return(
    <ul>
        <StatelessLink activeRouter={this.state.activeRouter} router='home' handleClick={this.handleSwitch.bind(this)} />
        <StatelessLink activeRouter={this.state.activeRouter} router='blog' handleClick={this.handleSwitch.bind(this)} />
        <StatelessLink activeRouter={this.state.activeRouter} router='about' handleClick={this.handleSwitch.bind(this)} />
    </ul>
    )
    
  }
}

ReactDOM.render(<Nav />, document.getElementById('root2'))

 通过ReactDOM渲染组件 nav,在constructor方法中设置this.state标记默认选择,render返回react元素,由多个statelesslink组件组成,并绑定router属性的值与点击事件,activeRouter动态取当前初始化

设置的home。

nav中返回的元素由StatelessLink组件组成,因此在返回之前会进到StatelessLink中的constructor和render方法返回react元素,StatelessLink在返回之前定义了一个变量用于判断选中项控制变色。
第一次加载控件, ul中的三个StatelessLink元素 会全部走一遍class StatelessLink 组件的定义,因为nav中在构造函数中设定了当前活动的路由为home,作为唯一一个可用满足active判断的元素
(相当于后台代码中的循环判断),因此加载完成后默认选择第一项标红。StatelessLink 触发点击事件时,会先触发handleSwitch 重新设置当前选中项然后在重新渲染,单个li属于无状态组件,通过nav
容器组合之后需要一个状态来标记。

受控与非受控组件

受控组件

一般涉及到表单元素时我们才会使用这种分类方法,在后面一节课程表单及事件处理中我们还会再次谈论到这个话题。受控组件的值由props或state传入,用户在元素上交互或输入内容会引起应用state的改变。在state改变之后重新渲染组件,我们才能在页面中看到元素中值的变化,假如组件没有绑定事件处理函数改变state,用户的输入是不会起到任何效果的,这也就是“受控”的含义所在。

非受控组件

类似于传统的DOM表单控件,用户输入不会直接引起应用state的变化,我们也不会直接为非受控组件传入值。想要获取非受控组件,我们需要使用一个特殊的ref属性,同样也可以使用defaultValue属性来为其指定一次性的默认值。

class ControlledInput  extends React.Component{
  constructor(){
    super();
    this.state={value:'请输入...'};

  }
  handlechange(event)
  {
   
    this.setState({value:event.target.value})

  }

  render(){
    return(
    <lable>
      输入的值是:
      <input 
        type="text" 
        value ={this.state.value} 
        onChange={e=>this.handlechange(e) }
        />
    </lable>
  );
  }
}

class UncontrolledInput extends React.Component {
  constructor(){
    super();
  }
  handleChange(){
    
      console.log("Uncontrolled change:", this.input.value);
  }
  render(){
    return(
    <label>
      不可控的文本框
        <input 
          type="text"
           defaultValue="请输入..."
           ref={input => (this.input = input)}
          onChange={() => this.handleChange()}
         />
      </label>
    )
    
  }
}


ReactDOM.render(<controlledInput/>,document.getElementById('root'))
ReactDOM.render(<UncontrolledInput/>,document.getElementById('root2'))
controlledInput与UncontrolledInput 区别就在于用户输入不会直接引起应用state的变化

//用一个函数处理多个输入
class ContactEdit extends React.Component{
  constructor(){
    super();
    this.state={
      contact:{
        firstName: 'Bolun',
        lastName: 'Yu',
        phone: '123123123'
      }
    }
    this.handleChangeFor=propertyName=>event=>{
      const {contact} =this.state;
      const newContact = {
          ...contact,
          [propertyName]: event.target.value
        };
        this.setState({contact:newContact})
    }
  }
  render(){
    return (
       <div>
        <input
          type="text"
          onChange={this.handleChangeFor("firstName")}
          value={this.state.contact.firstName}
        />
        <input
          type="text"
          onChange={this.handleChangeFor("lastName")}
          value={this.state.contact.lastName}
        />
        <input
          type="text"
          onChange={this.handleChangeFor("phone")}
          value={this.state.contact.phone}
        />
      </div>
    )
  }
  
}

组合与继承 

class ContactEdit extends React.Component {
  constructor() {
    super();
    this.state = {
      contact : {
        firstName: 'Bolun',
        lastName: 'Yu',
        phone: '123123123'
      }
    }
    this.handleChangeFor = propertyName => event => {
      const { contact } = this.state;
      const newContact = {
        ...contact,
        [propertyName]: event.target.value
      };
      this.setState({ contact: newContact });
    };
  }

  render() {
    return (
      <div>
        <input
          type="text"
          onChange={this.handleChangeFor("firstName")}
          value={this.state.contact.firstName}
        />
        <input
          type="text"
          onChange={this.handleChangeFor("lastName")}
          value={this.state.contact.lastName}
        />
        <input
          type="text"
          onChange={this.handleChangeFor("phone")}
          value={this.state.contact.phone}
        />
      </div>
    );
  }
}

 

posted @ 2017-10-09 18:06  风吹一点云  阅读(225)  评论(0编辑  收藏  举报