手摸手创建一个 Vue + Ts 项目(一) —— 初始化项目
介绍
本教程是为大家介绍如何一步步搭建一个后台的前端项目,只实现最最基本的功能,基于 Vue3
+ TypeScript 和 NaiveUI
的技术方案。从零开始,手摸手一步步来搭建一个后台项目。它可能并不能帮助你快速搭建企业级中台产品原型,但可以让你更好地了解整个项目。
技术栈:
- Vite
- Vue3
- VueRouter
- Pinia
- TypeScript
- NaiveUI
- Axios
- Echarts
- Unocss
环境准备
安装 Node
这里使用 nvm
来安装、管理 NodeJS,该框架主要是为了可以方便地安装和切换不同版本的 NodeJS。
nvm 中文网站:nvm.uihtm.com/
安装好 nvm
后,可以通过如下命令安装和使用 LTS 版本的 NodeJS:
-- 安装最新的 lts 版 NodeJS
nvm install --lts
-- 切换 lts 版 NodeJS
nvm use --lts
安装 pnpm
使用 pnpm 代替 npm 来作为软件包管理器。
可以使用 npm 来全局安装 pnpm:
npm install -g pnpm
之后在执行 npm 命令时,可以直接替换为 pnpm,例如安装一个依赖包,可以直接执行 pnpm install xxx
.
使用 nrm 管理 npm 源
nrm
可以简单快速地切换不同的 npm 镜像源,可以用它来快速切换淘宝镜像源。
- 安装
nrm
npm install -g nrm
- 使用
nrm
切换淘宝源nrm use cnpm
到此为止,前端所需要的环境基本完成,接下来就可以初始化一个前端项目了。
初始化项目
基于 Vite 初始化 Vue + Ts 项目
Vite 官网:cn.vitejs.dev/
使用 pnpm 来创建一个 Vue 项目:
pnpm create vite@latest easii-admin-ui -- --template vue
执行后,会让你选择 framework
和 variant
,这里分别选择 Vue
和 TypeScript
就可以。
执行后,在控制台输入如下:
linpl@iMac Workspace % pnpm create vite@latest easii-admin-ui -- --template vue
.../Library/pnpm/store/v3/tmp/dlx-16232 | Progress: resolved 1, reused 0, downloaded 0, added.../Library/pnpm/store/v3/tmp/dlx-16232 | +1 +
.../Library/pnpm/store/v3/tmp/dlx-16232 | Progress: resolved 1, reused 0, downloaded 0, added.../Library/pnpm/store/v3/tmp/dlx-16232 | Progress: resolved 1, reused 0, downloaded 1, addedPackages are hard linked from the content-addressable store to the virtual store.
Content-addressable store is at: /Users/linpl/Library/pnpm/store/v3
Virtual store is at: ../../Library/pnpm/store/v3/tmp/dlx-16232/node_modules/.pnpm
.../Library/pnpm/store/v3/tmp/dlx-16232 | Progress: resolved 1, reused 0, downloaded 1, added 0
? Select a framework: › - Use arrow-keys. Return to submit.
✔ Select a framework: › Vue
✔ Select a variant: › TypeScript
Scaffolding project in /Users/linpl/Development/Workspace/easii-admin-ui...
Done. Now run:
cd easii-admin-ui
pnpm install
pnpm run dev
按照控制台的提示,进入项目后,安装依赖,启动项目
cd easii-admin-ui
pnpm install
pnpm run dev
启动后,打开浏览器,输入控制台显示的 IP 和端口,效果如下:
OK,一个全新的 Vue3 + Ts 项目就初始化完成啦。接下来就按照我们需要的技术,一步步来操作。
安装 @types/node
@types/node
是一个 TypeScript 类型定义文件的包,主要用于提供 Node.js API 的类型定义,使得在 TypeScript 项目中使用 Node.js API 时,可以获得更好的代码提示、类型检查和代码补全等功能。这有助于提高代码的可读性、可维护性和安全性。
安装命令:
pnpm i -D @types/node
添加路径别名
在前端项目中,通常会用 @
来作为 src
目录的别名,这里演示一下 Vite
+ TypeScript
下,如何设置该别名。
配置 vite.config.ts
在 vite.config.ts
中,增加如下配置:
import { resolve } from 'path'
/** 路径查找 */
const pathResolve = (dir: string): string => {
return resolve(__dirname, '.', dir)
}
export default defineConfig({
// ......
resolve: {
alias: {
'@': pathResolve('src')
},
},
// ......
})
配置 tsconfig.json
在 tsconfig.json
中的 compilerOptions
中添加 baseUrl
和 paths
配置:
{
"compilerOptions": {
// ......
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
}
}
修改这两部分后,可以在 App.vue
文件中测试下效果:
之前引入 HelloWord
组件的方式:
import HelloWord from './components/HelloWorld.vue'
可以修改为:
import HelloWorld from '@/components/HelloWorld.vue'
修改后,启动正常,则表示已经生效啦。
安装 NaiveUI
NaiveUI 官网:www.naiveui.com/
// 安装 naive-ui
pnpm i -D naive-ui
// 安装 vfonts
pnpm i -D vfonts
安装 xicons
xicons 是一个第三方图标库,风格比较统计且细腻,是 NaiveUI
中推荐使用的。
安装 xicons 中所有的图标库(这里也可以部分安装):
pnpm i -D @vicons/fluent
pnpm i -D @vicons/ionicons4
pnpm i -D @vicons/ionicons5
pnpm i -D @vicons/antd
pnpm i -D @vicons/material
pnpm i -D @vicons/fa # font awesome
pnpm i -D @vicons/tabler
pnpm i -D @vicons/carbon
使用教程,可以参考 图标 Icon - Naive UI
自动引入组件功能
由于组件库和图标库等提供的组件较多,且不想全局引用时,这样子话,在每个文件中使用时,都会需要手动编写 import { xxx } from 'xxx'
。
这里介绍一款由 Vue 官方人员开发的自动引入插件 —— unplugin-vue-components
,可以省去比如 UI 库的大量 import 语句。
安装 unplugin-vue-components
pnpm i -D unplugin-vue-components
Vite 启用 unplugin-vue-components
编辑 vite.config.ts
,添加内容如下:
/**
* unplugin-vue-components
*/
import Components from 'unplugin-vue-components/vite'
export default defineConfig({
plugins: [
// ......
Components({
dts: true, // ts 环境下要启用
})
],
// ......
})
添加 NaiveUI 解析器
unplugin-vue-components
为多个流行的 UI 库提供了内置解析器,这里以 NaiveUI 为例,启用该解析器:
基于上面添加的内容:
/**
* unplugin-vue-components
*/
import Components from 'unplugin-vue-components/vite'
import {NaiveUiResolver} from 'unplugin-vue-components/resolvers' // ##### new #####
export default defineConfig({
plugins: [
// ......
Components({
dts: true, // ts 环境下要启用
resolvers: [NaiveUiResolver()] // ###### new ######
})
],
// ......
})
启用后,在 Vue 文件中,就可以不必再添加 import { xxx } from 'naive-ui'
相关代码,同时,会在根目录生成 components.d.ts
文件,来全局引入需要的组件。
引入自定义组件
unplugin-vue-components
还可以自动引入自定义的组件,默认情况下,会引入 src/components
目录下的组件,如果需要引入其他目录的组件,则需要配置 dirs
属性:
/**
* unplugin-vue-components
*/
import Components from 'unplugin-vue-components/vite'
export default defineConfig({
plugins: [
// ......
Components({
dts: true, // ts 环境下要启用
dirs: ['src/components', 'src/layouts'], // ###### new ######
})
],
// ......
})
自定义 Xicons 组件解析器
在使用 Xicons 组件库时,每次使用一个组件,都需要提前引入,冗余繁琐。所以这里基于 unplugin-vue-components
,来实现一个自动引入 Xicons 组件的解析器。
安装 fs、local-pkg
这两个依赖主要用于解析依赖包中的文件,在自定义的组件解析器中使用。
安装命令:
pnpm i local-pkg
pnpm i -D fs
增加 Xicons 组件解析器
在根目录新增文件:ViconsResolver.ts
,在其中实现组件解析的功能。
import { readdirSync } from 'fs'
import { dirname } from 'path'
// @ts-ignore
import { resolveModule } from 'local-pkg'
import type { ComponentResolver } from 'unplugin-vue-components'
/**
* key: 图标组件名称
* value: 模块
*/
let iconPkgMap: Map<string, string>
const iconPkgs: Array<string> = [
'@vicons/fluent',
'@vicons/ionicons4',
'@vicons/ionicons5',
'@vicons/antd',
'@vicons/fa',
'@vicons/material',
'@vicons/tabler',
'@vicons/carbon',
]
export function ViconsResolver(): ComponentResolver {
if (!iconPkgMap) {
try {
iconPkgMap = new Map();
iconPkgs.forEach(pkg => {
let icons = readdirSync(dirname(resolveModule(pkg as string) as string), { withFileTypes: true })
.filter((item) => !item.isDirectory() && item.name.match(/^[A-Z][A-Za-z0-9]+\.js$/))
.map((item) => item.name.replace(/\.js$/, ''))
icons.forEach(icon => iconPkgMap.set(icon, pkg))
})
} catch (error) {
console.error(error)
throw new Error(`[unplugin-vue-components] failed to load vicons, have you installed it?`)
}
}
return {
type: 'component',
resolve: (name: string) => {
if (iconPkgMap.has(name)) {
return {
name: name,
from: iconPkgMap.get(name)
}
}
},
}
}
添加该文件后,需要在 tsconfig.node.json
中引入该文件,在其 include
属性中,添加该文件:
{
// .......
"include": ["vite.config.ts", "ViconsResolver.ts"]
}
启用
在 unplugin-vue-components
的 resolvers
中添加该自定义的解析器,如下:
import {ViconsResolver} from './ViconsResolver'
export default defineConfig({
plugins: [
// ....
Components({
// ....
resolvers: [NaiveUiResolver(), ViconsResolver()]
})
],
// .......
})
安装 UnoCSS
UnoCSS 介绍
UnoCSS 官网:alfred-skyblue.github.io/unocss-docs…
这里引用一段作者(Antfu)对于 UnoCSS 的概括:“UnoCSS 是一个具有高性能且极具灵活性的即时原子化 CSS 引擎。它是一个引擎,而非一款框架,因为它并未提供核心工具类,所有功能可以通过预设和内联配置提供”。
这里又涉及到一个点 —— “原子化 CSS”。
什么是原子化 CSS 呢?
其实就是一种 CSS 的架构方式,倾向于小巧且用途单一的 class,并且会以视觉效果进行命名。举个例子:
.m-0 {
margin: 0;
}
.text-red {
color: red;
}
看完实例,就能简单理解什么是原子化 CSS 了。如果用熟悉的后端语言来说,就是一种符合“单一职责(一个类应该只有一项职责,这样可以保证类的内聚性,并且降低类之间的耦合性)”设计原则的一种 CSS class 定义方式,一个 class 只会实现一个效果。
关于这个框架的介绍,就到这里,想要了解更多,可以阅读下作者的文章:重新构想原子化 CSS (antfu.me)
安装 UnoCSS
- 安装 UnoCSS
pnpm i -D unocss
-
安装 UnoCSS 预设
有两个依赖包,第一个是 UnoCSS 的默认预设,第二个是启用属性化模式的规则
pnpm i -D @unocss/preset-attributify
pnpm i -D @unocss/preset-uno
启用 UnoCSS
- 首先在
vite.config.ts
中启用该插件:
import UnoCSS from 'unocss/vite'
export default defineConfig({
plugins: [
// ......
UnoCSS()
],
}
-
添加 UnoCSS 预设
基于上面的内容:
import UnoCSS from 'unocss/vite'
import presetUno from '@unocss/preset-uno' // ******** new *********
import presetAttributify from '@unocss/preset-attributify' // ******** new *********
export default defineConfig({
plugins: [
// ......
UnoCSS({
presets: [presetUno(), presetAttributify()] // ******** new *********
})
],
}
UnoCSS 的预设与 Tailwind CSS 和 Windi CSS 兼容,可以参考它们的文档以获取详细的使用方法。
- main.ts 中引入 uno.css
import 'uno.css'
示例
比如,我想要将一个标题颜色设置为深灰色,可以直接在其标签上面添加:text-gray-500
<template>
<h1 text-gray-500>{{ msg }}</h1>
</tempalte>
效果如下:
安装 Pinia
Pinia 官网:pinia.web3doc.top/
Pinia 是 Vue 的存储库,它允许跨组件/页面共享状态。
安装
pnpm i pinia
定义一个 store
在 src 目录下,创建一个 store 目录,用作存放 store 相关的文件。
目录定义如下:
这里以定义一个计数器的 Store 为例:
在 modules 目录中,新建一个 counter.ts:
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function increment() {
count.value++
}
return { count, increment }
})
使用 store
在 store 目录中的 index.ts 中,添加如下内容:
import type {App} from 'vue'
import {createPinia} from 'pinia'
const store = createPinia()
export function useStore(app: App<Element>): void {
app.use(store)
}
export {store}
使用
在 HelloWorld.vue 中,添加一个计数器功能:
<script setup lang="ts">
import {useCounterStore} from "@/store/modules/counter"
const counterStore = useCounterStore()
</script>
<template>
<div class="card">
<button type="button" @click="counterStore.increment">count is {{ counterStore.count }}</button>
</div>
</template>
效果如下:
结语
这篇文章中,手把手地讲述了如何创建一个后台前端项目。从环境搭建、初始化项目,以及安装各种最基本的依赖。这只是项目的第一步,下一篇将讲述如何实现一个左侧菜单栏,并搭配 vue-router 使用,为项目增添更多功能。
最后,欢迎关注我的公众号:「代码笔耕」和我的开源项目:「easii (easii) - Gitee.com」
转载自:https://juejin.cn/post/7237487578865729595