React學習(二)

學習過程當中本身弄得小項目javascript

在線預覽html

整理過程當中遇到了好用的前端js庫:前端

immutable(持久化數據結構、結構共享):vue

NPM 地址java

Immutable 詳解及 React 中實踐 · Issue #3 · camsong/blogreact

classnames(支持對className的邏輯操做):git

NPM地址github

 

1.React 安裝ajax

使用Facebook提供的 create-react-app 腳手架工具構建react項目npm

create-react-app 是來自於 Facebook,經過該命令咱們無需配置就能快速構建 React 開發環境。

create-react-app 自動建立的項目是基於 Webpack + ES6 。

配置 npm 的registry 下載package更快

$ npm config set registry https://registry.npm.taobao.org

 配置後可經過下面方式來驗證是否成功

$ npm config get registry

 create-react-app構建啓動項目

$ cnpm install -g create-react-app
$ create-react-app my-app
$ cd my-app/
$ npm start

附:create-react-app github地址

2.JSX語法    

一種 JavaScript 的語法擴展。 推薦在 React 中使用 JSX 來描述用戶界面

能夠任意地在 JSX 當中使用 JavaScript 表達式,在 JSX 當中的表達式要包含在大括號裏。

React DOM 在渲染以前默認會 過濾 全部傳入的值。它能夠確保你的應用不會被注入攻擊。全部的內容在渲染以前都被轉換成了字符串。這樣能夠有效地防止 XSS(跨站腳本) 攻擊。

若是你已經有了個 props 對象,而且想在 JSX 中傳遞它,你可使用 ... 做爲擴展操做符(Spread syntax)來傳遞整個屬性對象。下面兩個組件是等效的:

function App1() {
  return <Greeting firstName="Ben" lastName="Hector" />;
}

function App2() {
  const props = {firstName: 'Ben', lastName: 'Hector'};
  return <Greeting {...props} />;
}

 

警告:
    由於 JSX 的特性更接近 JavaScript 而不是 HTML , 因此 React DOM 使用 camelCase 小駝峯命名 來定義屬性的名稱,而不是使用 HTML 的屬性名稱。
    例如,class 變成了 className,而 tabindex 則對應着 tabIndex。
3.state & props & render

state:

構造函數是惟一可以初始化 this.state 的地方

修改state經過this.setState({comment: 'Hello'})

狀態更新多是異步的,要是修改state的變量依賴自己,須要經過setState的callback解決:

  incrementCount() {
    const me = this;
    me.setState((prevState) => {
      return { count: prevState.count + 1 }
    });
    //ERROR
    // me.setState({
    //   count : me.state.count + 1
    // });
  }

  incrementTwo() {
    const me = this;
    me.incrementCount();
    me.incrementCount();
  }

 props:

 不管是使用函數或是類來聲明一個組件,它決不能修改它本身的props

{props.children}獲取包含的子組件列表

render:

class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

組件的返回值只能有一個根元素。這也是咱們要用一個<div>來包裹全部<h1/><h2/>元素的緣由。

布爾值、Null 和 Undefined 被忽略渲染時會被忽略

<div />
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{undefined}</div>
<div>{true}</div>

4.keys

React提供key屬性,來提升元素變動以後從新渲染的效率

Keys能夠在DOM中的某些元素被增長或刪除的時候幫助React識別哪些元素髮生了變化。所以你應當給數組中的每個元素賦予一個肯定的標識。

一個元素的key最好是這個元素在列表中擁有的一個獨一無二的字符串。一般,咱們使用來自數據的id做爲元素的key

若是列表能夠從新排序,咱們不建議使用索引來進行排序,由於這會致使渲染變得很慢

不能經過props.key獲取key的值。

舉個例子:

<li>a</li>
<li>b</li>

 改變後:

<li>c</li>
<li>a</li>
<li>b</li>

肉眼很容易看出來在第一行加了一個 c ,但React並不知道,而是一行一行的比較(a 與 c),因此須要在每一個 li 都一個 key ,利於React辨別,從而提供效率


5.form 表單使用

html:
<textarea>
  Hello there, this is some text in a text area
</textarea>

jsx:
<textarea value={this.state.value} onChange={this.handleChange} />


html:
<select>
  <option value="grapefruit">Grapefruit</option>
  <option value="lime">Lime</option>
  <option selected value="coconut">Coconut</option>
  <option value="mango">Mango</option>
</select>

