我的项目源码

https://github.com/astak16/ac...

我的项目构造

src/common; // 公共组件src/pages; // 页面src/static; // 动态资源src/store; // 主 storeApp.js; // 根组件index.css; // 款式index.js; // 入口文件

重置 css

搜寻reset.css,复制过去

styled-components

css文件一旦在一个文件中被引入,会在全局中失效

这样写css会有些问题,当页面中有多个组件时,款式存在被笼罩的危险

咱们心愿在写款式的时候,每个组件的款式是独立的,不会相互的影响

应用

  1. index.css重命名为style.js
  2. index.js引入style.js

    import "style.js";
  3. style.js

    import { injectGlobal } from "styled-components";injectGlobal`  body{    padding: 10px  }`;

在组件中应用

组件申明

// Header/style.jsimport styled from "styled-components";export const HeaderWrapper = styled.div`  height: 56px;`;// Header/index.jsimport { HeaderWrapper } from "./style";class Header extends Component {  render() {    return <HeaderWrapper></HeaderWrapper>;  }}

图片应用

style.js中应用背景图片的话,间接应用background: url('/images/logo.png')是没有成果的,因为webpack在打包的时候,不晓得工程目录是啥样的,它会把门路当成字符串

须要这样写

import logoPic from "/images/logo.png";export const Logo = style.a`  background: url(${logoPic})`;

设置属性

import logoPic from "/images/logo.png";export const Logo = style.a.attr({  href: "/",})`  background: url(${logoPic})`;

参数传递

组件中要传递不同的参数进来,styled提供了函数性能

<RecommendItem key='1' imgURL='/images/1.png'>1</RecommendItem><RecommendItem key='2' imgURL='/images/2.png'>1</RecommendItem>// style.jsexport const RecommendItem = styled.div`  width: 280px;  height: 50px;  background: url(${props => props.imgURL});  background-size: contain;`

immutable.js

reducer中,state的数据是不心愿被扭转的,在写我的项目的时候,很容易在人不知;鬼不觉中把state给改了,从而造成异样。

immutable.js能够帮忙解决问题,它会生成一个immutable对象,这个对象是不可被扭转的。

immutable提供了fromJS的办法,能够把js对象转换成immutable对象

const a = fromJS({ age: 18 });

immutable提供了getgetIn两种办法来读取数据

const a = fromJS({  age: 18  feature: {    height: 180  }})const age = a.get('age')const height = a.getIn(['feature', 'height'])// 或者const height = a.get('feature').get('height')

immutable提供了setmerge两种办法来设置数据。

immutable对象的set办法,会联合之前的immutable对象的值,和设置的值,返回一个全新的对象。它并不会去改之前的immutable数据。

const a = fromJS({  age: 18,  name: "uccs",});a.set("age", 19).set("name", "tiantain");// 或者a.merge({  age: 1,  name: "tiantian",});

当最里面应用immutable对象时,外部的Object类型的数据也会变成immutable类型,所以在应用set设置时,先要把一般对象变成immutable对象才行。

