學習過程當中本身弄得小項目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
的回調函數,在卸載時則會傳入 null
。ref
回調會在componentDidMount
或 componentDidUpdate
這些生命週期回調以前執行。
注意: 若是 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:爲企業後臺而生
13.react router & react redux介紹
react router4.x :
官方文檔:https://reacttraining.com/react-router/
官方文檔提供了不少 examples ,文檔也比較清楚,能夠直接查看文檔學習。
react redux:
核心思想:
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