Vue2项目搭建(Layout布局、全局样式、VueX、Vue Router、axios封装)

前言

主要是记录 项目的搭建 大家也可以一起交流学习

后续还准备Nuxt、Vue3、Uniapp、Qiankun、CMS的搭建

不积跬步无以至千里

初始化

node版本为18.20.6

js 复制代码
npm install -g @vue/cli

使用Vue Cli安装Vue2

js 复制代码
vue create your_project_name

推荐 www.npmjs.com/package/tre...

可以分析项目结构

进入项目先yarn安装下依赖接下来 yarn serve启动项目

项目启动成功 搭建 Layout 布局 在src文件夹下新建layout文件夹

js 复制代码
<template>
  <div>
    <!-- 头部 -->
    <header>header</header>

    <!-- 路由出口 -->
    <!-- https://v2.cn.vuejs.org/v2/api/#transition -->
    <transition name="fade" mode="out-in" appear>
      <router-view />
    </transition>

    <!-- 底部 -->
    <footer>footer</footer>
  </div>
</template>

<script>
export default {
  name: 'DefaultLayout',
}
</script>

<style scoped>
.fade-enter {
  opacity: 0;
}
/* https://v2.cn.vuejs.org/v2/guide/transitions.html */
.fade-enter-active {
  transition: opacity 1s;
}

header,
footer {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px dotted #000;
  box-sizing: border-box;
}

header {
  height: 90px;
}

footer {
  height: 60px;
}
</style>

在App.vue中使用

编写第一个路由页面

Layout布局已经生效 但是发现四周有边距 其实是浏览器的默认样式没有清除

先做个准备工作 配置 alias 别名

引入 reset.css 在 App.vue 中使用

最后效果如下

预编译器less的使用

在实际项目开发中,不会使用纯CSS去编写样式,通常使用预编译器以及对应loader提升开发效率

js 复制代码
 npm install -g less   
 npm install  less-loader -D

再进一步 维护全局的通用样式 安装下述依赖

js 复制代码
npm install style-resources-loader vue-cli-plugin-style-resources-loader --save-dev

env环境变量的使用

在实际开发中,通常有(本地、模拟、测试、生产)多个环境,不同环境中提供不同变量值

VueX使用

推荐模块化 不同板块 放不同的

vuex.vuejs.org/zh/

axios的封装

包含请求重试配置

js 复制代码
import axios from "axios";

// 创建axios示例
const request = axios.create({
  baseURL:
    process.env.NODE_ENV === "development"
      ? "http://localhost:8080"
      : process.env.VUE_APP_API_BASE_URL,
  timeout: 5000,
  withCredentials: true,
});

// 请求拦截器
request.interceptors.request.use(
  (config) => {
    const token =
      typeof window !== "undefined" ? localStorage.getItem("token") : null;
    if (token) {
      config.headers["Authorization"] = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    // 处理请求错误
    console.error("请求错误:", error);
    return Promise.reject(error);
  }
);

// 响应拦截器
request.interceptors.response.use(
  (response) => {
    const { data, status } = response;
    // 这里可以根据自己的后端接口规范自定义
    if (status !== 200) {
      console.error("接口请求失败:", data);

      // 处理特定错误码
      if (response.status === 401) {
        // 401: 未授权
        // 可以在这里处理登出逻辑
        console.error("未授权,请重新登录");
      }
      return Promise.reject(new Error(data.message || "请求失败"));
    }

    // 统一包装返回数据格式
    if (data.data !== undefined) {
      // 如果后端已经包装了data字段,直接返回
      return data;
    } else {
      // 如果后端没有包装data字段,手动包装
      return {
        code: 200,
        data,
        message: "success",
        success: true,
      };
    }
  },
  (error) => {
    // 如果是取消请求的错误,直接返回
    if (axios.isCancel(error)) {
      console.log("请求被取消:", error.message);
      return Promise.reject(error);
    }

    console.error("响应错误:", error);
    let message = "请求出错了,请稍后再试";

    // 处理请求重试
    const config = error.config;
    if (config && config.retry && config.retry > 0) {
      config.retry--;
      const retryDelay = config.retryDelay || 1000;

      console.log(
        `请求失败,${retryDelay}ms后重试,剩余重试次数:${config.retry}`
      );

      // 创建新的Promise用于延迟重试
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve(axios(config));
        }, retryDelay);
      });
    }

    if (error.response) {
      // 请求成功发出且服务器也响应了状态码,但状态代码超出了2xx的范围
      switch (error.response.status) {
        case 400:
          message = "请求错误(400)";
          break;
        case 401:
          message = "未授权,请重新登录(401)";
          // 可以在这里处理登出逻辑
          break;
        case 403:
          message = "拒绝访问(403)";
          break;
        case 404:
          message = "请求的资源不存在(404)";
          break;
        case 500:
          message = "服务器错误(500)";
          break;
        default:
          message = `连接出错(${error.response.status})!`;
      }
    } else if (error.request) {
      // 请求已经成功发起,但没有收到响应
      message = "网络异常,请检查您的网络连接!";
    } else {
      // 发送请求时出了点问题
      message = error.message;
    }

    // 可以在这里集成全局的错误提示
    console.error(message);

    return Promise.reject(error);
  }
);

