開發(fā)react須知

react官網教程基礎解析

1、使用redux和沒有redux,react寫法有什么不同嗎?

答:組件寫法一樣,但是state不一定交給組件內部管理,可能放到store上統(tǒng)一管理。

2、認識react,一個hello world!

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('root')
);

3、如何使用react?

答:推薦你使用ES6語法來寫react,首先你需要Babel編譯你的ES6代碼,其次,你才可以使用比如 => (箭頭函數),class(類),模板文字,let和const語句等ES6語法。

4、JSX介紹

答:JSX是一種表達式,它有一個根標簽,在內部可以嵌入表達式,使用{}(大括號)包裹起來。它看起來就是html的一部分,或者叫一個html模塊。

class T extends React.Component {
    render() {
        return <div className="left-enter" style={}>{value}</div>
    }
}

從上面的代碼例子你可以看到幾個和html不同的地方,class =》className,style是一個object,你還可以在dom元素中使用{}插入數據。

使用JSX還可以防止XSS(跨站腳本攻擊),因為JSX只是表達式,它需要先轉換成字符串,然后才能渲染到真實DOM上面,但對于真正的黑客來說,這種做法也不是安全的。

4、元素和組件的概念

react組件:

class T extends React.Component {
    render() {
        return <div className="left-enter" style={}>{value}</div>
    }
}

react元素:

<div className="left-enter" style={}>{value}</div>

5、組件的使用

函數組件:函數組件沒有狀態(tài)和生命周期,但是你可以返回一個react元素。

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

class組件:非常強大,有自己的state和生命周期。和函數組件一樣,class組件也需要返回一個react元素。

class Welcome extends React.Component {
  componentWillMount() {}
  componentDidMount() {}
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

在一個龐大復雜的網站應用中,要如何拆分組件呢?官網上說組件拆分的越細,復用性就越強,從實際開發(fā)中來看,這個說法沒有錯,但是
會帶來一個比較嚴重的問題,就是組件太多,管理起來不方便。有人使用第三方react組件的時候,只有那些文檔非常強大的開源組件
才能給你的開發(fā)提高效率。如果你自己的組件也想拆分到細致,那么寫好文檔是最重要的一步。

react還提到了一點,傳遞給組件的數據是"只讀"的,要保證組件中的數據是"純數據",輸入即輸出。那么,如果你需要在組件中修改props.data
該怎么做呢?

render() {
    const { data } = this.props
    //定義一個新的變量來保存修改后的值。
    let _data = data + 1;
}

6、組件的狀態(tài)和生命周期

前面我們提到組件分為函數組件和類組件,函數組件是無狀態(tài),類組件有狀態(tài)和生命周期。

什么是狀態(tài)?

答:通俗理解,就是組件不同時候的不同表現,比如,一個按鈕組件,可能有激活狀態(tài),不可點擊狀態(tài),顯示狀態(tài),隱藏狀態(tài)等,在react用state來保存這些狀態(tài)。
而state本身不僅僅表示組件狀態(tài),還可以保存組件的數據。

class Button extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
        isShow: true,
        text: props.text,
        disabled: true
    };
  }

  render() {
      const { isShow, text, disabled} = this.state
      return <button disabled={disabled} style={{display: isShow ? "block" : "none"}}>{text}</button>
  }
}

如果要修改state,請使用,注意,你不能在render函數里面直接修改state,而是要通過事件去觸發(fā)state更新。

this.setState({
    isShow: false,
    disabled: false
})

由于setState有批處理功能,所以該方法可能不一定同步更新,如果你需要依賴上一次的狀態(tài)和本次狀態(tài)的計算,那么需要寫成下面這種形式。

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

demo網址:http://codepen.io/hyy1115/pen/GmdOKJ?editors=0011

有時候,子組件不需要關注自身的狀態(tài),而是通過父組件的狀態(tài)來改變,這時候的子組件可以寫成函數形式,通過props傳遞父組件給的狀態(tài)。

react生命周期
生命周期表示組件的一生,從出生到輝煌到死亡,中間最主要也是最常用的3個狀態(tài)是:

componentWillMount:出生了,把組件的狀態(tài)和屬性都設置好。

componentDidMount:渲染出來了,我不再是JSX,而是真實DOM了。

componentWillUnmount:要死了,死之前把遺產處理好。

class Button extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
        isShow: true,
        text: props.text,
        disabled: true
    };
  }
  
  componentWillMount() {
      //出生了,可以給我數據和設置我的狀態(tài)
  }
  componentDidMount() {
      //活著多好
  }
  componentWillUnmount() {
      //要死了,把我的一生痕跡都清除
  }

  render() {
      const { isShow, text, disabled} = this.state
      return <button disabled={disabled} style={{display: isShow ? "block" : "none"}}>{text}</button>
  }
}

還有其他幾個生命周期,并不是非常常用,需要用到的時候去看下別人的博客。

7、事件處理

 <button onClick={(e) => this.handleClick(e)}>
 按鈕
</button>

<input type="text" onChange={(e) => this.handleClick(e)} />

8、條件渲染

前面button的例子我們已經使用到了條件渲染,條件渲染通過state來判斷,常用的是控制style、className、DOM屬性,JSX。