jsx:
<select value={this.state.value} onChange={this.handleChange}> 
	<option value="grapefruit">Grapefruit</option> 
	<option value="lime">Lime</option> 
	<option value="coconut">Coconut</option> 
	<option value="mango">Mango</option> 
</select>

6.propTypes 屬性約束 & 設置默認屬性值

屬性約束:

import PropTypes from 'prop-types';

class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}

Greeting.propTypes = {
  name: PropTypes.string
};

具體有哪些驗證器:參考官網

屬性默認值:

能夠經過配置 defaultProps 爲 props定義默認值:

class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}

// 爲屬性指定默認值:
Greeting.defaultProps = {
  name: 'Stranger'
};

// 渲染 "Hello, Stranger":
ReactDOM.render(
  <Greeting />,
  document.getElementById('example')
);
提示:
    類型檢查發生在 defaultProps 賦值以後,因此類型檢查也會應用在 defaultProps 上面。

7.refs

Refs 提供了一種訪問在 render 方法中建立的 DOM 節點或 React 元素的方式

什麼時候使用 Refs
下面是幾個適合使用 refs 的狀況:
    處理焦點、文本選擇或媒體控制。
    觸發強制動畫。
    集成第三方 DOM 庫

若是能夠經過聲明式實現,則儘可能避免使用 refs。
例如,不要在 Dialog 組件上直接暴露 open() 和 close() 方法,最好傳遞 isOpen 屬性。

經典案例:

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.focus = this.focus.bind(this);
  }

  focus() {
    // 直接使用原生 API 使 text 輸入框得到焦點
    this.textInput.focus();
  }

  render() {
    // 使用 `ref` 的回調將 text 輸入框的 DOM 節點存儲到 React
    // 實例上(好比 this.textInput)
    return (
      <div>
        <input
          type="text"
          ref={(input) => { this.textInput = input; }} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focus}
        />
      </div>
    );
  }
}

React 組件在加載時將 DOM 元素傳入 ref 的回調函數,在卸載時則會傳入 nullref 回調會在componentDidMountcomponentDidUpdate 這些生命週期回調以前執行。

注意:
若是 ref 回調之內聯函數的方式定義,在更新期間它會被調用兩次,第一次參數是 null ,以後參數是 DOM 元素。這是由於在每次渲染中都會建立一個新的函數實例。
所以,React 須要清理舊的 ref 而且設置新的。經過將 ref 的回調函數定義成類的綁定函數的方式能夠避免上述問題,可是大多數狀況下可有可無。

8.Fragments

React 中一個常見模式是爲一個組件返回多個元素。Fragments 可讓你聚合一個子元素列表,而且不在DOM中增長額外節點

class Columns extends React.Component {
  render() {
    return (
      <React.Fragment>
        <td>Hello</td>
        <td>World</td>
      </React.Fragment>
    );
  }
}

9.Error Boundaries錯誤邊界

部分 UI 的異常不該該破壞了整個應用。爲了解決 React 用戶的這一問題,React 16 引入了一種稱爲 「錯誤邊界」 的新概念。

若是一個類組件定義了一個名爲 componentDidCatch(error, info): 的新方法,則其成爲一個錯誤邊界

錯誤邊界沒法捕獲以下錯誤:
    1.事件處理 (瞭解更多)
    2.異步代碼 (例如 setTimeout 或 requestAnimationFrame 回調函數)
    3.服務端渲染
    4.錯誤邊界自身拋出來的錯誤 (而不是其子組件)        

經典案例

10.組件生命週期

圖解

組件的生命週期可分紅三個狀態:
    Mounting:已插入真實 DOM
    Updating:正在被從新渲染
    Unmounting:已移出真實 DOM

生命週期的方法有:

componentWillMount 在渲染前調用,在客戶端也在服務端
componentDidMount 在第一次渲染後調用,只在客戶端。以後組件已經生成了對應的DOM結構,能夠經過this.getDOMNode()來進行訪問。 若是你想和其餘JavaScript框架一塊兒使用,能夠在這個方法中調用setTimeout, setInterval或者發送AJAX請求等操做(防止異部操做阻塞UI)
componentWillReceiveProps 在組件接收到一個新的 prop (更新後)時被調用。這個方法在初始化render時不會被調用
shouldComponentUpdate 返回一個布爾值。在組件接收到新的props或者state時被調用。在初始化時或者使用forceUpdate時不被調用。
能夠在你確認不須要更新組件時使用
componentWillUpdate 在組件接收到新的props或者state但尚未render時被調用。在初始化時不會被調用
componentDidUpdate 在組件完成更新後當即調用。在初始化時不會被調用
componentWillUnmount 在組件從 DOM 中移除的時候馬上被調用

