React 入門簡介

這裏是以前寫的一些入門的教程,並不是很深入,但對大致瞭解react有一定的幫助。

React的意義

React 把過去不斷重複構建 UI 的過程抽象成了組件,且在給定參數的情況下約
定渲染對應的 UI 界面。React 能充分利用很多函數式方法去減少冗餘代碼。此外,由於它本身就
是簡單函數,所以易於測試。可以說,函數式編程纔是 React 的精髓

JSX(含易錯點)

JSX簡介

下面是最簡單的JSX變量

const element = <h1>Hello, world!</h1>;

可以在JSX內直接使用JavaScript 表達式,但是:在 JSX 當中的表達式要包含在大括號裏

const element = (
  <h1>
    Hello, {formatName(user)}!
  </h1>
);

JSX屬性

引號定義字符串屬性,大括號定義以JS表達式爲值的屬性。
但是:大括號外面再嵌套引號,會將引號內的都處理爲字符串

const element = <div tabIndex="0"></div>;
const element = <img src={user.avatarUrl}></img>;

JSX嵌套

標籤是閉合的,必須像HTML那樣有結尾,如 /> JSX使用駝峯法定義屬性名稱,更像JS

JSX代表objects 對象

組件

組件從概念上看就像是函數,它可以接收任意的輸入值(稱之爲“props”),並返回一個需要在頁面上展示的React元素。
props就像是即將傳入組件的參數
下方是定義一個組件的方法,它接收一個單一的props”對象並返回一個React元素。我們之所以稱這種類型的組件爲函數定義組件,是因爲從字面上來看,它就是一個JavaScript函數。

//使用JS函數
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
//使用ES6 class
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

組件渲染

當React遇到的元素是用戶自定義的組件,它會將JSX屬性作爲單個對象傳遞給該組件,這個對象稱之爲“props”。例如,這段代碼會在頁面上渲染出”Hello,Sara”:

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

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

組件必須以大寫字母開頭

組件組合

組件可以組合,但是:組件的返回值只能有一個根元素。這也是我們要用一個div包裹組件元素的原因

function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

組件提取(重點)

//原複雜組件,不可重用
function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <img className="Avatar"
             src={props.author.avatarUrl}
             alt={props.author.name} />
      </div>
    </div>
  );
}
//拿出來獨立的部分,自定義組件(因爲是組件,所以author和user究竟叫什麼,意義不大,只要組件易懂即可)
function Avatar(props) {
  return (
    <img className="Avatar"
      src={props.user.avatarUrl}
      alt={props.user.name}
    />
  );
}
//當需要使用Avatar這個組件的時候,傳入屬性值,能夠從父組件得到數據即可,這裏假設,父組件的屬性,就是命名爲author,現在使用Avatar:
<Avatar user={props.author} />
//可以看到,這裏,Avatar就的user就是它父組件的author,獲得了屬性值。這就是最基本的組件提取

props的只讀性

像純函數那樣使用props:當它沒有改變它自己的輸入值,當傳入的值相同時,總是會返回相同的結果。state可以在不違反上面規則的前提下,動態改變輸出

state和生命週期

定義爲類的組件,纔有額外的特性。

將函數轉換爲類

方法步驟:
1. 創建一個名稱擴展爲React.Component的ES6 類
2. 創建一個叫做render()的空方法
3. 將函數體移動到render()方法中
4. 在render()方法中,使用this.props替換props
5. 刪除剩餘的空函數聲明

//原 函數定義的組件
function Clock(props) {
  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {props.date.toLocaleTimeString()}.</h2>
    </div>
  );
}
//現 類組件 
class Clock extend React.Component{
    render(){
      return (
        <div>
          <h1>Hello, world!</h1>
          <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
        </div>
  );
    }
}

還有一種老方法,React.createClass,區別點擊鏈接

事件處理

語法不同

  1. React事件綁定屬性的命名採用駝峯式寫法,而不是小寫。
  2. 如果採用 JSX 的語法你需要傳入一個函數作爲事件處理函數,而不是一個字符串(DOM元素的寫法)
//HTML寫法
<button onclick="activateLasers()">
  Activate Lasers
</button>
//JSX寫法
<button onClick={activateLasers}>
  Activate Lasers
</button>

阻止默認行爲

不能使用返回 false 的方式阻止默認行爲。你必須明確的使用 preventDefault

//HTML
<a href="#" onclick="console.log('The link was clicked.'); return false">
  Click me
</a>
//reafunction ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('The link was clicked.');
  }

  return (
    <a href="#" onClick={handleClick}>
      Click me
    </a>
  );
}

2種事件處理的寫法(疑問:爲什麼必須將handleClick: function(event)等換成handleClick(event)才能順利運行?)

