react 依賴
- react-native 移動端跨平臺
- 16.13.1版本
- react: 核心程式碼
- react-dom: 渲染在不同平臺需要的核心程式碼
- babel:jsx轉換react程式碼工具
//crossorigin 在控制檯顯示遠端的錯誤資訊
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
ReactDom.render(<App/>,documnet.getElementById('root'))
</script>
//1有繼承extends,子類必須呼叫super()
class Person {
constructor(name,age){
this.name=name;
this.age=age;
}
}
class Student extends Person{
constructor(name,age){
super(name,age)
}
}
jsx核心語法
書寫規範:
- 只能有一個根元素div(或者用Fragment)片段,空標籤佔位
- 用小括號包裹
- 可以寫雙標籤,或者單標籤,必須/>結尾
{js表示式}
1.註釋書寫:
{/*我是一段註釋*/}
2.在{}中不能顯示,被忽略
test1:null
test2:undefined
test3:Boolean
friend:{
name:'kobe'
}
this.setState.test3.toString()可以展示在頁面
this.setState.friend //報錯,物件不能直接這樣展示 ,不能作為jsx的子類
3.嵌入表示式
{/*三元表示式*/}
{isLogin?'歡迎':'登入'}
{/*函式呼叫*/}
4.jsx繫結屬性className
<div className ='' style={{color:'red',fontSize:'30px'}}></div>
<label htmlFor=''></label>
//方式一,顯示繫結
<button onClick={this.btnClick.bind(this)}></button>
//方式二
this.btnClick=this.btnClick.bind(this)
<button onClick={this.btnClick}></button>
<button onClick={(e)=>{this.btnClick(item,index)}}></button>//執行另外一個函式 --推薦
//只要一個引數(e),括號可以省略 e=>{}
btnClick(item,index){
}
//方式三 推薦
<button onClick={this.btnClick></button>
const btnClick=()=>{
}
5.傳遞引數
6.return () 用小括號包裹起來,標籤可以換行
7.條件渲染
// 1.方案一:透過if判斷: 邏輯程式碼非常多的情況
let welcome = null;
let btnText = null;
if (isLogin) {
welcome = <h2>歡迎回來~</h2>
btnText = "退出";
} else {
welcome = <h2>請先登入~</h2>
btnText = "登入";
}
{/* 2.方案二: 三元運算子 */}
<button onClick={e => this.loginClick()}>{isLogin ? "退出" :"登入"}</button>
{/* 3.方案三: 邏輯與&& */}
{/* 邏輯與: 一個條件不成立, 後面的條件都不會進行判斷了 */}
<h2>{ isLogin && "你好啊, coderwhy" }</h2>
{ isLogin && <h2>你好啊, coderwhy</h2> }
react腳手架:create-react-app 專案名稱(dccweb-hd)不允許大寫字母
npm | yarn |
---|---|
npm install | yarn install |
npm install | yarn add |
PWA 離線
serviceWork.js
yarn eject 暴露webpack配置資訊 此操作不可逆
元件的生命週期
生命週期
類元件:可以維護資料狀態,有this
函式沒有生命週期,沒有this,不能管理資料狀態
類裡面的叫方法,有this繫結
外部叫函式
掛載階段 mounting
constroct
cwm→ componentWillMount = () => { } DEPRECATED!!! 過時的
cdm→ componentDidMount = () => { } *****
cwr→ componentWillReceiveProps = (nextProps) => { } DEPRECATED!!!
更新階段 Updating
scu→ shouldComponentUpdate = (nextProps, nextState) => { }
cwup→ componentWillUpdate = (nextProps, nextState) => { } DEPRECATED!!!
cdup→ componentDidUpdate = (prevProps, prevState) => { } *****
解除安裝Unmount
cwun→ componentWillUnmount = () => { }
元件的資料傳遞
父子元件的通訊
父元件透過屬性=值 prodectList={prodectList}
子元件props引數獲取
function Main(props) {
const {prodectList}=props
子元件傳遞父元件
父元件 itemClick={函式}
子元件 執行函式
// 父元件裡呼叫子元件 是否允許ppt向下慣性運動
const flagRef = useRef(true);//是否允許ppt向下慣性運動,預設true,允許,點選一鍵置頂按鈕時,不允許
const getIsInertiaMove = (val: boolean) => {
flagRef.current = val;
};
<Topping
parentCallback={getIsInertiaMove}
currScrollPos={currScrollPosY}
/>
//子元件接收
interface IToppingProps {
currScrollPos: any;
parentCallback: Function;
}
function Topping(props: IToppingProps) {
const { currScrollPos, parentCallback } = props;
// 觸發一鍵置頂按鈕,不允許向下慣性運動
parentCallback(false);
}
跨元件通訊
1.props,一級一級傳值
2.屬性展開:jsx語法
const props={firstName='hobby',lastName='Hector'}
<ProfileHeader {...props}/>
<ProfileHeader firstName="Ben" lastName="Hector" />
3.Context:★
類元件
第一步:建立 export const WordContext = createContext({} as IMobSignContext);
<WordContext.provider value={}>
<Profile/> //不包含在這個裡面,傳遞的就是預設值
<WordContext.provider/>
第二步:
ProfileHeader.contextType=WordContext;
this.context
函式元件:
consumer
後續用redux替代 ★
//插槽 slot
<NavBar>
<span></span>
<div></div>
</NavBar>
this.props.children 獲取元件內部標籤
跨元件事件傳遞 events
yarn add events
API
建立物件:eventBus
import { EventEmitter } from 'events';
const eventBus = new EventEmitter();
發出事件eventBus.emit("事件名稱",引數列表)
監聽事件eventBus.addListener("事件名稱",監聽函式)
移除事件:eventBus.removeListener("事件名稱",監聽函式)
setState
setState是非同步更新的
提高效能:獲取多個更新,然後批次更新
如果同步,不能保證render和props同步,不能保證state和props一致性
this.setState({
message:'你好啊'
},()=>{
//拿到非同步的資料,類似vue裡面的nextTick
console.log(this.state.message)
})
componentDidUpdate()方式二:獲取非同步資料
同步更新:
放在定時器裡面執行,變成同步
資料合併:傳物件
setState內部合併:
累計合併:傳函式
setState((preState,props)=>{
return{
counter:preState.counter+1
}
})
react效能最佳化
函式元件:memo包裹
counter改變,包裹memo的元件不會重新渲染
類元件:extends PureCompontent
Ref
React.createRef()
current 獲取元素
react中的CSS
CSS in js
yarn add styled-components
style.ts
import styled from 'styled-components';
export const BtnWrapper = styled.div<{ isActive: boolean; activeBgi: any }>`
border: ${(props) =>props.isActive ? '0.05rem solid #0181ff' : '0.05rem solid red'};
span{
&.active{
color:red //表示同時是span並且有active
}
}
`;
<BtnWrapper>
<BtnWrapper/>
react 新增class
/**
* 特點:
* 1.props穿透
* 2.attrs的使用
* 3.傳入state作為props屬性
*/
const HYInput = styled.input.attrs({
placeholder: "coderwhy",
bColor: "red"
})`
background-color: lightblue;
border-color: ${props => props.bColor};
color: ${props => props.color};
`
<HYInput type="password" color={this.state.color}/>
高階用法:
1.繼承
styled(HYInput)`
`
2.設定主題
import styled {ThemeProvider} from 'styled-components';
<ThemeProvider theme={{themeColor:'red',fontSize:'20px'}}>
<ThemeProvider/>
color: ${(props) =>props.theme.themeColor}
動態新增classNames
三元表示式
第三方庫:classNames★
classNames({foor:true})
className={classNames(['clear', { iconActive: isBtnActive }])}
<div
className={classnames({
[styles.sheet]: true,
[styles.active]: current.sheetId == v.sheetId,
})}
>
const active = useMemo(
() =>
classNames({
[styles.active]: activeCurrentPage===activeIndex,
}),
[activeCurrentPage],
);
- webpack下,import store from './store/index.js'
- index.js可以省略。,import store from './store'
- import * as actionType from './constants'; actionType.
import {
incAction,
addAction,
changeBannersAction,
changeRecommendAction
} from '../store/actionCreators'
redux
//★actionCreators
export const addAction = num => ({
type: ADD_NUMBER,
num
});
//★constants //export const ADD_NUMBER = "ADD_NUMBER";
//★index
//★reducer
// 拆分counterReducer
const initialCounterState = {
counter: 0
}
function counterReducer(state = initialCounterState, action) {
switch (action.type) {
case ADD_NUMBER:
return { ...state, counter: state.counter + action.num };
case SUB_NUMBER:
return { ...state, counter: state.counter - action.num };
case INCREMENT:
return { ...state, counter: state.counter + 1 };
case DECREMENT:
return { ...state, counter: state.counter - 1 };
default:
return state;
}
}
export default counterReducer;
import { useSelector, shallowEqual } from 'react-redux';
import reducer, { defaultState } from './reducer';
import React, {
memo,
useRef,
useState,
useReducer,
useContext,
useCallback,
useMemo,
useEffect,
useLayoutEffect,
} from 'react';
store
const init={
friend:[
{name:'why'}
]
}
import reducer from './reducer.js';
const store = redux.createStore(reducer);
一般會有多個reducer,需要合併
action
派發(dispatch())action 更新
const action1={type:'ADD_FRIEND',info:{name:'lucy'}}
store.dispatch(action1)
---
---
reducer 純函式,不能產生副作用
reducer將sotre和action 聯絡起來
import {
ADD_NUMBER,
SUB_NUMBER,
INCREMENT,
DECREMENT
} from './constants.js';
const defaultState = {
counter: 0
}
function reducer(state = defaultState, action) {
switch (action.type) {
case ADD_NUMBER:
return { ...state, counter: state.counter + action.num };
case SUB_NUMBER:
return { ...state, counter: state.counter - action.num };
case INCREMENT:
return { ...state, counter: state.counter + 1 };
case DECREMENT:
return { ...state, counter: state.counter - 1 };
default:
return state;
}
}
export default reducer;
中介軟體:redux-thunck
hooks
useState
useEffect
useContext
useReducer
useCallback
useMemo
useRef
useImperativeHandle
useLayoutEffect
自定義hooks
useSelector
import { useSelector } from 'umi';
import { useSelector, shallowEqual } from 'react-redux';
★useState 返回一個陣列
* 元素1: 當前state的值
* 元素2: 設定新的值時,使用的一個函
<React.StricMode>
<App/>
<React.StricMode/>
嚴格模式下,render會被渲染兩次
注意:不要再函式,條件判斷,for迴圈裡面使用hooks
const [counter,setCounter]=useState(0)
setCounter(counter+1)
傳入函式
const [count, setCount] = useState(() => 10);
setCount((prevCount) => prevCount + 10);
usestate 快捷鍵,按下tab鍵
★useEffect 生命週期
useEffect(() => {
console.log("訂閱一些事件");
//生命週期 componentWillUnmount
return () => {
console.log("取消訂閱事件")
}
}, []);
[]表示第一次渲染的時候執行一次;如果不寫,只要元件重新渲染,都會執行一遍
★useContext 子孫元件傳遞資料
export const UserContext= createContext()
export const PcSignContext = createContext({} as IPcSignContext);
{/* <UserContext.Provider value={{name: "why", age: 18}}>
<TokenContext.Provider value="fdafdafafa">
<CustomContextShareHook/>
</TokenContext.Provider>
</UserContext.Provider> */}
const user = useContext(UserContext);
const theme = useContext(ThemeContext);
★useReducer 是useState的一種替代方案 不共享state
const [state, dispatch] = useReducer(reducer, {counter: 0});
dispatch({type: "increment"})}
export default function reducer(state, action) {
switch(action.type) {
case "increment":
return {...state, counter: state.counter + 1};
case "decrement":
return {...state, counter: state.counter - 1};
default:
return state;
}
}
★useCallback 效能最佳化 針對函式 meno
場景: 在將一個元件中的函式, 傳遞給子元素進行回撥使用時, 使用useCallback對函式進行處理.
const increment2 = useCallback(() => {
console.log("執行increment2函式");
setCount(count + 1);
}, [count]);
//也可以用useMome
const increment3 = useMemo(() => {
return () => {
console.log("執行increment2函式");
setCount(count + 1);
}
}, [count]);
★useMemo 效能最佳化 針對返回值,返回記憶值
複雜計算的應用
const total = useMemo(() => {
return calcNumber(count);
}, [count]);
傳入子元件 或者用useState
const info = useMemo(() => {
return { name: "why", age: 18 };
}, []);
<HYInfo info={info} />
★useRef 只能在class元件中使用,在函式式元件中使用需要用forwardRef包裹
const titleRef = useRef();
function changeDOM() {
titleRef.current.innerHTML = "Hello World";
inputRef.current.focus();
console.log(testRef.current);
console.log(testRef2.current);
}
<h2 ref={titleRef}>RefHookDemo01</h2>
*** const numRef = useRef(count);
useEffect(() => {
numRef.current = count;
}, [count])
//儲存一個函式,在整個生命週期中儲存不變
使用場景:記錄上一次的值
★useImperativeHandle 和forwardRef關聯 目的不過多暴露給父元件
forwardRef 可以將ref轉發到子元件
const HYInput = forwardRef((props, ref) => {
const inputRef = useRef();
//()用小括號包裹起來,返回的是一個物件
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}), [inputRef])
return <input ref={inputRef} type="text"/>
})
export default function UseImperativeHandleHookDemo() {
const inputRef = useRef();
return (
<div>
<HYInput ref={inputRef}/>
<button onClick={e => inputRef.current.focus()}>聚焦</button>
</div>
)
}
★useLayoutEffect 佈局作用,阻塞瀏覽器的更新 // 稍稍阻塞瀏覽器的重繪,儘可能刪除存在滯留隱患的監聽器
useEffect 不會阻塞dom更新,dom更新完畢之後執行
export default function LayoutEffectCounterDemo() {
const [count, setCount] = useState(10);
//頁面不會閃0,如果用useEffect ,頁面是先出現0,在出現隨機數
useLayoutEffect(() => {
if (count === 0) {
setCount(Math.random() + 200)
}
}, [count]);
return (
<div>
<h2>數字: {count}</h2>
<button onClick={e => setCount(0)}>修改數字</button>
</div>
)
}
★自定義hoos 相同邏輯抽取到一個裡面,
const Profile = (props) => {
useLoggingLife("Profile");
return <h2>Profile</h2>
}
//普通函式不能使用hook,只能在自定義hook中使用,use開頭就代表自定義hook
function useLoggingLife(name) {
useEffect(() => {
console.log(`${name}元件被建立出來了`);
return () => {
console.log(`${name}元件被銷燬掉了`);
}
}, []);
}
//Context共享
export function usePptContext() {
const context = useContext(PptContext);
return context;
}
//獲取滾動位置
function useScrollPosition() {
const [scrollPosition, setScrollPosition] = useState(0);
useEffect(() => {
const handleScroll = () => {
setScrollPosition(window.scrollY);
}
document.addEventListener("scroll", handleScroll);
return () => {
document.removeEventListener("scroll", handleScroll)
}
}, []);
return scrollPosition;
}
const position = useScrollPosition();
★useSelector
const { banners, recommends, counter } = useSelector(state => ({
banners: state.banners,
recommends: state.recommends,
counter: state.counter
}), shallowEqual);
專案
yarn add normalize.css
reset.css
@import "~normalize.css"; //從模組裡匯入
@import "~antd/dist/antd.css";
配置別名: yarn add @craco/craco
"scripts": {
"start": "craco start",
"build": "umi build",
},
匯入檔案處理:
最上面第三方的東西
中間匯入功能類的東西,比如網路請求,actionCreators,utils
最後匯入元件
分號儘量加上
專案裡引入redux(24節,一小時)
yarn add redux react-redux redux-thunk 3個依賴
react-redux:作用把react元件和redux結合起來,其中最重要的conText 和Provider
store/index.js 建立store
★store
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import reducer from './reducer';
//除錯工具生效 如果有就使用,否則使用compose
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducer, composeEnhancers(
applyMiddleware(thunk)
));
export default store;
一般會有多個reducer,需要合併
★reducer: store/ireducer.js
import { combineReducers } from 'redux-immutable';//用redux-immutable',在useSelector中取值,用getIn方式
//import { combineReducers } from 'redux';
import { reducer as recommendReducer } from '../pages/discover/c-pages/recommend/store';
import { reducer as playerReducer } from '../pages/player/store';
const cReducer = combineReducers({
recommend: recommendReducer,
player: playerReducer
});
export default cReducer;
App.js
import { Provider } from 'react-redux';
import store from './store';
//Provider共享出去,然後透過connect獲取store裡面的state,disPatch類似的東西
<Provider store={store}>
<HashRouter>
<HYAppHeader />
<Suspense fallback={<div>page loading</div>}>
{renderRoutes(routes)}
</Suspense>
<HYAppFooter />
<HYAppPlayerBar/>
</HashRouter>
</Provider>
★actionCreatios:
export const getLyricAction = (id) => {
return dispatch => {
getLyric(id).then(res => {
const lyric = res.lrc.lyric;
const lyricList = parseLyric(lyric);
dispatch(changLyricListAction(lyricList));
})
}
}
constants
index
reducer
redux hooks
useDispatch()
//拿到裡面的值,第一個是一個回撥函式
//shallowEqual效能最佳化,淺層比較
// redux
const {
htmlName,
currentPage,
pageCount,
applicationType,
} = useSelector(
(state: { app: Application; appstate: AppState }) => ({
htmlName: state.app.param.htmlName,
currentPage: state.appstate.currentPage,
pageCount: (state.app.doc as WpDocument).pageCount,
currentPagesSize: state.appstate.currentPagesSize,
applicationType: state.app.param.applicationType,
}),
shallowEqual,
);
★ImmutableJS //最佳化,提高效能,節省記憶體空間,只要修改會返回新的物件,舊的物件不發生變化
const im = Immutable;
// Map的使用
// const info = {
// name: "kobe",
// age: 30,
// friend: {
// name: "james",
// age: 25
// }
// }
// const infoIM = im.Map(info);//改成Immutable物件
// const obj = infoIM;
// const infoIM2 = infoIM.set("name", "why");
// console.log(obj.get("name"));
// console.log(infoIM2.get("name"));
// List的使用
// const names = ["abc", "cba", "nba"];
// // const arr = names;
// // names[0] = "why";
// // console.log(arr);
// const namesIM = im.List(names);//改成Immutable物件
// const arrIM = namesIM.set(0, "why");
// console.log(namesIM.get(0));//abc 舊的
// console.log(arrIM.get(0));//why 新的
const info = {
name: "kobe",
age: 30,
friend: {
name: "james",
age: 25
}
}
// const infoIM = im.Map(info);//改成Immutable物件 ,淺層轉換
const infoIM = im.fromJS(info);//深層巢狀也會轉換Immutable物件 ct
console.log(infoIM.get("friend"));
引入專案
//Map比fromJS效能更高
import { Map ,fromJS} from 'immutable';
import * as actionTypes from './constants';
const defaultState = Map({
topBanners: [],
upRanking: {},
});
function reducer(state = defaultState, action) {
switch (action.type) {
case actionTypes.CHANGE_TOP_BANNERS:
return state.set("topBanners", action.topBanners);//返回新的資料
case actionTypes.CHANGE_UP_RANKING:
return state.set("upRanking", action.upRanking);
default:
return state;
}
}
export default reducer;
取值:
// redux hook
const {
currentSong,
sequence,
lyricList,
currentLyricIndex
} = useSelector(state => ({
currentSong: state.getIn(["player", "currentSong"]),
sequence: state.getIn(["player", "sequence"]),
lyricList: state.getIn(["player", "lyricList"]),
currentLyricIndex: state.getIn(["player", "currentLyricIndex"])
}), shallowEqual);
const dispatch = useDispatch();
路由
yarn add react-router-dom
import { renderRoutes, matchRoutes } from 'react-router-config';//將所有的路由統一管理
import {
BrowserRouter,
Link,
Route,
NavLink,
Switch,
withRouter
} from 'react-router-dom';
元件裡寫法:
<NavLink exact to="/about" activeClassName="about-active">企業歷史</NavLink>
<NavLink exact to="/about/culture" activeClassName="about-active">企業文化</NavLink>
<NavLink exact to="/about/contact" activeClassName="about-active">聯絡我們</NavLink>
<NavLink exact to="/" activeClassName="link-active">首頁</NavLink>
<NavLink to="/about" activeClassName="link-active">關於</NavLink>
<NavLink to="/profile" activeClassName="link-active">我的</NavLink>
<NavLink to="/abc" activeClassName="link-active">abc</NavLink>
<NavLink to="/user" activeClassName="link-active">使用者</NavLink>
<NavLink to={`/detail/${id}`} activeClassName="link-active">詳情</NavLink>
<NavLink to={`/detail2?name=why&age=18`} activeClassName="link-active">詳情2</NavLink>
<NavLink to={{
pathname: "/detail3",
search: "name=abc",
state: info
}}
activeClassName="link-active">
詳情3
</NavLink>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/profile" component={Profile} />
<Route path="/:id" component={User} />
<Route path="/user" component={User} />
<Route path="/login" component={Login} />
<Route path="/product" component={Product} />
<Route path="/detail/:id" component={Detail} />
<Route path="/detail2" component={Detail2} />
<Route path="/detail3" component={Detail3} />
<Route component={NoMatch} />
<Switch/>
{renderRoutes(this.props.route.routes)}// 子路由
父頁面裡面寫法:
{renderRoutes(routes)}
export default withRouter(App);
<BrowserRouter>
<App/>
</BrowserRouter>
BrowserRouter使用history模式
HashRouter使用hash模式
動態路由/$(id)
this.props.location
const routes = [
{
path: "/",
exact: true,//精確匹配
component: Home
},
{
path: "/about",
component: About,
routes: [
{
path: "/about",
exact: true,
component: AboutHisotry
},
{
path: "/about/culture",
component: AboutCulture
},
]
},
{
path: "/profile",
component: Profile
},
{
path: "/user",
component: User
}
]
axios網路請求 封裝
- 傳送請求
- 建立例項
- 攔截器
- 請求封裝
get,post,head,
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
interface IResponse {
data: any;
errorcode: number;
message: string;
}
const instance = axios.create({
timeout: 60000
});
instance.interceptors.request.use((config) => {
// 請求文件資料的攔截
// if (config.url?.includes('index.json')) {
// eventBus.emit('reqSent', '請求文件資料中...');
// }
// 發起籤批提交請求的攔截
if (config.url?.includes('index.json')) {
// console.log(config,'config.url')
// eventBus.emit('reqSent', '伺服器解析籤批資料中...');
}
return config;
});
// instance.interceptors.response.use((res: AxiosResponse<IResponse>) => {
// const { status, statusText } = res;
// const { data, message, errorcode } = res.data;
// if (
// errorcode === 0 ||
// message === '操作成功' ||
// status.toString().startsWith('2') ||
// statusText === 'OK'
// ) {
// // 延遲測試
// // setTimeout(() => {
// // }, 1000);
// // eventBus.emit('reqSucceeded');
// } else {
// // eventBus.emit('reqFailed');
// }
// // console.log(res);
// return res;
// });
//請求失敗,自動重新傳送請求
instance.interceptors.response.use(null, function axiosRetryInterceptor (error) {
error.config.__retryCount = error.config.__retryCount || 0
error.config.__retryCount += 1
if (error.config.__retryCount >= 4) {
console.log(error.config.__retryCount,'error.config.__retryCount')
console.log(`url:${error.config.url}重發達到最大次數,停止重發`)
return Promise.reject(error)
} else {
location.reload();
// console.log(`url:${error.config.url}開始重發,次數:${error.config.__retryCount},狀態:${error.status},data:${JSON.stringify(error.config)}`)
// return new Promise(function (resolve) {
// return setTimeout(function () {
// return resolve(axios(error.config))
// }, 1000)
// })
}
})
// get封裝
export function get(url: string, params = {}) {
return new Promise((resolve, reject) => {
instance({
url: url,
params,
method: 'get',
})
.then((res) => {
if (res.status === 200) {
resolve(res.data);
} else {
reject(res);
}
})
.catch((err) => {
reject(err)
});
});
}
// post封裝
export function post(
url: string,
params = {},
data = {},
// 進一步配置其他項
otherConfigs = {} as AxiosRequestConfig,
) {
return new Promise((resolve, reject) => {
instance({
url,
method: 'post',
params,
data,
...otherConfigs,
})
.then((res) => {
const { data } = res;
const { status, statusText } = res;
if (
data.errorcode === 0 ||
data.message === '操作成功' ||
status.toString().startsWith('2') ||
statusText === 'OK'
) {
resolve(data);
} else {
reject(data);
}
})
.catch((err) => {
reject(err);
});
});
}
// head封裝
export function head(url: string, params = {}) {
return new Promise((resolve, reject) => {
instance({
url: url,
params,
method: 'head',
})
.then((res) => {
if (res.status === 200) {
resolve(res.data);
} else {
reject(res);
}
})
.catch((err) => {
reject(err);
});
});
}
export default {
get,
post,
head,
};
import service from './request'
let resp =await service.get(url)