diff --git a/.env b/.env index a671b7f..cbdd3de 100644 --- a/.env +++ b/.env @@ -1 +1 @@ -VITE_APP_API_BASE_URL=http://127.0.0.1:8080/ \ No newline at end of file +VITE_BASE_URL=http://127.0.0.1:8080/ \ No newline at end of file diff --git a/README.md b/README.md index 4f67b32..f81dfed 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,26 @@ # 技术选型 - - 本项目采用的vue3 + vite + js脚手架搭建 - - 包管理工具为Yarn + +- 本项目采用的 vue3 + vite + js 脚手架搭建 +- 包管理工具为 Yarn # 代码规范 - > 随着团队的不断扩大,每个人都有自己的coding风格,但是如果一个项目中的代码存在多种风格,那对于代码的可维护性和可读性都大大减少,所以说一个项目规范对于前端团队来说很重要。 - ## Prettier + +> 随着团队的不断扩大,每个人都有自己的 coding 风格,但是如果一个项目中的代码存在多种风格,那对于代码的可维护性和可读性都大大减少,所以说一个项目规范对于前端团队来说很重要。 + +## Prettier + 1、vscode插件 --- Prettier - Code formatter 2、.prettierrc文件 + +# 全局状态管理 + +> 使用 pinia + +# axios 封装 + +> src/service + +- 灵活的拦截器; +- 可以创建多个实例,灵活根据项目进行调整; +- 每个实例,或者说每个接口都可以灵活配置请求头、超时时间等; +- 取消请求(可以根据 url 取消单个请求也可以取消全部请求)。 diff --git a/package.json b/package.json index 70d7641..8f168a8 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "preview": "vite preview" }, "dependencies": { + "axios": "^1.3.4", "pinia": "^2.0.32", "vue": "^3.2.45", "vue-router": "^4.0.13" diff --git a/src/api/index.js b/src/api/index.js new file mode 100644 index 0000000..06c5764 --- /dev/null +++ b/src/api/index.js @@ -0,0 +1,17 @@ +import request from '@/service' + +export const get15DaysWeatherByArea = data => { + return request({ + url: '/api/common/weather/get15DaysWeatherByArea', + method: 'GET', + data, + interceptors: { + requestInterceptors(res) { + return res + }, + responseInterceptors(result) { + return result + }, + }, + }) +} diff --git a/src/components/Count.vue b/src/components/Count.vue index 9326b98..f4a9792 100644 --- a/src/components/Count.vue +++ b/src/components/Count.vue @@ -13,7 +13,8 @@ diff --git a/src/service/index.js b/src/service/index.js new file mode 100644 index 0000000..0d7b154 --- /dev/null +++ b/src/service/index.js @@ -0,0 +1,38 @@ +import Request from './request' +/** + * 后续封装get post delete等方法的简单调用。 + */ + +const request = new Request({ + baseURL: import.meta.env.BASE_URL, + timeout: 1000 * 60 * 5, + interceptors: { + // 请求拦截器 + requestInterceptors: config => config, + // 响应拦截器 + responseInterceptors: result => result, + }, +}) + +/** + * @description: 函数的描述 + * @param config 不管是GET还是POST请求都使用data + * @returns {Promise} + */ +const dreamworkRequest = config => { + const { method = 'GET' } = config + if (method === 'get' || method === 'GET') { + config.params = config.data + } + return request.request(config) +} +// 取消请求 +export const cancelRequest = url => { + return request.cancelRequest(url) +} +// 取消全部请求 +export const cancelAllRequest = () => { + return request.cancelAllRequest() +} + +export default dreamworkRequest diff --git a/src/service/request.js b/src/service/request.js new file mode 100644 index 0000000..a108868 --- /dev/null +++ b/src/service/request.js @@ -0,0 +1,132 @@ +import axios from 'axios' + +class Request { + // axios 实例 + instance + // 拦截器对象 + interceptorsObj + + /* + 存放取消方法的集合 + * 在创建请求后将取消请求方法 push 到该集合中 + * 封装一个方法,可以取消请求,传入 url: string|string[] + * 在请求之前判断同一URL是否存在,如果存在就取消请求 + */ + cancelRequestSourceList + /* + 存放所有请求URL的集合 + * 请求之前需要将url push到该集合中 + * 请求完毕后将url从集合中删除 + * 添加在发送请求之前完成,删除在响应之后删除 + */ + requestUrlList + + constructor(config) { + this.requestUrlList = [] + this.cancelRequestSourceList = [] + this.instance = axios.create(config) + this.interceptorsObj = config.interceptors + // 拦截器执行顺序 接口请求 -> 实例请求 -> 全局请求 -> 实例响应 -> 全局响应 -> 接口响应 + this.instance.interceptors.request.use( + res => res, + err => err, + ) + + // 使用实例拦截器 + this.instance.interceptors.request.use( + this.interceptorsObj?.requestInterceptors, + this.interceptorsObj?.requestInterceptorsCatch, + ) + this.instance.interceptors.response.use( + this.interceptorsObj?.responseInterceptors, + this.interceptorsObj?.responseInterceptorsCatch, + ) + // 全局响应拦截器保证最后执行 + this.instance.interceptors.response.use( + // 因为我们接口的数据都在res.data下,所以我们直接返回res.data + res => { + return res.data + }, + err => err, + ) + } + /** + * @description: 获取指定 url 在 cancelRequestSourceList 中的索引 + * @param {string} url + * @returns {number} 索引位置 + */ + getSourceIndex(url) { + return this.cancelRequestSourceList?.findIndex(item => { + return Object.keys(item)[0] === url + }) + } + /** + * @description: 删除 requestUrlList 和 cancelRequestSourceList + * @param {string} url + * @returns {*} + */ + delUrl(url) { + const urlIndex = this.requestUrlList?.findIndex(u => u === url) + const sourceIndex = this.getSourceIndex(url) + // 删除url和cancel方法 + urlIndex !== -1 && this.requestUrlList?.splice(urlIndex, 1) + sourceIndex !== -1 && this.cancelRequestSourceList?.splice(sourceIndex, 1) + } + request(config) { + return new Promise((resolve, reject) => { + // 如果我们为单个请求设置拦截器,这里使用单个请求的拦截器 + if (config.interceptors?.requestInterceptors) { + config = config.interceptors.requestInterceptors(config) + } + const url = config.url + // url存在保存取消请求方法和当前请求url + if (url) { + this.requestUrlList?.push(url) + config.cancelToken = new axios.CancelToken(c => { + this.cancelRequestSourceList?.push({ + [url]: c, + }) + }) + } + this.instance + .request(config) + .then(res => { + // 如果我们为单个响应设置拦截器,这里使用单个响应的拦截器 + if (config.interceptors?.responseInterceptors) { + res = config.interceptors.responseInterceptors.res + } + + resolve(res) + }) + .catch(err => { + reject(err) + }) + .finally(() => { + url && this.delUrl(url) + }) + }) + } + // 取消请求 + cancelRequest(url) { + if (typeof url === 'string') { + // 取消单个请求 + const sourceIndex = this.getSourceIndex(url) + sourceIndex >= 0 && this.cancelRequestSourceList?.[sourceIndex][url]() + } else { + // 存在多个需要取消请求的地址 + url.forEach(u => { + const sourceIndex = this.getSourceIndex(u) + sourceIndex >= 0 && this.cancelRequestSourceList?.[sourceIndex][u]() + }) + } + } + // 取消全部请求 + cancelAllRequest() { + this.cancelRequestSourceList?.forEach(source => { + const key = Object.keys(source)[0] + source[key]() + }) + } +} + +export default Request diff --git a/yarn.lock b/yarn.lock index 56bb888..f122adb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -217,11 +217,37 @@ resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.47.tgz#e597ef75086c6e896ff5478a6bfc0a7aa4bbd14c" integrity sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +axios@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.4.tgz#f5760cefd9cfb51fd2481acf88c05f67c4523024" + integrity sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + csstype@^2.6.8: version "2.6.21" resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e" integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w== +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + esbuild@^0.16.14: version "0.16.17" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.16.17.tgz#fc2c3914c57ee750635fee71b89f615f25065259" @@ -255,6 +281,20 @@ estree-walker@^2.0.2: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== +follow-redirects@^1.15.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + fsevents@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" @@ -286,6 +326,18 @@ magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.8" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + nanoid@^3.3.4: version "3.3.4" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" @@ -318,6 +370,11 @@ postcss@^8.1.10, postcss@^8.4.21: picocolors "^1.0.0" source-map-js "^1.0.2" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + resolve@^1.22.1: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"