2.第三方库集成
2.1. vue.config.js配置
Vue CLI依赖于Webpack,但是Vue CLI是将Webpack中的配置隐藏起来了,如果我们对Webpack中的某些配置不满意,如果我们确实想要修改CLI中Webpack的某个配置,可以通过vue.config.js。vue.config.js中的配置会和Vue CLI中Webpack的配置合并。
https://cli.vuejs.org/
遇到问题先从官方文档找答案

vue.config.js有三种配置方式:(终于把这点搞懂了!)
* 方式一:直接通过CLI提供给我们的选项来配置:(名称和webpack中的可能不一样,但是一一对应)
* 比如publicPath:配置应用程序部署的子目录(默认是 `/`,相当于部署在 `https://www.my-app.com/`);
* 比如outputDir:修改输出的文件夹;
* 方式二:通过configureWebpack修改webpack的配置:(和webpack中的名称一样,直接合并)
* 可以是一个对象,直接会被合并;
* 可以是一个函数,会接收一个config,可以通过config来修改配置;

* 方式三:通过chainWebpack修改webpack的配置:(对webpack中的相关配置进行覆盖)
* 是一个函数,会接收一个基于 [webpack-chain](https://github.com/mozilla-neutrino/webpack-chain) 的config对象,可以对配置进行修改;
对比下面方式二的1和方式二的2以及方式三对别名的修改,因为方式二的第一种是和webpack的配置合并,而webpack中是有对src起别名为'@',所以如下操作。但是方式二的2以及方式三是对webpack中相关配置进行覆盖,所以需要拿到src,重新对它起别名,因此要获取path,拿到绝对路径(这里又涉及到一个require的查找规则,注意复习(jsplus--24))。另外注意方式二接收函数和方式三的区别。
1 const path = require(‘path’) 2 3 4 module.exports = { 5 // 配置方式二: 6 configureWebpack: { 7 resolve: { 8 alias: { 9 components: '@/components' 10 } 11 } 12 }, 13 configureWebpack: (config) => { 14 config.resolve.alias = { 15 '@': path.resolve(__dirname, 'src'), 16 components: '@/components' 17 } 18 }, 19 // 方式三: 20 chainWebpack: (config) => { 21 config.resolve.alias 22 .set('@', path.resolve(__dirname, 'src')) 23 .set('components', '@/components') 24 } 25 }
2.2. vue-router集成(怎么这个步骤就记不住呢)
- 安装vue-router的最新版本:
1 npm install vue-router@next
- 创建router对象:(在src下新建一个router文件夹,下面index.ts)
1 import { createRouter, createWebHashHistory } from 'vue-router' 2 import { RouteRecordRaw } from 'vue-router' 3 4 const routes: RouteRecordRaw[] = [ #ts是有类型的哦! 5 { 6 path: '/', 7 redirect: '/main' 8 }, 9 { 10 path: '/main', 11 component: () => import('../views/main/main.vue') 12 }, 13 { 14 path: '/login', 15 component: () => import('../views/login/login.vue') 16 } 17 ] 18 19 const router = createRouter({ 20 routes, 21 history: createWebHashHistory() 22 }) 23 24 export default router
- 安装router 注册路由:
1 import router from './router' #export default导出的router 不需要括号 2 3 createApp(App).use(router).mount('#app')
- 在App.vue中配置跳转:
1 <template> 2 <div id="app"> 3 <router-link to="/login">登录</router-link> 4 <router-link to="/main">首页</router-link> 5 <router-view></router-view> 6 </div> 7 </template>
2.3. vuex集成
- 安装vuex:
1 npm install vuex@next
- 创建store对象:(在src下面新建一个store文件夹,然后新建一个index.ts)
1 import { createStore } from 'vuex' 2 3 const store = createStore({ 4 state() { 5 return { 6 name: 'coderwhy' 7 } 8 } 9 }) 10 11 export default store
- 安装store 注册:
1 import store from './store' 2 createApp(App).use(router).use(store).mount('#app')
- 在App.vue中使用:
1 <h2>{{ $store.state.name }}</h2>
使用volar插件对ts的检测会更加严格,比如上面的$store在script中没有声明就会报错(没有报错啊!!),这里可以
在shims-vue.d.ts中声明一下:(不过因为我使用的是vetur插件,所以就不需要。这两个插件的作用就是语法高亮 错误提示等)
1 declare let $store: any
2.4. element-plus集成(这部门直接看官网更好)
Element Plus,一套为开发者、设计师和产品经理准备的基于Vue3.0的桌面端组件库:
* 相信很多同学在Vue2中都使用过element-ui,而element-plus正是element-ui针对于vue3开发的一个UI组件库;
* 它的使用方式和很多其他的组件库是一样的,所以学会element-plus,其他类似于ant-design-vue、NaiveUI、VantUI都是差不多的;
安装element-plus
1 npm install element-plus
2.4.1. 全局引入
一种引入element-plus的方式是全局引入,代表的含义是所有的组件和插件都会被自动注册:
1 import ElementPlus from 'element-plus' 2 import 'element-plus/dist/index.css' 3 4 import router from './router' 5 import store from './store' 6 7 createApp(App).use(router).use(store).use(ElementPlus).mount('#app')
---全局引入(所有的组件全部集成):优点:集成比较简单 缺点:会全部打包
---局部引入(按需引用):优点:包会小一些
快速开始 | Element Plus (gitee.io)
官网按需引入的方法好像一直在该,这次按照它上面来居然没成功,所以还是把过程记录一下吧!
1 npm install -D unplugin-vue-components
修改vue.config.js的配置
1 const Components = require('unplugin-vue-components/webpack') 2 const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
然后就可以直接使用了,但是要注意,图标比较特殊哦!
补充知识点
app.use()中可以传入一个函数,也可以传入一个对象。
传入一个函数时,默认会自动执行这个函数,并且会把app传入此函数。
传入一个对象时,默认会去执行这个对象的install,在执行这个对象的install时也会默认传入app
2.5. axios集成(难点)
- 安装axios:
npm install axios
- 封装axios:(为什么要封装?1、如果不封装,各个文件中都直接使用axios,那么一旦axios不更新了或者升级了,我们就要改很多地方,维护起来很麻烦;2、在发送网络请求时可能有很多共同的特性,比如像后台管理系统这样的项目一般除了登录接口之外,其他接口在进行请求时都需要携带token,每个token最好放在header里面,再发送请求,既然每个请求都需要做这个操作,不如封装起来,不然会有很多重复逻辑。)
- 封装逻辑:(感觉自己突然顿悟了!!!)在src--service中创建一个index.ts作为service的出口文件(其他地方需要使用只需导入'./service'就可以了,不用加index.ts),在service--request中创建index.ts里面封装一个HYRequest类,如下。在src--service--index.ts中实例化HYRequest这个类,然后其他地方就可以直接使用实例.方法进行调用!
- 我们之前用的axios.get等等中的axios其实是axios实例
- 为什么要选择把所有的axios封装到一个类中?如果有很多逻辑需要封装,类是一个不错的选择,因为类具有更强的封装性,类本身就具备封装(还有继承、多态)
- 封装逻辑详细描述:
1.大多数情况下项目是只有一个base_url的,但是如果一个项目有两个base_url呢?我们要导出两个new Request吗?要知道axios是可以配置base_url的,也就是说我根本没办法区分谁是谁,那怎么办?可以在对axios进行封装的时候根据不同的config就创建不同的axios实例

2.思考:有一些公共的逻辑,比如除了login页面都要进行的携带token,再比如loading动画,这些操作写在哪更合适呢?
答:写到拦截器中!
再复杂一点,比如不同实例拦截的东西不一样,怎么办?
答:所以想让每个实例都有自己的拦截器,但是config里面可以不能传拦截器,那就要自己定义类,后面再把这些类型定义的抽取出去。

关于拦截器我们即让某一个实例有,又让整个类都有,又让某个请求有


3.token放在哪?因为每个请求都需要携带token,所以token应该放在实例的请求拦截中。Bearer是信差、信使的意思,我们把Bearer和token的拼接值放在Authorization字段中

4.拦截器响应拦截,拦截到的res有哪些呢?

其实我们要使用的就是res.data,而响应拦截本来就是把响应到的数据处理后再返回,所以现在我们就不要再返回res了,而是返回res.data
5.第一种响应失败会返回一个错误码。

第二种是表面请求成功但是没有返回对应的数据


6.关于el-loading使用中遇见的一些问题
-
-
- 按道理我是按需引入element-plus,想要使用哪个样式直接用就可以了,但是使用el-loading如果不导入样式,就没有样式
-
1 import { ElLoading } from 'element-plus' 2 // 按道理这里是不需要导入样式的 不知道问题出在哪 3 import 'element-plus/theme-chalk/el-loading.css'
- loading应该放在所有实例都有的请求拦截器上
1 // 添加所有的实例都有的拦截器 2 this.instance.interceptors.request.use( 3 (config) => { 4 ElLoading.service({ 5 lock: true, 6 text: '正在请求数据...', 7 background: 'rgba(0, 0, 0, 0.5)', 8 fullscreen: true 9 }) 10 return config 11 }, 12 (err) => { 13 return err 14 } 15 ),
-
-
- 下面就是请求开始时进行loading的展示,数据响应后取消loading的展示
-
7.现在又有一个问题,我们在外面还是拿不到数据,数据是在request请求中拿到的,怎么办?
-
- Promise 通过return new Promise((resolve,reject)=> {}),但你会发现代码会报错,因为现在request函数的返回值类型需要是Promise类型,具体什么类型应该是由外界决定的,这里就涉及到泛型了,具体见代码:
![]()
-
- 定义类型,通过泛型传过去

-
-
- 当然被调用的函数要通过resolve把res传出去
-
这时又出现问题了:我希望res是我之前定义的T类型,但是它告诉我res是AxiosResponse类型

解决:

怎么解决上面的问题?

改成any,有点粗暴!
8.封装get、post、delete、patch其实就是调用request
![]()
参照代码
补充一点:ElLoading的类型要从哪看呢?

在最后那几个文件夹里面找找吧,能找到的!
2.6环境变量的配置
见32ppt
补充知识点:
当在项目中加载一些特殊文件时,比如.vue,.png,.jpg,.jpeg,默认ts是不认识这些文件的,会报错。而这里不会报错,是因为在我们使用CLI创建项目时,内部已经帮我们做了一些处理。
************
补充知识点:
defineComponent的意义:从js的角度来说,相当于传入一个组件然后返回这个组件,没有什么意义。
从ts的角度来说,可以通过泛型进行默认类型推导,能传入哪些东西,不能传入哪些有明确的规定,可以让编写的代码更加严谨。


浙公网安备 33010602011771号