react项目实战笔记

2020-12-01  本文已影响0人  三天两觉_

项目实战

1.脚手架生成项目

create-react-app jianshu

2.styled-components的使用

yarn add styled-components
import { createGlobalStyle  } from "styled-components";
//导出全局样式
export const GlobalStyle = createGlobalStyle `
//此处是全局样式表,可以把reset.css放在这里
html, body, div, span{...}
`
import React from 'react';
import ReactDOM from 'react-dom';
//引入全局样式
import {GlobalStyle} from "./css/style.js";
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    /*全局样式*/
    <GlobalStyle />
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

3.在组建中使用styled-components

import react,{Component} from "react";
import {HeaderWrapper,NavLogo,Nav,NavLeft,NavRight,HeaderLink,LinkItem} from "./style"

class header extends Component{
    render(){
        return (
            <HeaderWrapper>
                <NavLogo href="/"></NavLogo>
                <Nav>
                    <NavLeft>
                        <p className="p1">首页</p>
                        <p className="p2">下载APP</p>
                        <input type="text" placeholder="搜索"/>
                    </NavLeft>
                    <NavRight>
                        <p>Aa</p>
                        <a href="">登录</a>
                    </NavRight>
                </Nav>
                <HeaderLink>
                    <LinkItem>注册</LinkItem>    
                    <LinkItem className="link2">写文章</LinkItem>    
                </HeaderLink>  
            </HeaderWrapper>
        )
    }
}
export default header;

style.js代码如下

import styled from "styled-components";
//引入图片
import logoImg from "../../asstes/img/nav-logo.png";
//HeaderWrapper会被解析成div元素 模板字符串中写样式,把HeaderWrapper暴露出去,在组件中使用就不会产生样式冲突问题了。
export const HeaderWrapper = styled.div`
  display: flex;
  height: 58px;
  padding: 0 39px;
  border-bottom:1px solid #eee;
`;
//NavLogo会被解析成a标签 注意图片要用import的方式
export const NavLogo = styled.a`
  background: url("${logoImg}") no-repeat;
`;
//NavLeft有子元素,子元素样式的写法
export const NavLeft = styled.div`
  NavLeft的样式
  .p1{
      p1的样式
  }
  .p2{
      p2的样式
  }
  input{
      input的样式
  }
`;
//其他代码省略....

4.使用redux改造代码

import  { Component } from "react";
import {connect} from "react-redux";

import {changeFocusStatus} from "../../store/actionCreator";
class header extends Component {
  constructor(props){
    super(props);
    this.state = {
      focus:false
    }
  }
  render() {
    const {props} = this;
    return (
      <HeaderWrapper>
        /*重点代码 其他代码省略*/
        <div className="search" className={props.foucsed==true?"search focus":"search"} >
            <input type="text" placeholder="搜索" onFocus={()=>{props.changeFoucs(true)}} onBlur={()=>{props.changeFoucs(false)}} />
            <span className="iconfont icon-fangdajing"></span>
         </div> 
      </HeaderWrapper>
    );
  }
}
const mapStateToProps = (state)=>{
  return {
    foucsed:state.foucsed
  }
}
const mapActionToProps = (dispatch)=>{
  return {
    changeFoucs(value){
      const action = changeFocusStatus(value);
      dispatch(action)
    }
  }
}
export default connect(mapStateToProps,mapActionToProps)(header);
5.拆分reducer.js,然后使用combineReducers进行组合,类似于vue的store拆分
import { combineReducers } from "redux";
import { reducer as HeaderReducer } from "../common/header/store";

const reducer = combineReducers({
    header:HeaderReducer
});

export default reducer;
import reducer from "./reduce";
import * as constant from "./constant";
import * as actionCreators from "./actionCreators";

export { reducer , constant , actionCreators }
import {CHANGE_FOUCS_STATUS} from "./constant";
const defaultStore = {
    foucsed:false
};
export default (store = defaultStore, action) => {
    if(action.type==CHANGE_FOUCS_STATUS){
        const newStore = JSON.parse(JSON.stringify(store));
        newStore.foucsed = action.value;
        return newStore;
    }
    return store;
};

constant.js(也就是actionTypes.js)代码 constant是常量的意思

export const CHANGE_FOUCS_STATUS = "change_foucs_status";

actionCreators.js代码

import { CHANGE_FOUCS_STATUS } from "./constant";

export const changeFocusStatus = (value) => {
  return {
    type: CHANGE_FOUCS_STATUS,
    value,
  };
};
//其他代码省略
import { actionCreators } from "./store";
const mapActionToProps = (dispatch)=>{
  return {
    changeFoucs(value){
      const action = actionCreators.changeFocusStatus(value);
      dispatch(action)
    }
  }
}

