本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Vue.js是一款轻量级前端框架,以组件化开发和响应式数据绑定著称。本项目为“Vue.js高仿饿了么商城实战项目”,提供未打包源码,帮助开发者深入理解Vue.js在电商类Web应用中的实际应用。项目涵盖Vue CLI 3、Vuex状态管理、Vue Router路由控制、组件通信、API请求交互等核心技术,并结合ES6语法、CSS3动画等前端技术,打造一个高性能、结构清晰的单页应用。适合初学者与进阶开发者学习Vue项目开发全流程,提升实战能力。

1. Vue.js基础语法与实战应用

Vue.js 是一款轻量级、高效的渐进式 JavaScript 框架,广泛应用于现代前端开发。其核心特性包括响应式数据绑定、指令系统、组件化开发和生命周期管理,适合从简单页面到复杂单页应用(SPA)的开发需求。

本章将从 Vue.js 的基础语法入手,逐步深入讲解其核心机制。首先,我们会介绍 Vue 实例的创建方式,以及如何通过 data 属性实现数据驱动视图更新。接着,学习 Vue 的模板语法,包括插值表达式、条件渲染( v-if v-show )、列表渲染( v-for )以及事件绑定( v-on )。同时,我们将通过一个简单的“待办事项”应用,演示如何将这些语法应用到实际项目中,帮助读者快速上手。

2. Vue CLI 3项目初始化与配置

Vue CLI 3 是 Vue.js 官方提供的项目脚手架工具,极大地简化了 Vue 项目的初始化与构建流程。它不仅提供了开箱即用的默认配置,还支持高度定制化的项目配置方式,适用于从入门到企业级项目的各种开发需求。本章将深入讲解 Vue CLI 3 的项目初始化、核心配置文件、开发服务器与构建流程、以及插件与依赖管理等内容,帮助开发者快速搭建并优化 Vue 项目。

2.1 Vue CLI 3的安装与项目创建

在使用 Vue CLI 3 构建项目之前,必须确保开发环境已经安装了 Node.js 和包管理工具(如 npm 或 yarn)。接下来将详细介绍如何通过 Vue CLI 创建 Vue 项目,并说明其基本目录结构。

2.1.1 Node.js环境搭建与npm/yarn使用

Node.js 是 JavaScript 的运行环境,Vue CLI 3 基于 Node.js 构建,因此第一步是安装 Node.js。可以通过访问 Node.js 官网 下载并安装适合操作系统的版本。

安装完成后,验证是否安装成功:

node -v
npm -v

如果输出版本号,说明安装成功。推荐使用 yarn 作为包管理器,安装方式如下:

npm install -g yarn

验证 yarn 是否安装:

yarn -v
npm 与 yarn 的常用命令对比
功能 npm 命令 yarn 命令
初始化项目 npm init yarn init
安装所有依赖 npm install yarn install
安装指定包 npm install package-name yarn add package-name
卸载指定包 npm uninstall package-name yarn remove package-name
更新包 npm update package-name yarn upgrade package-name

2.1.2 使用Vue CLI 3初始化项目

Vue CLI 3 通过 @vue/cli 包提供服务。安装方式如下:

npm install -g @vue/cli

验证是否安装成功:

vue --version

接下来使用 Vue CLI 创建项目:

vue create my-project

在创建过程中,CLI 会提示选择预设配置或手动选择功能(如 Babel、TypeScript、Router、Vuex 等)。完成选择后,进入项目目录并启动开发服务器:

cd my-project
yarn serve

项目创建完成后,目录结构如下:

my-project/
├── node_modules/
├── public/
├── src/
│   ├── assets/
│   ├── components/
│   ├── views/
│   ├── App.vue
│   └── main.js
├── .gitignore
├── babel.config.js
├── package.json
└── README.md
  • src/ :项目源代码目录。
  • public/ :静态资源目录,不会被 Webpack 处理。
  • main.js :入口文件,用于挂载 Vue 实例。
  • App.vue :根组件。
  • package.json :项目依赖与脚本配置。
Vue CLI 3 创建项目流程图
graph TD
A[安装 Node.js 和 npm/yarn] --> B[全局安装 vue-cli]
B --> C[执行 vue create 创建项目]
C --> D{选择预设配置}
D -- 默认配置 --> E[使用默认插件配置]
D -- 自定义配置 --> F[手动选择插件]
F --> G[生成项目结构]
G --> H[进入项目目录]
H --> I[运行 yarn serve 启动开发服务器]

2.2 项目配置文件详解

Vue CLI 3 的配置方式相比早期版本更加简洁,其核心配置文件是 vue.config.js ,它允许开发者在不暴露 Webpack 配置的前提下,进行项目级别的定制。

2.2.1 vue.config.js的作用与配置项

vue.config.js 是一个可选的配置文件,如果项目根目录存在该文件,Vue CLI 会在启动时自动读取并应用其中的配置。

示例配置
module.exports = {
  // 基本路径
  publicPath: process.env.NODE_ENV === 'production' ? '/my-app/' : '/',
  // 输出文件目录
  outputDir: 'dist',
  // 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录
  assetsDir: 'assets',
  // 是否在开发环境下通过 eslint-loader 在每次保存时 lint 代码
  lintOnSave: true,
  // webpack-dev-server 配置
  devServer: {
    port: 8081,
    open: true,
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        pathRewrite: { '^/api': '' }
      }
    }
  }
};
配置项说明
配置项 作用说明
publicPath 指定部署应用包时的基本路径
outputDir 构建输出目录,默认为 dist
assetsDir 静态资源目录
lintOnSave 是否启用 ESLint 检查
devServer 开发服务器配置,包括端口、代理等

2.2.2 环境变量与模式配置

Vue CLI 支持基于不同模式加载不同的环境变量。例如:

  • .env :所有模式下加载。
  • .env.development :仅在 development 模式下加载。
  • .env.production :仅在 production 模式下加载。

环境变量需以 VUE_APP_ 开头,如:

VUE_APP_API_URL=http://api.example.com

在代码中使用:

console.log(process.env.VUE_APP_API_URL);
不同模式加载环境变量示意图
graph LR
A[启动项目] --> B{判断 NODE_ENV}
B -- development --> C[加载 .env.development]
B -- production --> D[加载 .env.production]
B -- test --> E[加载 .env.test]

