1、安装
cnpm i create-react-app@3.2.0 -g
create-react-app -V
create-react-app 名_字 //下载时间比较长
cnpm(npm) run start //启动2、目录介绍
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 //依赖的安装包 (一般不用动)
(1)public(静态资源不会被打包)
manifest.json 缓存使用 App名称 图标 图片大小 主色调 等配置
logo192.png || logo512.png 启动图标
robots.txt 爬虫协议 设置网站是否允许爬虫搜索到
# https://www.robotstxt.org/robotstxt.html
User-agent:*
意思是允许所有爬虫搜索(2)src
入口文件 index.js
.gitignore
设置不会被git上传的文件
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.gitignore
.pnp.js
.gitignore
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*3、非弹射状态配置
cnpm run eject webpack深度开发设置,操作不可逆转
React官方不推荐 执行cnpm run eject
弹射的作用可以看到脚手架所有的配置,进行深度开发
设置别名,最新版配置
下载
npm install react-app-rewired customize-cra --save-dev
cnpm 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 设置别名
//在根目录创建
/* 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
src>创建 components> layout >tab.jsx
main >index>index.jsx
>list>index.jsx
>test>index.jsx
src>创建 router >index.js下载模块
npm i react-router-dom -S
cnpm i react-router-dom -S入口文件 index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from '@/App.jsx';
import * as serviceWorker from './serviceWorker';
+ import { HashRouter as Router } from "react-router-dom";
ReactDOM.render(
+ <Router>
<App />
+ </Router>
, document.getElementById('root'));
serviceWorker.unregister();router >index.js
import React, { Fragment } from "react";
import { Route, Redirect, Switch } from "react-router-dom";
import Index from "@/components/main/index/index.jsx"
import List from "@/components/main/list/index.jsx"
import Test from "@/components/main/test/index.jsx"
export default class extends React.Component {
render() {
return (
<Fragment>
<Switch>
<Route path="/index" component={Index} />
<Route path="/list" component={List} />
<Route path="/test" component={Test} />
<Redirect path="/" to="/index" />
</Switch>
</Fragment>
)
}
} src > compoonents > layout > tab.jsx
import React from "react";
import { withRouter, Link } from "react-router-dom";
import { TabBar } from 'antd-mobile';
class Tab extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedTab: 'blueTab',
hidden: false,
fullScreen: false,
};
}
render() {
return (
<div style={{ position: 'fixed', width: '100%', bottom: 0 }}>
<TabBar
unselectedTintColor="#949494"
tintColor="#33A3F4"
barTintColor="white"
hidden={this.state.hidden}
>
<TabBar.Item
title="Glp"
key="Glp"
icon={
<Link to="/index">
<div style={{
width: '22px',
height: '22px',
background: 'url(https://zos.alipayobjects.com/rmsportal/sifuoDUQdAFKAVcFGROC.svg) center center / 21px 21px no-repeat'
}}
/>
</Link>
}
selectedIcon={<div style={{
width: '22px',
height: '22px',
background: 'url(https://zos.alipayobjects.com/rmsportal/iSrlOTqrKddqbOmlvUfq.svg) center center / 21px 21px no-repeat'
}}
/>
}
selected={this.state.selectedTab === 'blueTab'}
onPress={() => {
this.setState({
selectedTab: 'blueTab',
});
}}
data-seed="logId"
>
</TabBar.Item>
<TabBar.Item
icon={
<Link to="/list">
<div style={{
width: '22px',
height: '22px',
background: 'url(https://gw.alipayobjects.com/zos/rmsportal/BTSsmHkPsQSPTktcXyTV.svg) center center / 21px 21px no-repeat'
}}
/>
</Link>
}
selectedIcon={
<div style={{
width: '22px',
height: '22px',
background: 'url(https://gw.alipayobjects.com/zos/rmsportal/ekLecvKBnRazVLXbWOnE.svg) center center / 21px 21px no-repeat'
}}
/>
}
title="Koubei"
key="Koubei"
selected={this.state.selectedTab === 'redTab'}
onPress={() => {
this.setState({
selectedTab: 'redTab',
});
}}
data-seed="logId1"
>
</TabBar.Item>
<TabBar.Item
icon={
<Link to="test">
<div style={{
width: '22px',
height: '22px',
background: 'url(https://zos.alipayobjects.com/rmsportal/psUFoAMjkCcjqtUCNPxB.svg) center center / 21px 21px no-repeat'
}}
/>
</Link>
}
selectedIcon={
<div style={{
width: '22px',
height: '22px',
background: 'url(https://zos.alipayobjects.com/rmsportal/IIRLrXXrFAhXVdhMWgUI.svg) center center / 21px 21px no-repeat'
}}
/>
}
title="Friend"
key="Friend"
dot
selected={this.state.selectedTab === 'greenTab'}
onPress={() => {
this.setState({
selectedTab: 'greenTab',
});
}}
>
</TabBar.Item>
<TabBar.Item
icon={{ uri: 'https://zos.alipayobjects.com/rmsportal/asJMfBrNqpMMlVpeInPQ.svg' }}
selectedIcon={{ uri: 'https://zos.alipayobjects.com/rmsportal/gjpzzcrPMkhfEqgbYvmN.svg' }}
title="My"
key="my"
selected={this.state.selectedTab === 'yellowTab'}
onPress={() => {
this.setState({
selectedTab: 'yellowTab',
});
}}
>
</TabBar.Item>
</TabBar>
</div>
);
}
}
export default withRouter(Tab);
App.jsx
import React from 'react';
import './App.css';
+ import Routers from "@/router";
+ import Tabs from "@/components/layout/tab";
class App extends React.Component {
render() {
return (
<div>
<h1>我在</h1>
<hr />
+ <Routers /> //路由跳转
+ <Tabs /> //底部导航
</div>
)
}
}
export default App;
React-redux
下载插件
npm 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
cnpm i redux react react-dom react-redux redux-immutable redux-thunk immutable -S -Dsrc > store > index.js
import {createStore,applyMiddleware} from "redux";
import {combineReducers} from "redux-immutable";
import thunk from "redux-thunk";
import indexReducer from "@/components/main/index/indexReducer";
const store = combineReducers({
indexReducer
})
export default createStore(store,applyMiddleware(thunk));
入口文件index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from '@/App.jsx';
import * as serviceWorker from './serviceWorker';
import { HashRouter as Router } from "react-router-dom";
+ import store from "@/store";
+ import { Provider } from "react-redux";
//console.log(store);//正常 {dispatch: ƒ, subscribe: ƒ, getState: ƒ, replaceReducer: ƒ, Symbol(observable): ƒ}
ReactDOM.render(
+ <Provider store={store}>
<Router>
<App />
</Router>
+ </Provider>, document.getElementById('root'));
serviceWorker.unregister();
src > components>main>index>indexReducer.js
import {fromJS} from "immutable";
const defaultState=fromJS({
num:0,
});
export default (state=defaultState,action)=>{
return state;
};
src > components>main>index>index.jsx
import React from "react";
import { connect } from "react-redux";
class Index extends React.Component {
render() {
return (
<div>
<h1>index</h1>
<h1>数字{this.props.num}</h1>
</div>
)
}
}
const mapStateToProps = state => {
return {
num: state.getIn(["indexReducer", "num"])
}
};
const mapDispatchToProps = dispatch => {
return {
// dispatch({
// type: "INDEX_NUM_ADD",
// })
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Index);axios 库 Fetch 原生 flyio
微应用时代 uni-app
代理
src下创建 setupProxy.js
//模块直接有,不需要下载
var proxy = require("http-proxy-middleware");
module.exports = function(app) {
app.get("/test",(req,res)=>{
res.send("run");
})
app.use(
proxy("/apis", {
// 我要代理的主机
target: "https://cnodejs.org",
changeOrigin: true,
pathRewrite: {
"^/apis": ""
}
})
);
};mock(模拟数据)
下载
cnpm i mockjs -D setupProxy.js
//模块直接有,不需要下载
const proxy = require("http-proxy-middleware");
+ var Mock = require('mockjs')
module.exports = function(app) {
app.get("/test",(req,res)=>{
// 使用 Mock
+ var data = Mock.mock({
+ 'list|1-10': [{
+ 'id|+1': 1
+ }]
+ });
+ res.json(data);
})
app.use(
proxy("/apis", {
// 我要代理的主机
target: "https://127.0.0.1",
changeOrigin: true,
pathRewrite: {
"^/apis": ""
}
})
);
};Feach
Es6Ajax方案
Promis,axios,fetch,flyio 都支持promise API
如果返回的是字符串 使用 .text()
如果返回的是json 使用 .json()
GET请求
src > components>main>index>index.jsx
//Query String Parameters 标准的 GET 请求
//Promise {<pending>} 原生 promise
<button onClick={this.props.getTest.bind(this)}>GET</button>
const mapDispatchToProps = dispatch => {
return {
getTest() {
fetch("/apis/PHP1904/Vue/php/index.php?uname=Glp&upwd=123456", {
method: "GET"
}).then((data) => {
// console.log(data); //body: ReadableStream 可读的流
return data.text();
}).then(res => {
console.log(res); //你好!Glp本次服务即将开始,祝你旅行愉快!
});
}
}
}POST请求
//From Data
<button onClick={this.props.PostTest.bind(this)}>Post</button>
PostTest(){
var temp= new FormData();
temp.append("uname","郭立鹏")
temp.append("upwd","123456")
fetch("/apis/PHP1904/Vue/php/txt.php", {
method: "POST",
body:temp
}).then((data) => {
// console.log(data);
return data.text(); //.text()
}).then(res => {
console.log(res);
});
}async await 解决异步的先后问题
拿同步解决异步问题
await 必须写在 async 的内部
async 最终返回结果是一个 promise
await 后面跟一个promise
<button onClick={this.props.AwaitTest.bind(this)}>Await</button>
AwaitTest() {
function testNum(num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num + 1);
},2000)
})
}
testNum(1).then(res => {
console.log(res);
})
// async function testAdd(num){
// return num+1;
// }
// testAdd(1).then(res=>{
// console.log(res);
// })
const testFn = async () => {
// return await testNum(1);
let res1 = await testNum(1);
let res2 = await testNum(res1 + 1);
return res2;
}
testFn().then(res => {
console.log(res);
})
// console.log(testFn()); Promise {<resolved>: "ok"}
},实践 async await
<button onClick={this.props.SAwaitTest.bind(this)}>SAwait</button>
SAwaitTest() {
const testFetch = async () => {
var temp = new FormData();
temp.append("uname", "郭立鹏");
temp.append("upwd", "123456");
let respons = await fetch("/apis/PHP1904/Vue/php/txt.php", {
method: "POST",
body: temp
});
return respons.text();
};
testFetch().then((res) => {
console.log(res);
});
}