create-react-app@3.2.0
React的官方推荐脚手架工具
安装
cnpm i create-react-app@3.2.0 -g//全局安装工具
create-react-app -V //查看版本
create-react-app xxxx //初始化项目目录
npm run start //启动
//问题
//丢失模块,删除node_modules重新下载
//node版本低 10以上
//Mac系统加上前缀sudo权限
目录
node_modules //第三方依赖的包
public //资源目录
favicon.ico //左上角的图标
index.html //项目首页模板
manifast.json //定义 app 的图标 网址 主题颜色等
robots.txt //robots协议 User-agent: * 允许所有 #注释协议网址
src //项目所有的源代码
index.js //整个程序的入口 (react 的理念 all in js)
index.css //初始化样式,存放于网站根目
App.js //项目通用部分
App.test.js //自动化测试文件
App.css //项目的样式
logo.svg //首页 logo
serviceWorker.js //将网页存储在浏览器内 如果突然断网了 可以继续访问该网页
.gitignore //设置禁止传到 git 文件
package.json //模块清单 和项目介绍 ( 命令行 命令 ) 等
README.md //项目的说明文件
yarn.lock //依赖的安装包 (一般不用动)
非弹射设置
cnpm run eject webpack深度开发设置,操作不可逆转
React官方不推荐 执行cnpm run eject
设置别名,最新版配置
npm install react-app-rewired customize-cra --save-dev
/* package.json */
"scripts": {
- "start": "react-scripts start",
+ "start": "react-app-rewired start",
- "build": "react-scripts build",
+ "build": "react-app-rewired build",
- "test": "react-scripts test --env=jsdom",
+ "test": "react-app-rewired test --env=jsdom",
}
//在根目录创建
/* config-overrides.js */
const path = require('path');
const { override,addWebpackAlias } = require('customize-cra');
//customize-cra 在不弹射情况下 复写 webpack 配置
module.exports = override(
addWebpackAlias({
"@": path.resolve(__dirname, "src")
})
)
Router
router > index.js
import React, { Component, Fragment } from "react"
import { Route, Redirect } from "react-router-dom";
import Info from "@/components/main/Info/Info.jsx"//剧院
import News from "@/components/main/News/News.jsx"//主页
import Mine from "@/components/main/Mine/Mine.jsx"//我的
export default class extends Component {
render() {
<Fragment>
<Route path="/info" component={Info} />
<Route path="/news" component={News} />
<Route path="/test" component={Test} />
<Redirect path="/" to="/info"/>
</Fragment>
}
}
index 入口文件
import { HashRouter as Router } from "react-router-dom";
<Router>
<App />
</Router>
export default withRouter(App)
App.jsx
import React from 'react';
import Routers from "@/router"
import Header from "@/components/layout/header.jsx"
export default class extends React.Component{
render(){
return (
<div>
<Routers/> //路由跳转
<Header/> //导航
</div>
)
}
}
Redux
注意版本问题
库注册
import {createStore,applyMiddleware} from "redux";
import thunk from 'redux-thunk'; //dispatch支持传入一个函数
import {combineReducers} from "redux-immutable";//最外层也为Map对象
import indexReducer from "@/components/index/indexReducer";//fn
import listReducer from "./listReducer";
// 多库形式
const store=combineReducers({
indexReducer,
listReducer
})
export default createStore(store, applyMiddleware(thunk));
注册全局
cnpm i redux@4.0.4 react@16.10.2 react-dom@16.10.2 react-redux@7.1.0 redux-immutable@4.0.0 redux-thunk@2.3.0 immutable@4.0.0 --save-dev
import { Provider } from "react-redux";
import store from "@/store";//基于 redux,先把 redxu store部分初始化完成
console.log(store)// store.getState store.subscribe dispatcher.dispatch
ReactDom.render(
//注入全局
<Provider store={store}>
<App/>
</Provider>,
document.querySelector("#root")
);
//组件使用
import {connect} from "react-redux";
var mapStateToprops=state=>({});
var mapDispatchToprops=dispatch=>({});
export default connect(mapStateToprops,mapDispatchToprops)(Com);
//export default connect(mapStateToprops,mapDispatchToprops)writeRouter(Com);
Proxy与Mock
不需要下载初始化有这个模块
src目录建 setupProxy.js 固定写法
这个里面其实是一个 express 执行环境
Mock.js 在服务端接口还没有回来使用Mock数据,它只是生成数据
代理本地服务数据
var proxy = require("http-proxy-middleware");
//cnpm i mockjs -D
var mock =require("mockjs")
module.exports = function(app) {
app.use(
proxy("/apis", {
// 我要代理的主机
target: "https://cnodejs.org",
changeOrigin: true,
pathRewrite: {
"^/apis": ""
}
})
);
app.use(
proxy("/msea", {
// 我要代理的主机
target: "https://cnodejs.org",
changeOrigin: true,
pathRewrite: {
"^/msea": ""
}
})
);
//localhost:3000/test
app.get("/test",(req,res)=>{
/* list|1-10[
{}
]*/
res.send("OK")
})
};
Fetch请求
promise使用
var promise=new Promise(
function (resolve, reject) {
resolve('成功') // 数据处理完成
// reject('失败') // 数据处理出错
}
)
//结果是一个promins
promise.then((str)=>{
return str //返回为下一个结果
}).then((res)=>{
return res
}).then((res)=>{
console.log(res);
})
async/await
ES7的async/await提案 ,async/await是一个用同步思维解决异步问题的方案
async结果是一个promis对象
await 必须在async中执行
await关键字后面跟Promise对象 强制后面点代码等待 直到Promise对象resolve
主要替传统的callback嵌套
const test= async ()=>{
return {
uname:"Msea"
}
}
test()//结果是一个promis,他的结果取决函数内部返回随
testAsync() {
function testNum(num){
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num+1);
}, 2000)
})
}
const test= async ()=>{
let testNum1=await testNum(1);
let testNum2=await testNum(testNum1);
return testNum2;//只有返回才会有结果
}
test().then((res)=>{
console.log(res);//3
})
}
//await 错误处理
testAsync(ms) {
function testNum(num){
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("run");
reject('发生错误'); //返回错误
},ms)
})
}
const test= async ()=>{
try {
console.log('start');
var res= await testNum(1);
console.log(res);
return res;
console.log('end'); //所以这句代码不会被执行了
} catch(err) {
console.log(err); //这里捕捉到错误error
}
}
test();
}
Fetch Request
fetch是一种HTTP数据请求的方式,是XMLHttpRequest的一种替代方案。
fetch不是ajax的进一步封装,而是原生js。Fetch函数就是原生js,
fetch(url)//参数 xxx?name=Msea&upwd=1122334
fetch(url,{method:"GET"}) //参数 xxx?name=Msea&upwd=1122334
//payLoad
fetch(url,{method:"POST",body:JSON.stringify({uname:"Msea"})})
//fromData
var formData=new FormData();
formData.append("uname","Msea");
formData.append("sex","1111111");
fetch(url,{method:"POST",body:formData})
const loadTest= async ()=>{
var resp=fetch(url,{method:"POST",body:JSON.stringify({uname:"Msea"})});
try {
var data= await resp;
return data.json();
} catch(err) {
console.log(err); //这里捕捉到错误error
}
}
loadTest(),then((res)=>{
console.log(res);
});
基本使用
创建 actionCreator.js 创建异步回调,异步渲染遍历
fetch("https://cnodejs.org/api/v1/topics")
.then(data =>{
//成功回调
console.log(data); //结果是直接字符串 使用.text() 返回json数据.json()
return data.json();
}).then((res)=>{
console.log(res);
}).catch(e =>{
//异步回调
console.log(e)
});
export const LOAD_TEST_DATA = "index/get_test_data";
export const loadGetTestDate = (dispatch,params) => {
return () => {
fetch("/apis/api/v1/topics", {
method: "GET"
})
.then(data => {
return data.json();
})
.then(res => {
dispatch({
type:LOAD_TEST_DATA,
val:res.data
})
});
};
};
const mapDispatchToPros=dispatch=>{
handelTestLoad(){
dispatch(loadGetTestDate(dispatch,{uname:"Msea"}));
}
}
打包
npm run build
打包默认生成一个 build目录,注意默认是 /
<img src="/1.jpg"> //在服务器环境下直接获取 ajax{"/apis"}
//修改为 当前目录修改package.json文件
//最后一行加上
"homepage":"."
<img src="./1.jpg"> //在服务器环境下直接获取 index.html
修改端口
下载模块 yarn add cross-env --dev
修改pageage.json
"start": "cross-env PORT=5000 react-scripts start"
配置Ant-mobile
配置按需引入 cnpm install babel-plugin-import --save-dev
const path=require("path");
const {override,addWebpackAlias,fixBabelImports } =require("customize-cra");
module.exports = override(
addWebpackAlias({
"@":path.resolve(__dirname,"src")
}),
fixBabelImports('import', {
libraryName: 'antd-mobile',
style: 'css'
})
)
//按需引入方式进行引入
import { Button } from 'antd';
<Button type="primary">Button</Button>