vue3 + ts + pinia + router + eslint 项目起步流程
创建项目
目标:使用 vite
初始化项目
核心步骤:
- 初始化项目
yarn create vue
或
npm init vue
- 一顿操作
√ Project name: ... vue3-ts-pinia-router-eslint
√ Add TypeScript? ... Yes ✅
√ Add JSX Support? ... Yes ✅
√ Add Vue Router for Single Page Application development? ... Yes ✅
√ Add Pinia for state management? ... Yes ✅
√ Add Vitest for Unit Testing? ... No ❌
√ Add Cypress for both Unit and End-to-End testing? ... No ❌
√ Add ESLint for code quality? ... Yes ✅
√ Add Prettier for code formatting? ... Yes ✅
- 进入到
vue3-ts-pinia-router-eslint
项目中,安装依赖包
yarn
eslint
格式化项目文件
yarn lint
- 启动项目
yarn dev
创建 Vue3
项目命令对比
Vue3
基础阶段命令
- 能使用,但是配置太简单了,学习
Vue3
基础可以,项目还需要额外配置很多东西,效率低。
yarn create vite
Vue3
项目阶段命令
Vue3
官方推荐方式,可以根据项目情况按需选择配置,推荐使用。
yarn create vue
Node 版本问题
yarn create vue
的依赖包要求 Node 16+
以上,或者 14.17.0
版本,建议大家升级 Node 版本。
01-项目起步-目录调整
-
删除 src 目录所有文件
-
创建
src/App.vue
<template> <h1>Hello vue3 + ts👍</h1> </template>
-
创建
src/main.ts
import { createApp } from "vue"; import App from "./App.vue"; const app = createApp(App); app.mount("#app");
02-项目起步-请求工具库axios
-
安装
npm i axios -S
-
src/App.vue
<script setup lang="ts"> // 导入 axios 实例 import { onMounted } from "vue"; import request from "./utils/request"; // 在组件挂载完毕后 onMounted(async () => { // 发送请求 const res = await request.get("/home/banner"); console.log(res); }); </script> <template> <h1>Hello vue3 + ts👍</h1> </template>
-
src/utils/request.ts
import axios from "axios"; // 创建 axios 实例 const instance = axios.create({ baseURL: "http://pcapi-xiaotuxian-front-devtest.itheima.net/", timeout: 50000, }); // 添加请求拦截器 instance.interceptors.request.use( function (config) { // 在发送请求之前做些什么 return config; }, function (error) { // 对请求错误做些什么 return Promise.reject(error); } ); // 添加响应拦截器 instance.interceptors.response.use( function (response) { return response; }, function (error) { // 对响应错误做点什么 return Promise.reject(error); } ); export default instance;
03-项目起步-统一VSCode配置和格式化配置
新建.editorconfig
文件
用于跨不同的编辑器和 IDE 为多个开发人员维护一致的编码风格的配置文件
# editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
editorconfig 属性
-
charset
编码格式- 值为
latin1
、utf-8
、utf-8-bom
、utf-16be
和utf-16le
- 值为
-
root
- 顶级配置文件
-
indent_style
缩进风格- 空格
space
- Tab键
tab
- 空格
-
indent_size
缩进大小- 2 or 4
-
end_of_line
换行符类型- 换行
lf
- 回车
cr
- 回车换行
crlf
Dos和Windows采用回车+换行(cr+lf)来表示换行
UNIX和Linux采用换行符(lf)来表示换行
MAC OS采用回车符(cr)来表示换行 - 换行
-
insert_final_newline
true
—> 以换行符结尾
-
trim_trailing_whitespac
- 删除换行符之前的任何空白字符
true
- 删除换行符之前的任何空白字符
新建 .gitattributes
文件
用于定义每种文件的属性,方便 git 帮我们统一管理
* text eol=lf
*.txt text eol=lf
* text eol=lf
- 对git任何文件,进行行尾规范化 ,使用
lf
换行
*.txt text eol=lf
- 对于
.txt
文件,标记为文本文档,并进行行尾规范化 ,检出工作目录时,行尾保持为lf
.gitignore
文件
取消忽略 .vscode 文件
- .vscode/*
.prettierrc
文件
统一团队代码格式,同时在vscode — setting.json注释掉自己的格式(可留着字体大小
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"printWidth": 80
}
.vscode/extensions.json
推荐下载的 vscode 插件
{
"recommendations": [
"vue.volar",
"vue.vscode-typescript-vue-plugin",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"usernamehw.errorlens",
"editorconfig.editorconfig"
]
}
.vscode/settings.json
文件
{
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"eslint.enable": true,
"eslint.run": "onType",
"eslint.options": {
"extensions": [
".js",
".ts",
".vue",
".jsx",
".tsx",
]
},
// 操作时作为单词分隔符的字符
"editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?",
// 一个制表符等于的空格数
"editor.tabSize": 2,
// 保存时格式化
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": true,
"source.fixAll.eslint": true
},
// 文件行尾符号
"files.eol": "\n",
// 是否以紧凑形式展示文件夹
"explorer.compactFolders": false
}
04-项目起步-样式处理-less和mixin
安装 less npm i less -S
src/assets/styles/mixins.less
// 鼠标经过上移阴影动画
.hoverShadow () {
transition: all 0.5s;
&:hover {
transform: translate3d(0, -3px, 0);
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.2);
}
}
src/assets/styles/variables.less
// 主题
@xtxColor: #27ba9b;
// 辅助
@helpColor: #e26237;
// 成功
@sucColor: #1dc779;
// 警告
@warnColor: #ffb302;
// 价格
@priceColor: #cf4444;
src/App.vue
<template>
<h1>Hello vue3 + ts👍</h1>
</template>
<style lang="less">
// 导入后才能使用
@import './assets/styles/variables.less';
@import './assets/styles/mixins.less';
h1 {
color: @xtxColor;
.hoverShadow();
}
</style>
05-项目起步-vite配置自动导入less
变量是有作用域的,只是在单个文件引入,其他文件不可用(如果只是样式的话不需要这个步骤)
vite.config.ts
// defineConfig 节点
// css 配置
css: {
// https://cn.vitejs.dev/config/shared-options.html#css-preprocessoroptions
// 预处理器选项
preprocessorOptions: {
// less
less: {
// 自动添加代码
additionalData: `
@import "@/assets/styles/variables.less";
@import "@/assets/styles/mixins.less";
`,
},
},
},
src/App.vue
- @import './assets/styles/variables.less';
- @import './assets/styles/mixins.less';
06-项目起步-样式重置和公共样式
安装 npm i normalize.css -S
src/main.ts
// 全局导入 normalize.css 让所有标签在不同浏览器风格统一 (PS:如果用组件库,内部集成了就不用额外安装)
import 'normalize.css'
// 全局导入 公共的样式 如:版心类名
import '@/assets/styles/common.less';
src/assets/styles/common.less
@import url('./variables.less');
// 按照网站自己的需求,提供公用的样式,例如:
* {
box-sizing: border-box;
}
html {
height: 100%;
font-size: 14px;
}
body {
height: 100%;
color: #333;
min-width: 1240px;
font: 1em/1.4 'Microsoft Yahei', 'PingFang SC', 'Avenir', 'Segoe UI',
'Hiragino Sans GB', 'STHeiti', 'Microsoft Sans Serif', 'WenQuanYi Micro Hei',
sans-serif;
}
ul,
h1,
h3,
h4,
p,
dl,
dd {
padding: 0;
margin: 0;
}
a {
text-decoration: none;
color: #333;
outline: none;
}
i {
font-style: normal;
}
input[type='text'],
input[type='search'],
input[type='password'],
input[type='checkbox'] {
padding: 0;
outline: none;
border: none;
-webkit-appearance: none;
&::placeholder {
color: #ccc;
}
}
img {
max-width: 100%;
max-height: 100%;
vertical-align: middle;
// background: #ebebeb;
}
ul {
list-style: none;
}
#app {
background-color: #f5f5f5;
}
.container {
width: 1240px;
margin: 0 auto;
position: relative;
}
// 一行省略
.ellipsis {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
// 二行省略
.ellipsis-2 {
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.fl {
float: left;
}
.fr {
float: right;
}
.clearfix:after {
content: '.';
display: block;
visibility: hidden;
height: 0;
line-height: 0;
clear: both;
}
// 闪动画
.shan {
&::after {
content: '';
position: absolute;
animation: shan 1.5s ease 0s infinite;
top: 0;
width: 30%;
height: 100%;
background: linear-gradient(
to left,
rgba(255, 255, 255, 0) 0,
rgba(255, 255, 255, 0.3) 50%,
rgba(255, 255, 255, 0) 100%
);
transform: skewX(-45deg);
}
}
@keyframes shan {
0% {
left: -100%;
}
100% {
left: 120%;
}
}
// 离开淡出动画
.fade {
&-leave {
&-active {
position: absolute;
width: 100%;
transition: opacity 0.5s 0.2s;
z-index: 1;
}
&-to {
opacity: 0;
}
}
}
// 1. 离开,透明度 1---->0 位移 0---->30
// 2. 进入,透明度 0---->1 位移 30---->0
// 执行顺序,先离开再进入
.pop {
&-leave {
&-from {
opacity: 1;
transform: none;
}
&-active {
transition: all 0.5s;
}
&-to {
opacity: 0;
transform: translateX(20px);
}
}
&-enter {
&-from {
opacity: 0;
transform: translateX(20px);
}
&-active {
transition: all 0.5s;
}
&-to {
opacity: 1;
transform: none;
}
}
}
// 表单
.xtx-form {
padding: 50px 0;
&-item {
display: flex;
align-items: center;
width: 700px;
margin: 0 auto;
padding-bottom: 25px;
.label {
width: 180px;
padding-right: 10px;
text-align: right;
color: #999;
~ .field {
margin-left: 0;
}
}
.field {
width: 320px;
height: 50px;
position: relative;
margin-left: 190px;
.icon {
position: absolute;
left: 0;
top: 0;
width: 40px;
height: 50px;
text-align: center;
line-height: 50px;
color: #999;
~ .input {
padding-left: 40px;
}
}
.input {
border: 1px solid #e4e4e4;
width: 320px;
height: 50px;
line-height: 50px;
padding: 0 10px;
&.err {
border-color: @priceColor;
}
&:focus,
&:active {
border-color: @xtxColor;
}
}
}
.error {
width: 180px;
padding-left: 10px;
color: @priceColor;
}
}
.submit {
width: 320px;
height: 50px;
border-radius: 4px;
background: @xtxColor;
height: 50px;
line-height: 50px;
text-align: center;
font-size: 16px;
color: #fff;
display: block;
margin: 0 auto;
}
}