React入門

React入門

本文介紹React的相關(guān)概念,使用方式。目的是使讀者對React有一個大致的了解,以便于能夠更加深入的學(xué)習(xí)、快速上手React。學(xué)習(xí)React要掌握其中的幾個重要的概念JSX、元素(事件處理)、組件(props、state、ref、受控組件、生命周期)。

React優(yōu)缺點

React是一個前端框架,學(xué)習(xí)框架必然要了解框架的優(yōu)缺點、以便根據(jù)不同的項目采用合適的框架。
優(yōu)點:

  • 能夠?qū)崿F(xiàn)服務(wù)器端的渲染,便于搜索引擎優(yōu)化。
  • 能夠很好的和現(xiàn)有的代碼結(jié)合。React只是MVC中的View層,對于其他的部分并沒有硬性要求。
  • 組件化的開發(fā)方式,能夠更好的復(fù)用代碼、更好的定位bug。
  • 使用virtual dom,性能很好

缺點:

  • 不是完整的開發(fā)框架需要加上其他東西才能寫大型應(yīng)用。

JSX

JSX是JavaScript Syntax eXtension的縮寫,它是一種在JavaScript中嵌入XML的React語法,類似于E4X。React推薦使用JSX來描述用戶界面

JSX語法需要寫在<script type="text/babel"></script>標(biāo)簽中或者使用babel轉(zhuǎn)碼器進(jìn)行轉(zhuǎn)碼

JSX基本語法規(guī)則:遇到 HTML 標(biāo)簽(以 < 開頭),就用 HTML 規(guī)則解析;遇到代碼塊(以 { 開頭),就用 JavaScript 規(guī)則解析。

JSX 允許直接在模板插入 JavaScript 變量。如果這個變量是一個數(shù)組,則會展開這個數(shù)組的所有成員

<script type="text/babel">
var arr = [
  <h1>Hello world!</h1>,
  <h2>React is awesome</h2>,
];
ReactDOM.render(
  <div>{arr}</div>,
  document.getElementById('example')
);
</script>

元素

元素是構(gòu)成React應(yīng)用的最小單位,React中元素時普通的對象。React DOM可以確保瀏覽器DOM的數(shù)據(jù)內(nèi)容與React元素保持一致。

const element = <h1>Hello, world</h1>;
// 使用ReactDOM.render渲染到頁面上
ReactDOM.render(
  element,
  document.getElementById('root')
);

當(dāng)元素被創(chuàng)建之后,是無法改變其內(nèi)容或?qū)傩缘?。如果想要改變需要將它傳入ReactDOM.render()方法中。(react只會渲染必要的部分)

元素除了可以是DOM元素外,還可以是自定義的組件。

事件處理

駝峰式命名,使用函數(shù)名作為事件處理函數(shù),需要使用e.preventDefault()來阻止默認(rèn)行為,不能直接使用return false阻止返回值。

<script type="text/babel">
class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(e) {
    e.preventDefault();
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}
</script>

e是一個合成事件不需要考慮跨瀏覽器的兼容性問題。

使用實驗性的屬性初始化器語法來綁定this

<script type="text/babel">
class LoggingButton extends React.Component {
  // This syntax ensures `this` is bound within handleClick.
  // Warning: this is *experimental* syntax.
  handleClick = () => {
    console.log('this is:', this);
  }
  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}
</script>

組件

顧明思議是用來將UI切分成可復(fù)用且獨立的部件。

函數(shù)、類定義組件:

<script type="text/babel">
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

