vite创建vue3项目
(vue3+vue-router+ts+vite+element-plus+pinia+axios)
1. 初始化项目
-
npm init vite@latest
-
输入项目名称
-
选择vue3 + ts
-
创建完毕cd到页面
-
安装默认依赖并运行
2. 初始配置
此处选用vscode进行编写代码,值得注意的是vue3中使用vscode的插件时需要禁用以前vue2常使用的插件Vetur,而安装Vue Language Features (Volar)插件。不然代码会提示报错。
-
配置所需依赖
npm install @types/node --save-dev
-
修改vite.config.ts配置文件代码
import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { resolve } from 'path' export default defineConfig({ plugins: [vue()], //解决“vite use `--host` to expose” base: './', server: { host: '0.0.0.0', // port: 8080, open: true }, resolve:{ //别名配置,引用src路径下的东西可以通过@如:import Layout from '@/layout/index.vue' alias:[ { find:'@', replacement:resolve(__dirname,'src') } ] } })
-
安装路由
npm install vue-router@4
-
在src目录下新建router文件夹,在router里创建index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router' // import Layout from '../components/HelloWorld.vue' const routes: Array<RouteRecordRaw> = [ { //路由初始指向 path: '/', name: 'HelloWorld', component:()=>import('../components/HelloWorld.vue'), } ] const router = createRouter({ history: createWebHistory(), routes }) export default router
-
main.ts中导入挂载路由
import { createApp } from 'vue' import './style.css' import App from './App.vue' import router from './router' const app = createApp(App); app.use(router).mount('#app')
-
修改App.vue管理路由
<script setup lang="ts"> </script> <template> <router-view></router-view> </template> <style> </style>
-
运行看是否报错。如图打开了路由指向的HelloWorld.vue页面的内容就对了
-
配置ts文件采用@方式导入,在tsconfig.json文件中添加配置
{ "compilerOptions": { "target": "esnext", "useDefineForClassFields": true, "module": "esnext", "moduleResolution": "node", "strict": true, "jsx": "preserve", "sourceMap": true, "resolveJsonModule": true, "isolatedModules": true, "esModuleInterop": true, "lib": ["esnext", "dom"], "skipLibCheck": true, //添加--- "suppressImplicitAnyIndexErrors": true, //允许字符串用作下标 "ignoreDeprecations":"5.0", //高版本上句报错,此句解决。如此句报错可注释掉 "baseUrl": ".", "paths": { "@/*":[ "src/*" ] } //--------- }, "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], "references": [{ "path": "./tsconfig.node.json" }], //添加 "exclude":["node_modules"] // // ts排除的文件 }
-
安装代码检测工具
npm install --save-dev eslint eslint-plugin-vue
-
在根目录创建.eslintrc.js文件
module.exports = { root: true, parserOptions: { sourceType: 'module' }, parser: 'vue-eslint-parser', extends: ['plugin:vue/vue3-essential', 'plugin:vue/vue3-strongly-recommended', 'plugin:vue/vue3-recommended'], env: { browser: true, node: true, es6: true }, rules: { 'no-console': 'off', 'comma-dangle': [2, 'never'] //禁止使用拖尾逗号 } }
在rules可以添加自己的验证规则
-
安装 css 预处理器 sass
npm install -D sass sass-loader
-
引入element-plus
npm install element-plus --save npm install @element-plus/icons-vue // 图标
element-plus是vue3目前大流行组件库,用法基本和element ui一样
-
main.ts中引入
import { createApp } from 'vue' import './style.css' import App from './App.vue' import router from './router' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import * as ElementPlusIconsVue from '@element-plus/icons-vue' import zhCn from "element-plus/es/locale/lang/zh-cn";//国际化 const app = createApp(App); app.use(ElementPlus, { locale: zhCn }).use(router).mount('#app') //全局注册图标组件 for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component) }
-
国际化报错注意
> 国际化时如果安装了^2.3.8上的高版本或找不到包,解决方法:
> 需要在vite-env.d.ts加入
> declare module "element-plus/dist/locale/zh-cn.mjs"
> main.ts 中
> import zhCn from "element-plus/dist/locale/zh-cn.mjs"
> 若仍然有问题,修改为如下引用
> import zhCn from "element-plus/es/locale/lang/zh-cn"
-
使用element plus组件
<template> <el-button type="primary" size="default" :icon='Plus'>新增</el-button> </template> <script setup lang="ts"> import {Plus} from '@element-plus/icons-vue'; </script> <style scoped lang="scss"> </style>
清除原有Helloworld.vue内容,添加element-plus按钮
-
安装pinia(状态管理,类似vue2中的vuex)
npm install pinia
-
全局引入pinia
import { createApp } from 'vue' import './style.css' import App from './App.vue' import router from './router' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import * as ElementPlusIconsVue from '@element-plus/icons-vue' import zhCn from "element-plus/es/locale/lang/zh-cn";//国际化 import { createPinia } from 'pinia' const app = createApp(App); // 实例化 Pinia const pinia = createPinia() app.use(ElementPlus,{locale: zhCn}).use(router).use(pinia).mount('#app') //全局注册图标组件 for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component) }
-
开发提示
上面代码引用了默认的style.css文件(引用位置main.ts中),可能里面样式对我们开发有干扰,可自行处理修改style.css默认样式。建议:全删除,自己设置html,body,#app样式。以下参考可自行发挥:
*{
margin: 0;
padding: 0;
}
html,body,#app {
width: 100%;
height: 100%;
}
3. axios配置
-
下载依赖包
npm install axios
-
在src文件夹下面创建utils文件夹,其下创建request.ts文件
import axios from 'axios' // 创建axios实例 const request = axios.create({ baseURL: '',// 所有的请求地址前缀部分 timeout: 80000, // 请求超时时间(毫秒) withCredentials: true,// 异步请求携带cookie // headers: { // 设置后端需要的传参类型 // 'Content-Type': 'application/json', // 'token': x-auth-token',//一开始就要token // 'X-Requested-With': 'XMLHttpRequest', // }, }) // request拦截器 request.interceptors.request.use( config => { // 如果你要去localStor获取token,(如果你有) // let token = localStorage.getItem("x-auth-token"); // if (token) { //添加请求头 //config.headers["Authorization"]="Bearer "+ token // } return config }, error => { // 对请求错误做些什么 Promise.reject(error) } ) // response 拦截器 request.interceptors.response.use( response => { // 对响应数据做点什么 return response.data }, error => { // 对响应错误做点什么 return Promise.reject(error) } ) export default request
-
封装请求
在src文件夹下面创建api文件夹,其下创建index.ts文件
import instance from "@/utils/request"; //一般情况下,接口类型会放到一个文件 // 下面两个TS接口,表示要传的参数 interface ReqLogin { name: string paw: string } interface ReqStatus { id: string navStatus: string } // Res是返回的参数,T是泛型,需要自己定义,返回对数统一管理*** type Res<T> = Promise<ItypeAPI<T>>; // 一般情况下响应数据返回的这三个参数, // 但不排除后端返回其它的可能性, interface ItypeAPI<T> { data: T,//请求的数据,用泛型 msg: string | null // 返回状态码的信息,如请求成功等 code: number //返回后端自定义的200,404,500这种状态码 } // post请求 ,没参数 export const LogoutAPI = (): Res<null> => instance.post("/admin/logout"); // post请求,有参数,如传用户名和密码 export const loginAPI = (data: ReqLogin): Res<string> => instance.post("/admin/login", data); // post请求 ,没参数,但要路径传参 export const StatusAPI = (data: ReqStatus): Res<null> => instance.post(`/productCategory?ids=${data.id}&navStatus=${data.navStatus}`); // get请求,没参数, export const FlashSessionListApi = (): Res<null> => instance.get("/flashSession/list"); // get请求,有参数,路径也要传参 (也可能直接在这写类型,不过不建议,大点的项目会维护一麻烦) export const ProductCategoryApi = (params: { parentId: number }): any => instance.get(`/productCategory/list/${params.parentId}`, { params }); // get请求,有参数,(如果你不会写类型也可以使用any,不过不建议,因为用了之后 和没写TS一样) export const AdminListAPI = (params: any): any => instance.get("/admin/list", { params });
-
使用请求
使用方式一:直接使用(和vue2在cretae上用一样,setup自带async,await在顶层可以直接使用)
<script setup lang="ts"> import { indexAPI} from "@/api/index.ts"; //直接使用,一般用在进入页面入请求数据的接口 let res = await indexAPI() console.log( "***" ,res); </script>
使用方式二:使用 async / await,(setup虽然自带async,但单独用await只能在顶层使用,如果在函数下还是要async / await一起写)
<script setup lang="ts"> import { returnApplyListAPi } from "@/api/index.ts"; const search = async(val: IUseTableParam) => { let res = await returnApplyListAPi({ ...val, }) console.log( "***" ,res); let { list, pageNum, pageSize, total } = res.data console.log(list, pageNum, pageSize, total); } </script>
使用方式三:使用.then
<script setup lang="ts"> import { returnApplyListAPi} from "@/api/index.ts"; const logout = () => { returnApplyListAPi({ ...val, }).then((res) => { console.log('***',res ); let { list, pageNum, pageSize, total } = res.data }) }; </script>
-
跨域代理
跨域需要代理才写
vite.config.ts文件中
export default defineConfig({
plugins: [vue()],
server: {
proxy: {
'/api': { // 匹配请求路径,
target: '你要代理的地址', // 代理的目标地址
changeOrigin: true,
// secure: true, // 是否https接口
// ws: true, // 是否代理websockets
// 路径重写,**** 如果你的后端有统一前缀(如:/api),就不开启;没有就开启
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})