企业网站设计北京求老哥给几个靠谱的网站
描述
之前用过react的ahook很舒服,但是vue的ahook功能太少。于是仿照react ahooks的useRequest 写的异步请求状态管理 加载更多,成功,加载中,失败
示意图
测试代码
<template><view><h2>自动触发</h2><view v-if="state.loading">loading</view><view v-else-if="state.error">error</view><view v-else>{{state.data}}</view><view>------------------------</view><h2>手动触发</h2><view v-if="manualState.loading">loading</view><view v-else-if="manualState.error">error</view><view v-else>{{manualState.data}}</view><button @click="manualState.run()">加载数据</button><view>------------------------</view><h2>局部刷新</h2><view v-if="hotState.loading">loading</view><view v-else-if="hotState.error">error</view><view v-else>{{hotState.data}}<text v-if="hotState.isRefresh">局部刷新中</text></view><button @click="hotState.reFresh()">局部刷新</button><view>------------------------</view><h2>加载更多</h2><view v-if="listState.loading">loading</view><view v-else-if="listState.error">error</view><view v-for="item in listState.data">{{item.name}}</view><view v-if="listState.loadingMore">加载中</view><view v-if="!listState.isThereMore">没有更多了</view><button @click="loadMore">加载更多</button><view>------------------------</view></view>
</template><script>
import {useRequest} from './useRequest'
import moment from "moment";//模拟普通接口
function commonApi() {return new Promise((resolve, reject) => {setTimeout(() => {resolve({code: 0,result: moment().format("hh:mm:ss"),message: 'success'})}, 1000)})
}
//模拟列表
function listApi(data){return new Promise((resolve, reject) => {setTimeout(()=>{resolve({code:0,message:"",result:{total:12,records:[{name:'tang'+data,id:1},{name:'tang',id:2},{name:'tang',id:3},{name:'tang',id:1},]}})},1000)})
}//模拟调用接口
async function getCommonData() {const e = await commonApi()if (e.code === 0) return e.resultelse throw e.message
}
//模拟调用接口
async function getListData(data) {const e = await listApi(data)if (e.code === 0) return e.resultelse throw e.message
}
export default {created() {//如果参数依赖其他的data,则只能在data初始化之后操作//pageNum没啥用 只是告诉下 带参数怎么使用this.listState=useRequest(()=>getListData(this.pageNum),{loadMoreMod: true})},data() {return {state: useRequest(getCommonData),manualState:useRequest(getCommonData,{manual:true}),hotState:useRequest(getCommonData),listState:"",pageNum:1,}},methods: {loadMore(){this.pageNum++this.listState.loadMore()},}
}
</script><style></style>
useRequest 代码
/*** 描述:异步状态管理* 参数1 apiFunc* 必须是一个Promise。* 参数2 option* manual:是否要手动出发,默认false,初始化时候就会调用一次接口,否则则需要自己手动调用run方法* onSuccess:成功时候的回调,返回获取的数据* onError:失败时候的回调,返回失败信息* loadMoreMod 将以 加载更多 模式运行 将所有请求数据合并数组 .then(e)成功返回的数据必须有为{total:Number,records:[]},不是的自己await时候洗一下.* 返回值* 普通模式下* let state = {data: null, //返回的数据loading: !manual, //是否正在加载error: null, //错误信息isRefresh: false, //是否正在局部刷新run(params) ,调用接口,params是参数,会直接传给了apiFunc(params),当然如果你的apifunc不接受参数,那就当然没用了。reFresh() 局部刷新。和run的区别就是,调用的时候不会将data重新置为null,而是在加载成功后替换掉。}加载更多模式下let state = {data: null, //返回的数据loading: !manual, //是否正在加载error: null, //错误信息run(params) ,调用接口,params是参数,会直接传给了apiFunc(params),当然如果你传递apiFunc不接受参数,那就当然没用了。isThereMore:是否还有更多的数据loadingMore:是否正在加载更多中isReloading:是否正在重新加载中,只是为了和loading状态区分开。reLoad():重新加载loadMore():加载更多}*/
function useRequest(apiFunc, option = {manual: false,onSuccess: false,onError: false,loadMoreMod:false,
}) {const {manual, onSuccess, onError,loadMoreMod} = option//通用状态let state = {data: null,loading: !manual,error: null,isRefresh: false,}//如果开启了加载更多模式则添加【是否有更多数据状态】if(loadMoreMod){state.isThereMore=truestate.loadingMore=falsestate.isReloading=false}//保存下查询的参数,列表带参数,调用reload后传递的参数保存下,给下次loadMore时候用。let tempParams=""const execute = (params,opt={isRefresh:false,isReload:false}) => {const {isRefresh,isReload}=optapiFunc(params).then((e) => {state.loading = false//加载更多模式 合并请求的数据if(loadMoreMod){state.loadingMore=falsehandleLoadMoreModData(e,isReload)}//普通模式else {state.data = eif(isRefresh){state.isRefresh=false}}//如果是正在reload 关闭状态if(isReload)state.isReloading=falseif (onSuccess) {onSuccess(e)}}).catch((e) => {state.error = e.toString()state.loading = falseif(isRefresh){state.isRefresh=false}uni.showToast({title: '错误:' + e.toString(),icon: "none",duration: 2000})if (onError) {onError(e.toString())}})}//加载更多模式下处理s tate.data 合并数据const handleLoadMoreModData=(e,isReload)=>{const {total,records}=e//第二次之合并数据 如果不是reloadif(state.data&&!isReload){//合并数据state.data=[...state.data,...records]//判断是否还有数据const recordsLength=state.data.length/** 为啥是大于等于呢,正常情况下等于是没问题的* 但是第一次查10条,一共十二条,第二次查询的时候,突然删的只剩下一条数据了,那么返回的total是不是1 是不是就比当前合并的数组少了。* */if(recordsLength>=total)state.isThereMore=false}//第一次直接赋值else{//如果有值if(total!==0)state.data=recordselse{state.data=[]state.isThereMore=false}}}//普通执行 会清空之前查询的数据 相当于reLoad 、const run = (params) => {if(loadMoreMod){state.loadingMore=falsestate.isThereMore=truestate.isReloading=falsetempParams=params//加载更多模式保存查询参数,给reload,和loadMore用}state.error = null//重置错误状态state.loading = true//加载状态改为加载中state.data = null//重置之前查询的数据//执行execute(params)}//局部刷新const reFresh=()=>{state.isRefresh = true//加载状态改为加载中//执行if(tempParams)execute(tempParams,{isRefresh: true})elseexecute(undefined,{isRefresh: true})}//加载更多const loadMore=()=>{//如果还要更多的数据,而且当前不是正在加载更多的状态if(state.isThereMore&&!state.loadingMore){state.loadingMore=true//执行//如果有保存的参数,则传递保存的参数if(tempParams)execute(tempParams)elseexecute()}}//重新加载const reload=()=>{state.loading=falsestate.error=nullstate.loadingMore=falsestate.isThereMore=truestate.isReloading=true//执行if(tempParams)execute(tempParams,{isReload:true})elseexecute(undefined,{isReload:true})}//如果手动触发为false,则直接run查询if (!manual) run()state.run=run//加载更多模式不适用局部刷新if(!loadMoreMod){state.reFresh=reFresh}//只有加载更多模式下才有的reload 和loadMoreif(loadMoreMod){state.reload=reloadstate.loadMore=loadMore}return state
}export {useRequest
}