【小入門】react極簡入門

前端小助手發表於2019-07-22

前言

本文為react入門介紹,一些基本的概念和知識點,僅供未使用過react童鞋瞭解參考,若已使用過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

複製程式碼

相關文章