以前都没用过快速构建工具来搭react环境,这次通过学习来走一遍,并且记录下知识点(纯属个人愚见)

1.构建出现public文件目录

  • 架手架 create-react-app demo 后生成public文件-----> public文件 是放一些静态资源的,是不会参与构建的,你输入是怎样,最终打包构建还是怎样,不像src文件下的代码会参与打包构建

2.自定义数据.json 一些操作指令 比如:test文件下有api文件下的data.json

  • test ls ---> 出现 api
  • test ls api/ ---> api文件下出现data.json
  • test vi api/data.json -----> 进入到 .json 文件
  • 左下角 :q ------> 就是退出该文件

3.create-react-app 已经集成了代理转发的功能,需要在package.json中配置 (要先把mock数据放到mock服务器上并配置5000端口,比如mock服务器上有很多.json文件)

"proxy":{   "/api":{    (例子)"target": "http://localhost:5000" }
}
复制代码

4.直接把mock数据放在public文件夹下

public文件夹mock文件夹data.json文件{"data":"test"}localhost:3000/mock/data.json   这样也能拿到mock的模拟数据
public文件下的内容会原封不动的打包到整个项目当中,是一些静态资源
复制代码

5.父级传参到子级,可以通过...扩展运算符来传递

todos是父级传给子级的props todos = [{id:1,text:"1111"},{id:2,text:"2222"}]todos.map(todo=>{return <Todo key={todo.id} {...todo}/>
})
复制代码

6.通过...扩展运算符往旧数组里加数据

const todo = {id: this.indexId++,text: text,completed: true
}
const newTodoArr = [...this.state.todoArr,todo]
复制代码

7.通过...扩展运算符往旧对象里里更改某个数据

如果用户自定义的属性,放在扩展运算符后面,则扩展运算符内部的同名属性会被覆盖掉,这用来修改现有对象部分的部分属性就很方便了。const newTodo = this.state.todos.map(item=>{return item.id === 1? {...item, completed: !item.completed} :item
})
复制代码

8.用redux时,actions文件夹下一般有2个文件

index.js文件下:import {ADD_TODO, ………等} from "./actionTypes";export addTodo = (text)=>({type:ADD_TODO,text})……………等……………一般情况下 type 同方法名称相同并且改成大写即可actionTypes.js文件下:export const ADD_TODO = "ADD_TODO";…… …… ……
复制代码

9.用reducer时,reducer文件夹下的index.js文件

const initState = {filter: "",todos: [],text: ""
}const todoApp = (state = initState, action)=>{switch(action.type){case ADD_TODO:return {...state,todos:[...state.todos,{id: action.id,text:action.text,completed: false}]}case SET_FILTER:…… ……case SET_TODO_TEXT:…… ……default :return state}
}
export default todoApp;reducer里的state是不能直接操作的,必须返回一个新的state,返回新的state对象的方法有很多,比如 Object.assign({},……)也是其中一种方法
复制代码

10. index.js文件下的 reducer拆分

其中一个例子,分解reducer中的 SET_TODO_TEXT新建一个text.js 用来拆分 SET_TODO_TEXTimport {…… ……} from ""../actions/actionTypes;
const text = (state = "", action)=>{switch (action.type){case SET_TODO_TEXT:return action.textdefault:return state}
}
export default text分解完上面那个大reducer之后,把reducer文件夹中的index里面的大reducer删掉,逐步引入拆分的各个小的reducerindex.js:import { combineReducers } from "redux";import text from "./text";import …… ……export default combineReducers({text,…… ……});必须安装redux这个依赖 npm install redux 因为create-react-app 并没有安装redux
复制代码

11. 在src文件夹下创建 store.js

import { createStore } from "redux";
import rootReducer from "./reducers";
import { addTodo ,…… …… } from "./actions";export const store = createStore(rootReducer);// 得到初始的state
store.getState()
// 订阅state的变化
store.subscribe(()=>{console.log(store.getState)
})
// 发生actions
store.dispatch(addTodo("11111"));
复制代码

12. 集成react-redux(容器型组件拆分,编写 )

  • 向根组件注入 Store -> Provider 组件
  • 连接React组件和redux状态层 -> connect
  • 获取React组件所需的State和Actions -> map api
  • 先安装react-redux这个依赖 npm install react-redux 因为create-react-app 并没有安装react-redux
