[1] 博客筆記結合《React快速上手開發》再次系統地、全面地走一遍。html
[2] React JS Tutorials:包含了JS --> React --> Redux --> Mobx 前端
着眼於ful-stack全局,瞭解先後端的部署,以後才能深入理解react的角色與位置。java
1. 服務器部署react
[AWS] Deploy react project on EC2git
2. 用戶權限管理es6
[AWS] OAuth2.0github
[AWS] Amazon Cognitoredux
3. 這就是將來後端的趨勢後端
<script> ReactDOM.render(
React.DOM.h1( {id: "my-heading"}, React.DOM.span(null, React.DOM.em(null, "Hell"), "o" ), " world!" ),
document.getElementById('app')
); </script>
<script> ReactDOM.render( /* // COUNTEREXAMPLE // this doesn't work React.DOM.h1( { class: "pretty", for : "me", }, "Hello world!" ), */ // PROPER EXAMPLE // this works React.DOM.h1( { className: "pretty", htmlFor : "me", }, "Hello world!" ), document.getElementById('app') ); </script>
style卻是常常用到。
<script> ReactDOM.render( /* // COUNTEREXAMPLE // this doesn't work React.DOM.h1( { style: "background: black; color: white; font-family: Verdana", }, "Hello world!" ), */ // PROPER EXAMPLE // this works React.DOM.h1( { style: { background: "black", color: "white", fontFamily: "Verdana", } }, "Hello world!" ), document.getElementById('app') ); </script>
思考:可見以上的寫法,可讀性比較差,這也是以後引入JSX的重要緣由。
下圖中上面的JSX寫法就接近了原始的HTML格式,看起來更更爲習慣。
Goto for more details: [React] 01 - Intro: javaScript library for building user interfaces - React JSX
<script>
var Component = React.createClass({ render: function() { return React.DOM.span(null, "I'm so custom"); } });
ReactDOM.render( React.createElement(Component), // 這裏以前是React.DOM代碼,如今封裝了起來 document.getElementById("app") );
</script>
附加題:React 工廠方法——createFactory使用詳解【爲什麼感受用處不是很大】
<script>
var Component = React.createClass({
/**
* 能夠採用PropTypes檢查props
*/
/**
* 若是沒有name屬性,會報錯,
* 能夠設置一個默認的
*/ render: function() { return React.DOM.span(null, "My name is " + this.props.name); }
});
ReactDOM.render( React.createElement(Component, { name: "Bob", }),
<Component name="Bob" /> // <---- 看來JSX的寫法更爲舒服,createElement看着彆扭!
document.getElementById("app") );
</script>
附加題:react demo10 (設置組件屬性的默認值getDefaultProps)
複合組件:Composite Component 表示 建立多個組件來合成一個組件,把組件的不一樣功能點進行分離。Goto for more details: [React] 01 - Intro: javaScript library for building user interfaces - 複合組件,React Props
子節點的獲取:[React] 01 - Intro: javaScript library for building user interfaces - this.props.children
<script> var TextAreaCounter = React.createClass({ propTypes: { text: React.PropTypes.string, }, getDefaultProps: function() { return { text: '', }; }, getInitialState: function() { return { text: this.props.text, }; }, _textChange: function(ev) { this.setState({ // Jeff: setState 觸發界面更新,由於這裏把prop變了 text: ev.target.value, // event.target:使用合成事件來消除瀏覽器之間的不一致狀況 }); }, render: function() { return React.DOM.div(null, React.DOM.textarea({ value : this.state.text, onChange: this._textChange, }), React.DOM.h3(null, this.state.text.length) ); } });
ReactDOM.render( React.createElement(TextAreaCounter, { text: "Bob", // 這裏實際上是個初始值,因此命名爲defaultValue會好些 }), document.getElementById("app") ); </script>
附加題:事件處理,書p20。
React 組件 API,除了setState,還有其餘6種方法:
如何定義」外部「?經過 myTextAreaCounter 設置新的state值 as following。
myTextAreaCounter.setState({text: "Hello outside world!" });
如下定義了myTextAreaCounter。
<script>
var TextAreaCounter = React.createClass({
propTypes: { defaultValue: React.PropTypes.string, },
getInitialState: function() { return { text: this.props.defaultValue, }; },
_textChange: function(ev) { this.setState({ text: ev.target.value, }); },
render: function() { return React.DOM.div(null, React.DOM.textarea({ // text --> input value : this.state.text, onChange: this._textChange, }), React.DOM.h3(null, this.state.text.length) ); }
});
---------------------------------------------------------
var myTextAreaCounter = ReactDOM.render( React.createElement(TextAreaCounter, { defaultValue: "Bob", }), document.getElementById("app") );
</script>
附加題:組件也算是代碼"分離思想"的一種體現,參看筆記:[React] 08 - Tutorial: evolution of code-behind【from HTML靜態頁面 to 複合組件】
參見筆記 [React] 09 - Tutorial: components
(11) 子組件向父組件傳值 - 子組件調用父組件的「方法」,以」函數指針「的相似形式;
(12) 子組件之間的傳值
(13) 雙向數據綁定
[Redux]
經過這件事,讓咱們明白了Redux的重要性。
Goto for more details: [React] 02 - Intro: why react and its design pattern - 背後的思想:一步一步進化到 Redux
以及相關筆記:
- [React] 11 - Redux: redux
- [React] 12 - Redux: async & middleware
- [React] 13 - Redux: react-redux
- [React] 14 - Redux: Redux Saga
- [React] 15 - Redux: TodoMVC
- [看漫畫,學 Redux] —— A cartoon intro to Redux
- 如何評價數據流管理架構 Redux? - 楊森
有必要另起一文走一遍!
Ref: React建立組件的三種方式及其區別
無狀態組件
React.createClass
定義的組件 【`React.createClass`是react剛開始推薦的建立組件的方式,這是ES5的原生的JavaScript來實現的React組件】extends React.Component
定義的組件隨着React的發展,React.createClass
形式自身的問題暴露出來:
(1) 當前老舊寫法:
var InputControlES5 = React.createClass({
propTypes: {//定義傳入props中的屬性各類類型 initialValue: React.PropTypes.string }, defaultProps: { //組件默認的props對象 initialValue: '' }, // 設置 initial state getInitialState: function() {//組件相關的狀態對象 return { text: this.props.initialValue || 'placeholder' }; }, handleChange: function(event) { this.setState({ //this represents react component instance text: event.target.value }); }, render: function() { return ( <div> Type something: <input onChange={this.handleChange} value={this.state.text} /> </div> ); } });
--------如下沒區別------------------------
InputControlES5.propTypes = { initialValue: React.PropTypes.string }; InputControlES5.defaultProps = { initialValue: '' };
(2) 將來推崇寫法:【其實就是使用了js6的類的新特性】
class InputControlES6 extends React.Component {
constructor(props) { super(props); // 設置 初始狀態 this.state = { text: props.initialValue || 'placeholder' }; // ES6 類中函數必須手動綁定 this.handleChange = this.handleChange.bind(this); // 建立的組件,其成員函數不會自動綁定this,須要開發者手動綁定,不然this不能獲取當前組件實例對象。 } handleChange(event) { this.setState({ text: event.target.value }); } render() { return ( <div> Type something: <input onChange={this.handleChange} value={this.state.text} /> </div> ); } }
React.Component
--------如下沒區別------------------------
InputControlES6.propTypes = { initialValue: React.PropTypes.string }; InputControlES6.defaultProps = { initialValue: '' };
Jeff:
可是,使用類的概念後,意思就天然而然地跟着變了:
做爲組件類的屬性,不是組件實例的屬性,也就是所謂的類的靜態屬性來配置的。
經過bind鎖定this:
method.bind(this)
來完成綁定,<div onClick={this.handleClick.bind(this)}></div> // 2.使用bind來綁定
<div onClick={()=>this.handleClick()}></div> // 3.使用arrow function來綁定
一、只要有可能,儘可能使用無狀態組件建立形式。
二、不然(如須要state、生命週期方法等),使用`React.Component`這種es6形式建立組件。
Ref: React中的無狀態和有狀態組件【原文看似不錯】
無狀態的函數寫法,又稱爲純組件SFC。它是一種只負責展現的純組件。
對於這種無狀態的組件,使用函數式的方式聲明,會使得代碼的可讀性更好,並能大大減小代碼量,箭頭函數則是函數式寫法的最佳搭檔:
const Todo = (props) => ( <li onClick={props.onClick} style={{textDecoration: props.complete ? "line-through" : "none"}} > {props.text} </li> )
上面定義的 Todo
組件,輸入輸出數據徹底由props
決定,並且不會產生任何反作用。
對於props
爲 Object
類型時,咱們還可使用 ES6 的解構賦值:
const Todo = ({ onClick, complete, text, ...props }) => ( <li onClick={onClick} style={{textDecoration: complete ? "line-through" : "none"}} {...props} > {props.text} </li> )
無狀態組件通常會搭配高階組件(簡稱:HOC)一塊兒使用,高階組件用來託管state
,Redux 框架就是經過 store
管理數據源和全部狀態,其中全部負責展現的組件都使用無狀態函數式的寫法。
這種模式被鼓勵在大型項目中儘量以簡單的寫法 來分割本來龐大的組件,而將來 React 也會面向這種無狀態的組件進行一些專門的優化,好比避免無心義的檢查或內存分配。因此建議你們儘量在項目中使用無狀態組件。
無狀態組件內部實際上是可使用ref
功能的,雖然不能經過this.refs
訪問到,可是能夠經過將ref
內容保存到無狀態組件內部的一個本地變量中獲取到。
Ref: React無狀態組件——爲可複用而生
如何利用react提供的jsx語法寫好一個可複用的組件呢?---- 最經常使用的組件是「無狀態組件」
所謂無狀態,也能夠叫作無生命週期,無state,組件是一個純jsx類或者對象。
這個組件內部沒有任何的生命週期和state狀態,那麼若是須要管理state狀態,該怎麼辦呢?---- Redux
# 這裏自定義了一個head主鍵,能夠複用,由於head的各部分細節由參數控制。
export class Header extends Component { render() { const {title, imgUrl, linkTo, bgColor} = this.props
//提供4個接口參數給父容器作設置,能夠不傳參。 return ( <header className='header' style={bgColor}> {title} <Link to={linkTo} className="a_link" > <img src={imgUrl} className="a_img" /> </Link> </header> ) }
//嚴格來講,這些暴露給外部的參數都須要作驗證,經常使用的驗證類型爲array,bool,func,number,object,string static propTypes = { title: React.PropTypes.string.isRequired }
}
附加題:Mixins的支持不一樣 ----> 走向"高階組件"
For more details, go to: [React] 16 - Topic: Mixins & Higher-Order Components
React.Component
這種形式並不支持Mixins
,至今React團隊尚未給出一個該形式下的官方解決方案;可是React開發者社區提供一個全新的方式來取代
Mixins
,那就是 Higher-Order Components。所謂 HOC:會返回組件的組件,Redux就是一個實現例子,可處理狀態。
因爲React團隊已經聲明 React.createClass最終會被React.Component的類形式所取代。
可是在找到
Mixins
替代方案以前是不會廢棄掉React.createClass
形式。因此:
"能用React.Component建立的組件的就儘可能不用React.createClass形式建立組件"
參見筆記 [React] 09 - Tutorial: components,並結合raisl365系列 之 誘人的 react 視頻教程-基礎篇
【代碼有必要詳細研究與實踐】
實驗代碼的基本思路是:
"點擊按鈕 ----> 改變某state ----> 觸發render ----> 經過if判斷語句,跳過某component的渲染 ----> 達到組件消失的效果「
核心待解決的問題:沒有登陸的話,就沒有權限訪問這個路由。
RR4 本次採用單代碼倉庫模型架構(monorepo),這意味者這個倉庫裏面有若干相互獨立的包,分別是:
react-router
# React Router 核心react-router-dom
# 用於 DOM 綁定的 React Routerreact-router-native
# 用於 React Native 的 React Routerreact-router-redux
# React Router 和 Redux 的集成react-router-config
# 靜態路由配置的小助手
[React] 05 - Route: connect with ExpressJS
[React] 06 - Route: koa makes your life easier
可見,路由的處理採用的是:在後端代碼中採用相似switch的方式判斷前端發來的URL request。
那麼問題來了,react是前端的東西,react-router是前端仍是後端?或者,是一個介於中間的東西?
答案是:前端路由!
參見:[React] 10 - Tutorial: router
Yuan Yifeng有整理:React Router 使用教程,在此補充些遺漏的內容。
Ref: 官方路由示範代碼
如此,不用使用關鍵字:exact
用戶訪問/repos
時,
App
組件,Repos
組件。<Router history={hashHistory}> <Route path="/" component={App}> <Route path="/repos" component={Repos}/> <Route path="/about" component={About}/> </Route> </Router>
URL with hash value.
http://localhost:8080/#/about?_k=z86gvy
export default React.createClass({ render() { return ( <div> <h1>React Router Tutorial</h1> <ul role="nav"> <li><Link to="/about">About</Link></li> <li><Link to="/repos">Repos</Link></li> </ul> {this.props.children} </div> ) } })
Result:
導入全部的參數並展開
<ul role="nav"> <li><NavLink to="/about">About</NavLink></li> <li><NavLink to="/repos">Repos</NavLink></li> </ul>
將Link 統一變爲記錄活動狀態帶有顏色的link。
render() { return <Link {...this.props} activeClassName="active"/> }
更多內容:
詳見 [React] 10 - Tutorial: router - URL的參數處理
11、表單處理
12、路由的鉤子
Jeff: 以上即是react周邊最爲親近的一些知識點