styled-components
文档
安装
npm install --save styled-components
createGlobalStyle 设置全局样式
在 styled-components v4.0 之后定义全局样式的方法跟之前不一样
// 全局样式 style.js
import { createGlobalStyle } from 'styled-components'
const GlobalStyle = createGlobalStyle`
body {
margin: 0;
padding: 0;
font-family: sans-serif;
background: #eee;
}
`
export default GlobalStyle
// 在项目入口文件中引入全局样式
import React from 'react'
import ReactDOM from 'react-dom'
import GlobalStyle from './style.js'
import App from './App'
const Wrapper = (
<React.Fragment>
<GlobalStyle />
<App />
</React.Fragment>
)
ReactDOM.render(Wrapper, document.getElementById('root'))
styled 设置组件样式
style.js
import styled from 'styled-components'
// 设置样式
export const HeaderWrapper = styled.div`
height: 56px;
background: #fff;
border-bottom: 1px solid #f0f0f0;
`
// 设置标签属性
export const HeaderLogo = styled.a.attrs({
href: '/'
})`
color: #0ea86a;
display: flex;
align-items: center;
height: 100%;
font-size: 24px;
`
业务组件
import React from 'react'
import { HeaderWrapper } from './style'
class Header extends React.Component {
render () {
return (
<HeaderWrapper>这是一个header</HeaderWrapper>
)
}
}
export default Header
从业务组件接收参数
// style.js
import styled from 'styled-components'
exports const Item = styled.div`
background: url(${(props) => props.imgUrl})
`
// index.js
import React from 'react'
import { Item } from './style'
class Home extends React.Component {
render () {
return (
<Item imgUrl="https://cdn.baidu.com"></Item>
)
}
}
Ant-Design
文档
安装
npm install antd --save
设置全局样式
安装必要的Package
npm install react-app-rewired customize-cra -D
npm install less less-loader babel-plugin-import -D
在根目录下创建config-overrides.js
const { override, fixBabelImports, addLessLoader } = require('customize-cra')
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true,
}),
addLessLoader({
javascriptEnabled: true,
// 样式配置写在这里
modifyVars: {
'@primary-color': '#1DA57A'
}
})
)
页面上使用
// src/App.js
import React, { Component } from 'react';
import { Button } from 'antd';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<Button type="primary">Button</Button>
</div>
);
}
}
export default App;
react-transition-group
文档
安装
npm install react-transition-group --save
react-redux
安装
npm install react-redux --save
Provider 组件
通过 Provider 将 Redux 的 store 提供给 Provider 下的所有组件。
import { Provider } from 'react-redux';
import store from './store';
import ReactRedux from './ReactRedux';
// 通过 Provider 将 Redux 的 store 提供给 Provider 下的所有组件
const App = (
<Provider store={store}>
<ReactRedux />,
</Provider>
)
ReactDOM.render(App, document.getElementById('root'));
connect()
使业务组件和store进行连接,该业务组件必须在Provider组件下
import React, { Component, Fragment } from 'react'
import { connect } from 'react-redux'
class ReactRedux extends Component {
constructor (props) {
super(props)
}
render () {
return (
<Fragment>
<div>
<input placeholder="你接下来想做什么" value={this.props.inputValue} onChange={this.props.changeInputValue}/>
<button onClick={this.props.handleClick}>提交</button>
</div>
<ul>
{this.props.list.map((item, index) => (<li key={index} onClick={() => {
return this.props.handleItemDelete(index)
}}>{item}</li>))}
</ul>
</Fragment>
)
}
}
// 将 Redux 的 store 挂载到 props
const mapStateToProps = (state) => {
return {
inputValue: state.inputValue,
list: state.list
}
}
// 将 Redux 的 dispatch 挂载到 props
const mapDispatchToProps = (dispatch) => {
return {
changeInputValue (e) {
const action = {
type: 'change_input_value',
value: e.target.value
}
dispatch(action)
},
handleClick () {
const action = {
type: 'add_list_item'
}
dispatch(action)
},
handleItemDelete (itemIndex) {
const action = {
type: 'delete_list_item',
itemIndex
}
dispatch(action)
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ReactRedux);
redux-devtools-extension
Redux 浏览器调试插件
文档
immutable-js && redux-immutable
文档
安装
npm install immutable --save
fromJS()
将js对象,转化为immutable对象
import { fromJS } from 'immutable'
const defaultState = fromJS({
focused: false
})
// immutable 对象获取属性
defaultState.get('focused')
immutableObj.get()
immutable对象获取属性
immutableObj.get('focused')
immutableObj.set()
immutableObj.set()会结合之前immutableObj的值和设置的值,返回一个全新的对象。不会直接修改旧的数据,而是通过返回新对象的方式来修改数据
immutableObj.set('focused', true) // immutable 对象设置值
[重要]通过请求获取 immutable 数据
在通过ajax获取数据,并将数据设置到 immutable 对象时,需要注意,通过ajax获取到的为普通js对象,例如: 数组。但是当 immutable 对象初始化空数组时,已经将普通 js 数组转化为 immutable 的数组,所以在设置值时需要通过fromJS()将获取到的数据转化为immutable的数据类型,再赋值。
export const setSearchInfo = (data) => ({
type: actionTypes.SET_SEARCH_INFO,
data: fromJS(data)
})
redux-immutable
将 redux 和 immutable 结合
安装
npm install redux-immutable --save
store 中配置
- import { combineReducers } from 'redux' // 直接使用 redux
+ import { combineReducers } from 'redux-immutable' // 直接使用 immutable
import { reducer as headerReducer } from '../common/header/store'
// 使用 redux-immutable 之后,store.state 将变为一个 immutable 对象
const reducer = combineReducers({
header: headerReducer
})
export default reducer
页面上使用
state.get('header').get('focused') // immutable 对象获取属性
// or
state.getIn(['header', 'focused']) // 多级 immutable 对象获取属性
redux-thunk
文档
安装
npm install redux-thunk --save
在Store中的配置
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import reducer from './reducer';
// https://github.com/zalmoxisus/redux-devtools-extension
const middlewareList = [thunk]
const composeEnhancers = typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
const enhancer = composeEnhancers(applyMiddleware(...middlewareList));
const store = createStore(reducer, enhancer);
// 不需要使用 devtools 时的配置,devtools也是一个中间件
// const store = createStore(
// reducer,
// applyMiddleware(thunk),
// );
export default store;
在不使用redux-thunk的时候,action返回的是一个对象,在使用redux-thunk之后,action可以返回一个函数
在actionCreator.js中配置
import { INIT_STORE_DATA } from './actionTypes';
export const getInitStoreData = (data) => ({
type: INIT_STORE_DATA,
data
});
// 当使用 redux-thunk 返回一个函数时,函数可以接收到 store 的 dispatch 方法作为参数
export const getTodoList = () => {
return (dispatch) => {
axios.get('/api/todolist').then((res) => {
const data = res.data;
const action = getInitStoreData(data);
dispatch(action);
});
}
}
在组件中使用
import { getTodoList } from './store/actionCreator';
componentDidMount () {
const action = getTodoList();
store.dispatch(action);
}
Axios
文档
安装
npm install axios --save
React-router-dom
安装
npm install react-router-dom --save
简单使用
import { BrowserRouter, Route } from 'react-router-dom'
// exact 表示必须路径完全相同才会展示
const App = () => {
return (
<React.Fragment>
<BrowserRouter>
<Route path='/' exact render={() => (<div>Home Page</div>)}></Route>
// 访问路径: /detail/123456
<Route path='/detail/:id' exact component={Detail}></Route>
</BrowserRouter>
</React.Fragment>
)
}
export default App
单页应用跳转及参数获取
第一种
路由设置
import { BrowserRouter, Route } from 'react-router-dom'
<BrowserRouter>
// 访问路径: /detail/123456
<Route path='/detail/:id' exact component={Detail}></Route>
</BrowserRouter>
跳转设置
import { Link } from 'react-router-dom'
render () {
return (
<div>
// 动态路由
<Link to={'/detail/' + this.state.id}>
<div>跳转到详情</div>
</Link>
</div>
)
}
目标路由获取参数
this.props.match.params.id
第二种
路由设置
import { BrowserRouter, Route } from 'react-router-dom'
<BrowserRouter>
// 访问路径: /detail?id=123456
<Route path='/detail' exact component={Detail}></Route>
</BrowserRouter>
跳转设置
import { Link } from 'react-router-dom'
render () {
return (
<div>
// 动态路由,第一种写法
<Link to={'/detail?id=' + this.state.id}>
<div>跳转到详情</div>
</Link>
</div>
)
}
目标路由获取参数
this.props.location.search
react-infinite-scroller
滚动自动加载列表
文档
安装
npm install react-infinite-scroller --save
react-virtualized
结合react-virtualized实现滚动加载无限长列表,带有虚拟化(virtualization)功能,能够提高数据量大时候长列表的性能。
virtualized是在大数据列表中应用的一种技术,主要是为了减少不可见区域不必要的渲染从而提高性能,特别是数据量在成千上万条效果尤为明显
文档
安装
npm install react-virtualized --save
React-loadable
用于动态加载组件
文档
安装
npm install react-loadable --save
简单使用
在页面组件目录下创建loadable.js
// 使用 react-loadable
import React from 'react'
import Loadable from 'react-loadable'
import Loading from './my-loading-component';
const LoadableComponent = Loadable({
loader: () => import('./index'), // 需要异步加载的组件
loading () {
return <div>正在加载...</div>
}
})
export default <LoadableComponent />
在路由文件中使用,从之前引入 组件的index.js 改为引入 **组件的loadable.js
import React from 'react'
import { Provider } from 'react-redux'
import { BrowserRouter, Route } from 'react-router-dom'
import store from './store'
import Home from './pages/home'
import Detail from './pages/detail/loadable'
// 通过 Provider 将 Redux 的 store 提供给 Provider 下的所有组件
const App = () => {
return (
<Provider store={store}>
<BrowserRouter>
<Route path='/' exact component={Home}></Route>
<Route path='/detail/:id' exact component={Detail}></Route>
<Bottom />
</BrowserRouter>
</Provider>
)
}
export default App
在页面中,如果 需要使用路由传递的参数 ,需要使用withRouter()
import React from 'react'
import { withRouter } from 'react-router-dom'
class Detail extends React.Component {
constructor (props) {
super(props)
}
render () {
return (
<div>{this.props.match.params.id}</div>
)
}
}
export default withRouter(Detail)
Lodash
文档
对象/数组 深度比较
_.isEqual(nextProps.list, this.props.list) // 判断是否相等