舉幾個常用的例子。

render() {
    return (
        <div>
        {
            this.state.isShow && <button>按鈕</button>    
        }
        </div>
    )
}
render() {
    return (
        <div>
        {
            this.state.isShow ? <button>按鈕</button> : <span>文本</span>
        }
        </div>
    )
}
render() {
    return <button disabled={this.state.disabled}>按鈕</button>
}

9、列表渲染

2個注意點:

數組要判斷是否為空;

必須給一個key。

render() {
    const { arr } = this.state
    return arr.length > 0 && arr.map((value, key) => <li key={key}>{value}</li> )
}

10、表單

我曾經經歷過的一次阿里的面試,就考到了react表單的知識點。

受控組件:由react控制輸入的表單組件。

在下面的例子中,input的value值由state來決定,用戶輸入觸發(fā)onChange事件,然后更新state,達到修改value的目的。

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  render() {
    return (
          <input type="text" value={this.state.value} onChange={this.handleChange} />
    );
  }
}

或許你沒看出來和正宗input元素的區(qū)別,看一個真實DOM元素的例子,value由inupt自身維護,我們沒有給value綁定值。

<input type="text">

textarea和input是一樣的用法。

select有些許不同,將value綁定到select上,而不是option。

<select value={this.state.value} onChange={this.handleChange}>
    <option value="1">1</option>
    <option value="2">2</option>
</select>

還有一種是多個輸入框的情況,比如登錄,有賬號、密碼等,這時候操作這些不同的input可以通過ref或者name,class,id等方法去setState,看
官方demo。

class Reservation extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isGoing: true,
      numberOfGuests: 2
    };

    this.handleInputChange = this.handleInputChange.bind(this);
  }

  handleInputChange(event) {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const name = target.name;

    this.setState({
      [name]: value
    });
  }

  render() {
    return (
      <form>
          <input
            name="isGoing"
            type="checkbox"
            checked={this.state.isGoing}
            onChange={this.handleInputChange} />
          <input
            name="numberOfGuests"
            type="number"
            value={this.state.numberOfGuests}
            onChange={this.handleInputChange} />
      </form>
    );
  }
}

不受控組件:很簡單,就是DOM自己維護狀態(tài)的組件,不受react控制。你可以給它設置defaultValue,但是不能去setState。

<input type="text" ref={(input) => this.input = input} defaultValue="默認值"/>

相信有人會試過設置defaultValue之后執(zhí)行了setState去修改value,這樣做控制臺會發(fā)出警告。

總結:受控組件是指受react控制的組件,表單組件中的value和state同步,不受控組件是指不受react控制的組件,表單組件中的
value不通過state同步,只能操作DOM去讀取value。

11、狀態(tài)提升

你一定聽說過變量提升,函數提升,那么狀態(tài)提升是什么呢?

首先你得了解雙向綁定和單向數據流,雙向綁定中,數據可以在不同的組件之間實現共享,這樣做的確有很大的好處,但是在react中,
不推薦使用雙向綁定,而是使用狀態(tài)提升的方式。

記得和阿里的一個面試官聊的時候,他要求我用react實現雙向綁定,而我認為react應該采用狀態(tài)提升來實現。最后沒說服他,或許讓Dan來
和他聊聊才有用,哈哈。

狀態(tài)提升:state推崇單向數據流,數據從父組件通過props流向子組件,如果你在子組件中,需要修改state來和其他子組件共享數據更新,
你需要使用回調函數給使數據更新給父組件,然后從父組件流向其他的子組件,這樣做是保證數據有單一的來源。

如果實子組件和子組件之間任意共享數據,那么,后期維護會比較痛苦,特別是找bug的時候。

看一個狀態(tài)提升的例子吧。


class Child extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    this.props.upDateValue(e.target.value);
  }

  render() {
    const {name, value} = this.props;
    return (
      <div>
        <p>{name}:</p>
        <input value={value}
               onChange={this.handleChange} 
          />
      </div>
    );
  }
}

class Demo extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: '', name: ''};
    
    this.upDateValue = this.upDateValue.bind(this);
  }

  upDateValue(value) {
    this.setState({value: value})
  }
  
  render() {
    const {value} = this.state;

    return (
      <div>
        <Child name="組件1" value={value} upDateValue={this.upDateValue} />
        <Child name="組件2" value={value} upDateValue={this.upDateValue} />
      </div>
    );
  }
}

ReactDOM.render(
  <Demo />,
  document.getElementById('root')
);

demo網址:http://codepen.io/hyy1115/pen/xdjoZQ?editors=0011

12、選擇組合還是繼承?

用過原生js或者jQuery的同學可能對基礎非常熟悉,繼承可以實現擴展很多功能。

在react組件開發(fā)中,我們的每個react組件都是繼承于React.Component。

class MyComponent extends React.Component {
    
}

我們不推薦你繼承MyComponent。

//不推薦
class NextComponent extends MyComponent {
    
}

你應該充分利用react組件的強大性能,開發(fā)各種你需要的組件繼承至React.Component。組件之間的嵌套非常強大,你可以嵌套函數組件,嵌套類組件。

詳情前往:https://facebook.github.io/react/docs/composition-vs-inheritance.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容