const a = fromJS({  list: [], // 这个 list 也是 immutable 数组});const data = [1, 2, 3];a.set("list", fromJS(data));

immutable.js提供了toJS办法,是为了将immutable对象转换成js对象

const a = fromJS({  list: [1, 2, 3],});const b = a.toJS();b[1];

redux-thunk

redux-thunk的作用是能够在action中写函数

redux

首页须要装置reduxreact-redux

react-redux是不便在react中应用redux

redux的应用能够看:redux 学习笔记

store/index.js

// store/index.jsimport { createStore, applyMiddleware, compose } from "redux";import thunk from "redux-thunk";import reducer from "./reducer";const store = createStore(reducer, compose(applyMiddleware(thunk))); // 在 store 中应用 redux-thunkexport default store;

store/reducer.js

// 主 store/reducer.jsimport { combineReducers } from "redux-immutable";import { headerReducer } from "../common/header/store";export default combineReducers({  header: headerReducer,});// 分 header/store/reducer.jsimport { Search_Focus } from "./actionType";import { fromJS } from "immutable";const defaultState = fromJS({  focused: false, // 默认数据});export default (state = defaultState, action) => {  switch (action.type) {    case Search_Focus:      return state.set("focused", action.data);    default:      return state;  }};

redux-immutable提供了一个combineReducers办法,这个办法用来组合各个拆分进去的reducer

header/store/actionCreators.js

// header/store/actionCreators.jsimport {Search_Focus} from './actionType'const searchFocus = (data) => {  type: Search_Focus,  data}export const getList = async () => {  return (dispatch) => {    const res = await axios.get('api/header.json')    dispatch(searchFocus(res.data))  }}

header/store/actionType.js

// header/store/actionType.jsexport const Search_Focus = "header/search_focus";

App.js

// App.jsimport { Provider } from "react-redux";import store from "./store";<Provider store={store}>  <BrowserRouter>    <div>      <Header />    </div>  </BrowserRouter></Provider>;

react-redux有一个外围组件Provider,这个组件有一个store属性,将咱们定义的store传给它,这样Provider外面所有组件都有能力去应用store中的数据了

组件连贯 store

Providerstore提供给了各组件,然而组件想应用store中的数据,还要做连贯

import { connect } from "react-redux";class Header extends React.Component {}export default connect()(Header);

react-redux提供了connect办法,connect就是帮忙组件和store建设连贯的。
connect接管两个参数:mapStateToPropsmapDispatchToProps

import { actionCreators } from "./store/actionCreators";const mapStateToProps = (state) => {  return {    focused: state.getIn(["header", "focused"]),  };};const mapDispatchToProps = (dispatch) => {  return {    handleInputFocus() {      dispatch(actionCreators.getList());    },  };};export default connect(mapStateToProps, mapDispatchToProps)(Header);

组件中应用this.props.focused

react-router-dom

Route

  • render办法能够渲染一个货色
  • exact齐全匹配门路

    • exactfalse时,//detail都能匹配上
  • component渲染组件
import { BrowserRouter, Route } from "react-router-dom";import Home from "./pages/home";import Detail from "./pages/detail/loadable";function App() {  return (    <Provider store={store}>      <BrowserRouter>        <div>          <Route path="/" exact component={Home} />          <Route path="/detail/:id" exact component={Detail} />        </div>      </BrowserRouter>    </Provider>  );}export default App;

动画

换一换旁边有个icon,每次点击的时候,这个icon须要转动起来。

每次点击的时候只有扭转icontrannform: rotate() 的值就能够了。每次减少 360°

通过ref能够获取到react渲染进去的实在节点。

<SearchInfoSwitch onClick={() => handleChangePage(this.spinIcon)}>  <i className='iconfont spin'     ref={icon => this.spinIcon = icon}  >&#xe852;</i>换一批</SearchInfoSwitch>handleChangePage(spin) {  let originAngle = spin.style.transform.replace(/[^0-9]/ig, '')  if (originAngle)    originAngle = parseInt(originAngle, 10)  else    originAngle = 0  spin.style.transform = `rotate(${originAngle + 360}deg)`}

其余

  1. Link代替a做跳转,能够做到按需加载
  2. PureComponent组件等价于Component+shouldComponentUpdate
  3. dangerouslySetInnerHTML={{__html: '<div>文本</div>'}}能够渲染HTML内容
  4. <Route path='/detail/:id'/>路由参数获取this.props.match.params.id
  5. 异步组件redux-immutable,应用异步组件时须要用withRouterexport default connect(mapState, mapDispatch)(withRouter(Detail));

    // detail/loadable.jsimport React from "react";import Loadable from "react-loadable";const LoadableComponent = Loadable({  loader: () => import("./"),  loading() {    return <div>正在加载</div>;  },});export default () => <LoadableComponent />;// App.jsimport Detail from "./pages/detail/loadable";

总结

路由

我的项目技术栈:

  • react-router:路由
  • react-redux:数据挂你工具
  • react-loadable: 按需加载
  • react-transition-group:动画
  • redux-immutable:将state变成immutable对象
  • redux-thunk:能够在action中应用函数
  • styled-components:部分款式
  • axiosajax申请