axios数据交互
开启后端服务
1.数据库导入数据
2.开启后端服务
创建项目
1.create-react-app u-orange
2.cnpm i react-router-dom@5.3.0 axios qs -S
3.修改端口号
4.npm start #启动项目
5.项目运行在: http://localhost:5000
package.json做配置代理
//配置代理
{ "proxy":"http://localhost:3000",}
//重启项目: npm start
数据请求案例
import React, { Component } from 'react'
import axios from 'axios'
export default class Home extends Component {
constructor(){
super()
this.state = {
getNew :[],//新人专享
}
}
// 组件挂载完成发起异步请求
componentDidMount(){
// 发起新人专享请求
axios.get('/api/getnew').then(res=>{
if(res.data.code === 200){
this.setState({getNew:res.data.list})
}
})
}
}
手动配置代理
安装http-proxy-middleware
cnpm i http-proxy-middleware -S
创建setupProxy.js文件
- src/setupProxy.js
const { createProxyMiddleware }=require("http-proxy-middleware");
module.exports=(app)=>{
app.use(createProxyMiddleware('/api', {
target: 'http://localhost:3000',//目标地址
changeOrigin: true,//是否允许跨域 true:是 false:否
ws: true,//websoket 长连接
pathRewrite: {//路径重写
"^/api":"http://localhost:3000"
},
}));
}
//重启项目: npm start
- getNew
import React, { Component } from 'react'
import axios from 'axios'
export default class Home extends Component {
constructor(){
super()
this.state = {
getNew :[],
}
}
componentDidMount(){
// 地址: http://localhost:3000/api/getnew
// 本地: /api === http://localhost:3000
// 本地访问: /api/api/getnew
axios.get('/api/api/getnew').then(res=>{
if(res.data.code === 200){
this.setState({getNew:res.data.list})
}
})
}
}
fetch
- fetch是Ajax的替代品
get请求
fetch('地址').then(res=>{
return res.json()
}).then(res=>{
//服务端响应的结果
}).catch(err=>{
//捕获异常错误
})
post请求
fetch('地址',{
method:'post',
headers:{
"Content-Type":"application/x-www-form-urlencoded"
},
body:qs.stringify(data)//数据要是json格式
}).then(res=>{
return res.json()
}).then(res=>{
//服务端响应的结果数据
}).catch(err=>{
//捕获异常错误信息
})
封装
- get请求
// 封装get
export function get(url){
return fetch(url).then(res=>{
return res.json()
})
}
- api.js
import {get} from './http'
// 获取新人专享
export const getNew = ()=>get('/api/api/getnew')
- post请求
// 封装post
export function post(url,data){
return fetch(url,{
method:'post',
headers:{
"Content-Type":"application/x-www-form-urlencoded"
},
body:qs.stringify(data)
}).then(res=>{
return res.json()
})
}
- …展开,并修改原数组。
constructor() {
super()
this.state = {
user: {
phone: '',
password: '',
}
}
}
changeUser(e, type) {
this.setState({
user: {
...this.state.user,
[type]:e.target.value//[]将变量转为字符串,而对象键值对都为字符串。
}//...之后写对象中有的属性为修改,没有的为添加
})
}
render() {
const {user} = this.state
return (
<div>
<input type="text" value={user.phone} onChange={(e) => this.changeUser(e, 'phone')} />
<input type="password" value={user.password} onChange={(e) => this.changeUser(e, 'password')} />
</div>)
}
redux原理
网址:https://www.redux.org.cn/
阮一峰:https://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html
什么是redux
- Redux 是 JavaScript 状态容器,提供可预测化的状态管理。
使用redux
- 某个组件的状态,需要共享
- 某个状态需要在任何地方都可以拿到
- 一个组件需要改变全局状态
- 一个组件需要改变另一个组件的状态
- 多交互,多数据源时使用redux
redux的三大原则
单一数据源
- 整个应用的 state 被储存在一棵
object tree
中,并且这个object tree
只存在于唯一一个store
中。
//Object tree
const initialState = {
name:'zs',
age:20,
goods:[],
orders:[],
}
state、action
- state是只读的。
- 唯一改变
state
的方法就是触发action
action
是一个用于描述已发生事件的普通对象。
const action = {type:'操作的类型'[,data:'']}
//组件中通过store.dispatch触发action
store.dispatch(action)
reducers函数执行修改
- 为了描述 action 如何改变
state tree
,你需要编写reducers
。 reducers
是真正执行修改的函数。
//reducer函数
function reducer(state=initialState,action){
switch(action.type){
case 'add':
执行添加操作并且返回新值
case 'update':
执行修改state数据并返回新值
case 'list':
返回查询的最新数据
case 'del':
执行删除操作并返回新值
default:
return state
}
}
使用redux
安装
cnpm i redux -S
创建仓库store
- 接受参数为:reducer函数
import {createStore} from 'redux'
const store = createStore(reducer)
// 导出
export default store
state
// 声明state初始值
const initialState = {
name:'zs',
age:20,
}
action
action = {type:'changeName',name:'ww'}
reducer
- 参数一为:state为上一次更新的最新数据, 默认有初始值。
- 参数二为:action。
function reducer(state = initialState,action){
switch (action.type) {
// action = {type:'changeName',name:'ww'}
case 'changeName':
return {
...state,
name:action.name
}//...之后写对象中有的属性为修改,没有的为添加
default:
return state//默认返回初始state
}
}
store常用的方法
- store常用的方法,在组件中使用。
getState
获取store中state的状态数据
const {name,age} = store.getState();
dispatch
const action = {type:'changeName',name}
store.dispatch(action)
subscribe
- 参数:callback
- 返回值:取消监听方法
componentDidMount(){
// 监听state状态数据的改变,只要变化就触发
store.subscribe(()=>{
//store.getState() === {name:'王翠花',age:20}
this.setState(store.getState())
})
}
取消监听
subscribe返回值为取消监听方法.
componentDidMount(){
this.un = store.subscribe(()=>{
this.setState(store.getState())
})
}
componentWillUnmount(){
// 取消监听
this.un()
}
actionCreator
- 作用:方便在各个组件中调用
index
// 封装actionCreator
export const actions = {
changeName:(name)=>({type:'changeName',name}),
changeAge:(age)=>({type:'changeAge',age})
}
组件
import store,{actions} from '../store/index'
changeName(name){
store.dispatch(actions.changeName(name))
}
actionType的封装
- 作用:方便在action和reducer函数中移植和操作
// 封装Type
const TYPES = {
"CHANGE_NAME":"CHANGE_NAME",
"CHANGE_AGE":"CHANGE_AGE",
}
reducer拆分(子模块)
子模块: [state | actionType | actionCreator | reducer]
// 导出orderReducer
export default orderReducer
// 导出reducer
export default userReducer
store/index.js
import {createStore,combineReducers} from 'redux'
// 引入子模块reducer函数
import userReducer from './modules/user'
import orderReducer from './modules/order'
// 合并子模块的reducer函数
const reducer = combineReducers({
user:userReducer,//命名空间
order:orderReducer
})
// 创建store仓库
const store = createStore(reducer)
// 导出store
export default store