1. 程式人生 > >react 學習1

react 學習1

React 是什麼?

React 是一個採用宣告式,高效而且靈活的用來構建使用者介面的框架。

 

狀態提升

當你遇到需要同時獲取多個子元件資料,或者兩個元件之間需要相互通訊的情況時,把子元件的 state 資料提升至其共同的父元件當中儲存。之後父元件可以通過 props 將狀態資料傳遞到子元件當中。

 

受控元件

子元件 不再擁有自身的狀態資料了,從福罪案接受資料並將資料要改變的事件通知父元件改變狀態資料,我們成為受控元件

在寫元件的時候 儘量把元件寫成無狀態的受控元件  把資料放在父元件裡 這樣利於資料維護

但是這樣就會牽扯到元件之間的相互通訊,如果多個元件改變同一個資料的時候  就會相互影響,為了避免這樣的影響,就需要 淺拷貝——不可變性

改變應用資料的方式一般分為兩種。第一種是直接修改已有的變數的值。第二種則是將已有的變數替換為一個新的變數。

直接修改資料

var player = {score: 1, name: 'Jeff'};
player.score = 2;
// Now player is {score: 2, name: 'Jeff'}

替換修改資料

var player = {score: 1, name: 'Jeff'};

var newPlayer = Object.assign({}, player, {score: 2});
// Now player is unchanged, but newPlayer is {score: 2, name: 'Jeff'}

// 或者使用最新的物件分隔符語法,你可以這麼寫:
// var newPlayer = {...player, score: 2};

通過這樣的方式,我們可以得到以下幾點好處:

1.實現 撤銷/重做 以及時間旅行。 因為不改變已有的資料  所以我們在需要的時候隨時切換回歷史資料

2.記錄變化 每次我們都返回一個新的物件 所以要判斷對想是否被替換 那麼其中的資料肯定就改變了,檢查到替換之後 就可以執行對應的操作

編寫元件最好編寫 純元件 pure components  對於效能優化可以用  shouldComponentUpdate()

 

 

key 是 React 當中使用的一種特殊的屬性(除此之外還有 ref

 屬性)。當元素被建立時,React 會將元素的 key 值和對應元素繫結儲存起來。儘管 key 看起來像是 props 的一部分,可是事實上我們無法通過 this.props.key 獲取到 key 的值。React 會自動的在判斷元素更新時使用 key ,而元件自己是無法獲取到 key 的。

當一個列表被重新渲染時,React 會根據較新的元素內容依據相應的 key 值來匹配之前的元素內容。當一個新的 key 值新增到列表當中時,表示有一個元件被建立;被刪除時表示有一個元件被銷燬。Key 值可以讓 React 明確標識每個元件,這樣它才能在每次重新渲染時保有對應的狀態資料。假如你去改變某個元件的 key 值的話,它會在下次渲染時被銷燬並當作新的元件重新渲染進來。

強烈建議你在渲染列表項時新增 keys 值。 假如你沒有現成可以作為唯一 key 值的資料使用的話,你可能需要考慮重新組織設計你的資料了

 

根據官網寫的遊戲demo

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

// Square 元件代表一個單獨的 <button>
class Square extends React.Component {
  constructor() {
    super();
    this.state = {
      value: null,
    }
  }
  render() {
    return (
      <button className="square" onClick={this.props.onClick}>
        {this.state.value || this.props.value}
      </button>
    );
  }
}


//Board 元件包含了9個squares
class Board extends React.Component {

  renderSquare(i) {
    return <Square value={this.props.squares[i]}
      onClick={() => this.props.onClick(i)} />;
  }

  render() {
    //檢查是否有人獲勝 獲勝無法繼續落子
    const winner = calculateWinner(this.props.squares);
    let status;
    if (winner) {
      status = 'Winner:' + winner;
    } else {
      status = 'Next player: ' + (this.props.xIsNext ? 'X' : 'O');
    }

    return (
      <div>
        <div className="status">{status}</div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}


//Game 元件則為我們即將要編寫的程式碼預留了一些位置
class Game extends React.Component {

  constructor() {
    super();
    this.state = {
      history: [{
        squares: Array(9).fill(null),
      }],
      xIsNext: true,
      stepNumber: 0

    }
  }

  handleClick(i) {
    const history = this.state.history;
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      history: history.concat([{
        squares: squares
      }]),
      stepNumber: history.length,
      xIsNext: !this.state.xIsNext,
    })
  }

  jumpTo(step) {
    this.setState({
      stepNumber: step,
      xIsNext: (step % 2) ? false : true,
    })
  }
  render() {
    const history = this.state.history;
    const current = history[this.state.stepNumber];
    const winner = calculateWinner(current.squares);


    const moves = history.map((step, move) => {
      const desc = move ?
        'Move #' + move :
        'Game start';

      return (
        <li key={move}>
          <a href="#" onClick={() => this.jumpTo(move)} >{desc}</a>
        </li>
      );
    })
    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }

    return (
      <div className="game">
        <div className="game-board">
          <Board
            squares={current.squares}
            onClick={(i) => this.handleClick(i)}
          />
        </div>
        <div className="game-info">
          <div>{status}</div>
          <ol>{moves}</ol>
        </div>
      </div>
    );
  }
}

// ========================================

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


//判斷遊戲獲勝方的程式碼
function calculateWinner(squares) {
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
}