//第一種,ES6寫法
 class LikeButton extends React.Component {
           constructor(props) {
         super(props);
         this.state = {liked: true};
              this.handleClick = this.handleClick.bind(this);
      }
         getInitialState() {
          return {liked: false};
        }
        handleClick(event) {
          this.setState({liked: !this.state.liked});
        }
        render() {
          var text = this.state.liked ? '喜歡' : '不喜歡';
          return (
            <p onClick={this.handleClick}>
              你<b>{text}</b>我。點我切換狀態。
            </p>
          );
        }
      }

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

 //第二種
  var LikeButton = React.createClass({
        getInitialState: function() {
          return {liked: false};
        },
        handleClick: function(event) {
          this.setState({liked: !this.state.liked});
        },
        render: function() {
          var text = this.state.liked ? '喜歡' : '不喜歡';
          return (
            <p onClick={this.handleClick}>
              你<b>{text}</b>我。點我切換狀態。
            </p>
          );
        }
      });

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

條件渲染

與JS種使用沒什麼區別,使用較簡單

與運算符 && 的特性

{unreadMessages.length > 0 &&
        <h2>
          You have {unreadMessages.length} unread messages.
        </h2>
      }

在 JavaScript 中,true && expression 總是返回 expression,而 false && expression 總是返回 false。因此,如果條件是 true,&& 右側的元素就會被渲染,如果是 false,React 會忽略並跳過它。

列表 keys

map()函數

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
console.log(doubled);//[2, 4, 6, 8, 10]

使用map()渲染列表

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((numbers) =>
  <li>{numbers}</li>
);//listItems 渲染的是很多個<li></li>標籤,裏面的內容是numbers經過map()出來的,所以下方會渲染出5個li,外面需加上ul嵌套,否則報錯?(**需確認**)

ReactDOM.render(
  <ul>{listItems}</ul>,
  document.getElementById('root')
);

用keys提取組件

官方文檔的解釋有點不夠清晰
實際上,在哪輸出列表,就是在哪定義key。即使使用某組件接收列表值,也是在接收的時候定義key,而不是在這個組件中定義key。其實這個稍微想一想就可以理解了。
組件就是放在那給大家使用的,誰都能用,你給他定義了key,那怎麼玩?

function ListItem(props) {
  // 對啦!這裏不需要明確出key:
  return <li>{props.value}</li>;
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    // 又對啦!key應該在數組中被明確出來
    <ListItem key={number.toString()}
              value={number} />
  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

表單

受控組件

<input><textarea>, 和 <select>這類表單元素會維持自身狀態,並根據用戶輸入進行更新。但在React中,可變的狀態通常保存在組件的狀態屬性中,並且只能用 setState(). 方法進行更新

這邊直接可以在文檔中查看,鏈接

在react中,<input>,<textarea><select>是非常相似的,也是用this.state = {value: '你好.'};設置默認值。用handleChange(event) {this.setState({value: event.target.value});}獲取輸入值,用<textarea value={this.state.value} onChange={this.handleChange} />動態渲染輸入值。

但是在React中,會在根select標籤上而不是在當前的selected屬性上使用value屬性。代碼鏈接

//通過以下代碼可以看到,{value: 'lime'}中的默認值是小寫的,即,是標籤上的屬性,否則默認選擇第一個屬性
this.state = {value: 'lime'};
//省略代碼
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>

多個輸入框的解決辦法

當你有處理多個受控的input元素時,你可以通過給每個元素添加一個name屬性,來讓處理函數根據 event.target.name的值來選擇做什麼。

class Reservation extends React.Component {
  constructor(props) {
    super(props);
    //this.state這邊設置默認值
    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;
    //定義目標的name值
    const name = target.name;

    //this.setState這邊根據標籤的name,來確定設置的值
     this.setState({
      [name]: value
    });
  }

  render() {
    return (
      <form>
        <label>
          Is going:
          <input
      //這裏的name
            name="isGoing"
            type="checkbox"
            checked={this.state.isGoing}
            onChange={this.handleInputChange} />
        </label>
        <br />
        <label>
          Number of guests:
          <input
      //這裏的name
            name="numberOfGuests"
            type="number"
            value={this.state.numberOfGuests}
            onChange={this.handleInputChange} />
        </label>
      </form>
    );
  }
}

狀態提升

點擊鏈接參考詳細文檔

組合繼承

首先children是保留關鍵字,在使用props.children的時候,才能在組件中直接嵌套JSX
只有當此處是children時,才能在組件中直接嵌套JSX。自定義的組件應當屬性傳遞給父組件

function Child() {
  return <div>子組件</div>;
}
function Father(props) {
  return (
    <div>
      <p>父組件</p>
      {props.aaa}
    </div>
  );
}
function App() {
  return (
    <Father aaa={<Child/>}>
      <p>直接嵌套的JSX</p>
    </Father>
  );
}
ReactDOM.render(
  <App/>,
  document.getElementById('root')
);
//上面的代碼顯示爲:父組件 子組件

function Child() {
  return <div>子組件</div>;
}
function Father(props) {
  return (
    <div>
      <p>父組件</p>
      {props.children}
    </div>
  );
}
function App() {
  return (
    <Father children={<Child/>}>
      <p>直接嵌套的JSX</p>
    </Father>
  );
}
ReactDOM.render(
  <App/>,
  document.getElementById('root')
);
//上面的代碼顯示爲: 父組件 直接嵌套的JSX
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章