# 搭建聊天室(前端 vue3 + pinia + axios + elementplus)01 搭建项目基本框架
# 一、项目技术栈选型
vue3:
- 更小的包大小:Vue 3 通过使用模块化架构和逐渐引入编译时的 Tree-shaking,可以产生更小的包大小,提高应用程序的加载速度。
- 更好的性能:Vue 3 对响应式系统进行了全面重写,提供了更好的性能和内存利用率。
- Composition API:Vue 3 引入了 Composition API,使得组件逻辑更加可组合和可重用。
pinia:
- 类型安全:Pinia 是一个状态管理库,基于 Vue 3 的响应式系统,并且提供了类型安全的状态管理解决方案。
- 插件化:Pinia 支持插件机制,可以扩展它的功能,例如中间件、插件等。
- 简洁易用:Pinia 提供了简洁的 API 和开发体验,使得状态管理变得更加直观和容易。
vue-router:
- 路由管理:Vue Router 是 Vue 官方提供的路由管理库,可以帮助你实现单页面应用的路由控制。
- 嵌套路由:Vue Router 支持嵌套路由,可以更好地组织和管理你的应用程序。
- 导航守卫:Vue Router 提供了导航守卫机制,可以在路由切换前后执行相应的逻辑。
axios:
- 强大的 HTTP 客户端:Axios 是一个流行的基于 Promise 的 HTTP 客户端,用于发送 AJAX 请求。
- 简单易用:Axios 提供了简单易用的 API,支持拦截器、请求取消、错误处理等功能。
- 跨平台兼容性:Axios 可以在浏览器和 Node.js 中使用,具有良好的跨平台兼容性。
element-plus:
- 丰富的组件:Element Plus 提供了丰富的 UI 组件,包括按钮、表单、对话框、表格等,可以帮助快速搭建出美观的用户界面。
- 友好的文档和示例:Element Plus 提供了清晰的文档和示例,方便开发人员快速上手,并且可以参考示例进行定制化开发。
- 主题定制:Element Plus 支持主题定制,可以根据项目需求进行样式定制,保证 UI 组件与项目风格一致。
- 国际化支持:Element Plus 提供了多语言国际化支持,可以轻松实现多语言切换,适配不同地区的用户需求。
websocket:
- 实时双向通信:WebSocket 提供了一种基于 TCP 协议的全双工通信方式,可以实现实时的双向通信。
- 较低的延迟:相比传统的 HTTP 请求,WebSocket 可以减少通信的延迟,使得实时性更强。
- 服务器推送:WebSocket 支持服务器主动推送消息给客户端,可以轻松实现即时通讯功能。
scss:
- 变量和混合:SCSS 提供了变量和混合功能,可以方便地定义和重复使用样式属性和代码块,减少了代码量和维护成本。
- 嵌套规则:SCSS 支持嵌套规则,使得 CSS 的层级关系更加清晰和易于理解,同时也可以减少选择器的复杂度。
- 继承:SCSS 支持继承功能,可以避免样式的重复定义,提高了代码的重用性和可维护性。
- 导入其他文件:SCSS 支持导入其他 SCSS 文件,可以将样式代码拆分到多个文件中,方便管理和维护。
- 自定义函数:SCSS 支持自定义函数,可以实现一些常用的计算和处理,例如颜色转换等。
vite:
- 快速开发:Vite 是一个基于 ES Modules 的快速开发工具,具有快速的冷启动、模块热更新等特性,提高了开发效率。
- 按需加载:Vite 通过按需加载模块,减少了不必要的加载时间,加快了应用程序的加载速度。
- 简化配置:Vite 使用原生的 ES Modules,不需要繁琐的构建配置,简化了项目的配置过程。
综上所述,我们可以快速的搭建出一个聊天室前端部分。后端部分因为本人不是专业后端,没学过 java,不过也会写点业务,之后会出教程。
# 二、初始化项目
找到 vite 官网
# 搭建项目 | |
pnpm create vite | |
# project name: anixuil-chat | |
# language: vue javascript | |
# 进入项目 | |
cd anixuil-chat | |
# 安装依赖 | |
pnpm i | |
pnpm i scss sass pinia vue-router axios element-plus -D | |
# 自动引入 | |
pnpm install -D unplugin-vue-components unplugin-auto-import | |
# 运行项目 | |
pnpm run dev |
main.js
import { createApp } from "vue"; | |
import "@/styles/reset.scss"; // global css | |
import App from "./App.vue"; | |
import router from "@/router"; | |
import ElementPlus from "element-plus"; | |
import zhCn from "element-plus/dist/locale/zh-cn.mjs"; | |
const app = createApp(App); | |
app.use(router); | |
app.use(ElementPlus, { | |
locale: zhCn, | |
}); | |
app.mount("#app"); |
vite.config.js
/* | |
* @Author: Anixuil | |
* @Date: 2024-02-24 13:32:06 | |
* @LastEditors: Anixuil | |
* @LastEditTime: 2024-02-28 15:27:29 | |
* @Description: vite 配置文件 | |
*/ | |
import { defineConfig } from "vite"; | |
import vue from "@vitejs/plugin-vue"; | |
import path from "path"; | |
import AutoImport from "unplugin-auto-import/vite"; | |
import Components from "unplugin-vue-components/vite"; | |
import { ElementPlusResolver } from "unplugin-vue-components/resolvers"; | |
const pathSrc = path.resolve(__dirname, "src"); | |
// https://vitejs.dev/config/ | |
export default defineConfig({ | |
server: { | |
port: 2001, | |
open: true, | |
}, | |
css: { | |
preprocessorOptions: { | |
scss: { | |
additionalData: `@use "@/styles/element/index.scss" as *;`, | |
}, | |
}, | |
}, | |
envPrefix: "CHAT", // 环境变量前缀 | |
plugins: [ | |
vue(), | |
AutoImport({ | |
imports: ["vue", "vue-router"], | |
// 自动引入修改主题色添加这一行,使用预处理样式,不添加将会导致使用 ElMessage,ElNotification 等组件时默认的主题色会覆盖自定义的主题色 | |
resolvers: [ | |
ElementPlusResolver({ | |
importStyle: "sass", | |
}), | |
], | |
}), | |
Components({ | |
resolvers: [ | |
ElementPlusResolver({ | |
// 自动引入修改主题色添加这一行,使用预处理样式 | |
importStyle: "sass", | |
}), | |
], | |
}), | |
], | |
resolve: { | |
// 配置路径别名 | |
alias: { | |
"@": pathSrc, | |
}, | |
}, | |
}); |
@/styles/element/index.scss
/* 只需要重写你需要的即可 */ | |
@forward "element-plus/theme-chalk/src/common/var.scss" with ( | |
$colors: ( | |
"primary": ( | |
"base": rgb(245, 30, 30), | |
) | |
) | |
); | |
// @use "element-plus/theme-chalk/src/index.scss" as *; |
reset.scss
body, | |
h1, | |
h2, | |
h3, | |
h4, | |
h5, | |
h6, | |
hr, | |
p, | |
blockquote, | |
dl, | |
dt, | |
dd, | |
ul, | |
ol, | |
li, | |
pre, | |
form, | |
fieldset, | |
legend, | |
button, | |
input, | |
textarea, | |
th, | |
td { | |
margin: 0; | |
padding: 0; | |
} | |
body, | |
button, | |
input, | |
select, | |
textarea { | |
font: 12px/1.5tahoma, arial, \5b8b\4f53; | |
} | |
h1, | |
h2, | |
h3, | |
h4, | |
h5, | |
h6 { | |
font-size: 100%; | |
} | |
address, | |
cite, | |
dfn, | |
em, | |
var { | |
font-style: normal; | |
} | |
code, | |
kbd, | |
pre, | |
samp { | |
font-family: couriernew, courier, monospace; | |
} | |
small { | |
font-size: 12px; | |
} | |
ul, | |
ol { | |
list-style: none; | |
} | |
a { | |
text-decoration: none; | |
} | |
a:hover { | |
text-decoration: underline; | |
} | |
sup { | |
vertical-align: text-top; | |
} | |
sub { | |
vertical-align: text-bottom; | |
} | |
legend { | |
color: #000; | |
} | |
fieldset, | |
img { | |
border: 0; | |
} | |
button, | |
input, | |
select, | |
textarea { | |
font-size: 100%; | |
} | |
table { | |
border-collapse: collapse; | |
border-spacing: 0; | |
} |
@/styles/common.scss
body { | |
font-size: 14px; | |
// 伪类隐藏页面滚动条 | |
&::-webkit-scrollbar { | |
display: none; | |
} | |
} | |
/* fade-transform 路由切换动画效果 */ | |
.fade-transform-leave-active, | |
.fade-transform-enter-active { | |
transition: all 0.5s; | |
} | |
.fade-transform-enter-from, | |
.fade-transform-leave-to { | |
opacity: 0; | |
transform: translateY(30px); | |
} |
@/styles/index.scss
@import "element/index.scss"; | |
@import "common.scss"; |
# 三、遇到的问题
在搭建项目中,遇到了 elementplus 主题色无法修改的问题,重点是这一句
还有一个就是路由跳转动画的问题。
核心实现逻辑是这样,但是动画样式只有出去的没有进来的,也就是只有 leave-to,没有 enter-from
最后发现是我借鉴我的 vue2 项目,vue2 和 vue3 transition 的一些语法稍微有些区别,我直接赋值过来是有问题的。
/* | |
* @Author: Anixuil | |
* @Date: 2024-02-24 13:49:36 | |
* @LastEditors: Anixuil | |
* @LastEditTime: 2024-02-24 15:43:09 | |
* @Description: 路由配置 | |
*/ | |
import { createRouter, createWebHashHistory } from "vue-router"; | |
const routes = [ | |
{ path: "/", redirect: "/index" }, | |
{ | |
path: "/index", | |
name: "index", | |
component: () => import("@/views/index.vue"), | |
meta: { | |
title: "首页", | |
transition: "fade-transform", | |
}, | |
}, | |
{ | |
path: "/login", | |
name: "login", | |
component: () => import("@/views/login.vue"), | |
meta: { | |
title: "登录", | |
transition: "fade-transform", | |
}, | |
}, | |
]; | |
const router = createRouter({ | |
history: createWebHashHistory(), | |
routes, | |
}); | |
export default router; |
路由配置如上,pinia 没有放在这里集成是因为我觉得虽然 pinia 相比 vuex 感觉上差不多,但是其实搭配 vue3 使用的时候,还是有一些区别的,尤其是在一些封装上面,我觉得可以抛弃脑中 vuex 的记忆,重新学习一下 pinia。所以下一章就是单独讲 pinia 的集成。(绝对不是今天写到这不想写了)