forceUpdate:
component.forceUpdate(callback)
默認狀況,當你的組件或狀態發生改變,你的組件將會重渲。若你的render()方法依賴其餘數據,你能夠經過調用forceUpdate()來告訴React組件須要重渲。
調用forceUpdate()將會致使組件的 render()方法被調用,並忽略shouldComponentUpdate()。這將會觸發每個子組件的生命週期方法,涵蓋,每一個子組件的shouldComponentUpdate() 方法。若當標籤改變,React僅會更新DOM。
一般你應該嘗試避免全部forceUpdate() 的用法並僅在render()函數裏從this.props和this.state讀取數據。


11.ajax使用

React 組件的數據能夠經過 componentDidMount 方法中的 Ajax 來獲取,當從服務端獲取數據時能夠將數據存儲在 state 中,再用 this.setState 方法從新渲染 UI。

當使用異步加載數據時,在組件卸載前使用 componentWillUnmount 來取消未完成的請求。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      items: []
    };
  }

  componentDidMount() {
    fetch("https://api.example.com/items")
      .then(res => res.json())
      .then(
        (result) => {
          this.setState({
            isLoaded: true,
            items: result.items
          });
        },
        (error) => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      )
  }

  render() {
    const { error, isLoaded, items } = this.state;
    if (error) {
      return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
        <ul>
          {items.map(item => (
            <li key={item.name}>
              {item.name} {item.price}
            </li>
          ))}
        </ul>
      );
    }
  }
}

12.React UI庫推薦

Element:一套爲開發者、設計師和產品經理準備的基於 Vue 2.0 的桌面端組件庫

https://eleme.github.io/element-react/#/zh-CN/quick-start 

 

Ant Desgin:一個服務於企業級產品的設計體系,基於『肯定』和『天然』的設計價值觀和模塊化的解決方案,讓設計者專一於更好的用戶體驗

https://ant.design/docs/react/introduce-cn 

 

UXCore:爲企業後臺而生

http://uxco.re/


13.react router  & react redux介紹

react router4.x :

官方文檔:https://reacttraining.com/react-router/

官方文檔提供了不少 examples ,文檔也比較清楚,能夠直接查看文檔學習。

react redux:

官方文檔:http://www.redux.org.cn/

核心思想:

  1.單一數據源:

    整個項目只有一個state樹。

  2.state只讀:

    只能經過觸發action 修改state。

  3.使用純函數執行修改:

    爲了描述 action 如何改變 state tree ,你須要編寫 reducers。

重要概念:

  Action:

    描述要幹什麼事情。準備須要的一些數據(一個簡單對象)

 {
  type: ADD_TODO, text: 'Build my first Redux app' }

   Reducer:

    到底要怎麼幹。處理state,並返回新的state

function todoApp(state = initialState, action) {
	  switch (action.type) {
		case ADD_TODO:
		  return Object.assign({}, state, {
			todos: [
			  ...state.todos,
			  {
				text: action.text,
				completed: false
			  }
			]
		  })
		default:
		  return state
	  }
}

   Store:

  找到人正式幹活。派發事件

store.dispatch(addTodo('Learn about actions'))

  展現組件:

    僅僅基於React,描述怎麼展現,數據都從props裏面獲取

  容器組件:

    描述如何獲取數據,狀態更新,邏輯處理。基於react-redux

重要API:

 createStore:http://www.redux.org.cn/docs/api/createStore.html

 combineReducers:http://www.redux.org.cn/docs/api/combineReducers.html

   applyMiddleware:http://www.redux.org.cn/docs/api/applyMiddleware.html

react-redux文檔 :http://www.redux.org.cn/docs/react-redux/api.html

綜合案例參見官網TODOS:https://github.com/reduxjs/redux/tree/master/examples/todos

效果圖:

 

14.拓展

react動畫:

https://reactcommunity.org/react-transition-group/

react單元測試

React測試必須使用官方的測試工具庫,可是它用起來不夠方便,因此有人作了封裝,推出了一些第三方庫,其中Airbnb公司的Enzyme最容易上手。

官方也推薦使用  Enzyme 它在相同的功能上提供了一個更棒的高級 API。

Enzyme是官方測試工具庫的封裝,它模擬了jQuery的API,很是直觀,易於使用和學習。

它提供三種測試方法:
        shallow
        render
        mount

 

 

推薦閱讀:http://www.aliued.com/?p=4095

相關文章
相關標籤/搜索