React 项目中常用的 Package

408 阅读4分钟

styled-components

文档

styled-components.com/

安装

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

Ant-Design

文档

ant.design/

安装

npm install antd --save

设置全局样式

文档 ant.design/docs/react/…

安装必要的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

文档

github.com/reactjs/rea…

安装

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 浏览器调试插件

文档

github.com/zalmoxisus/…

immutable-js && redux-immutable

文档

github.com/immutable-j…

安装

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

文档

github.com/reduxjs/red…

安装

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

文档

www.kancloud.cn/yunye/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>
      <Route path='/detail' exact render={() => (<div>Detail Page</div>)}></Route>
    </BrowserRouter>
  </React.Fragment>
  )
}
export default App