学习过程当中本身弄得小项目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