5.使用immutable包保证state中的数据不被修改(防止写代码误操作)

import { CHANGE_FOUCS_STATUS } from "./constant";
//引入immutable库,mutable"可变的"的意思,immutable"不可变的"意思 
import { fromJS } from "immutable";
//通过fromJS方法传入一个对象,得到一个immutable对象
const defaultStore = fromJS({
  focused: false,
});
export default (store = defaultStore, action) => {
  if (action.type == CHANGE_FOUCS_STATUS) {
    // immutable对象的set方法,会结合之前immutable对象(也就是defaultStore)的值和要设置的值,返回一个全新的immutable对象,并不会对之前的对象做修改。
    return store.set("focused",action.value);
  }
  return store;
}; 
//header组件代码改动
const mapStateToProps = (state)=>{
  return {
    //由于
    focused:state.header.get("focused")
  }
}

6.在总的reducer.js中结合dedux-immutable库把最外层的reducer对象也变成immutable对象,改造代码如下:

// import { combineReducers } from "redux";
//引入包的时候combineReducers从redux-immutable引入就可以了。
import { combineReducers } from "redux-immutable";
import { reducer as HeaderReducer } from "../common/header/store";
const reducer = combineReducers({
    header:HeaderReducer
});
export default reducer;
const mapStateToProps = (state)=>{
  return {
    // focused:state.get("header").get("focused")
    //下面的写法等价于上面的写法
    focused:state.getIn(["header","focused"])
  }
}

7.搜索框聚焦,请求搜索历史数据,使用redux-thunk中间件,把异步请求数据操作写在actionCreator中。效果如下:

image.png
import { createStore, compose, applyMiddleware } from "redux";
import reducer from "./reducer";
import thunk from "redux-thunk";
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducer, composeEnhancers(
    applyMiddleware(thunk)
));
export default store;
//注意一个小细节,由于header中的store数据是调用fromJS得到的immutable数据,所以此处把拿到的数据也转换成immutable数据
import { fromJS } from "immutable";
const setKeywordList = (list) => ({
  type: KEYWORD_LIST,
  list:fromJS(list)
});
//暴露出去一个函数
export const getKeywordList = (data)=>{
  return async (dispatch)=>{
    const {data} = await axios.get("http://127.0.0.1:5500/data/headerList.json");
    const action = setKeywordList(data.list)
    dispatch(action);
  }
}
import { CHANGE_FOUCS_STATUS,KEYWORD_LIST } from "./constant";
//引入immutable库,mutable"可变的"的意思,immutable"不可变的"意思 
import { fromJS } from "immutable";
//通过fromJS方法传入一个对象,得到一个immutable对象
const defaultStore = fromJS({
  focused: false,
  list:["罗小黑","刺客伍六七"]
});
export default (store = defaultStore, action) => {
  switch(action.type){
    case CHANGE_FOUCS_STATUS:
      // immutable对象的set方法,会结合之前immutable对象的值和要设置的值,返回一个全新的对象。
      return store.set("focused",action.value); 
    case KEYWORD_LIST:
      return store.set("list",action.list);
    default:
      return store
  }
};
import { Component } from "react";
import { connect } from "react-redux";
import { actionCreators } from "./store";
class header extends Component {
  //渲染历史记录
  getHisTory(state, list) {
    if (state) {
      return (
        <History>
          {list.map((item) => {
            return (
              <div className="item" key={item}>
                <div className="item__left">
                  <i className="iconfont icon-clock"></i>
                  <span>{item}</span>
                </div>
                <i className="iconfont icon-chahao"></i>
              </div>
            );
          })}
        </History>
      );
    }
  }
  render() {
    const { focused,changeFoucs,list } = this.props;
    return (
      <NavLeft>
        <p className="p1">首页</p>
        <p className="p2">下载APP</p>
        <div className={focused == true ? "search focus" : "search"}>
          <input
            type="text"
            placeholder="搜索"
            onFocus={() => {
              changeFoucs(true);
            }}
            onBlur={() => {
              changeFoucs(false);
            }}
          />
          <span className="iconfont icon-fangdajing"></span>
          {this.getHisTory(focused, list)}
        </div>
      </NavLeft>
    );
  }
}
const mapStateToProps = (state) => {
  return {
    focused: state.getIn(["header", "focused"]),
    list: state.getIn(["header", "list"]),
  };
};
const mapActionToProps = (dispatch) => {
  return {
    changeFoucs(value) {
      const action = actionCreators.changeFocusStatus(value);
      dispatch(action);
      //如果聚焦,就去请求后端数据
      if(value)dispatch(actionCreators.getKeywordList())
    }
  };
};
export default connect(mapStateToProps, mapActionToProps)(header);
上一篇下一篇

猜你喜欢

热点阅读