React學習筆記

安裝:

概述

  • React起源于FaceBook的內(nèi)部項目,因為該公司對市場上所有的JavaScript MVC框架都不滿意,就決定自己寫一套用來假設(shè)Instagram的網(wǎng)站,2013年5月開源。
  • 一般有三個庫文件,react.js,react-dom.js和Browser.js,它們必須首先加載,其中react.js是React的核心庫,react-dom.js是提供與DOM相關(guān)的功能,Browser.js的作用是將JSX的語法轉(zhuǎn)換為JavaScript語法,這一步很消耗時間,最好放到服務(wù)器完成。
  • script標簽的type屬性:
    • 自己書寫的js代碼,script標簽的type屬性要改成:text/babel,這是因為React獨有的JSX語法跟javaScript不兼容。凡是使用JSX的地方都要加上type="text/balbel"
  • $babel src --out build :將src子目錄的js文件進行語法轉(zhuǎn)換,轉(zhuǎn)碼后的文件全部放在build子目錄

核心:

ReactDoM.render()

  • 是React的最基本的用法,用于將模板轉(zhuǎn)為HTML語言,并插入指定的DOM節(jié)點。

JSX語法:

  • 概述:JavaScript的擴展語法。JSX用來聲明React當中的元素。
  • 基本解析規(guī)則:遇到HTML標簽(以<開頭),就用HTML規(guī)則解析,遇到代碼塊(以{開頭的),就用javascript規(guī)則解析。
  • 書寫規(guī)則:一般都會帶上換行和縮進,增強代碼可讀性。同時在JSX代碼紋面擴上一個小括號,這樣可以防止分號自動插入的bug,
- eg1:
var names = ['alice', 'emily', 'kate'];

ReactDOM.render(
<div>
{
    names.map(function (name){
        return <div key={v.toString()}>Hello,{name}!</div> 
    })
}
</div>, // 注意使用循環(huán)結(jié)構(gòu)時要添加key
document.getElementById('example')
);
//運行結(jié)果:


- eg2: 
const element = <h1>Hellow, world!</h1>

  • 可以用引號來定義以字符串為值的屬性:
const element = <div tabIndex = "0></div>;
  • 使用大括號來定義以javascript表達式為值得屬性:
const element = <img src = {user.avatarUrl}/>

  • 注意
    • 如果使用了大括號包裹javascrit表達式,就不要在外面用引號了。JSX會將引號當中的內(nèi)容識別為字符串而不是表達式
    • 因為JSX的特性更接近Javascript所以使用駝峰命名來定義屬性名。
  • 想要給渲染出的html標簽添加一個類名要寫成:className = "類名",不能用class
  • JSX防注入攻擊:
    • 可以放心的在JSX中使用用戶輸入,ReactDom在渲染之前會默認過濾所用傳入的值。他可以確保你的應(yīng)用不會被注入攻擊。所有內(nèi)容在渲染之前都被轉(zhuǎn)換成了字符串。
  • JSX轉(zhuǎn)化:
    • Babel轉(zhuǎn)義器會把jsx轉(zhuǎn)換成一個名為React.createElement()的方法調(diào)用。

元素渲染:

  • 元素是構(gòu)成React應(yīng)用的最小單位。與瀏覽器的Dom元素不同,React當中的元素事實上是普通的對象,ReactDOM可以確保瀏覽器DOM的數(shù)據(jù)與React元素保持一致。
  • 將元素渲染到DOM中。
    • 通過ReactDOM.render()的方法來將其渲染到頁面上:
    • 該方法有兩個參數(shù):第一個是要渲染的React元素,第二個是要插入的DOM節(jié)點。
  • React的元素都是不可變的,元素被創(chuàng)建之后,你是無法改變其內(nèi)容或者屬性的,一個元素好像就是動畫里的一幀,它代表應(yīng)用界面在某一時間點的樣子。對于初學者來說,更新界面的唯一辦法是創(chuàng)建一個新的元素,然后將它傳入React.render()方法。
  • eg
function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(
    element,
    document.getElementById('root')
  );
}