2.3 开发服务器与构建流程

Vue CLI 3 提供了开箱即用的本地开发服务器和构建工具,支持热更新、代理设置等功能。

2.3.1 启动本地开发服务器

使用以下命令启动开发服务器:

yarn serve

该命令会调用 Vue CLI 内部的 Webpack Dev Server,自动监听文件变化并进行热更新。

启动开发服务器的核心逻辑
// node_modules/@vue/cli-service/commands/serve.js
const WebpackDevServer = require('webpack-dev-server');
const webpack = require('webpack');
const config = require('../webpack.config');

const compiler = webpack(config);
const server = new WebpackDevServer(compiler, {
  hot: true,
  open: true,
  historyApiFallback: true
});

server.listen(8080, 'localhost', () => {
  console.log('Starting development server...');
});

逐行解析:

  1. 引入 WebpackDevServer 和 webpack。
  2. 加载 Webpack 配置文件。
  3. 创建 Webpack 编译器。
  4. 创建开发服务器实例并配置热更新、自动打开等选项。
  5. 启动服务器并监听 8080 端口。

2.3.2 构建生产环境代码

构建生产环境代码的命令如下:

yarn build

该命令会调用 Webpack 进行打包,并输出到 dist/ 目录。

构建流程分析
// node_modules/@vue/cli-service/commands/build.js
const webpack = require('webpack');
const config = require('../webpack.config.prod');

webpack(config, (err, stats) => {
  if (err) {
    console.error(err.stack || err);
    return;
  }
  console.log(stats.toString({ colors: true }));
});

参数说明:

  • config :Webpack 的生产环境配置,包含压缩、代码分割等优化。
  • stats :构建过程的输出信息,包含打包体积、耗时等。
构建优化策略
优化项 描述
代码压缩 使用 UglifyJS 或 Terser 压缩 JS 文件
图片优化 使用 image-webpack-loader 压缩图片
代码分割 使用 Webpack 的 SplitChunksPlugin 拆分代码
Tree Shaking 剔除未使用代码,减小包体积

2.4 插件与依赖管理

Vue CLI 支持通过插件系统扩展项目功能,同时也支持添加第三方库。

2.4.1 添加和配置Vue插件

Vue CLI 提供了 vue add 命令来安装官方插件。例如添加 Vue Router:

vue add router

CLI 会自动安装 vue-router 并修改项目结构,如创建 router/index.js 并在 main.js 中引入。

插件配置示例:添加 Vuex
vue add vuex

CLI 会生成 store/index.js 并注入到 Vue 实例中:

// main.js
import store from './store'

new Vue({
  store,
  router,
  render: h => h(App)
}).$mount('#app')

2.4.2 第三方库的引入与使用

以引入 axios 为例:

yarn add axios

在组件中使用:

import axios from 'axios';

export default {
  methods: {
    async fetchData() {
      try {
        const response = await axios.get('/api/data');
        this.data = response.data;
      } catch (error) {
        console.error('API请求失败:', error);
      }
    }
  }
}
第三方库引入流程图
graph TD
A[执行 yarn add package-name] --> B[安装包到 node_modules]
B --> C[在组件中 import 引入]
C --> D[使用库提供的 API]
第三方库管理建议
类型 推荐方式
UI 框架 通过 vue add 添加
网络请求库 yarn add axios
状态管理 vue add vuex
路由 vue add router
表单验证 vee-validate 或 vuelidate

本章详细介绍了 Vue CLI 3 的项目初始化流程、核心配置文件的使用、开发服务器与构建流程的操作步骤,以及插件与依赖管理的最佳实践。通过这些内容,读者可以全面掌握 Vue CLI 3 的使用方式,并为后续实战项目打下坚实基础。

3. Vuex状态管理模块设计与实现

在现代前端开发中,随着应用规模的增长,状态管理逐渐成为项目架构设计中的关键部分。Vuex 作为 Vue.js 的官方状态管理库,提供了一套集中式的状态管理模式,适用于中大型项目的状态共享与管理。本章将围绕 Vuex 的核心概念、模块化设计思想、以及在商城类项目中的具体应用,逐步展开深入讲解,帮助开发者构建可维护、易扩展的状态管理体系。

3.1 Vuex基础概念与核心组件

3.1.1 Store、State、Getter、Mutation、Action简介

Vuex 的核心概念包括 Store、State、Getter、Mutation 和 Action。它们分别承担着不同的职责:

  • Store :是 Vuex 的核心容器,所有状态都存储在其中。
  • State :是状态的唯一数据源,组件通过映射 State 来获取数据。
  • Getter :用于从 State 中派生出一些新的状态,类似于计算属性。
  • Mutation :是更改 State 的唯一方式,必须是同步操作。
  • Action :用于处理异步操作,通过提交 Mutation 来改变 State。
示例:一个基础的 Vuex Store
// store.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    count: 0,
  },
  getters: {
    doubleCount: state => state.count * 2,
  },
  mutations: {
    increment(state) {
      state.count++;
    },
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment');
      }, 1000);
    },
  },
  modules: {}
});

代码逻辑分析:

  • state :定义了一个 count 变量,用于存储当前计数。
  • getters :定义了 doubleCount ,用于返回 count 的两倍值。
  • mutations increment 是一个同步方法,用于增加 count 的值。
  • actions incrementAsync 是一个异步方法,通过调用 commit 提交 increment Mutation 来更新状态。
  • modules :用于模块化管理状态,将在下一节详细介绍。
表格:Vuex核心组件对比
组件 类型 是否异步 职责说明
State 数据源 存储应用的共享状态
Getter 派生属性 从 State 中派生出新状态
Mutation 方法 同步修改 State
Action 方法 异步操作,提交 Mutation 修改状态

3.1.2 模块化设计的必要性

随着项目规模的扩大,将所有的状态、Mutation、Action 都放在一个 Store 中会导致代码难以维护和管理。因此,Vuex 提供了模块化机制,允许开发者将状态拆分成多个模块,每个模块拥有自己的 State、Getter、Mutation 和 Action。

