国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

React 快速入門

ChristmasBoy / 2115人閱讀

摘要:中的方法調(diào)用了并傳入了最新的值。在前一次渲染中,已經(jīng)將的設(shè)置為,并將的設(shè)置為

本文采用 es6 語法,完全參考 https://reactjs.org/docs/
本文完全參考 React 官方 Quick Start 部分,除了最后的 thinking-in-react 小節(jié)
安裝

首先你需要點擊安裝 nodejs(npm)。然后執(zhí)行:

npm install -g create-react-app

如果上述命令執(zhí)行失敗可以運行以下命令:

npm install -g create-react-app --registry=https://registry.npm.taobao.org

然后建立一個 react 并運行:

create-react-app myApp
cd myApp
npm start

這樣你就簡單的完成了一個 react app 建立,其目錄結(jié)構(gòu)如下( 圖中不包括 node_modules 目錄,下同 ):

Hello World

我們刪除一些不必要的東西,然后修改目錄結(jié)構(gòu)如下(不能刪 node_modules 目錄,如果刪了就在項目目錄下運行 npm i 就好了):

其中 components 是個目錄。

修改 index.js 如下:

import React from "react";
import ReactDOM from "react-dom";

ReactDOM.render(
  

hello world!

, document.getElementById("root") );

然后命令行運行:

npm start

你就可以看到熟悉的 "hello world" 了

JSX

JSX 是 react 中允許 js 和 html 混寫的語法格式,需要依賴 babel 編譯。這里我就只研究它的語法:

const element = 

Hello, world!

;

可以通過花括號在其中插入表達(dá)式:

function formatName(user){
  return user.firstName + " " + user.lastName;
}

const user = {
  firstName: "Harper",
  lastName: "Perez"
};

const element = (
  

Hello, {formatName(user)}!

); ReactDOM.render( element, document.getElementById("root") );

可以將 HTML 語句寫為多行以增加可讀性,用小括號括起來可以防止自動插入分號導(dǎo)致的錯誤。

JSX 也是個表達(dá)式,所以可以用在 for 和 if 中:

  function getGreeting(user){
    if (user){
      return 

Hello, {formatName(user)}!

; } return

Hello, Stranger.

; }

我們可以正常使用引號給 HTML 標(biāo)簽添加屬性,也可以使用 js 表達(dá)式

const element = 
; const element = ; //注意空標(biāo)簽以 /> 結(jié)尾,像 XML 一樣

注意 html 屬性名請使用小駝峰(camelCase)寫法

React 會在渲染之前 escape 所有在 JSX 嵌入的值,可以有效的防止 XSS 攻擊。

babel 會編譯 JSX 成 React.createElement() 的參數(shù)調(diào)用:

const element = (
  

Hello, world!

); // 編譯為以下形式 const element = React.createElement( "h1", {className: "greeting"}, "Hello, world!" );

而 React.createElement() 會生成這樣一個對象(React 元素):

const element = {
  type: "h1",
  props: {
    className: "greeting",
    children: "Hello, world"
  }
};
元素渲染

./public/index.html 中有一個 id 為 root 的 div。我們將這個 div 作為 react 渲染的容器。

回看 hello world 程序,通過 ReactDOM.render() 方法很輕松的把內(nèi)容渲染到了目標(biāo)容器上:

ReactDOM.render(
  

hello world!

, document.getElementById("root") );

當(dāng)然也可以這樣寫:

let content = 

hello world!

; ReactDOM.render( content, document.getElementById("root") );

下面我們寫一個復(fù)雜的,這是個實時更新的時鐘,通過 setInerval 每隔 1s 調(diào)用 ReactDOM.render:

function Tick(){
  const element = (
    

Hello, world!

It is {new Date().toLocaleTimeString()}.

); ReactDOM.render( element, document.getElementById("root") ); } setInterval(Tick, 1000);

重寫上面時鐘組件的代碼如下,使其組件化程度更高:

