React-Router Documents
安装
npm install history react-router@latest
`</pre>
react-router 依赖 history 模块
<pre>`import {Router, Route, Link} from 'react-router'
可以从 lib 目录 require 需要的部分
`</pre>
import { Router } from 'react-router/lib/Router'
<pre>`import React from 'react'
import { Router, Route, Link } from 'react-router'
const App = React.createClass({/*..*/})
const About = React.createClass({/*...*/})
const ...
H5 移动端注意点
使用 rem 作为单位
给手机这是 100px 的字体大小, 对于320px 的手机匹配是100px, 其他手机都是按比例分配, 因此设计稿上多少像素的话, rem = 设计稿像素/100
禁用 a, button, input, opigroup, select, textare 等标签背景变暗
在移动端使用 a 标签作为按钮或文字链接的时候, 点击按钮会出现一个暗色背景, 需要在 css 中加入
a, button, input, textarea, optgroud, select{
-webkit-tap-highlight-color: rgba(0,0,0,0)
}
`</pre>
meta 基础知识
页面窗口自动调整到设别宽度, 并禁止用户缩放页面
`<meta name="viewport" content="width=device-width,initial-width:1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"/>
`
忽略页面中的数字 ...
React 性能优化 Tip
慎用 setState, 因为他容易导致重复渲染, 请将数据都交给 redux 管理, 再通过 props 传入. 记得使用 shouldComponentUpdate 比较以确定是否需要重新渲染
请将方法的 bind 一律置于 constructor 中, 可以避免重复绑定, 多个实例的构造函数是共享的.
只传递 component 需要的 props, 传递的太多, 或者传递的太深, 都会加重 shouldComponentUpdate 里面的数据复旦
路由控制与拆包, 当项目变得更大规模与复杂的时候, 我们需要设计成 SPA, 这时路由管理就变得非常重要, 这使得特定 url 参数可以对应特定页面
其他常见:
1\. 使用 immutable 处理 props, state, store
2\. 使用 pure-render-decorator 与 immutablejs 搭配使用
3\. 慎用 setState
4\. 仅传必要的 props
5\. 将方法的 bind 置于 constructor
applyMiddleware 与 Enhancer
import { createStore, applyMiddleware, compose } from 'redux'
const store = createStore(
reducer,
preloadedState, // <----- 可选,前后端同构的数据同步
compose( // <------------ 还记得吗?compose 是从右到左的哦!
applyMiddleware( // <-- 这货也是 Store Enhancer 哦!但这是关乎中间件的增强器,必须置于 compose 执行链的最后
middleware1,
middleware2,
middleware3
),
enhancer3,
enhancer2,
enhancer1
)
)
Redux APIs
Compose(…funcs)/**
* compose(f,h,g)(...args) => f(g(h(...args)))
* 使用了 reduceRight, 从右开始执行
* @param {多个函数, 逗号隔开}
* @return {函数}
*/
export default function compose(...funcs){
if(funcs.length === 0){
return arg => arg
}
if(funcs.length === 1){
return funcs[0]
}
const last = funcs[funcs.length - 1]
const rest = funcs.slice(0,-1)
return (...args) => rest.reduceRight((composed, f) => f(composed), la ...
Middleware
You can include custom middleware functions to the dispatch method of your store.
The dispatch function is responsible for sending actions to one or more reducer functions for state changes. The composed specialized functions around the original dispatch method creates the new middleware capable dispatch method.
Source code for applyMiddleware(from Redux 1.0.1)
export default function applyMiddleware(...middlewares) {
return (next) =>
(reducer, initialState) => {
...
Connect 相关
预备知识回顾一下 Redux 基本用法
const reducer = (state = {count: 0}, action ) => {
switch(action.type){
case "INCRESE": return {count: state.count + 1}
case "DECRESE": return {count: state.count - 1}
default: return state;
}
}
const actions = {
increase: () => { type: 'INCREASE'},
decrease: () => { type: 'DECREASE'}
}
const store = createStore(reducer);
st ...
Configuring ESLint
Configuration Comments - use JS comments to embed configuration information directly into a file.
Configuration Files - use a JS, JSON, or YAML file to specify configuration information for an entire directory and all of its subdirectories. This can be in the form of an .eslintrc file or an eslintConfig field in a package.json file, both of which ESLint will look for and reed automatically, or you can specify a configuration file on the command line.
Specifying Parser OptionsESLint allows you ...
JS 开发工具
开发工具是让开发人员工作更轻松的一些软件, 传统上包括集成开发环境, 代码检查工具, 编译器, 调试工具和性能测试工具
但是 JS 是一种动态语言, 伴随他动态本质而来的是对更多运行时开发者工具的需求.
Quick List
Atom & Atom-ternjs
Chrome DevTools
PageSpeed Insights
BrowserSycn
TraceGL
ironNode
ESLint
Babel
React
Webpack + Hot Module Replacement
Redux + Redux DevTools
关于工具, 主要是编辑器和运行时环境(比如浏览器)
主要用 Atom, 需要 atom-ternjs 来开启 JavaScript 智能识别
很多很棒的 Atom 插件
调试器: Chrome DevTools, 注意其 flame charts 和 dominators view 功能
性能审查: PageSpeed Insights
BrowserSync 是一款测试响应式布局非常好用的工具, 可以一次模拟多种浏览器(电脑, 平板, 手机) ...
部署React + Redux 的 Web 开发环境
好的部署需要做到两点:1. 性能优化: 包括代码执行速度, 页面载入速度2. 自动化: 减少重复工作
使用 React+Redux 的时候往往会用到其调试工具 Redux DevTools, 在手动配置 DevTools 时需要针对 Store 和 Component 进行一些配置, 然而这些都是为了方便调试的, 生产环境下我们不希望加入这些东西, 所以建议从代码上隔离 development 和 production 环境:
containers/
Root.js
Root.dev.js
Root.prod.js
...
store/
index.js
store.dev.js
store.prod.js
`</pre>
同时采用单独的入口文件, 比如上面的 containers/Root.js, 按需要加载不同环境的代码
<pre>`if (process.env.NODE_ENV === 'production'){
module.exports = require('./Root.p ...
Webpack 常用 Plugin 和 Loader
常用 Loaderhtml 相关
html-loader
`</pre>
css 相关
<pre>`style-loader
css-loader
autoprefixer-loader
sass-loader
`</pre>
js 相关
<pre>`babel-loader
babel-core
babel-preset-es2015
babel-preset-react
babel-preset-stage3
eslint-loader
`</pre>
### 常用插件Plugin
#### config 类
<pre>`NormalModuleReplacementPlugin
ContextReplacementPlugin
IgnorePlugin
PrefetchPlugin
`</pre>
#### Optimize
<pre>`DedupePlugin
LimitChunkCountPlugin
OccurenceOrderPlugin
UglifyJsPl ...
ImmutableJS Introduction
Immutable data cannot be changed once created, leading to much simpler application development, no defensive copying, and enabling advanced memoization and change detection techniques with simple logic. Persistent data presetns a mutative API which does not update the data in-place, but instead always yields new updated data.
Immutable.js provides many Persistent Immutable data structures including: List, Stack, Map, OrderedMap, Set, OrderedSet and Record.
These data structures are highly effici ...
Redux 搭配 React
第一步是初始化 react 组件
getInitialState(){
return{
item: store.getState()
}
}
`</pre>
第二步是在组件 render 后调用 subscribe 函数, 每次 redux 发生 dispatch 的时候都要调用 react 的 setState
<pre>`componentDidMount(){
var unsubscribe = store.subscribe(this.onChange)
}
onChange(){
this.setState({
item: store.getState()
})
}
React 会根据 State 的变化重新 render 组件this.state.item.todos.map()
CommonChunks 插件
作用就是提取代码中的公共模块, 然后将公共模块打包到一个独立的文件中, 以便在其他的入口和模块中使用.
// in main.js
var a = require('./a');
a.sayHello();
var b = require('./b');
b.sayHello();
var c = require('./c');
c.sayHello()
`</pre>
<pre>`// in main2.js
var a = require('./a');
a.sayHello();
var b = require('./b');
b.sayHello();
`</pre>
a, b, c 和之前一样, 只有一个 sayHello 方法.
打包后看到`bundle.main.js` 和`bundle.main2.js` 中分别包含了 a, b, c 三个模块, 其中 a, b 是要使用`CommonChunksLoader` 提取出来的公共模块.
### ...
Webpack 发布配置
单文件模式// 新建 webpack.production.config.js
// in package.json
"deploy":"NODE_EVN=production webpack -p -config webpack.production.config.js"
// in web.production.config.js
// 和开发环境不同之处在于入口和出口. 相应的在 HTML 和 JS 源也要进行修改
var path = require('path')
var node_modules_dir = path.resolve(__dirname, 'node_modules')
module.exports = {
entry:[
'babel-polyfill',
path.resolve(__dirname, 'app/main.js')
],
output:{
path: path.resolve( ...
Webpack 配置 React/babel
安装 reactnpm install --save react react-dom
`</pre>
### 安装 babel-loader
<pre>`npm install --save-dev babel-loader babel-core babel-preset-es2015 babel-preset-react babel-preset-stage-2
// 支持 ES2015, JSX, ES7
`</pre>
<pre>`npm install --save polyfill
`</pre>
<pre>`npm install --save babel-runtime
npm install --save-dev babel-plugin-transform-runtime
// 减少打包时候的重复代码
`</pre>
### 配置 babel
<pre>`// 在入口添加 polyfill
entry:[
'babel-polyfill',
...
Webpack Dev Server
The webpack-dev-server is a little node.js Express server, which uses the webpack-dev-middleware to serve a webpack bundle. It also has a little runtime which is connected to the server via Socket.IO.
Let’s say you have the following config file(webpack.config.js)
var path = require('path');
module.exports = {
entry:{
app:['./app/main.js']
},
output:{
path: path.resolve(__dirname, 'build'),
publicPath:'/assets/',
filename: ...
React Ajax
组件的数据来源, 通常是通过 AJAX 请求从服务器获取, 可以使用 componentDidMount 方法设置 AJAX 请求, 等到请求成功, 再用this.setState()方法重新渲染 UI.
var UserGist = React.createClass({
getInitialState(){
return {
userName: '',
lastGistUrl: ''
}
},
componentDidMounted(){
$.get(this.props.source, function(result){
var lastGist = result[0];
if(this.isMouted()){
this.setState({
userName: lastGist.owner.login,
lastGi ...
React 表单
用户在表单输入的内容, 属于用户与组件的互动, 要用this.setState()修改
var Input = React.cr而奥特Class({
getInitialState(){
return {
value: 'Hello'
};
},
handleChange(event){
this.setState({
value: event.target.value;
})
},
render(){
return(
<div><input type='text' onChange={this.handleChange} value = {this.state.value} /><p>{this.state.value ...
PropTypes 与 getDefaultProps
组件的属性可以接受任意值. 有时候我们需要一种机制, 验证别人使用组件时, 提供的参数是否符合要求.
组件类的 PropTypes 属性, 就是用来验证组件实例的属性是否符合要求的.
var MyTitle = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequried,
},
render() {
return <h1> {this.props.title} </h1>;
}
});
`</pre>
上面的 `MyTitle` 组件有一个 `title` 属性, `PropTypes` 告诉 React, 这个 `title` 属性是必须的, 而且数据类型是字符串.
如果在实例化的时候设置 `title=123`, 控制台会显示一行错误信息
<pre>`Warning: Failed propType ...