示例:模块化结构
// moduleA.js
export default {
  namespaced: true,
  state: {
    user: null,
  },
  mutations: {
    setUser(state, user) {
      state.user = user;
    },
  },
  actions: {
    fetchUser({ commit }) {
      // 模拟API请求
      setTimeout(() => {
        commit('setUser', { id: 1, name: '张三' });
      }, 500);
    },
  },
  getters: {
    isLoggedIn: state => !!state.user,
  },
};
// store.js
import Vue from 'vue';
import Vuex from 'vuex';
import moduleA from './modules/moduleA';

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    user: moduleA,
  },
});

代码逻辑分析:

  • namespaced: true :开启命名空间,避免模块间命名冲突。
  • 模块注册 :在主 Store 中通过 modules 字段注册子模块。
  • 调用方式 :使用 mapActions dispatch 时需加上模块路径,如 user/fetchUser
模块化优势总结:
  • 提高代码组织性与可维护性;
  • 避免命名冲突;
  • 支持按功能拆分状态逻辑;
  • 易于测试与扩展。

3.2 商城项目中的状态管理需求

在商城类项目中,状态管理尤为关键,常见的状态包括用户信息、购物车内容、订单状态、商品详情等。这些状态需要在多个组件之间共享和同步。

3.2.1 用户状态管理

用户状态包括登录状态、用户信息、权限等。在 Vuex 中,可以通过模块来集中管理这些信息。

示例:用户状态模块
// modules/user.js
export default {
  namespaced: true,
  state: {
    userInfo: null,
    token: '',
  },
  mutations: {
    setUserInfo(state, info) {
      state.userInfo = info;
    },
    setToken(state, token) {
      state.token = token;
    },
  },
  actions: {
    login({ commit }, credentials) {
      // 模拟登录请求
      setTimeout(() => {
        const token = 'abc123';
        const userInfo = { id: 1, name: '李四' };
        commit('setToken', token);
        commit('setUserInfo', userInfo);
      }, 1000);
    },
  },
  getters: {
    isAuthenticated: state => !!state.token,
  },
};

使用方式:

<script>
import { mapActions } from 'vuex';

export default {
  methods: {
    ...mapActions('user', ['login']),
    handleLogin() {
      this.login({ username: 'admin', password: '123456' });
    },
  },
};
</script>

3.2.2 购物车状态同步

购物车状态需要在商品列表页、购物车页、结算页等多个组件中共享,因此非常适合使用 Vuex 管理。

示例:购物车模块
// modules/cart.js
export default {
  namespaced: true,
  state: {
    items: [],
  },
  mutations: {
    addToCart(state, product) {
      const existing = state.items.find(item => item.id === product.id);
      if (existing) {
        existing.quantity += 1;
      } else {
        state.items.push({ ...product, quantity: 1 });
      }
    },
    removeFromCart(state, productId) {
      state.items = state.items.filter(item => item.id !== productId);
    },
  },
  actions: {
    addProductToCart({ commit }, product) {
      commit('addToCart', product);
    },
  },
  getters: {
    cartItemCount: state => state.items.reduce((acc, item) => acc + item.quantity, 0),
    cartTotalPrice: state =>
      state.items.reduce((acc, item) => acc + item.price * item.quantity, 0),
  },
};

逻辑分析:

  • addToCart :判断是否已存在该商品,若存在则数量加1,否则新增;
  • removeFromCart :根据商品ID删除购物车中的商品;
  • cartItemCount :计算购物车总商品数量;
  • cartTotalPrice :计算购物车总价格。

3.3 Vuex模块化实现

3.3.1 分模块设计与命名空间配置

Vuex 模块化设计的核心是 命名空间(namespaced) ,它允许模块拥有独立的作用域,从而避免命名冲突。

示例:模块注册与命名空间
// store.js
import Vue from 'vue';
import Vuex from 'vuex';
import user from './modules/user';
import cart from './modules/cart';

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    user,
    cart,
  },
});

调用方式:

this.$store.dispatch('user/login', credentials);
this.$store.commit('cart/addToCart', product);

3.3.2 模块间的通信与数据共享

虽然模块是独立的,但在某些场景下仍需要跨模块访问数据。例如,用户登录后需要更新购物车中的用户信息。

实现方式:
  • 使用根 State :通过 rootState 访问其他模块的状态;
  • 触发其他模块的 Action 或 Mutation
  • 使用 mapGetters mapActions 显式引入跨模块的方法。
示例:跨模块调用
// modules/cart.js
actions: {
  checkoutCart({ rootState }) {
    const userId = rootState.user.userInfo.id;
    console.log(`用户 ${userId} 正在结算购物车`);
  },
}

调用方式:

this.$store.dispatch('cart/checkoutCart');

3.4 Vuex在Vue组件中的使用

3.4.1 mapState、mapActions等辅助函数

Vuex 提供了多个辅助函数简化组件与 Store 的交互,其中最常用的是:

  • mapState :将 Store 中的 State 映射为组件的计算属性;
  • mapActions :将 Store 中的 Action 映射为组件的方法;
  • mapMutations :将 Store 中的 Mutation 映射为组件的方法;
  • mapGetters :将 Store 中的 Getter 映射为组件的计算属性。
示例:使用 mapState 和 mapActions
<script>
import { mapState, mapActions } from 'vuex';

export default {
  computed: {
    ...mapState('user', ['userInfo']),
    ...mapGetters('cart', ['cartItemCount']),
  },
  methods: {
    ...mapActions('user', ['login']),
    ...mapActions('cart', ['addProductToCart']),
  },
};
</script>

3.4.2 在组件中调用Vuex方法

组件中可以直接通过 $store 对象调用 Store 中的方法:

<template>
  <div>
    <button @click="login">登录</button>
    <button @click="addToCart(product)">加入购物车</button>
  </div>
</template>

<script>
export default {
  methods: {
    login() {
      this.$store.dispatch('user/login', { username: 'test' });
    },
    addToCart(product) {
      this.$store.commit('cart/addToCart', product);
    },
  },
};
</script>

总结流程图(mermaid)

graph TD
    A[Vuex Store] --> B[模块化结构]
    B --> C[用户模块]
    B --> D[购物车模块]
    C --> E[State: 用户信息]
    C --> F[Mutation: 设置用户]
    C --> G[Action: 登录]
    D --> H[State: 购物车商品]
    D --> I[Mutation: 添加商品]
    D --> J[Action: 结算]
    A --> K[组件访问]
    K --> L[mapState / mapActions]
    K --> M[$store.dispatch / commit]