例子:在src下创建containers文件夹,创建TodoListContainer.js文件 容器组件import { connect } from "react -redux";import { toggleTodo } from "../actions";import TodoList from "../components/TodoList";const mapStateToProps = (state)=>({todos: state.todos})const mapDispatchToProps = (dispatch)=>({toggleTodo: id => dispatch(toggleTodo(id))})export default connect(mapStateToProps,  //redux中的state映射到react组件当中的props上mapDispatchToProps  //react组件需要使用的action方法,映射到组件的props当中)(TodoList);connect()属于高阶组件,将完成react层和redux层的逻辑连接例子:在src下的components文件夹的App.js文件下 引入containers里的容器组件import { TodoListContainer } from "../containers/TodoListContainer";    import …… ……return (<div><TodoListContainer/>…… ……</div>)例子:在src下的index.js 入口文件import { createStore } from "redux";import { Provider } from "react-redux";import rootReducer from "./reducers";const store = createStore(rootReducer);<Provider store={store}><App/></Provider>
复制代码

13. 异步Action 有时action里会通过调用api拿到一些数据,然后再dispatch(),这样就存在异步,数据会有延迟

例子:const getTodosSuccess = (data)=>({type: "TODOS_SUCCESS",data})const getTodosFailure = (error)=>({type: "TODOS_FAILURE",error})export const getTodos = ()=> dispatch =>{return new Promise((resolve,reject) => {axios.get({ url: 'xxxxxxxxx'}).then(res=>{dispatch(getTodosSuccess(res))resolve(res)}).catch(err=>{dispatch(getTodosFailure(err))reject(err)})})}getTodos()返回值是一个函数,这个函数我们是无法处理的,所以要借助redux的中间件来完成异步action这个操作最常用的是 npm install redux-thunk
复制代码

14. 异步Action 要用中间件解决 redux-thunk

例子: 在src目录的 index.js下import thunkMiddleware from "redux-thunk";import { createStore, applyMiddleware } from "redux";const store = createStore(rootReducer, applyMiddleware(thunkMiddleware))这样创建出来的store 就能处理异步action了
复制代码

15. 谷歌浏览器安装redux调试工具

在github上寻找 redux-devtools-extension找到 Advanced store setupif you setup your store with middleware and enhancers,change:xxxxxxxxxxxxxxxxxxxxxxxxxxx 这里的东西可以用,复制下来在src目录的 index.js下import { compose } from "redux";  //compose这个函数可以帮助我们将多个enhancers组合到一起,compose是个增强器可以增加store的功能const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION__COMPOSE__ || compose;const store = createStore(rootReducer, composeEnhancers(applyMiddleware(thunkMiddleware)));
复制代码

16. 项目结构组件方式

按照类型:action/-- action1.js   action2.jscomponents/-- component1.js   component2.jsreducers/-- reducer1.js   reducer2.js  index.js(所有reducer组合成一个)containers/  (容器型组件)-- containser1.js  containser2.js按照功能模块:(存在不同模块之间状态互相耦合的场景)feature1/-- components/-- Container.js-- actions.js-- reducer.jsfeature2/-- components/-- Container.js-- actions.js-- reducer.jsDucks: …………
复制代码

17. Middleware(中间件) 增强store dispatch的能力

例子:redux-thunk  可以处理函数类型的action了View -> ( mid1 -> mid2 -> …… …… ) -> reducer  //页面触发action 会逐步经过这些中间件,增强dispatch,dispatch所做的事就是派发actionFunction:({getState, dispatch}) => next => action在src文件夹下 新建 Middleware文件夹->logger.js// 打印action, state 的logger中间件const logger = ({getState, dispatch}) => next => action => {console.group(action.type);console.log("dispatching:", action);const result = next(action);console.log("next state:", getState()); consoel.groupEnd();return result;}export default logger;在index.js文件下 ,把自己写的中间件加进去import loggerMiddleware from "./middleware/logger";const store  = createStore(…… ……applyMiddleware(…… ……,loggerMiddleware))
复制代码

18. store enhancer 增强redux store的功能

store enhancer 一般结构:function enhancerCreator(){return createStore => (...arg) => {// do something based old store// return a new enhanced store}}在src文件夹下 新建enhancer文件夹 -> logger.js// 打印action, state 的增强器const logger = createStore => (...arg) => {const store = createStore(...arg);const dispatch = (action) => {console.group(action.type);console.log("dispatching:", action);const result = store.dispatch(action);console.log("next state:", store.getState()); consoel.groupEnd();return result;}return {...store, dispatch}  // 把新的dispatch方法覆盖到原来对象的dispatch}export default logger;在index.js文件下 ,把自己写的enhancer加进去import loggerEnhancer from "./enhancer/logger";const store  = createStore(…… ……compose(applyMiddleware(thunkMiddleware), loggerEnhancer))compose是可以把多个 store enhancer 进行组合的在平时中应该尽量多使用 Middleware 来增强dispatch的能力, 慎用 store enhancer 记住!
复制代码

18. Immutable.js 可以用来创建不可变的对象state 每次都可以返回个新的

npm install immutable
npm install redux-immutableimport Immutable from "immutable";
import { combineReducers } from "redux-immutable"; const initState = {…… ……,isFetching: false,todos: {……,data: []}
}//这样就创建了一个不可变的 immutable 对象
const state = Immutable.fromJS(initState) //设置属性,一次只能设置一个key
state.set("isFetching", true);  //merge可以一下设置多个
state.merge({isFetching: false,todos: Immutable.fromJS(action.data)  // 数据类型一定要统一用immutable的类型
});//get得到属性的值
state.get("isFetching");//getIn 从外层到内层逐层获取
state.getIn(["todos","data"]);//把immutable对象转化成普通JS对象
state.toJS();
因为在 mapStateToProps,…… 的对象要普通JS对象才能使用在reducers文件下的 index.js中import { combineReducers } from "redux-immutable";  // redux中的combineReducers只能识别普通JS对象
复制代码

19. Reselect库经常和redux一起使用, Reselect减少state的重复计算

npm install reselectimport { createSelector } from "reselect"const getFilter = (state) => state.filter;
const getTodos = (state) => state.todos.data;export const getVisibleTodos = createSelector([getTodos,getFilter],      //数组里面是其他所依赖的select函数(todos, filter) => {      //前2个函数返回的数据结果,可用来计算console.log("-----");  //用来测试看有没多余的重复执行switch(filter){case: "xxx":returncase ……:……default:……}}
);只有当select函数确实非常复杂并且整个redux性能有很大的问题才去考虑用reselect,并不是必须的
复制代码

20. Router相关库

  • react-router
  • react-router-dom
  • react-router-native
  • 建议在项目之中使用<BrowserRouter>组件
react-router这个库实现了路由的核心功能,react-router-dom是在react-router之上的一层封装,将react-router的路由功能和web的API进行了绑定<Router>常用组件: <BrowserRouter>1 . Html5 history API (pushState, repalceState等)2. 需要Web服务器额外配置localhost:3000/home     localhost:3000/about<Router>常用组件: <HashRouter>1. 使用url的hash部分作为路由的信息2. 主要为了兼容老版本浏览器localhost:3000/#/home     localhost:3000/#/about
复制代码

21. 路由配置:Route

<BrowserRouter><Route path="/" exact component={Home}/><Route path="/about" component={About}/><Route path="/user/:aaa" component={User}/>…… ……
<BrowserRouter/>组件中得到传过来的参数: this.props.match.params.aaa
复制代码

22. 路由匹配

<Route exact />  exact : url和path完全相同的情况下才会匹配成功import { Switch } from "react-router-dom";
<Switch><Route path="/about" component={About}/><Route path="/user/:aaa" component={User}/><Route path="/" component={Home}/>    // 当前面都匹配不成功时,根路径才会被匹配
<Switch/>Swicth 的功能是会去匹配第一个,被匹配到的<Route />,当第一个<Route/>匹配到的时候,其他的<Rpute>都不会被匹配
复制代码

23. 路由渲染组件的方式

  • <Route component />
  • <Rute render />
  • <Route children />
<Route path="/about" render={(props) => <About {...props}/>   //props是一个对象,包含了match,location,history
} />在App.js:<Router><Route path="/user" component={User}></Router>
在User.js:<div><Route path={`${this.props.match.path}/:user`} component={UserDetail}></div>
在UserDetail.js:<div>this.props.match.params.user</div>
复制代码

24. create-rwact-app 创建出来的默认的入口文件

    // If you want your app to work offline and load faster, you can change// unregister() to register() below. Note this comes with some pitfalls.// Learn more about service workers: https://bit.ly/CRA-PWAserviceWorker.unregister();serviceWorker  离线存储,加载优化的事情, 做项目时没使用到的话要把这句话删掉
复制代码

25. store.js 文件中的 process.env.NODE_ENV 环境变量 && 判断浏览器有没装redux调试工具

    判断当年程序的执行是开发环境还是生产环境 && 如果浏览器安装redux的调试工具 window对象下会有redux的调试方法添加进去if (process.env.NODE_ENV !== "production" &&window.__REDUX_DEVTOOLS_EXTENSION__){const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__;  // 作为store的增强器store = createStore(rootReducer, composeEnhancers(applyMiddleware(thunk)));  // 将REDUX_DEVTOOLS的功能增强到store当中} else {store = createStore(rootReducer, applyMiddleware(thunk));}复制代码

26. fetch()或者 axios 请求url

 axios 优缺点:- 从 node.js 创建 http 请求。- 支持 Promise API。- 提供了一些并发请求的接口(重要,方便了很多的操作)。- 在浏览器中创建 XMLHttpRequests。- 在 node.js 则创建 http 请求。(自动性强)- 支持 Promise API。- 支持拦截请求和响应。- 转换请求和响应数据。- 取消请求。- 自动转换 JSON 数据。- 客户端支持防止CSRF。- 客户端支持防御 XSRF。Fetch 链接 https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch (MDN)axios既提供了并发的封装,也没有fetch的各种问题,而且体积也较小,当之无愧现在最应该选用的请求的方式。
复制代码

27. 中间件的业务流程

文件 ./entities/products.jsexport const schema = {name: "products",id: "id"}…… …… ……*****************************************************文件 ./redux/home.jsimport FETCH_DATA from "../middleware/api"import schema from "./entities/products"export const types = {FETCH_LIKES_REQUEST:"FETCH_LIKES_REQUEST",FETCH_LIKES_SUCCESS:"FETCH_LIKES_SUCCESS",FETCH_LIKES_FAILURE:"FETCH_LIKES_FAILURE"}export const actions = {loadLikes: ()=>{return (dispatch, getState) => {const endpoint = url.getProductList(0,10);   // utils中的方法返回一个url路径return dispatch(fetchLikes(endpoint));}}}const fetchLikes = (endpoint)=>({[FETCH_DATA]: {                         types:[types.FETCH_LIKES_REQUEST,types.FETCH_LIKES_SUCCESS,types.FETCH_LIKES_FAILURE],endpoint,schema},});…… …… ……*****************************************************文件 middleware/api.jsexport const FETCH_DATA = "FETCH_DATA";export default store => next => action => {const callAPI = action[FETCH_DATA];if(typeof callAPI === "undefined"){return next(action);}const { endpoint, schema, types } = callAPIif(typeof endpoint !== "string"){throw new Error("endpoint要为字符串类型的url");}if(!schema){throw new Error("必须指定领域实体的schema");}if(!Array.isArray(types) && types.length !== 3){throw new Error("需要指定一个包含了3个action type的数组");}if(!types.every(type => typeof type === "string")){throw new Error("action types 必须为字符串类型");}// 里面有新东西,增强dispatch()const actionWith = (data) =>{const finalAction = {...action, ...data};delete finalAction[FETCH_DATA];return finalAction }const [requestType, successType, failureType] = types;next(actionWith({type: requestType}));return fetchData(endpoint, schema).then(response => next(actionWith({type: successType,response})),error => next(actionWith({type: failureType,error: error.message || "获取数据失败"})) )};// 执行网络请求const fetchData = (endpoint, schema) => {return get(endpoint).then(data => {return normalizeDate(data,schema)})}// 根据schema,将获取的数据扁平化处理const normalizeDate = (data,schema) => {const { id,name } = schema;let kvObj = {};let ids = [];if(Array.isArray(data)){data.forEach(item => {kvObj[item[id]] = item;ids.push(item[id]);})}else{kvObj[data[id]] = data;ids.push(data[id]);}return { [name]: kvObj,ids}}
复制代码

结语

前端react QQ群:788023830 ---- React/Redux - 地下老英雄

前端交流 QQ群:249620372 ---- FRONT-END-JS前端

(我们的宗旨是,为了加班,为了秃顶……,仰望大佬),希望小伙伴们加群一起学习

转载于:https://juejin.im/post/5cc96be351882540b244d601

create-react-app 脚手架构建项目,搬砖过程中持续总结心得相关推荐

  1. create react app创建的项目运行test的时候不能解析webpack的alisa配置的问题

    使用babel插件npm install babel-plugin-module-resolver,并在.babelrc文件中加入如下: {"plugins": [["m ...

  2. 深入浅出 Create React App

    本文差点难产而死.因为总结的过程中,多次怀疑本文是对官方文档的直接翻译和简单诺列:同时官方文档很全面,全范围的介绍无疑加深了写作的心智负担.但在最终的梳理中,发现走出了一条与众不同的路,于是坚持分享出 ...

  3. react快速开始(二)-使用脚手架Create React App创建react应用

    文章目录 react快速开始(二)-Create React App入门 什么是Create React App 快速开始 使用IDE webstrom创建react项目 create react a ...

  4. Create React App来搭建react项目

    版本过旧请参考此网址更新:Getting Started | Create React App npx create-react-app my-app 备注:react使用比较自由,不限制多或者少,愿 ...

  5. 在 .NET Core 5 中集成 Create React app

    翻译自 Camilo Reyes 2021年2月22日的文章 <Integrate Create React app with .NET Core 5> [1] 本文演示了如何将 Crea ...

  6. Create React App从使用到Docker部署

    一.介绍 Create React App 是 React 脚手架,它帮我们可以快速生成项目的工程化结构,脚手架让项目从搭建到开发再到部署,整个流程变得快速和便捷. 二.安装 Create React ...

  7. 【翻译】基于 Create React App路由4.0的异步组件加载(Code Splitting)

    基于 Create React App路由4.0的异步组件加载 本文章是一个额外的篇章,它可以在你的React app中,帮助加快初始的加载组件时间.当然这个操作不是完全必要的,但如果你好奇的话,请随 ...

  8. 如何使用Create React App DevOps自动化工作中所有无聊的部分

    by James Y Rauhut 詹姆士·鲁豪(James Y Rauhut) 如何使用Create React App DevOps自动化工作中所有无聊的部分 (How I automate al ...

  9. Create React App 2.0 正式发布:Babel 7、webpack 4 等

    英文原文:Create React App 2.0: Babel 7, Sass, and More – React Blog 以下是简要翻译 React 本身是没有附带任何编译工具的,如果没有测试运 ...

最新文章

  1. html css 隐藏和显示按钮
  2. java-mybaits-00101-基础安装配制
  3. linux做成service服务器,Zabbix2.0.3做成Service
  4. 核心员工要离职,怎么办?
  5. Windows Server Backup 裸机恢复
  6. JavaScript实现shortestCommonSupersequence最短公共超序列算法(附完整源码)
  7. Linux 进程(二) 进程地址空间
  8. 数字模拟信号 单双信道传输
  9. VB2005.Net 环境下使用Jmail组件发送邮件
  10. 白硕 | 基于区块链的众包社区激励机制
  11. 小白学JAVA,与你们感同身受,JAVA---day6:抽象类接口的理解。鲁迅的一句话:总之岁月漫长,然而值得等待。
  12. Linux运行8086代码,* linux下编译,链接,运行,汇编程序
  13. JEE_Ajax技术
  14. dubbo接口统一异常处理的两种方式
  15. android studio Available qualifiers(可用资源限定符)笔记(待完善)
  16. 由对称性知定点一定在x轴上_2021版江苏高考数学一轮复习讲义:第8章 第10节 圆锥曲线中的证明、探索性问题 Word版含答案...
  17. DRAM原理-Storage Cell
  18. 城市大脑从起源到终极状态的7个阶段
  19. 高性能ORM数据访问组件Deft,比dapper快20%以上
  20. python学什么内容_老男孩Python都需要学什么内容?老男孩教育

热门文章

  1. javascript学习(三) 内置对象
  2. Linux下SSH 客户端不用输入密码配置步骤
  3. 艾伟_转载:.NET内存管理、垃圾回收
  4. md5sum算法 —— linux或Unix上,md5sum是用来计算和校验文件报文摘要的工具程序
  5. 2019.7.9刷题统计
  6. 2018.12.05 codeforces 948C. Producing Snow(堆)
  7. 无法找到“XXX.exe”的调试信息,或者调试信息不匹配。未使用调试信息生成二进制文件...
  8. Mac下Jekyll安装
  9. Uuntu 20.04 install OpenLDAP
  10. 池化方法总结(Pooling)