本文为快速搭建vite4项目,一些插件的详情就不做过多的解释,都放有官网链接,需要深入了解的小伙伴可自行查看。至于为什么选择使用vite,因为它具备着快速启动、按需编译、模块热更新的亮点。归根结底最大的特点就是快。vue的创始人是尤雨溪大佬,vite也是他。所以放心大胆的用吧。
yarn create vite 你的项目名称 --template vue-ts
注:如果没有yarn的可通过npm执行命令npm install -g yarn进行安装
3️⃣ 启动成功以后浏览器访问http://127.0.0.1:5173/
yarn add element-plus pinia vue-router nprogress animate.css
yarn add @iconify-json/carbon @iconify-json/ep @iconify-json/noto -D
yarn add unplugin-vue-components unplugin-auto-import unplugin-icons -D
yarn add sass sass-loader @types/node @vitejs/plugin-vue-jsx -D
{
"compilerOptions": {
"target": "esnext", // 目标语言的版本
"useDefineForClassFields": true,
"module": "esnext", // 生成代码的模板标准
"moduleResolution": "node", // 模块解析策略,ts默认用node的解析策略,即相对的方式导入
"strict": true, // 开启所有严格的类型检查
"jsx": "preserve", // 指定将 JSX 编译成什么形式
"jsxFactory": "h", // 当使用经典的JSX运行时编译JSX元素时,更改.js文件中调用的函数,默认:React.createElement 。
"jsxFragmentFactory": "Fragment",
"sourceMap": true, // 生成目标文件的sourceMap文件
"resolveJsonModule": true, // 指定 JSX 片段工厂函数在指定了 jsxFactory 编译器选项的情况下针对 react JSX 发出时使用。
"esModuleInterop": true, // 允许export=导出,由import from 导入
// TS需要引用的库,即声明文件,es5 默认引用dom、es5、scripthost,如需要使用es的高级版本特性,通常都需要配置,如es8的数组新特性需要引入"ES2019.Array"
"lib": ["esnext", "dom"],
"types": ["vite/client", "element-plus/global", "unplugin-icons/types/vue"], // 加载的声明文件包
"baseUrl": ".", // 解析非相对模块的基地址,默认是当前目录
"skipLibCheck": true, // 忽略所有的声明文件( *.d.ts)的类型检查。
"paths": { // 路径映射,相对于baseUrl
"@/*": [
"src/*"
]
}
},
// 指定一个匹配列表(属于自动指定该路径下的所有ts相关文件)
"include": ["src/**/*.ts", "**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/autoImport/*.d.ts"],
"exclude": [
"node_modules"
]
}
为什么做按需引入,相对于全局引入来说很大程度上的减少了代码体积。
注:按需引入这里需要在src文件夹下新建一个autoImport的文件夹存在按需引入生成的文件。这样做的目的是,后期如果传git,可以屏蔽这个文件夹。
import { defineConfig } from 'vite'
import path from 'path'
import vue from '@vitejs/plugin-vue'
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import vueJsx from '@vitejs/plugin-vue-jsx';
const pathSrc = path.resolve(__dirname, 'src')
export default defineConfig({
resolve: {
alias: {
'@': pathSrc, // 文件系统路径别名
}
},
plugins: [
vue(),
vueJsx(), // 支持jsx、tsx的写法
AutoImport({
imports: ['vue'],
resolvers: [
ElementPlusResolver(),
IconsResolver({
prefix: 'Icon'
})
],
dts: path.resolve(pathSrc + '/autoImport', 'auto-imports.d.ts')
}),
Components({
resolvers: [
ElementPlusResolver(),
IconsResolver({
enabledCollections: ['ep', 'carbon', 'noto']
})
],
dts: path.resolve(pathSrc + '/autoImport', 'components.d.ts')
}),
Icons({
autoInstall: true,
compiler: 'vue3'
})
],
server: {
host: '0.0.0.0', // 指定服务器应该监听哪个 IP 地址
port: 9527, // 指定开发服务器端口
strictPort: true, // 若端口已被占用则会直接退出
https: false, // 启用 TLS + HTTP/2
open: false, // 启动时自动在浏览器中打开应用程序
}
})
Primary
Success
Info
Warning
++++
{{ count }}
至于vue-router的话,在vue2大家应该已经很熟悉了,vue全家桶必备知识。
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
export const asyncRoutes: RouteRecordRaw[] = [
{
path: '/',
name: 'home',
meta: {
title: 'home'
},
component: () => import('@/views/home.vue')
},
{
path: '/home1',
name: 'home1',
meta: {
title: 'home1'
},
component: () => import('@/views/home1.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes: asyncRoutes,
scrollBehavior: () => ({ left: 0, top: 0 })
})
export default router
import router from '@/router'
// @ts-ignore
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
NProgress.configure({
easing: 'ease', // 动画方式
showSpinner: true, // 是否显示加载ico
trickleSpeed: 200, // 自动递增间隔
minimum: 0.4, // 更改启动时使用的最小百分比
})
const whiteList = ['/login', '/redirect']
router.beforeEach((to, form, next) => {
// 这里处理自己的逻辑,比如需要登录以后才能访问其他页面等等
NProgress.start()
next()
NProgress.done()
})
import { createApp } from 'vue'
import App from './App.vue'
import 'animate.css'
import router from '@/router';
import '@/router/permission'
import 'element-plus/theme-chalk/dark/css-vars.css'
const app = createApp(App);
app.use(router)
app.mount('#app')
home.vue
去home
++++
{{ count }}
hom1.vue
回home
++++
{{ count }}
注:这里只是一个简单的搭建demo,所以拦截器没有做过多的扩展。我的另一篇文章有详细讲解动态路由的实现,但是建议先把本篇文章走完以后再去看。Vite4 + Vue3 + vue-router4 动态路由如果有问题的话可以联系我SH--TS。
为啥没有使用vuex而选择pinia来实现状态管理。相对于vuex来说,它更好的支持TypeScript、非常轻巧(体积约 1KB)等等优势。而且尤雨溪大佬也推荐使用。至于它俩如何做选择。可以根据自己的项目情况,如果是中小型项目的话推荐pinia。如果大规模、高复杂度的话就选vuex。
import { defineStore } from 'pinia'
export interface IViewsState {
count?: number
title?: string
}
// 创建一个pinia, defineStore接受两个参数,第一个是id(唯一的)。参数二是配置项
export const viewsModule = defineStore('VIEWS',{
state(): IViewsState {
return {
count: 1,
title: 'Etc.End'
}
},
//可以操作异步 和 同步提交state
actions:{
// 这里因为我的count定义的类型不是必有参数,所有它会存在空的情况.
// 后面只需要加个!让编译器知道它不会未定义或不会为null
// 也可以把上面的count?: number更改为count: number,下面就不用加!了
incremental() {
this.count!++
},
getCount() {
return this.count
}
},
// 类似于computed 可以帮我们去修饰我们的值
getters:{
newCount ():number | string {
return this.count = 0
},
newTitle ():string {
return `$-${this.title}`
}
},
})
import { viewsModule } from './modules/views';
export interface IAppStore {
viewsModule: ReturnType;
}
const appStore: IAppStore = {} as IAppStore;
export const registerStore = () => {
appStore.viewsModule = viewsModule();
};
export default appStore;
import { createApp } from 'vue'
import App from './App.vue'
import 'animate.css'
import { createPinia } from 'pinia';
import { registerStore } from '@/pinia';
import router from '@/router';
import '@/router/permission'
import 'element-plus/theme-chalk/dark/css-vars.css'
const app = createApp(App);
app.use(router)
app.use(createPinia())
// 这里是进行一个注册,不然的话页面上是拿不到值的
registerStore()
app.mount('#app')
去home1
直接修改count的值
批量修改pinia的值
actions修改pinia的值
{{ count }}
{{ title }}
回home
直接修改count的值
批量修改pinia的值
actions修改pinia的值
{{ count }}
{{ title }}
注:切换路由是没有问题,但页面刷新状态就会丢失。解决这个问题的话也很简单,搭配localStorage写一个插件就可以达到持久化。这里就不做演示了,自行研究一下。
Vite4 + Vue3 + ElementPlus 实现国际化包括表单校验(超详细)
我是Etc.End。如果文章对你有所帮助,能否帮我点个免费的赞和收藏。同时欢迎各位小伙伴一起学习,一起成长WX:SH--TS
❤️ ✨ ⭐️