通过本章的详细讲解与示例演示,我们了解了 Vuex 的基础概念、模块化设计思想,以及在商城项目中的具体应用方式。掌握这些内容,将有助于开发者构建出结构清晰、易于维护的大型 Vue.js 应用程序。

4. Vue Router路由配置与懒加载

在现代前端开发中,路由管理是构建单页应用(SPA)的核心组成部分。Vue.js 通过 Vue Router 提供了强大且灵活的路由管理功能,支持动态路由、嵌套路由、懒加载、权限控制等多种高级特性。本章将围绕 Vue Router 的核心配置方法、路由守卫机制、懒加载技术以及路由元信息的应用进行深入探讨,帮助开发者构建高效、可维护的前端路由体系。

4.1 Vue Router基本配置

Vue Router 是 Vue.js 官方推荐的路由管理器,其设计目标是为 Vue 应用提供简洁而强大的路由控制能力。本节将介绍 Vue Router 的安装方式、基本配置方法,并深入解析动态路由与嵌套路由的实现原理。

4.1.1 安装与基本路由配置

Vue Router 可以通过 npm yarn 安装到项目中。以 Vue CLI 3 项目为例,安装命令如下:

npm install vue-router --save
# 或者使用 yarn
yarn add vue-router

安装完成后,需要在项目中创建路由配置文件。通常,我们会在 src/router/index.js 中定义路由表,并将其注入到 Vue 实例中。

// src/router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    },
    {
      path: '/about',
      name: 'About',
      component: About
    }
  ]
})

main.js 中引入路由实例并挂载到 Vue 应用中:

import Vue from 'vue'
import App from './App.vue'
import router from './router'

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

参数说明:

  • mode: 'history' :使用 HTML5 History API 模式,避免 URL 中出现 #
  • routes :定义路由映射表,每个对象代表一个路由。
  • path :访问路径。
  • name :路由名称,可用于命名导航。
  • component :该路径对应的组件。

逻辑分析:

  1. 通过 Vue.use(Router) 注册 Vue Router 插件。
  2. 创建 Router 实例并配置路由表。
  3. 在 Vue 实例中通过 router 属性注入路由,使组件可通过 $router $route 访问路由信息。

4.1.2 动态路由与嵌套路由

Vue Router 支持动态路由和嵌套路由,使得路由配置更加灵活,适用于不同层级和结构的页面需求。

动态路由

动态路由允许你定义参数化的路径,例如 /user/:id ,其中 :id 是动态参数。示例:

{
  path: '/user/:id',
  name: 'User',
  component: () => import('@/views/User.vue')
}

组件中可以通过 $route.params.id 获取参数值:

<template>
  <div>User ID: {{ $route.params.id }}</div>
</template>
嵌套路由

嵌套路由用于实现页面的父子结构,例如“用户中心”页面下包含“个人信息”、“订单列表”等子页面。示例如下:

{
  path: '/user',
  name: 'User',
  component: () => import('@/views/User.vue'),
  children: [
    {
      path: 'profile',
      name: 'UserProfile',
      component: () => import('@/views/UserProfile.vue')
    },
    {
      path: 'orders',
      name: 'UserOrders',
      component: () => import('@/views/UserOrders.vue')
    }
  ]
}

路由结构图:

graph TD
    A[/user] --> B[/user/profile]
    A --> C[/user/orders]

逻辑分析:

  • 父级路由 /user 对应 User.vue 组件。
  • 子路由 /user/profile /user/orders 会渲染到 User.vue 中的 <router-view> 插槽位置。
  • 通过嵌套结构,可以实现页面内容的局部更新,提升用户体验。

4.2 路由守卫与权限控制

Vue Router 提供了路由守卫功能,允许在路由跳转前后执行逻辑判断,常用于登录验证、权限校验、页面缓存等场景。

4.2.1 beforeEach 与 afterEach 的使用

Vue Router 提供了全局前置守卫 beforeEach 和全局后置钩子 afterEach ,分别用于在路由跳转前和跳转后执行操作。

beforeEach 示例:登录权限验证
router.beforeEach((to, from, next) => {
  const requiresAuth = to.matched.some(record => record.meta.requiresAuth)
  const isAuthenticated = localStorage.getItem('token')

  if (requiresAuth && !isAuthenticated) {
    next('/login')
  } else {
    next()
  }
})
afterEach 示例:页面标题更新
router.afterEach((to, from) => {
  document.title = to.meta.title || '商城系统'
})

参数说明:

  • to :即将进入的目标路由对象。
  • from :当前导航正要离开的路由。
  • next :必须调用该函数来解析导航。

4.2.2 实现登录权限验证

结合 meta 字段和 beforeEach ,我们可以实现基于角色的权限控制。例如:

{
  path: '/dashboard',
  name: 'Dashboard',
  component: () => import('@/views/Dashboard.vue'),
  meta: { requiresAuth: true, roles: ['admin', 'editor'] }
}

权限判断逻辑:

router.beforeEach((to, from, next) => {
  const userRole = localStorage.getItem('role')
  const requiredRoles = to.meta.roles

  if (requiredRoles && !requiredRoles.includes(userRole)) {
    next({ name: 'Forbidden' })
  } else {
    next()
  }
})

逻辑分析:

  • meta.roles 定义了访问该路由所需的角色。
  • 在路由跳转前,通过判断用户角色是否在允许列表中决定是否放行。
  • 若无权限,则跳转至 403 页面。

4.3 路由懒加载与性能优化

路由懒加载是一种优化前端性能的常用技术,它允许将路由对应的组件按需加载,减少首屏加载体积,提升应用启动速度。

4.3.1 使用异步组件实现懒加载

Vue Router 支持通过动态 import() 实现组件的懒加载。示例:

{
  path: '/about',
  name: 'About',
  component: () => import('@/views/About.vue')
}

该写法会在访问 /about 路由时才加载 About.vue 组件,而不是在应用初始化时一次性加载所有组件。

性能优势:

  • 减少初始加载时间。
  • 提高用户体验,尤其适用于大型项目。

4.3.2 提升首屏加载速度

除了懒加载,还可以通过以下方式进一步优化首屏加载速度:

1. Webpack 分块配置

vue.config.js 中配置 Webpack 分块策略:

module.exports = {
  configureWebpack: {
    optimization: {
      splitChunks: {
        chunks: 'all'
      }
    }
  }
}

