npm create vite@latest my-cproject -- --template vue-ts
cd my-project
npm install
npm run dev
npm install vue-router@latest
npm install pinia
npm install pinia-plugin-persistedstate
npm install element-plus
npm install @element-plus/icons-vue
npm install axios
npm install vite-plugin-windicss windicss --save-dev
//如果你的项目是基于 Vite,Vite 默认已经支持 SCSS,
//你不需要额外配置。只需要确保安装了 sass 即可。
npm install sass sass-loader --save-dev
//NProgress 是一个轻量级的进度条库
npm install nprogress --save
如何配置vue-router
创建路由配置文件
在 src
目录下创建一个 router
文件夹,并在其中创建一个 index.ts
(或 index.js
)文件。这个文件将包含你的路由配置。
注意路由模式:
方式 1 使用 createWebHistory,这是一种 HTML5 History 模式的路由,URL 中不会出现 #。
方式 2 使用 createWebHashHistory,这是一种基于哈希的路由,URL 中会出现 #。
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router';
import Home from '../views/Home.vue';
import About from '../views/About.vue';
const routes = [
{
path: '/',
name: 'Home',
component: Home,
},
{
path: '/about',
name: 'About',
component: About,
},
// 可以在这里添加更多的路由
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
组件导入:
方式 1 使用动态导入(懒加载),即 () => import('@/views/Login.vue')。这种方式可以提高应用的初始加载性能,因为只有当用户访问特定路由时才会加载相应的组件。
方式 2 直接导入组件,即 import Index from '@/pages/index.vue'。这种方式会在应用初始化时加载所有组件,可能会增加初始加载时间。
import { createRouter, createWebHistory } from "vue-router";
import NotFound from "../views/404.vue";
const routes = [
// 通配符路由,捕获所有未定义的路径
{
path: "/:pathMatch(.*)*",
name: "not-found",
component: NotFound,
},
{
path: "/",
meta: { title: "登录" },
component: () => import("@/views/Login.vue"),
},
{
path: "/Login",
meta: { title: "登录" },
redirect: "/",
},
{
path: "/Index",
meta: { title: "MOKEXS复习室" },
component: () => import("@/views/Index.vue"),
children: [
{
path: "home", // 注意这里应该是相对路径,不需要加斜杠
meta: { title: "首页" },
component: () => import("@/views/Home.vue"),
},
{
path: "mail", // 注意这里应该是相对路径,不需要加斜杠
meta: { title: "邮件" },
component: () => import("@/views/Mail.vue"),
},
{
path: "message", // 注意这里应该是相对路径,不需要加斜杠
meta: { title: "消息" },
component: () => import("@/views/Message.vue"),
},
{
path: "beitie", // 注意这里应该是相对路径,不需要加斜杠
meta: { title: "碑帖赏析" },
component: () => import("@/views/resources/Beitie.vue"),
},
],
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
// 路由守卫:设置页面标题
router.afterEach((to) => {
if (to.meta && typeof to.meta.title === "string") {
document.title = to.meta.title;
}
});
export default router;
创建视图组件
确保你已经创建了 Home
和 About
视图组件。如果还没有创建,可以在 src/views
目录下创建这些组件。
<!-- src/views/Home.vue -->
<template>
<div>
<h1>Home Page</h1>
<p>Welcome to the home page.</p>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'Home',
});
</script>
<!-- src/views/About.vue -->
<template>
<div>
<h1>About Page</h1>
<p>This is the about page.</p>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'About',
});
</script>
在主应用文件中引入并使用路由
在 src/main.ts
中引入并使用路由配置。
// src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
const app = createApp(App);
app.use(router);
app.mount('#app');
在主应用组件中使用 <router-view>
在 src/App.vue
中使用 <router-view>
组件来显示当前的路由组件。
<!-- src/App.vue -->
<template>
<div id="app">
<header>
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
</header>
<main>
<router-view></router-view>
</main>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'App',
});
</script>
<style>
/* 你可以在这里添加样式 */
</style>
如何配置pinia
创建 Store
在 src
目录下创建一个 stores
文件夹,并在其中创建一个 counterStore.ts
文件。
// src/stores/counterStore.ts
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
actions: {
increment() {
this.count++;
},
decrement() {
this.count--;
},
},
getters: {
doubleCount: (state) => state.count * 2,
},
});
在主应用文件中引入并使用 Pinia
在 src/main.ts
中引入并使用 Pinia。
// src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import { createPinia } from 'pinia';
const app = createApp(App);
app.use(router);
app.use(createPinia());
app.mount('#app');
在组件中使用 Store
在你的 Vue 组件中使用 useCounterStore
来访问和修改状态。
<template>
<div>
<h1>Counter: {{ counter }}</h1>
<p>Double Count: {{ doubleCount }}</p>
<button @click="increment">Increment</button>
<button @click="decrement">Decrement</button>
</div>
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { useCounterStore } from '../stores/counterStore';
const counterStore = useCounterStore();
const counter = computed(() => counterStore.count);
const doubleCount = computed(() => counterStore.doubleCount);
const increment = () => {
counterStore.increment();
};
const decrement = () => {
counterStore.decrement();
};
</script>
总结
store
:用于集中管理和共享应用的状态。- 常见状态管理库:Vuex 和 Pinia。
- 示例:展示了如何使用 Pinia 创建和使用一个简单的状态管理 store。
通过使用 store
,你可以更好地组织和管理应用的状态,提高代码的可维护性和可读性。
如何配置pinia
持久化存储
配置 pinia-plugin-persistedstate
在你的主应用文件中(通常是 src/main.ts
),导入并配置 pinia-plugin-persistedstate
插件。
在 main.ts
中配置插件
// src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import { createPinia } from 'pinia';
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
const app = createApp(App);
const pinia = createPinia();
pinia.use(piniaPluginPersistedstate); // 使用插件
app.use(router);
app.use(pinia);
app.mount('#app');
在 Store 中启用持久化
在你的 store 中,通过选项启用持久化。你可以在 defineStore
的选项中添加 persist
配置。
启用持久化的 Store
// src/stores/counterStore.ts
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
actions: {
increment() {
this.count++;
},
decrement() {
this.count--;
},
},
persist: {
key: 'counter', // 用于存储的键名
storage: localStorage, // 使用 localStorage 进行存储
},
});
使用 Store
现在你可以在组件中使用这个 store,并且它的状态将会被持久化。
示例组件
<template>
<div>
<h1>Counter: {{ counter }}</h1>
<button @click="increment">Increment</button>
<button @click="decrement">Decrement</button>
</div>
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { useCounterStore } from '../stores/counterStore';
const counterStore = useCounterStore();
const counter = computed(() => counterStore.count);
const increment = () => {
counterStore.increment();
};
const decrement = () => {
counterStore.decrement();
};
</script>
总结
通过以上步骤,你可以配置 pinia-plugin-persistedstate
来持久化 Pinia store 的状态。以下是关键点总结:
- 安装
pinia-plugin-persistedstate
:使用 npm 或 yarn 安装。 - 创建并配置 Pinia Store:定义一个基本的 Pinia store。
- 配置
pinia-plugin-persistedstate
:在main.ts
中导入并使用插件。 - 在 Store 中启用持久化:在 store 的定义中添加
persist
选项。 - 使用 Store:在组件中使用 store,并享受持久化的状态管理。
如何配置Element Plus
在主应用文件中导入 Element Plus
在 src/main.ts
中导入并使用 Element Plus:
// src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';
const app = createApp(App);
app.use(router);
app.use(ElementPlus);
app.mount('#app');
检查组件名称拼写
确保你在模板中使用的 el-button
组件名称是正确的。例如:
<template>
<div>
<h1>Counter: {{ counter }}</h1>
<p>Double Count: {{ doubleCount }}</p>
<el-button type="primary" @click="increment">Increment</el-button>
<el-button type="primary" @click="decrement">Decrement</el-button>
</div>
</template>
<script lang="ts" setup>
import { computed } from "vue";
import { useCounterStore } from "../stores/counterStore";
const counterStore = useCounterStore();
const counter = computed(() => counterStore.count);
const doubleCount = computed(() => counterStore.doubleCount);
const increment = () => {
counterStore.increment();
};
const decrement = () => {
counterStore.decrement();
};
</script>
如何配置 element-plus/icons
全局注册所有图标
如果你希望在整个项目中都可以方便地使用这些图标,可以全局注册所有图标。
在 main.ts
中全局注册图标
// src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import { createPinia } from 'pinia';
import ElementPlus from 'element-plus';
import * as Icons from '@element-plus/icons-vue';
const app = createApp(App);
// 注册 Element Plus
app.use(router);
app.use(createPinia());
app.use(ElementPlus);
// 全局注册所有图标
for (const [key, component] of Object.entries(Icons)) {
app.component(key, component);
}
app.mount('#app');
在组件中使用全局注册的图标
如果已经全局注册了所有图标,你可以在任何组件中直接使用它们,而不需要再次导入。
示例组件
<template>
<div class="home">
<h2>图标</h2>
<el-icon size="30" color="red">
<Edit />
</el-icon>
<el-button type="danger" icon="Delete" circle />
<el-button type="danger" :icon="iconType" circle />
<el-button @click="changeIcon('Delete')">Set Delete Icon</el-button>
<el-button @click="changeIcon('Plus')">Set Plus Icon</el-button>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
// 动态图标名称
const iconType = ref("Delete"); // 可以根据需要改变这个值
// 如果你需要在运行时改变图标,可以这样做
function changeIcon(newIcon: string) {
console.log("Changing icon to:", newIcon);
iconType.value = newIcon;
}
</script>
<style lang="less" scoped></style>
总结
通过以上步骤,你可以在 Vue 项目中配置和使用 @element-plus/icons-vue
图标库。以下是关键点总结:
- 安装
@element-plus/icons-vue
:使用 npm 或 yarn 安装。 - 在单个组件中导入和使用图标:直接在组件中导入所需的图标。
- 全局注册所有图标:在
main.ts
中全局注册所有图标,以便在整个项目中方便地使用。 - 使用自定义名称:在全局注册时为图标指定自定义名称,以避免命名冲突或提高可读性。
如何配置
配置 Windi CSS
在 vite.config.ts
中添加插件
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import WindiCSS from 'vite-plugin-windicss';
export default defineConfig({
plugins: [
vue(),
WindiCSS(), // 添加 WindiCSS 插件
],
// 其他 Vite 配置
});
在main中引用Windi CSS
import "virtual:windi.css";
在组件中使用 Windi CSS
在你的 Login.vue
组件中,你可以直接使用 Windi CSS 的 @apply
指令。确保你在 <style>
标签中使用了 scoped
属性,并且正确地引入了 Windi CSS。
<!-- src/views/Home.vue -->
<template>
<div>
<h1>Home Page</h1>
<p class="p-4">Welcome to the home page.</p>
<div class="line"></div>
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Home",
});
</script>
<style scoped>
.line {
@apply h-[1px] w-16 bg-red-500;
}
</style>
如何配置 Tailwind CSS
安装 tailwindcss和postcss
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
初始化配置文件
npx tailwindcss init -p
添加对vue文件的识别
在tailwind.config.js添加对vue文件的识别,如果你介意 tailwind.config.js 的文件是 js,那么直接改为 ts 之后换成以下代码。注意postcss.config.js 不能改成 ts
/** @type {import('tailwindcss').Config} */
import type { Config } from "tailwindcss";
export default {
content: ["./src/**/*.{vue,js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
} satisfies Config;
引入样式文件
在src/assets 目录下创建目录styles,并在该目录下创建Tailwind.css,用 @tailwind 指令添加 Tailwind功能。
@tailwind base;
@tailwind components;
@tailwind utilities;
在main.js文件中引入Tailwind CSS的样式文件
import { createApp } from "vue";
import App from "./App.vue";
import "./assets/styles/Tailwind.css";
createApp(App).mount("#app");
使用 Tailwind CSS的样式
<script setup lang="ts">
import { ref } from "vue";
defineProps<{ msg: string }>();
const count = ref(0);
</script>
<template>
<h1>{{ msg }}</h1>
<h1 className="title">Hello world!</h1>
<div class="w-full mx-auto text-[#fff] text-[14px]">
<div class="flex flex-wrap sm:px-1">
<div class="w-full sm:w-1/3 p-2 box pb-0 sm:px-1">
<div class="bg-red-600 p-1">测试</div>
</div>
</div>
</div>
</template>
<style scoped>
.read-the-docs {
color: #888;
}
.title{
@apply text-3xl font-bold underline text-red-500;
}
</style>
配置 Visual Studio Code (VSCode)
- 忽略未知的 SCSS
@rules
和属性。
通常存储在 .vscode/settings.json
文件中。
点击设置---搜索settings,点击文本编辑器 【不建议此操作,有验证才是正确的】
禁用 CSS、Less 和 SCSS 文件的语法验证。
如何封装消息提示
封装Notification 通知
import { ElNotification } from "element-plus";
// 消息提示
export function toast(
title: string = "消息提示",
message: string,
type: "success",
dangerouslyUseHTMLString: boolean = false
): void {
ElNotification({
title, // 标题
message, // 默认没有值的情况下,提示请求失败
type, // 消息类型 Success | Warning | Info | Error
dangerouslyUseHTMLString, // 是否将 message 属性作为 HTML 片段处理
duration: 3000, // 显示时间, 单位为毫秒。 值为 0 则不会自动关闭 | 默认4500
});
}
使用Notification 通知
// 示例
// import { toast } from '@/composables/util';
// <el-button @click="showSuccessNotification">显示成功通知</el-button>
// const showSuccessNotification = () => {
// toast('操作成功', '您的操作已成功完成', 'success');
// };
// const showWarningNotification = () => {
// toast('警告', '请确认您的输入', 'warning');
// };
// const showInfoNotification = () => {
// toast('信息', '这是一个信息通知', 'info');
// };
// const showErrorNotification = () => {
// toast('错误', '发生了一个错误,请稍后再试', 'error');
// };
// 自定义 HTML 内容
//toast('自定义内容', '<strong>这是一个<strong> HTML 内容</strong>', 'info', true);
如何配置 NProgress
全局设置中配置 NProgress
在你的项目的入口文件(如 main.ts
或 main.js
)中引入 NProgress 的样式文件:
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import 'nprogress/nprogress.css';
import * as NProgress from 'nprogress';
// 开始进度条
router.beforeEach((to, from, next) => {
NProgress.start();
next();
});
// 结束进度条
router.afterEach(() => {
NProgress.done();
});
const app = createApp(App);
app.use(router);
app.mount('#app');
在组件中使用 NProgress
自定义 NProgress 样式
如果你需要自定义 NProgress 的样式,可以通过覆盖默认的 CSS 类来实现。例如,在你的全局样式文件(如 src/assets/styles/global.css
)中添加自定义样式:
/* 设置 NProgress 进度条的颜色 */
#nprogress .bar {
background: rgb(
221,
59,
34
) !important; /* 将进度条的背景颜色设置为蓝色 (#29d) */
}
/* 设置 NProgress 进度条上的小球(peg)的阴影效果 */
#nprogress .peg {
box-shadow: 0 0 10px rgb(7, 136, 2), 0 0 5px rgb(221, 34, 34) !important; /* 给小球添加两层阴影效果,一层是 10px 的模糊阴影,另一层是 5px 的模糊阴影,颜色都是蓝色 (#29d) */
}
/* 设置 NProgress 旋转加载图标(spinner)的颜色 */
#nprogress .spinner-icon {
border-top-color: rgb(
34,
221,
47
) !important; /* 设置旋转加载图标的顶部边框颜色为蓝色 (#29d) */
border-left-color: rgb(
221,
34,
34
) !important; /* 设置旋转加载图标的左侧边框颜色为蓝色 (#29d) */
}
然后在 main.ts
或 main.js
中引入这个全局样式文件:
import 'nprogress/nprogress.css';
import './assets/styles/global.css'; // 引入自定义样式
设置系统路径别名
//vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import path from "path";
import WindiCSS from "vite-plugin-windicss";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
WindiCSS(), // 添加 WindiCSS 插件
],
resolve: {
alias: {
// 设置 @ 为 src 目录的路径别名
"@": path.resolve(__dirname, "src"),
},
},
});
如果上面没有解决这个问题,那么继续设置tsconfig.app.json文件
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "preserve",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
//************************** 重要就是这块 *********************//
/* Path aliases */
"baseUrl": "./src", // 设置基础路径为 src 目录
"paths": {
"@/*": ["*"], // 设置 @ 为 src 目录的路径别名
"@": ["."] // 设置单独的 @ 为 src 目录
}
//*************************************************************//
},
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
}
如何使用 axios
//axios.js
import axios from "axios";
var service = axios.create({
baseURL: "/api",
});
export default service;
注意:代理中使用/api,那么实例中必须也使用/api
创建登录Post请求
//manager.js
import axios from "@/axios";
export function login(username, password) {
return axios.post("admin/login", { username, password });
}
调用请求方法
VUE3的全部生命周期
<template>
<div>
<p>{{ message }}</p>
<button @click="handleClick">点击我</button>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeMount, onUpdated, onBeforeUpdate, onUnmounted, onBeforeUnmount } from 'vue';
// 定义响应式数据
const message = ref('初始化状态');
// 模拟异步数据获取
function fetchMessage() {
setTimeout(() => {
message.value = '数据加载完成!';
}, 2000);
}
// 在组件挂载之前执行
onBeforeMount(() => {
console.log('组件即将被挂载');
// 模拟异步数据加载
fetchMessage();
});
// 组件挂载完成后执行
onMounted(() => {
console.log('组件已经被挂载');
});
// 在组件更新之前执行
onBeforeUpdate(() => {
console.log('组件即将更新');
});
// 组件更新完成后执行
onUpdated(() => {
console.log('组件已经更新');
});
// 在组件卸载之前执行
onBeforeUnmount(() => {
console.log('组件即将被卸载');
});
// 组件卸载完成后执行
onUnmounted(() => {
console.log('组件已经被卸载');
});
// 一个示例方法,用于触发组件更新
function handleClick() {
message.value = '按钮被点击了!';
}
</script>