function Clock(props){
  return (
    

Hello, world!

It is {props.date.toLocaleTimeString()}.

); } function Tick(){ ReactDOM.render( //這個地方不得不傳入一個參數(shù), 但理論上獲取一個時鐘直接獲取就可以了,這個問題我們后面再解決 , document.getElementById("root") ); } setInterval(Tick, 1000);
組件

React 給我們提供了更好的管理我的代碼——組件。這里我們還是首先我們先了解一下自定義標(biāo)簽:

const element = ;

對這個標(biāo)簽的理解也不難,它實際上調(diào)用了 Welcome 函數(shù),并且將所有的屬性(這里只有name)打包為一個對象傳給 Welcome 函數(shù)。所以下面這個代碼輸出 ”Hello Sara"

function Welcome(props){
  return 

Hello, {props.name}

; } const element = ; ReactDOM.render( element, document.getElementById("root") );

組件幫助我事先一些重復(fù)的工作,比如這樣:

function Welcome(props){
  return 

Hello, {props.name}

; } function App(){ return (
); } ReactDOM.render( , document.getElementById("root") );

我們可以通過傳遞參數(shù)得到同一個組件構(gòu)建的不同模塊。

這里我們需要補充一個重要的概念:__純函數(shù)!!!__

如果一個函數(shù)執(zhí)行過程中不改變其參數(shù),也不改變其外部作用于參數(shù),當(dāng)相同的輸入總能得到相同的值時,我們稱之這樣的函數(shù)為純函數(shù)。__React 要求所有組件函數(shù)都必須是純函數(shù)。__

其實之前的一段代碼中 Tick, Welcome 函數(shù)就可以看做是一個組件,同時 React 建議組件名的首字母大寫。但是更多情況下我們會用到 es6 的語法構(gòu)建組件。以之前時鐘代碼為例,轉(zhuǎn)換過程分為五個步:

新建一個類,類名同組件函數(shù)名Clock,并繼承自 React.Component;

給該類添加一個方法 render(/無參數(shù)/);

將 Clock 的函數(shù)體作為該函數(shù)的函數(shù)體;

將 render 方法中的 props 換為 this.props;

刪除原有的 Clock 函數(shù)

結(jié)果如下:

class Clock extends React.Component {
  render(){
    return (
      

Hello, world!

It is {this.props.date.toLocaleTimeString()}.

); } }

但這樣計時的功能就不能用了,我們繼續(xù)往下看……

State 和 Lifecycle

解決上面這個問題,就需要用到 State 和 Lifecycle 的知識了

我們給 Clock 類添加一個構(gòu)造函數(shù),并且刪除 Clock 標(biāo)簽中的參數(shù):

class Clock extends React.Component {
  constructor(props){
    super(props);
    this.state = {date: new Date()};    //state 用來記錄狀態(tài)
  }

  render(){
    return (
      

Hello, world!

It is {this.state.date.toLocaleTimeString()}.

); } } ReactDOM.render( , //刪除參數(shù) document.getElementById("root") );

為了控制計時的生命周期,我們需要引入 2 個方法 componentDidMount() 和 componentWillUnmount(),前者在渲染(render方法)完成時立即執(zhí)行,后者在該 render 的內(nèi)容即將被移除前執(zhí)行。

很明顯,前者適合注冊計時器,后者可以用來清除計時器(防止內(nèi)存泄露)

componentDidMount(){
  this.timerID = setInterval(
    () => this.tick(),
    1000
  );
}
componentWillUnmount(){
  clearInterval(this.timerID);
}

下一步我們重寫 tick 函數(shù),此時的 tick 函數(shù)只需要修改 this.state 就行了。注意 React 要求不能直接修改該屬性,而是使用 setState() 方法,所以 tick 函數(shù)如下:

tick(){
  this.setState({
    date: new Date()
  });
}

這里需要注意的是,當(dāng) state 中有很多屬性的時候,比如:

this.state = {name:"Lily", age: 12};

執(zhí)行 setState 方法修改其中的內(nèi)容時并不會影響未修改的屬性:

this.setState({name: "Bob"});   //此后 this.state 為 {name:"Bob", age: 12};

此外 setState 可能是異步的,所以不要在更新狀態(tài)時依賴前值:

// 這是個反例
this.setState({
  counter: this.state.counter + this.props.increment,
});

為例解決這個問題,你可以傳入函數(shù)參數(shù):
// Correct
this.setState((prevState, props) => ({ //這里 prevState 更新前的 state 對象,props 為新值構(gòu)成的對象
counter: prevState.counter + props.increment
}));

此時,完整的代碼為:

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

  componentDidMount(){
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount(){
    clearInterval(this.timerID);
  }

  tick(){
    this.setState({
      date: new Date()
    });
  }

  render(){
    return (
      

Hello, world!

It is {this.state.date.toLocaleTimeString()}.

); } } ReactDOM.render( , document.getElementById("root") );
事件

React 事件注冊和原生 DOM 事件類似的,這里需要理解一些不同點即可:

事件名使用小駝峰寫法,而不是全小寫,例如:onclick 寫作 onClick

注冊事件使用花括號表達(dá)式替代原有函數(shù)寫法

無法通過事件函數(shù) return false 的方式阻止默認(rèn)事件,必須顯式的調(diào)用 preventDefault(),并且在使用時不用糾結(jié)瀏覽器兼容問題,React 已經(jīng)幫你處理好了

React 建議通常不需要通過 addEventListener 添加事件,只需要像上方代碼那樣在 render 時綁定事件即可

在 es6 語法的組件中注冊事件只需要將事件函數(shù)定義為該類的一個方法,然后在 render 時綁定即可:

render(){
    return (
      
    );
  }

在 class 中,除了箭頭函數(shù)定義的方法中 this 符合預(yù)期,其余方法中的 this 都是 undefined,應(yīng)該手動綁定。因此以下三個按鈕中 click2 會報錯。

class Button extends React.Component {
  constructor(){
    super();
    this.name = "Bob";
    this.click3 = this.click2.bind(this);
    this.click1 = () => {
      console.log(`hello ${this.name}`);
    }
  }
  click2(){
    console.log(`hello ${this.name}`);
  }

  render(){
    return (
      
        
        
        
        
      
    );
  }
}

以上幾種方法,React 推薦使用 click3 的實現(xiàn)方法,重寫如下:

class Button extends React.Component {
  constructor(){
    super();
    this.name = "Bob";
    this.click = this.click.bind(this);
  }
  click(){
    console.log(`hello ${this.name}`);
  }

  render(){
    return (
      
        
      
    );
  }
}

傳遞參數(shù)給事件的時候,第一個參數(shù)為 id, 第二個參數(shù)為 event。實際調(diào)用可以去以下兩種方式:


以上兩種方法等效,后一個方法的參數(shù) e 可以省略。

條件渲染

根據(jù)不同的條件(通常指state)渲染不同的內(nèi)容, 比如下面段代碼可以根據(jù) isLoggenIn 渲染不同的問候語:

function UserGreeting(props) {
  return 

Welcome back!

; } function GuestGreeting(props) { return

Please sign up.

; } function Greeting(props) { const isLoggedIn = props.isLoggedIn; if (isLoggedIn) { // 根據(jù) isLoggenIn 渲染不同的問候語 return ; } return ; } ReactDOM.render( // 你可以嘗試設(shè)置 isLoggedIn={true}: , document.getElementById("root") );

下面用 class 實現(xiàn)一個復(fù)雜一點的,帶有登錄/注銷按鈕的:

function LoginButton(props) {
  return (
    
  );
}

function LogoutButton(props) {
  return (
    
  );
}
class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoggedIn: false
    };

    // 修正 this 綁定
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
  }

  handleLoginClick() {
    this.setState({isLoggedIn: true});
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const { isLoggedIn } = this.state;

    let button = null;
    if (isLoggedIn) {
      button = ;
    } else {
      button = ;
    }

    return (
      
{/* Greeting 取自上一個示例 (注意這里的注釋寫法)*/} {button}
); } } ReactDOM.render( , document.getElementById("root") );

當(dāng)然,對于這樣一個簡單的示例,使用 if 可能你會覺的太復(fù)雜了,我們也可以使用 && ?: 這些運算符來代替 if 語句,就像寫 javascript 代碼一樣。我們極力的化簡一下上面的代碼:

class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoggedIn: false
    };
  }

  render() {
    const { isLoggedIn } = this.state;
    const button = isLoggedIn ?
          
          : ;

    return (
      

{ isLoggedIn ? "Welcome back!" : "Please sign up." }

{button}
); } } ReactDOM.render( , document.getElementById("root") );