该配置将公共依赖打包成独立的 chunk,避免重复加载。

2. 路由预加载策略

可以使用 beforeRouteEnter 钩子预加载目标路由组件:

beforeRouteEnter(to, from, next) {
  import('@/views/Detail.vue').then(() => {
    next()
  })
}

4.4 路由元信息与动态路由匹配

路由元信息(meta)和动态路由匹配是 Vue Router 中实现灵活路由控制的重要工具。

4.4.1 meta 字段的用途

meta 字段可以用于存储任意路由元信息,如页面标题、权限要求、是否缓存等。示例:

{
  path: '/profile',
  name: 'Profile',
  component: () => import('@/views/Profile.vue'),
  meta: { title: '用户中心', requiresAuth: true }
}

可以在路由守卫或组件中访问 meta 数据:

beforeRouteEnter(to, from, next) {
  console.log(to.meta.title)
  next()
}

meta字段用途表:

字段名 用途说明
title 页面标题,用于设置 document.title
requiresAuth 是否需要登录权限
keepAlive 是否缓存该组件(用于 keep-alive)
roles 需要的角色列表

4.4.2 参数匹配与重定向

Vue Router 支持通配符匹配和参数捕获,便于处理 404 页面或动态重定向。

通配符路由(404 页面)
{
  path: '*',
  name: 'NotFound',
  component: () => import('@/views/NotFound.vue')
}
参数捕获与重定向
{
  path: '/user/:id*',
  redirect: to => {
    return '/user/' + to.params.id
  }
}

逻辑分析:

  • *:id 表示捕获所有参数。
  • redirect 支持函数形式,动态决定跳转路径。

小结

本章系统讲解了 Vue Router 的核心功能与实战技巧,包括基础路由配置、动态与嵌套路由、路由守卫与权限控制、懒加载优化策略以及 meta 字段与动态匹配的应用。通过合理配置路由,开发者可以实现结构清晰、性能优良、权限可控的前端应用。下一章我们将深入探讨组件化开发与父子组件通信的实现方式。

5. 组件化开发与父子组件通信

组件化开发是现代前端开发的核心理念之一,Vue.js 作为一款组件化驱动的框架,在构建大型应用时具有显著优势。通过组件的封装、复用和通信机制,可以有效提升代码的可维护性、可测试性和可扩展性。本章将深入讲解组件化开发的核心思想,并结合 Vue.js 的父子组件通信机制、非父子通信方案、插槽机制以及自定义指令等内容,帮助开发者构建结构清晰、逻辑严谨的组件体系。

5.1 组件化开发理念与优势

组件化开发是一种将UI界面拆分为独立、可复用单元的开发模式。在 Vue.js 中,每个组件都是一个独立的视图单元,具备自己的模板、逻辑和样式,可以在多个地方重复使用。

5.1.1 组件的复用性与可维护性

组件的复用性是其最显著的优势之一。例如,一个按钮组件可以在多个页面中重复使用,而无需重复编写相同代码。这不仅提升了开发效率,也降低了维护成本。

<!-- 组件:CustomButton.vue -->
<template>
  <button class="custom-button" @click="handleClick">
    {{ label }}
  </button>
</template>

<script>
export default {
  props: {
    label: {
      type: String,
      required: true
    }
  },
  methods: {
    handleClick() {
      this.$emit('click');
    }
  }
};
</script>

<style scoped>
.custom-button {
  background-color: #42b983;
  color: white;
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
</style>

代码解析:

  • props :定义了组件接收的外部参数, label 为按钮显示的文字。
  • $emit :用于向父组件传递事件,这里当按钮被点击时会触发 click 事件。
  • scoped :表示样式只作用于当前组件,避免样式污染。

使用示例:

<!-- 在父组件中使用 -->
<template>
  <div>
    <CustomButton label="提交" @click="onSubmit" />
  </div>
</template>

<script>
import CustomButton from './components/CustomButton.vue';

export default {
  components: { CustomButton },
  methods: {
    onSubmit() {
      alert('提交按钮被点击');
    }
  }
};
</script>

优势总结:
- 复用性强 :组件可在多个页面或项目中复用。
- 维护成本低 :修改一个组件即可影响所有使用它的地方。
- 模块化清晰 :组件职责单一,逻辑清晰。

5.1.2 组件通信的基本方式

组件之间的通信是构建复杂应用的关键。Vue 提供了多种组件通信机制,包括:

  • 父组件 → 子组件 :通过 props 传递数据。
  • 子组件 → 父组件 :通过 $emit 触发事件。
  • 非父子组件通信 :可通过事件总线(Event Bus)或 Vuex 状态管理实现。
通信方式 适用场景 特点
Props 父子组件间数据传递 单向流动,安全可靠
$emit 子组件向父组件反馈信息 事件驱动,便于解耦
Event Bus 非父子组件间通信 灵活但需注意事件管理
Vuex 多组件共享状态 适用于中大型项目
Provide/Inject 跨层级组件共享数据 不推荐频繁使用
$root / $parent 访问根组件或父组件数据 依赖性强,维护困难

5.2 父子组件通信实践

Vue 中的父子组件通信主要通过 props $emit 实现,这种机制保证了组件之间的数据流清晰可控。

5.2.1 props传递数据

props 是父组件向子组件传递数据的主要方式,它是一个对象,定义了子组件可以接收的属性。

<!-- 子组件:UserInfo.vue -->
<template>
  <div>
    <p>用户名:{{ username }}</p>
    <p>邮箱:{{ email }}</p>
  </div>
</template>

<script>
export default {
  props: {
    username: {
      type: String,
      required: true
    },
    email: {
      type: String,
      default: '未提供邮箱'
    }
  }
};
</script>

说明:
- username 为必填项,若父组件未传递会报错。
- email 设置了默认值,若未传值则使用默认值。

父组件使用:

<template>
  <UserInfo username="Tom" email="tom@example.com" />
</template>

5.2.2 $emit事件触发与响应

子组件通过 $emit 向父组件发送事件,父组件监听并处理。

<!-- 子组件:Counter.vue -->
<template>
  <button @click="increment">+1</button>
</template>

<script>
export default {
  methods: {
    increment() {
      this.$emit('update', 1); // 向父组件发送 update 事件,携带参数 1
    }
  }
};
</script>

父组件监听:

<template>
  <Counter @update="handleUpdate" />
  <p>当前计数:{{ count }}</p>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    };
  },
  methods: {
    handleUpdate(value) {
      this.count += value;
    }
  }
};
</script>

