likes
comments
collection
share

👍从0到1构架一个vue项目,如何组织目录结构、需要哪些步骤,文末附参考答案

作者站长头像
站长
· 阅读数 5

🌞写在前面

最近朋友面试的时候被问了这个问题,发现这个问题虽然考察的专业知识虽然不是很深奥,但是却是考察面试者的知识面广度,以及是否有过从0参加项目开发的经验,笔者结合日常的一些开发经验及网上的总结,在文末做了一个简单参考回答,不足的地方希望大家在评论区多多补充。

积少成多,对技术做加法。

🌍基础配置

安装Node.js和npm:确保开发环境中安装了Node.js和npm。

安装Vue CLI:Vue CLI是Vue.js官方的脚手架工具,它可以帮助你初始化Vue项目并提供开发和构建工具。 Vue3现在官方推荐使用create-vue 来创建基于Vite的新项目,都是基础脚手架而已。

🍕目录架构

目前大部分公司都是采用vue-cli的脚手架来进行开发,会生成默认的目录,所以除了默认的目录之外,需要封装一些业务或者功能类的目录

一个完整的vue目录应该存在以下的分级

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(组件目录):目录可以分为单独页面组件和公共组件
src/
├── components/
│   ├── Button.vue       # 自定义按钮组件
│   ├── FormInput.vue    # 自定义表单输入组件
│   ├── Navbar.vue       # 自定义导航栏组件
│   ├── Card.vue         # 自定义卡片组件
│   ├── Modal.vue        # 自定义模态框组件

  • utils(工具类目录):如日期、格式化限制、通用业务逻辑等封装;
src/
├── utils/
│   ├── api.js         # 封装API请求的工具
│   ├── helpers.js     # 通用辅助函数
│   ├── constants.js   # 常量定义
│   ├── validators.js  # 输入验证函数
│   ├── format.js      # 数据格式化函数

  • stores(状态管理目录):通常用于存储状态管理相关的文件,工具通常有vuex,pinia
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(页面分层,头部侧边栏底部等):通常用于组织和存放应用程序的布局组件和页面分层相关的内容
src/
├── layout/
│   ├── Header.vue       # 头部布局组件
│   ├── Sidebar.vue      # 侧边栏布局组件
│   ├── Footer.vue       # 底部布局组件

  • router(路由目录封装):通常用于封装和组织Vue.js应用程序的路由配置
src/
├── router/
│   ├── index.js         # 主路由配置文件
│   ├── routes/          # 路由模块
│   │   ├── home.js      # 主页路由配置
│   │   ├── products.js  # 产品页路由配置

🎉Eslint代码规范

俗话说磨刀不误砍柴工,对于eslint,一开始我也是拒绝的,毕竟一开始不会配置,对于很多的代码一开启eslint就会进入无限的报错,但是准确进行配置后会让我们的开发更加优雅,也避免很多报错的发生,建议配置,文末有网友提供的一个eslint配置,仅供参考。

比如我司使用的eslint配置,一些比较细微的代码错误都能识别出来

1.多余逗号 👍从0到1构架一个vue项目,如何组织目录结构、需要哪些步骤,文末附参考答案

2.无效引用

👍从0到1构架一个vue项目,如何组织目录结构、需要哪些步骤,文末附参考答案

3.空格缩进

👍从0到1构架一个vue项目,如何组织目录结构、需要哪些步骤,文末附参考答案

📚路由守卫配置

路由列表的配置就不用多说,基本上vue-router的路由列表很简单就能配置出来,但是如果架构的是一个需要权限的系统,那么路由的权限就显得很重要了,下面是一个比较简单的例子,也是项目中常见的一个路由权限配置的封装,主要是通过路由守卫来进行拦截

路由守卫又分为前置守卫和后置守卫

前置守卫:在用户进入某个路由之前执行,通常用于检查用户权限。

javascriptCopy code
router.beforeEach((to, from, next) => {
  // 检查用户是否有访问 to 路由的权限
  if (userHasPermission(to)) {
    next(); // 允许访问
  } else {
    next('/login'); // 重定向到登录页面
  }
});

后置守卫:在用户离开某个路由后执行。

javascriptCopy code
router.afterEach((to, from) => {
  // 记录用户访问记录,发送统计信息等
});

💪常用的库

vue3最常用的库应该是Vueuse,VueUse 是一个 Vue 3 Composition API 的函数库,用于提供各种实用的自定义函数,当然还有其他很常用的库,欢迎大家评论区补充

// 导入 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等设置获取、千分位设置、限制校验等

日期时间处理工具:封装日期时间处理函数,如格式化日期、计算时间差等:

// 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; // 返回毫秒数
}

字符串处理工具:封装字符串处理函数,如首字母大写、截断文本等:

// 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等重要数据,节省开发代码的时间。

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去配置解决跨域。

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://xxx-server.com',
        changeOrigin: true,
        pathRewrite: {
          '^/api': '',
        },
      },
    },
  },
};

🌍数据Mock

MockJS是一个日常用的比较多的随机数据生成库,它可以用于创建随机的模拟数据。可以在项目中使用它来生成各种你需要用到模拟字段,包括字符串、数字、日期、图像等,在后端没有出接口的情况下,前端的小伙伴就可以提前把接口模拟对接完成,坐着翘腿喝茶等待后端接口完成~

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实例创建时添加一些设置,例如为中文和英文分别指定字典目录。不要忘记处理页面刷新时的语言缓存,以确保用户的语言选择得以保留。

// 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配置

这里举一些比较简单的例子也是比较常用的配置。

自定义别名:你可以配置别名以简化模块导入路径。

// vite.config.js
export default {
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
};

CSS 预处理器:如果你使用 CSS 预处理器(如 Sass、Less、Stylus),可以在项目中安装相应的插件,并在 vite.config.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配置参考

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中使用单引号
  

💖回答参考

  1. 从0创建1个项目我会做以下事情:
  2. 首先是基本的环境搭建,然后如果是vue2我会用vue-cli来构建项目
  3. vue3项目我会用vite或者create-vue创建项目, 增加store,components,utils等业务目录,并且配置好一些基本的Eslint配置保证代码整洁规范
  4. 在工具方面,引入主要的插件:路由插件vue-router、状态管理vuex/pinia、element等UI库、使用axios封装API请求,引入常用的库比如vueuse,封装一些项目常用的utils
  5. 在业务方面,配置基本的路由守卫来准备后续的路由权限控制,配置proxy解决跨域配置及一些数据的Mock
  6. 最后是约定发布版本的一些规范,以及规范提交代码的提交

🙏 感谢您花时间阅读这篇文章!如果觉得有趣或有收获,请关注我的更新,给个喜欢和分享。您的支持是我写作的最大动力!

往期好文推荐