面试题答案
一键面试组件命名
- 采用帕斯卡命名法:即每个单词首字母大写,例如
MyComponent.vue
。这样命名清晰明了,一眼就能看出是一个组件,且符合Vue官方推荐的命名风格。 - 语义化命名:组件名要准确反映其功能,如
UserList.vue
表示用于展示用户列表的组件,方便团队成员理解和维护。避免使用无意义的缩写或随意命名。 - 遵循统一前缀:如果项目中有很多自定义组件,可以统一添加一个前缀,如
app-
,组件名形如app-header.vue
。这样便于区分自定义组件和第三方组件,同时在IDE中也更易识别。
样式书写
- 使用预处理器:推荐使用
Sass
或Less
等CSS预处理器,它们支持变量、混合、嵌套等功能,可提高样式的复用性和代码的简洁性。例如:
// 定义变量
$primary-color: #1890ff;
// 混合
@mixin center {
display: flex;
justify-content: center;
align-items: center;
}
// 使用
.container {
@include center;
color: $primary-color;
}
- BEM命名规范:采用
Block__Element--Modifier
的格式命名CSS类,如button__text--disabled
。这种命名方式能清晰地表明元素之间的关系,增强样式的可维护性。 - 局部作用域:在Vue组件中,使用
scoped
属性使样式只作用于当前组件,避免全局样式污染。例如:
<template>
<div class="container">
<p class="text">内容</p>
</div>
</template>
<style scoped>
.container {
background-color: #f0f0f0;
}
.text {
color: #333;
}
</style>
文件结构
- 按照功能模块划分:将相关的组件、接口、样式等文件放在同一个文件夹下,例如项目中有用户模块,可创建
user
文件夹,里面包含UserList.vue
、UserForm.vue
、userApi.js
、user.scss
等文件。这样结构清晰,方便查找和维护。 - 公共资源文件夹:创建
common
文件夹,用于存放全局的样式、工具函数、公共组件等。例如common/utils.js
存放常用的工具函数,common/components/Loading.vue
存放全局加载组件。 - 路由和视图文件夹:将路由相关文件放在
router
文件夹,视图组件放在views
文件夹。在router/index.js
中配置路由,指向views
下的具体视图组件,如:
import Vue from 'vue';
import Router from 'vue-router';
import Home from '@/views/Home.vue';
Vue.use(Router);
export default new Router({
routes: [
{
path: '/',
name: 'home',
component: Home
}
]
});
- 按层级组织文件:如果项目结构复杂,可按照层级进一步划分文件夹。如在电商项目中,
product
模块下可再细分product-list
、product-detail
等子文件夹,分别存放列表和详情相关的文件。
代码注释
- 组件注释:在每个组件文件开头,添加注释说明组件的功能、作者、创建时间等信息。例如:
/**
* @description 用户列表组件,用于展示所有用户信息
* @author John Doe
* @date 2023-01-01
*/
export default {
name: 'UserList',
data() {
return {
users: []
};
},
methods: {
// ...
}
};
- 方法注释:对于组件中的方法,注释要说明方法的功能、参数含义和返回值。例如:
/**
* 获取用户列表数据
* @param {number} page - 页码
* @param {number} limit - 每页数量
* @returns {Promise<Array>} - 返回用户列表数据的Promise
*/
async getUserList(page, limit) {
const res = await this.$axios.get('/api/users', {
params: {
page,
limit
}
});
return res.data;
}
- 复杂逻辑注释:对于代码中复杂的逻辑部分,添加注释解释思路,方便其他开发人员理解。例如:
// 计算总价,考虑折扣和满减
let totalPrice = this.products.reduce((acc, product) => {
return acc + product.price * product.quantity;
}, 0);
if (this.discount > 0) {
totalPrice = totalPrice * (1 - this.discount);
}
if (totalPrice >= this.fullReductionThreshold) {
totalPrice = totalPrice - this.fullReductionAmount;
}
代码格式化
- 使用ESLint:配置ESLint规则,统一代码风格,如缩进、引号使用、分号等。可以根据项目需求选择标准的规则集,如
eslint-config-standard
,并在项目根目录下创建.eslintrc.js
文件进行配置。例如:
module.exports = {
env: {
browser: true,
es2021: true
},
extends: [
'plugin:vue/essential',
'standard'
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module'
},
plugins: [
'vue'
],
rules: {
// 自定义规则,例如强制使用单引号
'quotes': ['error', 'single']
}
};
- 结合Prettier:Prettier是一个代码格式化工具,与ESLint配合使用可以进一步规范代码格式。可以在项目中安装
prettier
和eslint-plugin-prettier
,并在.eslintrc.js
中配置:
module.exports = {
// ...
plugins: [
'vue',
'prettier'
],
rules: {
// ...
'prettier/prettier': 'error'
}
};
同时在项目根目录下创建 .prettierrc.js
文件,配置Prettier的规则,如:
module.exports = {
semi: true,
singleQuote: true,
trailingComma: 'es5'
};
- IDE集成:在开发工具(如VS Code)中安装相应的ESLint和Prettier插件,配置自动格式化保存,确保每次保存文件时代码都符合规范。
接口请求
- 封装API请求:创建一个专门的文件夹(如
api
),将所有接口请求函数封装在不同的文件中。例如userApi.js
:
import request from '@/utils/request';
export const getUserInfo = () => {
return request.get('/api/user/info');
};
export const updateUser = (data) => {
return request.post('/api/user/update', data);
};
- 统一请求配置:在
request.js
中统一配置请求的基础URL、请求拦截、响应拦截等。例如:
import axios from 'axios';
const service = axios.create({
baseURL: '/api',
timeout: 5000
});
service.interceptors.request.use(config => {
// 添加token等请求头
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
}, error => {
return Promise.reject(error);
});
service.interceptors.response.use(response => {
if (response.data.code!== 0) {
// 处理错误响应,如提示用户
console.error('请求错误', response.data.message);
return Promise.reject(new Error(response.data.message));
}
return response.data;
}, error => {
console.error('网络错误', error);
return Promise.reject(error);
});
export default service;
- 使用Promise或async/await:接口请求统一使用Promise或async/await处理异步操作,使代码更易读。例如:
async getUserData() {
try {
const userInfo = await getUserInfo();
const userOrders = await getOrderList(userInfo.id);
console.log('用户信息', userInfo);
console.log('用户订单', userOrders);
} catch (error) {
console.error('获取数据失败', error);
}
}