setInterval(tick, 1000);

如下方法通過setInterval計時器每秒鐘調(diào)用一個ReactDOM.render()

  • 注意: 在實際生產(chǎn)開發(fā)中大多數(shù)應(yīng)用只會調(diào)用一個ReactDOM.render()

  • React只會更新必要的部分。

    • ReactDOM 首先會比較元素內(nèi)容先后的不同,而在渲染過程中只會更新變化的部分。如上的例子中React只改變了頁面中數(shù)字發(fā)生變化的部分。

組件&&props

概述:

  • 組件可以將UI切成一些獨立的、可服用的部件,這樣你就只需要專注構(gòu)建每一個單獨的部件。從概念上看其就像是函數(shù),他可以接收任意值(稱之為“props”),并返回一個需要在頁面上展示的React元素。

組件的定義:

  • 定義一個組件最簡單的方式是使用Javascript函數(shù)(必須要有一個return值):
  • eg:

規(guī)則:

  • 無論是使用函數(shù)或是類來聲明的組件都不能修改他自己的props(列入:給props增加屬性,刪除屬性,更改屬性值)。
function Welcome() {
    return <h1>Hello,{props.name}</h1>
}
// 該函數(shù)是一個有效的React組件,他接收一個單一的'props'對象并返回一個React元素。我們之所以成這種類型的組件為函數(shù)定義組件,是因為從字面上來看,他就是一個javascript函數(shù)。


  • 我們也可以使用ES6的class來定義一個組件:
  • eg
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

組件渲染

  • react的元素可以是HTML元素,也可以是用戶的自定義的組件
const element = <welcome name = "Sara" />

  • 當React遇到的元素是用戶自定組件,他會將JSX屬性作為單個的對象傳遞給改組件,這個對象稱之為'props'
  • eg:
function Welcome (props){
    retrun <h1>Hello,{props.name</h1>
}
const element = <Welcome name = "Sara" />
ReactDOM.render(
element,
document.getElementById('root')
);

// 如上在頁面展示內(nèi)容為:Hello ,Sara
  • 渲染流程:
    1.我們對<Welcome name="Sara"/>元素調(diào)用了ReactDOM.render()方法。
  1. React將{name: 'Sara'}作為props傳入并調(diào)用Welcome組件。
  2. Welcome組件將<h1>Hello, Sara</h1>元素作為結(jié)果返回。
  3. ReactDOM將DOM更新為<h1>Hello,Sara</h1>
  • 注意:組件的名稱必須以大寫字母開頭。eg:<div/>表示一個DOM標簽,但<Welcome/>表示一個組件并限定了它的可用范圍
  • 組合組件:
    • 組件可以在他的輸出中引用其他組件:

組件的生命周期和狀態(tài)

應(yīng)用條件

  • 組件的狀態(tài)state:與屬性非常相似,但是是私有的,完全受控于當前組件。
  • 要想使用組件的生命周期鉤子函數(shù),或者使用給組件加狀態(tài)必須以類的形式定義組件。

概述:

  • 每個組件都有幾個生命周期函數(shù),以will為前綴的函數(shù)是發(fā)生在母線是之前條用,以did為前綴的是在發(fā)生某些事之后調(diào)用。

Mounting : 如下方法在組件實例被創(chuàng)建和被插入到dom中時被調(diào)用。

  • constructor():
    • 在組件被mounted之前調(diào)用,我們的組件繼承自React.Component,constrcutor函數(shù)中我們在其他操作前應(yīng)該先調(diào)用super(props),否則this.props將會是undefined.
    • constructor是初始化state的好地方。如果我們不需要初始化state,也不需要bind任何方法,那么我們的組建中不需要出現(xiàn)constructor函數(shù)。
    • 注意如下情況,很容易產(chǎn)生bug,我們通常的做法是,提升state到父組件中,而不是使勁兒的同步state和props.
constructor (props){
    super(props);
    this.state={
        color:props.initialColor
    };
}
  • componentWillMount()

    • 此方法在mounting之前被立即調(diào)用,他在render()之前調(diào)用,因此在此方法中setState不會觸發(fā)重新渲染。此方法是服務(wù)渲染中調(diào)用的唯一的生命周期鉤子,通常我們建議使用constructor()
  • render()

    • render()方法應(yīng)該是一個純方法,級他不會修改組價的state,在每一次調(diào)用時返回同樣的結(jié)果。他不直接和瀏覽器交互,如果我們 想要交互,應(yīng)該在compentDidMount()或者其他的生命中期函數(shù)里面。
  • componentDidMount()

    • 此方法在組件被mounted之后立即被調(diào)用,初始化dom接單應(yīng)該在此方法中,如果要從遠程獲取數(shù)據(jù),這里是實例化網(wǎng)絡(luò)請求的好地方。此方法中setState會觸發(fā)組件重新渲染。
  • Updating

    • props和state的改變產(chǎn)生更新。在重新渲染組件時,如下的方法被調(diào)用:
    • componentWillReactProps(): 一個已經(jīng)mounted的組件接受一個新的props之前,componentWillReceiveProps()被調(diào)用,如果我們需要更新state來相應(yīng)prop的更改,我們可以再此方法中比較props和nexProps并使用this.setState來更改state.
    • 注意: 即使props沒有改變,React也可以調(diào)用這個方法,因此如果你只想要處理改變,請確保比較當前值和下一個值。當父組件重新渲染時,可能會發(fā)生這種情況。
    • React在組件mounting期間不會調(diào)用此方法,只有在一些組件的props可能被更新的時候才會調(diào)用。調(diào)用this.setState通常不會觸發(fā)發(fā)componentWillReceiveProps。
  • shouldComponentUpdate()

    • 使用此方法讓React知道組件的輸出是否不受當前state或props更改的影響。默認行為實在每次state更改是重新渲染組件,在大多數(shù)情況下,我們應(yīng)該默認該行為。 當接收到新的props或state時,shouldComponentUpdate()在渲染之前被調(diào)用。默認返回true,對于初始渲染或者使用forceUpdate()時,不調(diào)用此方法。返回false不會阻止子組件的state更改時,該子組件的重新渲染。
  • componentWillUpdate()

    • 當接收新的props或state時,componentWillUpdate()在組件渲染之前被立即調(diào)用。使用此函數(shù)作為更新方程之前執(zhí)行準備的機會。初始渲染不會不調(diào)用此方法。
    • 注意:這里不能調(diào)用this.setState(),如果調(diào)用了會產(chǎn)生死循環(huán),一只更新。

組件的生命周期和狀態(tài)簡述:(總共10個api)

實例化

  • getDefaultProps
    作用于組件類,只調(diào)用一次,返回對象用于設(shè)置的默認props,對于引用值,會在實例中共享。
  • getInitialState
    作用于組件的實例,在實例創(chuàng)建時調(diào)用一次,用于初始化每個state,此時可以訪問this.props。
  • componentWillMount
    在首次完成渲染之前條用,此時仍可以修改組件的state.
  • render
    比選方法,創(chuàng)建虛擬DOM,該方法具有特殊的規(guī)則:
    • 只能通過this.props和this.state訪問數(shù)據(jù)。
    • 可以返回null,false或者任何React組件(返回React組件時,必須要有一個根元素)。
    • 只能出現(xiàn)一個頂級組件(不能返回數(shù)組)
    • 不能改變組件的狀態(tài)。
    • 不能改DOM的輸出。
  • componentDidMount
    正式DOM被渲染出來之后調(diào)用,在方法中可以通過this.getDOMNode()訪問到真實的DOM元素。此時可以使用其他累出來操作這個DOM。在服務(wù)端中,改方法不會被調(diào)用。

存在期

  • componentWillReceiveProps
    組件接收到props時調(diào)用,并將其作為參數(shù)nextProps使用,此時可以更改組件的props及state.
componentWillReceiveProps:function(nextProps){
          if(nextProps.bool){
                  this.setState({
                        bool: true
                  });
          }

}
  • shouldComponentUpdate
    組件是否應(yīng)當渲染新的Props或者state,返回false表示跳過后續(xù)生命周期方法,通常不需要使用以避免出現(xiàn)bug。在出現(xiàn)瓶頸時,可以通過該方法進行適當?shù)膬?yōu)化。
  • componentDidUpdate
    完成渲染新的props或者state后調(diào)用,此時可以訪問到新的DOM元素。
  • componentWillUnmount
    組件被移除之前被調(diào)用,可以用于做一些清理工作,在componentDidMount方法中添加的所有任務(wù)都需要在該方法中撤銷,比如創(chuàng)建的定時器或添加的事件監(jiān)聽器。