// --------- 通用 API 方法 ---------
export default {
  // GET 请求:params -> query string
  get(url, params = {}, options = {}) {
    return request.get(url, {
      params,
      retry: options.retry || 0,
      retryDelay: options.retryDelay,
      headers: {
        ...options.headers,
      },
    });
  },

  // POST 请求:data -> body,支持 JSON、FormData 等
  post(url, data = {}, options = {}) {
    return request.post(url, data, {
      retry: options.retry || 0,
      retryDelay: options.retryDelay,
      headers: {
        "Content-Type": options.contentType || "application/json",
        ...options.headers,
      },
    });
  },

  // DELETE 请求
  delete(url, options = {}) {
    return request.delete(url, {
      retry: options.retry || 0,
      retryDelay: options.retryDelay,
      headers: {
        "Content-Type": options.contentType || "application/json",
        ...options.headers,
      },
    });
  },
};

项目目录

js 复制代码
📂 Directory Tree:
├── .browserslistrc
├── .env
├── .env.development
├── .env.production
├── .env.sml
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── babel.config.js
├── jsconfig.json
├── package-lock.json
├── package.json
├── public
│   ├── favicon.ico
│   └── index.html
├── README.md
├── src
│   ├── App.vue
│   ├── assets
│   │   ├── css
│   │   │   ├── common.less // 全局样式
│   │   │   └── reset.css 
│   │   └── logo.png
│   ├── components
│   ├── constant 
│   │   └── index.js // 常量文件
│   ├── layout
│   │   └── default.vue
│   ├── main.js
│   ├── router
│   │   └── index.js
│   ├── server
│   │   └── index.js
│   ├── service
│   │   └── request.js
│   ├── store
│   │   ├── index.js
│   │   └── modules
│   │       ├── home.js
│   │       └── my.js
│   ├── utils
│   │   └── index.js //工具类函数
│   └── views
│       └── home
│           └── home.vue
├── vue.config.js
└── yarn.lock

以上是一个vue2项目的基础架构,大家可以给出建议,多多向大佬们学习

TODO 国际化

相关推荐
拾光拾趣录43 分钟前
H5适配9大高频题连环炸!第3问90%人翻车?
前端·面试
拾光拾趣录1 小时前
给Electron-Claude应用构建全面的数据统计体系 - 从0到1的实践总结
前端·electron
拾光拾趣录2 小时前
8道题穿透前端原理层
前端·面试
海天胜景2 小时前
vue3 el-table 去除小数 并使用千分号
javascript·vue.js·elementui
cc蒲公英2 小时前
uniapp x swiper/image组件mode=“aspectFit“ 图片有的闪现后黑屏
java·前端·uni-app
前端小咸鱼一条2 小时前
React的介绍和特点
前端·react.js·前端框架
谢尔登2 小时前
【React】fiber 架构
前端·react.js·架构
哈哈哈哈哈哈哈哈8532 小时前
Vue3 的 setup 与 emit:深入理解 Composition API 的核心机制
前端
ytttr8733 小时前
5G毫米波射频前端设计:从GaN功放到混合信号集成方案
前端·5g·生成对抗网络