class Welcome extends React.Component {
   constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

const element = <Welcome name="Sara" />;
</script>

組件之間可以像普通標(biāo)簽一樣嵌套組合成新元素、新組件。

style屬性的設(shè)置不能寫成:style="opacity:{this.state.opacity};",而要寫成style={{opacity: this.state.opacity}}。因為React組件樣式是一個對象,所以第一重大括號表示這是JS語法,第二重大括號表示樣式對象。

props

class 屬性需要寫成 className ,for 屬性需要寫成 htmlFor ,這是因為 class 和 for 是 JavaScript 的保留字。

this.props 對象的屬性與組件的屬性一一對應(yīng),但是有一個例外,就是 this.props.children 屬性。它表示組件的所有子節(jié)點

this.props.children 的值有三種可能:如果當(dāng)前組件沒有子節(jié)點,它就是 undefined ;如果有一個子節(jié)點,數(shù)據(jù)類型是 object ;如果有多個子節(jié)點,數(shù)據(jù)類型就是 array 。所以,處理 this.props.children 的時候要小心。

React 提供一個工具方法 React.Children 來處理 this.props.children 。我們可以用 React.Children.map 來遍歷子節(jié)點,而不用擔(dān)心 this.props.children 的數(shù)據(jù)類型是 undefined 還是 object。

props的值不能夠被改變。

使用propTypes來驗證別人使用組件時,提供的參數(shù)是否符合要求
使用defaultProps設(shè)置默認(rèn)值

Greeting.propTypes = {
    title: React.PropTypes.string.isRequired,
    //限制為一個子代
    children: PropTypes.element.isRequired
};
Greeting.defaultProps = {
    name:"test"
};

state

每當(dāng)組件的狀態(tài)state發(fā)生改變時,組件就可以自動的更新。

state在構(gòu)造函數(shù)中初始化,使用書面語的形式,即this.state = {}

狀態(tài)的更新需要使用setState(可接收對象或函數(shù)(參數(shù)是上一個狀態(tài)、props))函數(shù),不能直接使用書面語(this.state.comment = "")

this.props 和 this.state 可能是異步更新的,不能直接依靠它們來計算state,而應(yīng)該是使用函數(shù)的形式。

列表 & Keys

Keys可以在DOM中的某些元素被增加或刪除的時候幫助React識別哪些元素發(fā)生了變化。因此你應(yīng)當(dāng)給數(shù)組中的每一個元素賦予一個確定的標(biāo)識。

key應(yīng)該在數(shù)組中被明確出來,可以使用id或索引來作為key

<script type="text/babel">
const todoItems = todos.map((todo, index) =>
  // Only do this if items have no stable IDs
  <li key={index}>
    {todo.text}
  </li>
);
</script>

受控組件

在HTML當(dāng)中,像<input>,<textarea>, 和 <select>這類表單元素會維持自身狀態(tài),并根據(jù)用戶輸入進(jìn)行更新。但在React中,可變的狀態(tài)通常保存在組件的狀態(tài)屬性中,并且只能用 setState(). 方法進(jìn)行更新.

因此使用“受控組件”的形式來編寫表單組件(值統(tǒng)一寫在value屬性中,更新方法寫在onChange函數(shù)中)

多個受控組件的統(tǒng)一解決方案,動態(tài)確定state的屬性

<script type="text/babel">
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>
        <label>
          Is going:
          <input
            name="isGoing"
            type="checkbox"
            checked={this.state.isGoing}
            onChange={this.handleInputChange} />
        </label>
        <br />
        <label>
          Number of guests:
          <input
            name="numberOfGuests"
            type="number"
            value={this.state.numberOfGuests}
            onChange={this.handleInputChange} />
        </label>
      </form>
    );
  }
}
</script>

非受控組件

在受控組件中,表單數(shù)據(jù)由 React 組件處理。如果讓表單數(shù)據(jù)由 DOM 處理時,替代方案為使用非受控組件。(使用ref獲取DOM并取值(必須要等到DOM插入后才能獲得DOM),使用defaultValue設(shè)置默認(rèn)值)

<script type="text/babel">
class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.input.value);
    event.preventDefault();
  }
    render() {
      return (
        <form onSubmit={this.handleSubmit}>
          <label>
            Name:
            <input
              defaultValue="Bob"
              type="text"
              ref={(input) => this.input = input} />
          </label>
          <input type="submit" value="Submit" />
        </form>
      );
    }
}
</script>

狀態(tài)提升

如果多個組件中有需要共用的狀態(tài),應(yīng)該將該狀態(tài)設(shè)置在父組件上,來實現(xiàn)狀態(tài)共享。

