🌞写在前面
最近朋友面试的时候被问了这个问题,发现这个问题虽然考察的专业知识虽然不是很深奥,但是却是考察面试者的知识面广度,以及是否有过从0参加项目开发的经验,笔者结合日常的一些开发经验及网上的总结,在文末做了一个简单参考回答,不足的地方希望大家在评论区多多补充。
积少成多,对技术做加法。
🌍基础配置
安装Node.js和npm:确保开发环境中安装了Node.js和npm。
安装Vue CLI :Vue CLI是Vue.js官方的脚手架工具,它可以帮助你初始化Vue项目并提供开发和构建工具。 Vue3现在官方推荐使用create-vue
来创建基于Vite
的新项目,都是基础脚手架而已。
🍕目录架构
目前大部分公司都是采用vue-cli的脚手架来进行开发,会生成默认的目录,所以除了默认的目录之外,需要封装一些业务或者功能类的目录
一个完整的vue目录应该存在以下的分级
js
my-vue-project/
├── public/ # 静态资源,不会被webpack处理
├── src/ # 源代码
│ ├── assets/ # 静态资源文件,如图片、字体
│ ├── components/ # Vue组件
│ ├── views/ # 页面级组件
│ ├── router/ # 路由配置
│ ├── store/ # 状态管理
│ ├── services/ # 服务层,包括API请求
│ ├── utils/ # 工具函数
│ ├── App.vue # 根组件
│ └── main.js # 入口文件
├── tests/ # 测试相关
├── .eslintrc.js # ESLint配置
├── .prettierrc.js # Prettier配置
├── package.json # 项目依赖和脚本配置
├── README.md # 项目文档
- components(组件目录):目录可以分为单独页面组件和公共组件
js
src/
├── components/
│ ├── Button.vue # 自定义按钮组件
│ ├── FormInput.vue # 自定义表单输入组件
│ ├── Navbar.vue # 自定义导航栏组件
│ ├── Card.vue # 自定义卡片组件
│ ├── Modal.vue # 自定义模态框组件
- utils(工具类目录):如日期、格式化限制、通用业务逻辑等封装;
js
src/
├── utils/
│ ├── api.js # 封装API请求的工具
│ ├── helpers.js # 通用辅助函数
│ ├── constants.js # 常量定义
│ ├── validators.js # 输入验证函数
│ ├── format.js # 数据格式化函数
- stores(状态管理目录):通常用于存储状态管理相关的文件,工具通常有vuex,pinia
js
src/
├── store/
│ ├── index.js # 主Vuex store文件
│ ├── actions.js # 包含Vuex actions
│ ├── mutations.js # 包含Vuex mutations
│ ├── getters.js # 包含Vuex getters
│ ├── modules/ # 模块化Vuex状态
│ │ ├── module1.js # 第一个模块的状态、actions、mutations、getters
│ │ ├── module2.js # 第二个模块的状态、actions、mutations、getters
- layout(页面分层,头部侧边栏底部等):通常用于组织和存放应用程序的布局组件和页面分层相关的内容
js
src/
├── layout/
│ ├── Header.vue # 头部布局组件
│ ├── Sidebar.vue # 侧边栏布局组件
│ ├── Footer.vue # 底部布局组件
- router(路由目录封装):通常用于封装和组织Vue.js应用程序的路由配置
js
src/
├── router/
│ ├── index.js # 主路由配置文件
│ ├── routes/ # 路由模块
│ │ ├── home.js # 主页路由配置
│ │ ├── products.js # 产品页路由配置
🎉Eslint代码规范
俗话说磨刀不误砍柴工
,对于eslint,一开始我也是拒绝的,毕竟一开始不会配置,对于很多的代码一开启eslint就会进入无限的报错,但是准确进行配置后会让我们的开发更加优雅,也避免很多报错的发生,建议配置,文末有网友提供的一个eslint配置,仅供参考。
比如我司使用的eslint配置,一些比较细微的代码错误都能识别出来
1.多余逗号
2.无效引用
3.空格缩进
📚路由守卫配置
路由列表的配置就不用多说,基本上vue-router的路由列表很简单就能配置出来,但是如果架构的是一个需要权限的系统,那么路由的权限就显得很重要了,下面是一个比较简单的例子,也是项目中常见的一个路由权限配置的封装,主要是通过路由守卫来进行拦截
路由守卫又分为前置守卫和后置守卫
前置守卫:在用户进入某个路由之前执行,通常用于检查用户权限。
scss
javascriptCopy code
router.beforeEach((to, from, next) => {
// 检查用户是否有访问 to 路由的权限
if (userHasPermission(to)) {
next(); // 允许访问
} else {
next('/login'); // 重定向到登录页面
}
});
后置守卫:在用户离开某个路由后执行。
javascript
javascriptCopy code
router.afterEach((to, from) => {
// 记录用户访问记录,发送统计信息等
});
💪常用的库
vue3最常用的库应该是Vueuse,VueUse 是一个 Vue 3 Composition API 的函数库,用于提供各种实用的自定义函数,当然还有其他很常用的库,欢迎大家评论区补充
js
// 导入 useLocalStorage 函数
import { useLocalStorage } from '@vueuse/core';
export default {
setup() {
// 使用 useLocalStorage 函数
const [data, setData] = useLocalStorage('myKey', 'defaultValue');
return {
data,
setData,
};
},
};
🌸Utils封装
可以封装一些常用的工具函数或utils,以提高开发效率并保持代码的可维护性。以下是一些常见的utils封装示如:时间转换、localstorage、sessionstorage、cookie等设置获取、千分位设置、限制校验等
日期时间处理工具:封装日期时间处理函数,如格式化日期、计算时间差等:
js
// utils/dateUtils.js
export function formatDate(date, format) {
const options = { year: 'numeric', month: 'long', day: 'numeric' };
return date.toLocaleDateString(undefined, options);
}
export function calculateTimeDifference(start, end) {
const startTime = new Date(start);
const endTime = new Date(end);
const timeDifference = endTime - startTime; // 差值单位为毫秒
return timeDifference; // 返回毫秒数
}
字符串处理工具:封装字符串处理函数,如首字母大写、截断文本等:
js
// utils/stringUtils.js
export function capitalize(text) {
return text.charAt(0).toUpperCase() + text.slice(1);
}
export function truncateText(text, maxLength) {
if (text.length > maxLength) {
return text.slice(0, maxLength) + '...';
}
return text;
}
😃封装API请求
封装axios,统一api调用风格,简化每个页面各个请求的调用,
比如请求和响应的拦截器,请求拦截加入token、判断token时效等
请求头的处理,根据不同的请求方式可以封装不同的格式,比如基础的post、get的请求格式还有下载请求的header配置,参数的处理,哪些参数放在地址栏,哪些参数放请求体里面,formdata的请求方式等。
响应拦截主要是对返回数据做状态判断,主要是状态码对应的路由或者提示处理方式、简化响应数据格式主要是简化出data等重要数据,节省开发代码的时间。
js
import axios from 'axios';
const API_BASE_URL = 'https://api.example.com'; // 替换为实际的API基础URL
// 创建 Axios 实例
const api = axios.create({
baseURL: API_BASE_URL,
timeout: 10000,
});
// 请求拦截器
api.interceptors.request.use(
(config) => {
// 在请求发送前可以进行一些处理,例如添加身份验证令牌
const token = getToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
📷跨域配置
跨域配置通常是针对前端向不同域的后端API请求时出现的跨域问题。这在我看来已经是一个背烂的八股了,解决跨域的答案无非是那几个,但真正用到的肯定就是proxy了。
vue中最常见的应该就是通过proxy去配置解决跨域。
js
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://xxx-server.com',
changeOrigin: true,
pathRewrite: {
'^/api': '',
},
},
},
},
};
笔者之前写过一篇有关vite项目解决跨域的文章有兴趣可以看下,webpack的配置也是大同小异,主要是学习是如何解决跨域的 vue3+vite用proxy解决跨域及proxy原理解析
🌍数据Mock
MockJS是一个日常用的比较多的随机数据生成库,它可以用于创建随机的模拟数据。可以在项目中使用它来生成各种你需要用到模拟字段,包括字符串、数字、日期、图像等,在后端没有出接口的情况下,前端的小伙伴就可以提前把接口模拟对接完成,坐着翘腿喝茶等待后端接口完成~
js
Mock.mock("/login", {
code: 200,
msg: "成功",
data: {
token: "abcdefg",
},
});
fetch("/api/data", {
method: "POST",
})
.then((response) => response.json())
.then((json) => console.log(json));
🌍国际化
当有国际化需求时,需要配置Vue支持多语言应用程序。Element UI的 i18n 提供了出色的国际化支持。配置国际化只需在Vue实例创建时添加一些设置,例如为中文和英文分别指定字典目录。不要忘记处理页面刷新时的语言缓存,以确保用户的语言选择得以保留。
js
// i18n.js
import Vue from 'vue';
import VueI18n from 'vue-i18n';
Vue.use(VueI18n);
const messages = {
en: {
welcome: 'Welcome to our app',
// 更多英文文本
},
fr: {
welcome: 'Bienvenue dans notre application',
// 更多法文文本
},
// 添加其他语言的文本
};
export default new VueI18n({
locale: 'en', // 默认语言
messages,
});
📚Vite配置
这里举一些比较简单的例子也是比较常用的配置。
自定义别名:你可以配置别名以简化模块导入路径。
arduino
// vite.config.js
export default {
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
};
CSS 预处理器 :如果你使用 CSS 预处理器(如 Sass、Less、Stylus),可以在项目中安装相应的插件,并在 vite.config.js
中配置。
js
// vite.config.js
import vue from '@vitejs/plugin-vue';
import VitePluginVue2 from 'vite-plugin-vue2';
import ViteRubyPlugin from 'vite-plugin-ruby-sass';
export default {
plugins: [vue(), VitePluginVue2(), ViteRubyPlugin()],
};
📚版本规范
现在我司对每个项目的版本控制有极其规范的流程,每次大版本更新都是一个新的版本号,比如7.3.11,如果是该版本出现新的小需求或者bug需要修改,那么每次小更新就是7.x.x_001,这样每次版本发布和后续中途出现问题定位有比较清晰的规范。该规范在分支合并也是一个比较重要的地方
🙏Eslint配置参考
js
module.exports = {
root: true,
env: {
node: true
},
extends: ["plugin:vue/strongly-recommended"],
rules: {
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
// 不加分号
"semi": [0],
// 不能有未定义的变量
"no-undef": 1,
// 不能有声明后未被使用的变量或参数
"no-unused-vars":[2, {
"vars": "local",
"args": "none"
}],
// 禁止修改const声明的变量
"no-const-assign": 2,
// 函数参数不能重复
"no-dupe-args": 2,
// 如果if语句里面有return,后面不能跟else语句
"no-else-return": 2,
// 块语句中的内容不能为空
"no-empty": 2,
// 禁止对null使用==或!=运算符
"no-eq-null": 2,
// 禁止扩展native对象
"no-extend-native": 2,
// 禁止不必要的函数绑定
"no-extra-bind": 2,
// 禁止非必要的括号
"no-extra-parens": 2,
// 禁止多余的冒号
"no-extra-semi":2,
// 禁止省略浮点数中的0 .5 3.
"no-floating-decimal": 2,
// 禁止行内备注
"no-inline-comments": 0,
// 不能有不规则的空格
"no-irregular-whitespace": 2,
// 不能用多余的空格
"no-multi-spaces": 1,
// 禁止重复声明变量
"no-redeclare": 2,
// 禁止使用javascript:void(0)
"no-script-url": 0,
// 禁止稀疏数组, [0,,2]
"no-sparse-arrays": 2,
// 禁止使用三目运算符
"no-ternary": 0,
// 一行结束后面不要有空格
"no-trailing-spaces": 1,
// 标识符不能以_开头或结尾
"no-underscore-dangle": 1,
// 是否允许非空数组里面有多余的空格
"array-bracket-spacing": [2, "never"],
// 箭头函数用小括号括起来
"arrow-parens": 0,
// =>的前/后括号
"arrow-spacing": 0,
// 块语句中使用var
"block-scoped-var": 0,
// 逗号风格,换行时在行首还是行尾
"comma-style": [2, "last"],
// 避免不必要的方括号
"dot-notation": [0, { "allowKeywords": true }],
// 必须使用全等
"eqeqeq": 2,
// 对象字面量中冒号的前后空格
"key-spacing": [0, {
"beforeColon": false,
"afterColon": true
}],
// 变量声明后是否需要空一行
"newline-after-var": 0,
// 引号类型 `` "" ''
"quotes": [1, "single"],
// 变量声明时排序
"sort-vars": 0,
// 禁止比较时使用NaN,只能用isNaN()
"use-isnan": 2,
//jsx中使用单引号
💖回答参考
- 从0创建1个项目我会做以下事情:
- 首先是基本的环境搭建,然后如果是vue2我会用vue-cli来构建项目
- vue3项目我会用vite或者create-vue创建项目, 增加store,components,utils等业务目录,并且配置好一些基本的Eslint配置保证代码整洁规范
- 在工具方面,引入主要的插件:路由插件vue-router、状态管理vuex/pinia、element等UI库、使用axios封装API请求,引入常用的库比如vueuse,封装一些项目常用的utils
- 在业务方面,配置基本的路由守卫来准备后续的路由权限控制,配置proxy解决跨域配置及一些数据的Mock
- 最后是约定发布版本的一些规范,以及规范提交代码的提交