當(dāng)然,如果你需要在某個條件下不進(jìn)行渲染,那么直接輸出 null 即可,比如下面這個組件,在 props.warnfalse 時不渲染任何內(nèi)容:

function WarningBanner(props) {
  if (!props.warn) {
    return null;
  }
  return (
    
Warning!
); }

需要注意的是,即便你輸出了 null, react 也會再渲染一次。同理,componentWillUpdatecomponentDidUpdate 也會被調(diào)用。

列表

在 React 中我們可以使用 map() 方法渲染列表,比如如下這個例子,將一組數(shù)據(jù)映射(map)為一組 dom:

const data = [1, 2, 3, 4, 5];
const listItems = data.map((item) =>
  
  • {item}
  • ); ReactDOM.render(
      {listItems}
    , document.getElementById("root") );

    我們注意到這里我們給 li (即列表的每個元素)標(biāo)簽加了一個 key 屬性,這個 key 用來幫助 React 判斷哪個元素發(fā)生了改變、添加或移除。關(guān)于這個 key 我們需要明白以下幾點:

    最好保證 key 是一個字符串,并且在該列表中唯一,如果你的數(shù)據(jù)中實在沒有唯一的 key 可以選擇,那么就使用數(shù)組的索引(index)吧(不推薦這樣)

    值得注意的是,如果你不給每個元素指定一個 key, react 會默認(rèn)使用索引(index)作為 key

    key 的值只是給 React 起到類似暗示的作用,不會真正的傳遞給 dom, 所以如果你需要使用 key 的值,應(yīng)使用一個其它變量傳遞該值。

    當(dāng)然,上面代碼我們也可以寫成 inline 的形式:

    const data = [1, 2, 3, 4, 5];
    ReactDOM.render(
      
      { data.map((item) =>
    • {item}
    • ); }
    , document.getElementById("root") );
    表單

    表單的處理會和原生的 html 有一些區(qū)別,因為 React 可以很好的幫助你使用 js 控制你的表單,這里我們需要引入一個新的概念:受控組件。

    受控組件說白了就是其值受 react 控制的組件。其中,表單的元素通常都會具有其自己的 state,該值會隨著用戶的輸入改變。比如下面這個例子,會在用戶提交時輸出用戶的名字:

    class NameForm extends React.Component {
      constructor(props) {
        super(props);
        this.state = {value: ""};
    
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
      }
    
      handleChange(event) {
        this.setState({value: event.target.value});
      }
    
      handleSubmit(event) {
        alert("A name was submitted: " + this.state.value);
        event.preventDefault();
      }
    
      render() {
        return (
          
    ); } }

    不難發(fā)現(xiàn),這里使用了,onchange 事件不斷的將用戶的輸入綁定到 this.state.value 上,然后通過和用戶輸入同步的重繪實現(xiàn)數(shù)據(jù)的顯示。這樣可以很好的控制用戶輸入,比如同步的將用戶輸入轉(zhuǎn)化為大寫:

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

    理解了上面的內(nèi)容我們可以知道,單純給一個 input 賦值一個值用戶是不能修改的,比如下面這行代碼:

    ReactDOM.render(, mountNode);

    但如果你不小心他的值設(shè)為 null 或 undefined(等同于沒有 value 屬性),這個 input 就可以被更改了:

    ReactDOM.render(, mountNode);
    setTimeout(function() {
      ReactDOM.render(, mountNode);
    }, 1000);

    在 React 中 textarea 也是通過 value 屬性實現(xiàn)其內(nèi)容變化的,而非其子節(jié)點:

    class EssayForm extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          value: "Please write an essay about your favorite DOM element."
        };
    
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
      }
    
      handleChange(event) {
        this.setState({value: event.target.value});
      }
    
      handleSubmit(event) {
        alert("An essay was submitted: " + this.state.value);
        event.preventDefault();
      }
    
      render() {
        return (