[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周边最为亲近的一些知识点