流程图:

graph TD
    A[子组件] -->|emit('update')| B[父组件]
    B --> C[执行 handleUpdate]
    C --> D[更新 count 值]

5.3 非父子组件通信方案

在实际项目中,经常遇到非父子组件之间需要通信的情况。此时,可以使用事件总线(Event Bus)或 Vuex 状态管理工具。

5.3.1 Event Bus机制

Event Bus 是一个简单的 Vue 实例,作为事件的中转站。

// event-bus.js
import Vue from 'vue';
export const EventBus = new Vue();

组件A发送事件:

import { EventBus } from './event-bus.js';

export default {
  methods: {
    sendData() {
      EventBus.$emit('data-sent', { message: 'Hello from Component A' });
    }
  }
};

组件B监听事件:

import { EventBus } from './event-bus.js';

export default {
  created() {
    EventBus.$on('data-sent', (data) => {
      console.log(data.message); // 输出:Hello from Component A
    });
  }
};

注意事项:
- 需要手动清理事件监听,避免内存泄漏。
- 适用于小型项目或局部通信。

5.3.2 使用Vuex进行全局状态通信

对于中大型项目,推荐使用 Vuex 管理全局状态。

// store.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    message: ''
  },
  mutations: {
    setMessage(state, payload) {
      state.message = payload;
    }
  },
  actions: {
    updateMessage({ commit }, message) {
      commit('setMessage', message);
    }
  }
});

组件A设置状态:

this.$store.dispatch('updateMessage', 'Hello from Component A');

组件B获取状态:

<p>{{ $store.state.message }}</p>

对比分析:

方案 优点 缺点
Event Bus 简单易用,灵活 事件管理复杂,易造成混乱
Vuex 集中式状态管理,易于维护 学习成本较高,适合中大型项目

5.4 组件插槽与自定义指令

除了数据通信,Vue 还提供了插槽机制和自定义指令,以增强组件的灵活性和可定制性。

5.4.1 默认插槽与具名插槽

插槽允许我们在组件中插入任意内容,提升组件的可定制性。

<!-- Card.vue -->
<template>
  <div class="card">
    <div class="card-header">
      <slot name="header"></slot>
    </div>
    <div class="card-body">
      <slot></slot> <!-- 默认插槽 -->
    </div>
  </div>
</template>

使用示例:

<Card>
  <template #header>
    <h3>卡片标题</h3>
  </template>
  <p>这里是卡片内容。</p>
</Card>

效果:
- #header 插槽内容显示在头部。
- 默认插槽内容显示在主体区域。

5.4.2 自定义指令的编写与使用

自定义指令用于操作 DOM,适用于某些需要直接操作 DOM 的场景。

// directives.js
export default {
  install(Vue) {
    Vue.directive('highlight', {
      bind(el, binding) {
        el.style.backgroundColor = binding.value;
      }
    });
  }
};

使用示例:

<p v-highlight="'yellow'">高亮文字</p>

执行逻辑说明:
- 指令 v-highlight 接收一个值 'yellow'
- bind 钩子函数在指令绑定时执行,将背景色设置为黄色。

应用场景:
- 高亮搜索关键词
- 自动聚焦输入框
- 权限控制类 DOM 操作

本章详细介绍了 Vue.js 中组件化开发的核心理念、父子组件通信机制、非父子通信方案以及插槽和自定义指令的应用。通过这些技术手段,开发者可以构建出高度解耦、易于维护的组件系统,为构建复杂前端应用打下坚实基础。

6. ES6+ JavaScript特性应用

ECMAScript 6(简称 ES6)是 JavaScript 的一次重大升级,引入了许多现代化的语言特性,极大提升了代码的可读性、可维护性和开发效率。在 Vue.js 开发中,尤其是结合 Vue CLI 3 和 Vuex 等现代框架时,熟练掌握 ES6+ 的特性是构建高质量应用的关键。本章将深入讲解 ES6+ 中的核心语法与实际应用场景,帮助开发者写出更优雅、高效的代码。

6.1 ES6常用语法与实践

ES6 的引入,解决了 JavaScript 早期版本中的一些痛点,比如变量作用域混乱、函数表达方式单一等。我们先从两个最基础也是最常用的特性入手: let/const 箭头函数

6.1.1 let/const 与块级作用域

在 ES5 及以前版本中,JavaScript 只有函数作用域,没有块级作用域。这导致在 if for 等语句块中定义的变量会被提升到函数作用域顶部,容易引发变量污染和逻辑错误。

for (var i = 0; i < 5; i++) {
    console.log(i); // 0,1,2,3,4
}
console.log(i); // 5,i 依然在全局作用域中存在

在 ES6 中, let const 引入了块级作用域,变量只在定义它的 {} 块中有效:

for (let i = 0; i < 5; i++) {
    console.log(i); // 0,1,2,3,4
}
console.log(i); // 报错:i is not defined
  • let 用于声明可变变量;
  • const 用于声明常量,一旦赋值不可重新赋值(但对象属性可以修改)。
实际应用示例:组件状态管理

在 Vue 组件中,使用 const 声明不可变状态(如配置项),使用 let 声明可变数据(如表单输入状态):

export default {
  data() {
    const config = { pageSize: 10 };
    let formData = { name: '', email: '' };
    return {
      config,
      formData
    };
  }
}

6.1.2 箭头函数与 this 的绑定

在 ES5 中,函数内部的 this 是动态绑定的,容易导致在回调函数中丢失上下文。ES6 引入的箭头函数解决了这个问题,它不会绑定自己的 this ,而是继承外层作用域的 this

// ES5 写法
var obj = {
  name: 'Vue',
  sayHello: function() {
    setTimeout(function() {
      console.log('Hello ' + this.name); // this 指向 window
    }, 100);
  }
};

// ES6 箭头函数写法
let obj = {
  name: 'Vue',
  sayHello: function() {
    setTimeout(() => {
      console.log('Hello ' + this.name); // this 正确指向 obj
    }, 100);
  }
};
箭头函数在 Vue 中的应用