state與props的區(qū)別:

state的作用:

  • state是React中組件的一個對象。React把用胡界面當做是狀態(tài)機,想象他又不同的狀態(tài),然后渲染這些狀態(tài),可以輕松的讓用戶界面與數(shù)據(jù)保持一致。
  • react中,更新組建的state最導致重新渲染用戶界面(不要操作DOM),簡言之:就是用戶界面會隨著state變化而變化。

state工作原理:

  • 常用的通知React數(shù)據(jù)變化的方法是調(diào)用setState(data,callback).這個方法。這個方法會合并data到this.state,并重新渲染組件。渲染完成后,調(diào)用可選的callback,大部分情況不需要提供callback,因為React會負責吧界面更新到最新狀態(tài)。

應(yīng)用場景:

  • 大部分組件的工作原理應(yīng)該是從props里取數(shù)據(jù)并渲染出來。但是,有時需要對用戶的輸入,服務(wù)器請求或者時間變化做出響應(yīng),這是才需要state.
  • 組件應(yīng)該盡可能的無狀態(tài),這樣能隔離state.把他放到最合理的地方(Redus做的就是這個事情),也能減少冗余并易于解釋程序運作過程。
  • 常用的模式就是創(chuàng)建多個只負責渲染數(shù)據(jù)的無狀態(tài)(stateless)組件,在他們的上層創(chuàng)建一個有狀態(tài)(statefull)組件并把它的狀態(tài)通過props傳遞給子級,有狀態(tài)的組件封裝了所有的用戶交互邏輯,而這些無狀態(tài)組件只負責聲明是的渲染數(shù)據(jù)。

那些應(yīng)該作為state

  • state應(yīng)該包括那些可能被組件的事件處理器改變并觸發(fā)用戶界面更新的數(shù)據(jù)。中數(shù)據(jù)一般很小且能被JSON序列化

條件渲染:

  • React中的條件渲染和javascript中的一致,使用javascript操作符if或者條件運算符來創(chuàng)建當前的元素,然后讓React根據(jù)他們來更新UI。
function UseGreeting(props){
  return <h1>Welcome back!</h1>
}
function GuestGreeting(props){
    return <h1>Please sign up.</h1>
}
// 創(chuàng)建一個條件渲染組件。
function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

ReactDOM.render(
  // Try changing to isLoggedIn={true}:
  <Greeting isLoggedIn={false} />,
  document.getElementById('root')
);
  • 元素變量:可以使用變量來存儲元素。他可以幫助你有條件的渲染組件的一部分,兒輸出的其他部分不會改變。
//新建兩個無狀態(tài)組件
function LoginButton(props) {
  return (
    <button onClick={props.onClick}>
      Login
    </button>
  );
}

function LogoutButton(props) {
  return (
    <button onClick={props.onClick}>
      Logout
    </button>
  );
}
/// 創(chuàng)建一個有狀態(tài)組件。
class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

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

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

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

    let button = null;
    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />;
    }

    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        {button}
      </div>
    );
  }
}

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

  • 與運算符 &&
    可以通過用花括號包裹代碼在JSX中嵌入任何表達式,也包括javascript的邏輯&&,他可以方便的條件渲染一個元素。