<script type="text/babel">
const scaleNames = {
  c: 'Celsius',
  f: 'Fahrenheit'
};

function toCelsius(fahrenheit) {
  return (fahrenheit - 32) * 5 / 9;
}

function toFahrenheit(celsius) {
  return (celsius * 9 / 5) + 32;
}

function tryConvert(temperature, convert) {
  const input = parseFloat(temperature);
  if (Number.isNaN(input)) {
    return '';
  }
  const output = convert(input);
  const rounded = Math.round(output * 1000) / 1000;
  return rounded.toString();
}

function BoilingVerdict(props) {
  if (props.celsius >= 100) {
    return <p>The water would boil.</p>;
  }
  return <p>The water would not boil.</p>;
}

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

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

  render() {
    const temperature = this.props.temperature;
    const scale = this.props.scale;
    return (
      <fieldset>
        <legend>Enter temperature in {scaleNames[scale]}:</legend>
        <input value={temperature}
               onChange={this.handleChange} />
      </fieldset>
    );
  }
}

class Calculator extends React.Component {
  constructor(props) {
    super(props);
    this.handleCelsiusChange = this.handleCelsiusChange.bind(this);
    this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this);
    this.state = {temperature: '', scale: 'c'};
  }

  handleCelsiusChange(temperature) {
    this.setState({scale: 'c', temperature});
  }

  handleFahrenheitChange(temperature) {
    this.setState({scale: 'f', temperature});
  }

  render() {
    const scale = this.state.scale;
    const temperature = this.state.temperature;
    const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
    const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;

    return (
      <div>
        <TemperatureInput
          scale="c"
          temperature={celsius}
          onTemperatureChange={this.handleCelsiusChange} />
        <TemperatureInput
          scale="f"
          temperature={fahrenheit}
          onTemperatureChange={this.handleFahrenheitChange} />
        <BoilingVerdict
          celsius={parseFloat(celsius)} />
      </div>
    );
  }
}

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

</script>

生命周期

組件的生命周期分成三個狀態(tài):

  • Mounting:已插入真實 DOM
  • Updating:正在被重新渲染
  • Unmounting:已移出真實 DOM

React 為每個狀態(tài)都提供了兩種處理函數(shù),will 函數(shù)在進(jìn)入狀態(tài)之前調(diào)用,did 函數(shù)在進(jìn)入狀態(tài)之后調(diào)用,三種狀態(tài)共計五種處理函數(shù)。

  • componentWillMount()
  • componentDidMount()
  • componentWillUpdate(object nextProps, object nextState)
  • componentDidUpdate(object prevProps, object prevState)
  • componentWillUnmount()

此外,React 還提供兩種特殊狀態(tài)的處理函數(shù)。

  • componentWillReceiveProps(object nextProps):已加載組件收到新的參數(shù)時調(diào)用
  • shouldComponentUpdate(object nextProps, object nextState):組件判斷是否重新渲染時調(diào)用

參考文獻(xiàn):
React入門實例教程——阮一峰
React文檔15.6
React優(yōu)缺點

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

相關(guān)閱讀更多精彩內(nèi)容

  • React簡介 React是一個用于構(gòu)建用戶界面的JavaScript庫,主要有以下幾個特點: 聲明式設(shè)計--Re...
    紫諾_qiu閱讀 953評論 0 2
  • 現(xiàn)在最熱門的前端框架,毫無疑問是React。在基于React的React Native發(fā)布一天之內(nèi),就獲得了 50...
    Mycro閱讀 1,127評論 3 6
  • 1.React 的學(xué)習(xí)資源 react官方首頁https://facebook.github.io/react/ ...
    賈里閱讀 4,125評論 0 0
  • 作者:阮一峰原文地址:http://www.ruanyifeng.com/blog/2015/03/react.h...
    IT程序獅閱讀 1,154評論 0 16
  • Tomact啟動失敗總結(jié)會不斷更新1、一次遇見的情況如果你遇見這個情況 并且運(yùn)行后出現(xiàn)這個情況 你運(yùn)行的項目
    CoderLJW閱讀 587評論 0 0

友情鏈接更多精彩內(nèi)容