在 Vue 的生命周期钩子或方法中使用箭头函数,可以避免手动绑定 this ,提升代码简洁性:

export default {
  data() {
    return {
      count: 0
    };
  },
  mounted() {
    setInterval(() => {
      this.count++; // this 指向组件实例
    }, 1000);
  }
}

6.2 模块化与解构赋值

随着项目规模的增长,模块化开发变得尤为重要。ES6 提供了原生的模块化系统,同时解构赋值简化了对象和数组的处理。

6.2.1 import/export 模块系统

在传统开发中,模块依赖通常通过 <script> 标签加载,难以维护。ES6 的 import export 提供了更清晰的模块化机制。

示例:导出模块
// math.js
export function add(a, b) {
  return a + b;
}

export const PI = 3.14159;
示例:导入模块
// main.js
import { add, PI } from './math';

console.log(add(2, 3)); // 5
console.log(PI); // 3.14159
Vue 中的模块化实践

在 Vue 项目中,我们可以将工具函数、配置、路由、Vuex 模块等分别封装成模块并导入使用:

// store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import user from './modules/user';

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    user
  }
});

6.2.2 对象与数组的解构使用

解构赋值允许从数组或对象中提取值,并赋给变量,使代码更简洁。

对象解构示例:
const person = { name: 'Alice', age: 25 };
const { name, age } = person;
console.log(name); // Alice
console.log(age);  // 25
数组解构示例:
const colors = ['red', 'green', 'blue'];
const [first, second] = colors;
console.log(first);  // red
console.log(second); // green
解构在 Vue 中的应用

在 Vue 组件中,解构可以用于从 props data 中提取数据:

export default {
  props: ['title', 'content'],
  setup(props) {
    const { title, content } = props;
    return { title, content };
  }
}

6.3 Promise 与异步处理

异步编程是前端开发中的核心问题之一。ES6 引入的 Promise 对象为异步操作提供了统一的接口,避免了“回调地狱”。

6.3.1 Promise 对象的使用

Promise 有三种状态: pending (进行中)、 fulfilled (已成功)和 rejected (已失败)。它通过 .then() .catch() 处理成功和失败的结果。

const fetchData = new Promise((resolve, reject) => {
  setTimeout(() => {
    const data = { id: 1, name: 'Vue' };
    resolve(data); // 成功
    // reject('Error fetching data'); // 失败
  }, 1000);
});

fetchData
  .then(data => console.log(data)) // { id: 1, name: 'Vue' }
  .catch(error => console.error(error));
Promise 在 Vue 中的使用

在 Vue 项目中,常用于处理接口请求、数据初始化等异步操作:

export default {
  data() {
    return {
      products: []
    };
  },
  created() {
    fetch('/api/products')
      .then(response => response.json())
      .then(data => {
        this.products = data;
      })
      .catch(err => console.error(err));
  }
}

6.3.2 错误处理与链式调用

Promise 支持链式调用,多个异步操作可以依次执行。同时, .catch() 会捕获链中任意一个 .then() 的错误。

fetchData()
  .then(data => {
    return process(data); // 返回新 Promise
  })
  .then(processedData => {
    console.log('Processed:', processedData);
  })
  .catch(err => {
    console.error('Error:', err);
  });

6.4 async/await 与现代异步编程

ES2017(ES8)引入了 async/await ,进一步简化了异步代码的编写,使其更接近同步代码的结构,提高了可读性和可维护性。

6.4.1 async 函数与 await 关键字

async 函数返回一个 Promise,函数内部可以使用 await 等待异步操作完成。

async function getData() {
  try {
    const response = await fetch('/api/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Fetch error:', error);
  }
}

getData().then(data => console.log(data));
async/await 流程图
graph TD
    A[开始] --> B[调用 async 函数]
    B --> C[遇到 await]
    C --> D[等待 Promise 完成]
    D -->|成功| E[继续执行后续代码]
    D -->|失败| F[进入 catch 块]
    E --> G[返回结果]
    F --> H[处理错误]
    G --> I[结束]
    H --> I

6.4.2 封装异步请求逻辑

在 Vue 项目中,推荐将异步请求封装为统一的 API 服务模块,提升代码复用性和可维护性。

示例:封装 API 请求模块
// api.js
import axios from 'axios';

const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 5000
});

export default {
  async getProducts() {
    const response = await apiClient.get('/products');
    return response.data;
  },
  async login(credentials) {
    const response = await apiClient.post('/login', credentials);
    return response.data;
  }
}
在 Vue 组件中使用封装好的 API
import api from '@/api';

export default {
  data() {
    return {
      products: []
    };
  },
  async created() {
    try {
      this.products = await api.getProducts();
    } catch (error) {
      console.error('获取商品失败:', error);
    }
  }
}

小结与延伸

本章系统地讲解了 ES6+ 的核心特性及其在 Vue.js 开发中的实际应用。从 let/const 的块级作用域,到 箭头函数 this 绑定;从模块化开发的 import/export ,到异步处理的 Promise async/await ,这些特性不仅提升了代码质量,也极大增强了开发效率。

在实际开发中,合理使用这些语法特性,可以有效提升代码的可读性、可维护性以及模块化程度。随着 Vue 3 对 ES6+ 的进一步支持(如 Composition API),掌握这些现代 JavaScript 特性已成为 Vue 开发者的必备技能。

7. 前后端API接口交互(使用axios)

在现代前端开发中,与后端API进行高效、可靠的交互是构建功能完整Web应用的核心环节。在Vue.js项目中,我们通常选择 axios 作为HTTP请求库,它不仅支持Promise API,还具备拦截器、取消请求、自动JSON转换等强大功能。本章将深入探讨如何在Vue商城项目中使用 axios 进行接口调用,并通过封装和优化提升接口管理效率与健壮性。

7.1 axios基础使用与配置

7.1.1 安装与基本请求方法

首先,确保项目中已安装 axios

npm install axios
# 或者使用 yarn
yarn add axios

在Vue组件中直接引入并使用 axios 示例:

import axios from 'axios';

export default {
  methods: {
    async fetchData() {
      try {
        const response = await axios.get('https://api.example.com/products');
        console.log(response.data);
      } catch (error) {
        console.error('请求失败:', error);
      }
    }
  }
}

