1. 程式人生 > >React基礎篇(2) -- state&props&refs

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>