Search K
Appearance
Appearance
博主自己使用的是yarn来安装,如果没有安装的小伙伴可以看这篇文章:
TIP
兼容性注意 Vite 需要 Node.js 版本 >= 12.0.0。
安装:
# npm 6.x
npm init vite@latest my-vue-app --template vue
# npm 7+, 需要额外的双横线:
npm init vite@latest my-vue-app -- --template vue
# yarn
yarn create vite my-vue-app --template vue
# pnpm
pnpm create vite my-vue-app -- --template vue
参考链接:Vite初始化项目
安装模板:
yarn create vite my-vue-app --template vue-ts
支持的模板类型:vanilla,vanilla-ts,vue,vue-ts,react,react-ts,preact,preact-ts,lit,lit-ts,svelte,svelte-ts
安装Vue-Router4.0以支持Vue3语法。:
yarn add vue-router@4.0.12
添加两个文件便于测试,src下面添加views文件夹,添加home和login文件夹,并在分别在两个文件夹里面新建index.vue文件。
<template>
<h2>login</h2>
</template>
src目录下创建 router目录,添加index.ts
// src/router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
const routes: RouteRecordRaw[] = [
{
path: '/login',
component: () => import("../views/login/index.vue")
},
{
path: '/',
component: () => import("../views/home/index.vue")
},
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
修改 src下的main.ts
import { createApp } from 'vue'
import router from "./router"
import App from './App.vue'
createApp(App).use(router).mount('#app')
修改 src下的App.vue
<template>
<router-view />
</template>
访问一下:
当前目录结构:
安装Vuex以支持Vue3语法
yarn add vuex@4.0.2 或 yarn add vuex@next
next表示最新版本,我们安装Vuex4.0.2的版本以支持vue3的语法。
安装Vuex持久化插件:
yarn add vuex-persistedstate
安装完成以后要进入配置阶段,养成好的习惯,我们要将 Store模块化,模块化的好处就在于阅读起来十分清晰。我们在 src下面建立一个store目录,在store目录下面建立modules目录以及index.ts文件,然后再modules下面建立一个user.ts文件来保存一些用户信息。
当前目录结构:
具体配置如下:
// /src/store/modules/user.ts
import { Module } from "vuex"
import { RootState } from "../index"
export interface userState{
counter: number
}
export const store:Module<userState,RootState> = {
namespaced:true,
state: ():userState => ({
counter: 0
}),
mutations: {
increment(state:userState,newVal:number):void{
state.counter = newVal
}
}
}
// /src/store/index.ts
import { InjectionKey } from 'vue'
import { createStore,Store,useStore as baseUseStore } from 'vuex'
// 持久化插件
import createPersistedState from "vuex-persistedstate"
import { store as user,userState } from "@/store/modules/user"
export interface RootState {
user: userState
}
export const key: InjectionKey<Store<RootState>> = Symbol()
export const store:Store<RootState> = createStore({
modules: {
user
},
plugins: [
createPersistedState({
paths: ['user']
})
]
})
export function useStore() {
return baseUseStore(key)
}
修改 main.ts
import { createApp } from 'vue'
import router from "./router"
import { store,key } from "./store"
import App from './App.vue'
createApp(App).use(store,key).use(router).mount('#app')
TIP
配置参考地址 Vuex官网
这样Vuex就配置好了,接下来我们要进行一些测试:
我们修改home/index.vue
<template>
<h2>home</h2>
<div>vuex中的count:{{ count }}</div>
</template>
<script setup lang="ts">
import { computed } from "vue"
import { useStore } from "@/store/index";
const store = useStore();
const count = computed(()=>{
return store.state.user.counter
})
</script>
再修改一下login/index.vue
<template>
<h2>login</h2>
<div>
vuex:{{count}}
</div>
<button @click="addCount">累加</button>
<div>
<router-link to="/">首页</router-link>
</div>
</template>
<script setup lang="ts">
import { computed } from "vue"
import { useStore } from '@/store/index'
const store = useStore()
const count = computed(()=>{
return store.state.user.counter
})
function addCount():void{
store.commit('increment',count.value+1)
}
</script>
如果出现以上错误则需要修改tsconfig.js配置:
主要是加上 paths配置,顺便也加上bseUrl配置。
在home以及login页面测试一下:
可以看到很nice,🤪🤪。
yarn add dart-sass sass --dev
测试一下:
<template>
<div class="home">
<h2 class="title">login</h2>
<div>vuex:{{ count }}</div>
<button @click="addCount">累加</button>
<div>
<router-link to="/">首页</router-link>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from "vue";
import { useStore } from "@/store/index";
const store = useStore();
const count = computed(() => {
return store.state.user.counter;
});
function addCount(): void {
store.commit("increment", count.value + 1);
}
</script>
<style lang="scss" scoped>
.home {
.title {
color: blue;
}
}
</style>
在src下assets里面建立style文件夹,然后添加main.scss,新建一个颜色变量用于测试。
$test-color: red;
接下来修改vite.config.ts
//vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
// 设置资源别名
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'), // src 路径
'utils': path.resolve(__dirname, 'src/utils') // src 路径
}
},
server: {
proxy: {
'/api': {
// 当遇到 /api 路径时,将其转换成 target 的值
target: '',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '') // 将 /api 重写为空
}
}
},
css:{
preprocessorOptions:{
scss:{
additionalData:'@import "@/assets/style/main.scss";'
}
}
},
base: '/',
})
主要是添加css配置
测试一下,修改login.vue
<template>
<div class="home">
<h2 class="title">login</h2>
<div>vuex:{{ count }}</div>
<button @click="addCount">累加</button>
<div>
<router-link to="/">首页</router-link>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from "vue";
import { useStore } from "@/store/index";
const store = useStore();
const count = computed(() => {
return store.state.user.counter;
});
function addCount(): void {
store.commit("increment", count.value + 1);
}
</script>
<style lang="scss" scoped>
.home {
.title {
color: $test-color;
}
}
</style>
到这里为止全局的scss文件就配置完成了。
接下来就是进行axios封装了,axios我相信大家应该都不陌生,我们先安装以下依赖:
# 安装 axios
yarn add axios
# 安装 nprogress 用于请求 loading
# 也可以根据项目需求自定义其它 loading
yarn add nprogress
# 类型声明,或者添加一个包含 `declare module 'nprogress'
yarn add @types/nprogress --dev
我们在 src下面建立一个service文件夹,并在里面建立一个http.ts文件封装axios请求,同时在service下面建立一个apis文件夹,apis文件夹里面建立一个login.ts和type.ts。
// servicce/http.ts
import axios,{ AxiosRequestConfig,AxiosResponse} from "axios"
import NProgress from "nprogress"
// 设置请求的基本地址
axios.defaults.baseURL = '/'
// 请求超时时间
axios.defaults.timeout = 10000
// 设置头部contenttype为json格式
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'
// 请求拦截
axios.interceptors.request.use(
(config):AxiosRequestConfig<any> => {
const token = sessionStorage.getItem('token')
if(token){
// token业务处理
// config.headers && config.headers.token && (config.headers.token = token)
}
return config
},
(error => {
return error
})
)
// 响应拦截
axios.interceptors.response.use(
(res):AxiosResponse<any> =>{
return res
},
(error =>{
console.error(error);
return error
})
)
// 定义响应类型
interface ResType<T> {
code: number | string
data? : T
msg: string
err?: string
}
// 定义请求Http类型
interface Http{
get<T>(url: string, params?: unknown): Promise<ResType<T>>
post<T>(url: string, params?: unknown): Promise<ResType<T>>
upload<T>(url: string, params: unknown): Promise<ResType<T>>
download(url: string): void
}
const http: Http = {
get(url, params) {
return new Promise((resolve, reject) => {
NProgress.start()
axios
.get(url, { params })
.then((res) => {
NProgress.done()
resolve(res.data)
})
.catch((err) => {
NProgress.done()
reject(err.data)
})
})
},
post(url, params) {
return new Promise((resolve, reject) => {
NProgress.start()
axios
.post(url, JSON.stringify(params))
.then((res) => {
NProgress.done()
resolve(res.data)
})
.catch((err) => {
NProgress.done()
reject(err.data)
})
})
},
upload(url, file) {
return new Promise((resolve, reject) => {
NProgress.start()
axios
.post(url, file, {
headers: { 'Content-Type': 'multipart/form-data' },
})
.then((res) => {
NProgress.done()
resolve(res.data)
})
.catch((err) => {
NProgress.done()
reject(err.data)
})
})
},
download(url) {
const iframe = document.createElement('iframe')
iframe.style.display = 'none'
iframe.src = url
iframe.onload = function () {
document.body.removeChild(iframe)
}
document.body.appendChild(iframe)
},
}
export default http
// service/api/login.ts
import http from '@/service/http'
import * as T from './type'
const loginApi: T.LoginApi = {
login(params:T.LoginParams){
return http.post('/login', params)
}
}
export default loginApi
// service/api/type.ts
export interface LoginParams {
userName: string
passWord: string | number
}
export interface LoginApi {
login: (params: LoginParams)=> Promise<any>
}
当前目录结构:
TIP
vite 提供了两种模式:具有开发服务器的开发模式(development)和生产模式(production)
在项目根目录下面添加 .env.development文件和.env.production文件。 .env.development文件
NODE_ENV=development
VITE_APP_WEB_URL= 'YOUR WEB URL'
.env.production文件
NODE_ENV=production
VITE_APP_WEB_URL= 'YOUR WEB URL'
vite中使用:
console.log(import.meta.env.VITE_APP_WEB_URL)
TIP
开启 gzip 可以极大的压缩静态资源,对页面加载的速度起到了显著的作用。
安装
yarn add --dev vite-plugin-compression
import viteCompression from 'vite-plugin-compression'
然后在vite.config.ts的plugins里面添加如下代码:
viteCompression({
verbose: true,
disable: false,
threshold: 10240,
algorithm: 'gzip',
ext: '.gz',
}),
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import viteCompression from 'vite-plugin-compression'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
// gzip压缩 生产环境生成 .gz 文件
viteCompression({
verbose: true,
disable: false,
threshold: 10240,
algorithm: 'gzip',
ext: '.gz',
}),
],
// 设置资源别名
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'), // src 路径
'utils': path.resolve(__dirname, 'src/utils') // src 路径
}
},
server: {
proxy: {
'/api': {
// 当遇到 /api 路径时,将其转换成 target 的值
target: '',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '') // 将 /api 重写为空
}
}
},
// build环境下面去除console.log打印信息
build: {
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
},
},
},
css: {
preprocessorOptions: {
scss: {
// 全局样式
additionalData: '@import "@/assets/style/main.scss";'
}
}
},
// 打包根目录
base: '/',
publicDir: 'assets',
sourcemap: true,
publicPath:'./',
outputDir:'dist',
assetsDir:'static'
})
Vite2+Vue3+TypeScript+Pinia搭建一套企业级的开发脚手架
博主在搭建的时候没有添加ui框架和一些eslint的配置,大家可以自行添加,这只是一个很轻量的模板。Typescript在dev阶段以及build阶段就可以帮助开发者发现许多隐藏的bug,个人觉得这真的很舒服,希望Typscript会发展的越来越好。
代码仓库奉上:vue3+ts+vite-template
编写良久,如对您有帮助,还望给个Star,如有错误的地方可在评论区指出🧐。
最后我想说一句,ts真香🤪!!!