参数说明:
- axios.get(url, config) :发送GET请求, config 可选,用于配置 headers、params 等。
- response.data :服务器返回的数据体。

7.1.2 请求拦截器与响应拦截器

通过拦截器,我们可以统一处理请求和响应,例如添加token、处理错误等。

// 在 main.js 或单独的 axios 实例配置文件中
import axios from 'axios';

const instance = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 10000,
});

// 请求拦截器
instance.interceptors.request.use(config => {
  const token = localStorage.getItem('token');
  if (token) {
    config.headers['Authorization'] = `Bearer ${token}`;
  }
  return config;
}, error => {
  return Promise.reject(error);
});

// 响应拦截器
instance.interceptors.response.use(response => {
  return response;
}, error => {
  if (error.response && error.response.status === 401) {
    // 处理未授权
    console.log('未授权,跳转登录页');
  }
  return Promise.reject(error);
});

export default instance;

说明:
- baseURL :所有请求的基础URL。
- timeout :请求超时时间。
- 拦截器用于统一添加token、处理错误等,提高可维护性。

7.2 商城项目中的接口调用实践

7.2.1 商品数据获取与展示

以商品列表接口为例,我们使用封装后的 axios 实例获取数据,并在组件中展示。

// services/productService.js
import axios from '../utils/request';

export default {
  getProducts() {
    return axios.get('/products');
  }
}

在组件中调用:

<template>
  <div>
    <ul>
      <li v-for="product in products" :key="product.id">
        {{ product.name }} - ¥{{ product.price }}
      </li>
    </ul>
  </div>
</template>

<script>
import productService from '@/services/productService';

export default {
  data() {
    return {
      products: []
    };
  },
  created() {
    this.loadProducts();
  },
  methods: {
    async loadProducts() {
      try {
        const res = await productService.getProducts();
        this.products = res.data;
      } catch (error) {
        console.error('获取商品失败', error);
      }
    }
  }
};
</script>

流程图:

graph TD
    A[组件创建] --> B[调用 loadProducts 方法]
    B --> C{调用 productService.getProducts()}
    C --> D[发送 GET 请求到 /products]
    D --> E[后端返回商品数据]
    E --> F[更新 products 数据]
    F --> G[渲染商品列表]

7.2.2 用户登录与注册接口处理

以登录接口为例,演示POST请求与错误处理:

// services/authService.js
import axios from '../utils/request';

export default {
  login(credentials) {
    return axios.post('/auth/login', credentials);
  },
  register(userData) {
    return axios.post('/auth/register', userData);
  }
}

在登录组件中使用:

<template>
  <form @submit.prevent="submitLogin">
    <input v-model="form.username" placeholder="用户名">
    <input v-model="form.password" placeholder="密码" type="password">
    <button type="submit">登录</button>
  </form>
</template>

<script>
import authService from '@/services/authService';

export default {
  data() {
    return {
      form: {
        username: '',
        password: ''
      }
    };
  },
  methods: {
    async submitLogin() {
      try {
        const res = await authService.login(this.form);
        localStorage.setItem('token', res.data.token);
        this.$router.push('/dashboard');
      } catch (error) {
        alert('登录失败,请检查用户名或密码');
      }
    }
  }
};
</script>

参数说明:
- axios.post(url, data, config) :用于发送POST请求, data 为请求体数据。

7.3 接口错误处理与重试机制

7.3.1 网络异常与服务器错误处理

在请求拦截器中我们已初步处理了401错误。接下来我们可以对网络错误进行分类处理:

// 响应拦截器增强版
instance.interceptors.response.use(response => {
  return response;
}, error => {
  const { response } = error;

  if (response) {
    switch (response.status) {
      case 400:
        console.log('请求参数错误');
        break;
      case 401:
        console.log('身份验证失败');
        break;
      case 500:
        console.log('服务器内部错误');
        break;
      default:
        console.log('未知错误');
    }
  } else {
    console.log('网络连接失败,请检查网络');
  }

  return Promise.reject(error);
});

7.3.2 设置请求重试策略

我们可以借助 axios-retry 插件实现请求失败自动重试:

npm install axios-retry

配置示例:

import axios from 'axios';
import axiosRetry from 'axios-retry';

const instance = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 5000
});

axiosRetry(instance, {
  retries: 3, // 重试次数
  retryDelay: (retryCount) => {
    return retryCount * 1000; // 每次重试延迟1秒
  },
  shouldResetTimeout: true
});

export default instance;

说明:
- 该策略在请求失败时最多重试3次,适用于网络不稳定或临时性错误。

7.4 接口封装与统一管理

7.4.1 接口服务模块设计

为提升可维护性,我们将接口统一封装到 services 目录中:

src/
├── services/
│   ├── authService.js
│   ├── productService.js
│   ├── cartService.js
│   └── index.js

index.js 中统一导出:

import authService from './authService';
import productService from './productService';
import cartService from './cartService';

export {
  authService,
  productService,
  cartService
};

在组件中使用:

import { productService } from '@/services';

export default {
  methods: {
    async fetchProducts() {
      const res = await productService.getProducts();
      this.products = res.data;
    }
  }
};

7.4.2 请求配置与环境适配

我们可以根据环境配置不同的 baseURL ,通过 process.env 读取:

// vue.config.js
module.exports = {
  devServer: {
    proxy: 'http://localhost:3000'
  }
};
// src/utils/request.js
import axios from 'axios';

const instance = axios.create({
  baseURL: process.env.VUE_APP_API_URL || 'https://api.default.com',
  timeout: 10000
});

export default instance;

.env 文件中定义:

VUE_APP_API_URL=https://api.staging.com

说明:
- 通过环境变量实现不同环境下的接口配置,便于开发、测试、生产部署。

(本章内容完,下章将介绍Vue组件进阶开发与复用技巧)

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Vue.js是一款轻量级前端框架,以组件化开发和响应式数据绑定著称。本项目为“Vue.js高仿饿了么商城实战项目”,提供未打包源码,帮助开发者深入理解Vue.js在电商类Web应用中的实际应用。项目涵盖Vue CLI 3、Vuex状态管理、Vue Router路由控制、组件通信、API请求交互等核心技术,并结合ES6语法、CSS3动画等前端技术,打造一个高性能、结构清晰的单页应用。适合初学者与进阶开发者学习Vue项目开发全流程,提升实战能力。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

更多推荐