function Mailbox(props) {
  const unreadMessages = props.unreadMessages;
  return (
    <div>
      <h1>Hello!</h1>
      {unreadMessages.length > 0 &&
        <h2>
          You have {unreadMessages.length} unread messages.
        </h2>
      }
    </div>
  );
}

const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
  <Mailbox unreadMessages={messages} />,
  document.getElementById('root')
);
  • 三目運算符:條件渲染的另一種方法是使用javascript的條件運算符:condition?true:false
eg1:
 render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
    </div>
  );
}

eg2:
render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      {isLoggedIn ? (
        <LogoutButton onClick={this.handleLogoutClick} />
      ) : (
        <LoginButton onClick={this.handleLoginClick} />
      )}
    </div>
  );
}
  • 阻止組件渲染:在極少數(shù)的情況下,你可能希望隱藏組件,即使他被其他組件渲染。讓render方法返回null而不是他的渲染結(jié)果即可實現(xiàn)。
 function (!props.warn){
    return null
}

return (
          <div className = "warning">
                 Warning!
         </div>
       )
}

class Page extends React.Component {
  constructor(props) {
    super(props);
    this.state = {showWarning: true}
    this.handleToggleClick = this.handleToggleClick.bind(this);
  }

  handleToggleClick() {
    this.setState(prevState => ({
      showWarning: !prevState.showWarning
    }));
  }

  render() {
    return (
      <div>
        <WarningBanner warn={this.state.showWarning} />
        <button onClick={this.handleToggleClick}>
          {this.state.showWarning ? 'Hide' : 'Show'}
        </button>
      </div>
    );
  }
}

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

列表&keys

  • 渲染多個組件:
    可以通過使用{}在JSX內(nèi)構(gòu)件一個元素集合
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li>{number}</li>
);
// 把整個listItems插入到ul元素中,然后渲染DOM:
ReactDOM.render(
    <ul>{listItems}</ul>
     document.getElementById('root')
);
  • 基礎(chǔ)列表組件:
    通常你需要渲染一個列表到組件中
 function NumberList(props){
    const number = props.number;
    const listItems = number.map((number)=>{
          <li>{number}</li>
    });
    return (
        <ul>{listItems}</ul>
    )
}
const numbers = [1,2,3,4,5];
ReactDOM.render(
    <NumberList number = {numbers} />
     document.getElementById('root')
) ;
  • keys
    keys可以在DOM中的木屑元素被增減或者刪除的時候幫助React識別哪些元素發(fā)生了變化。因此你應(yīng)當給數(shù)組中的每一個元素富裕一個明確的標識。一個元素的key最好是這個元素在列表中擁有的一個獨一無二的字符串。通常,我們使用來自數(shù)據(jù)的id作為元素的key,當元素沒有確定的ID時,你可以使用他的序列號索引index作為key
最后編輯于
?著作權(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)容

  • Learn from React 官方文檔 一、Rendering Elements 1. Rendering a...
    恰皮閱讀 2,726評論 2 3
  • 寫在前面 React入門學習筆記。 教程可參考:React 教程 | 菜鳥教程阮一峰的網(wǎng)絡(luò)日志 > React 入...
    年少有van閱讀 461評論 1 1
  • 本筆記基于React官方文檔,當前React版本號為15.4.0。 1. 安裝 1.1 嘗試 開始之前可以先去co...
    Awey閱讀 7,913評論 14 128
  • 摘要 React中的組件類似于狀態(tài)機,每個組件都被設(shè)計成為在其生命周期過程中輸出穩(wěn)定、語義化的標簽。React組件...
    桂圓_noble閱讀 2,636評論 2 11
  • 最近看了一本關(guān)于學習方法論的書,強調(diào)了記筆記和堅持的重要性。這幾天也剛好在學習React,所以我打算每天堅持一篇R...
    gaoer1938閱讀 1,803評論 0 5

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