Vue 从入门到实战笔记

1、前端核心分析

1.1 前端开发的核心变化

在 SSM 整合阶段,我们使用的是 JSP + JSTL + 原生 JS 的开发模式,存在以下痛点:

  • DOM 操作繁琐:原生 JS 获取、修改 DOM 元素代码量大,易出错。
  • 耦合度高:HTML 代码与 Java 代码(JSP)混合,维护困难。
  • 渲染低效:每次数据变化都需要整体刷新页面,用户体验差。
  • 缺乏组件化:页面复用困难,代码冗余。

1.2 Vue 解决了什么问题?

Vue 是一套渐进式 JavaScript 框架,核心解决了前端渲染与数据交互问题:

  • 数据驱动视图:只操作数据,DOM 操作由框架自动完成(Virtual DOM)。
  • 组件化开发:将页面拆分为独立的组件(按钮、表格、弹窗等),复用性极强。
  • 轻量级:体积小(约 33KB),性能优,上手门槛低。
  • 双向数据绑定:表单数据与模型自动同步,无需手动取值。

1.3 Vue 核心思想

  • MVVM 架构:Model(数据)↔ ViewModel(监听者)↔ View(视图)。
  • 声明式编程:只需要告诉计算机 "做什么",不需要关心 "怎么做"。

2、前端发展史

2.1 前端进化史(三个阶段)

阶段 时代特征 核心技术 开发模式 代表项目
第一阶段 静态网页时代 HTML + CSS 后端渲染(JSP/PHP) 传统 SSM 项目
第二阶段 异步交互时代 jQuery + AJAX 前后端不分离(局部刷新) 很多传统管理系统
第三阶段 组件化 / 工程化时代 Vue/React/Angular 前后端分离(RESTful API) 电商、后台管理系统

2.2 为什么学 Vue?

  • 市场占有率高:国内主流招聘岗位,Vue 是必备技能。
  • 生态完善:Vue Router(路由)、Vuex/Pinia(状态管理)、Vue CLI(脚手架)。
  • 易学易用:官方文档中文完善,API 设计人性化。
  • 结合 SSM 升级:后端 SSM 做接口,前端 Vue 做渲染,是目前企业最主流的开发模式。

3、第一个 Vue 程序

3.1 环境引入(CDN 方式,入门首选)

无需安装 Node.js,直接在 HTML 中引入 CDN 链接即可使用。

创建文件:src/main/webapp/vue_demo/01.hello.html

html

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>第一个 Vue 程序</title>
    <!-- 1. 引入 Vue CDN -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <!-- 2. 挂载点 -->
    <div id="app">
        <!-- 3. 插值表达式,获取数据 -->
        <h1>{{ message }}</h1>
    </div>

    <script>
        // 4. 创建 Vue 实例
        new Vue({
            el: "#app", // 挂载点,控制 id 为 app 的区域
            data: {     // 数据模型
                message: "Hello, Vue!"
            }
        });
    </script>
</body>
</html>

3.2 运行效果

启动服务器,访问该页面,将看到 Hello, Vue! 红色大字。

3.3 核心概念

  • el: "#app":挂载边界,Vue 只管辖该元素内部的代码,外部不受影响。
  • data:存放页面需要的数据,数据变化会自动反映到视图。
  • {``{ }}:插值表达式,用于输出 data 中的数据到页面。

4、Vue 基本语法

4.1 插值表达式(Mustache 语法)

用于输出文本,支持简单的运算。

html

复制代码
<div id="app">
    <!-- 1. 基本输出 -->
    <p>{{ msg }}</p>
    <!-- 2. 简单运算 -->
    <p>{{ number + 1 }}</p>
    <!-- 3. 字符串拼接 -->
    <p>{{ 'Hello ' + name }}</p>
    <!-- 4. 三元运算 -->
    <p>{{ flag ? '成功' : '失败' }}</p>
</div>

<script>
    new Vue({
        el: "#app",
        data: {
            msg: "Vue 语法",
            number: 10,
            name: "Vue",
            flag: true
        }
    });
</script>

4.2 指令(Directives)

指令是 Vue 模板中最核心的功能,带有 v- 前缀。

常用指令示例

html

复制代码
<div id="app">
    <!-- v-text:输出文本,不会解析标签 -->
    <div v-text="msg"></div>
    <!-- v-html:输出 HTML 代码(注意 XSS 攻击) -->
    <div v-html="htmlStr"></div>
    <!-- v-show:根据真假切换 display 属性(隐藏/显示) -->
    <div v-show="isShow">显示/隐藏</div>
    <!-- v-if:根据真假销毁/重建元素(更高的切换开销) -->
    <div v-if="isShow">条件渲染</div>
</div>

5、Vue 绑定事件

5.1 v-on 指令

用于绑定 DOM 事件,如点击、鼠标移入等。简写语法@ 替代 v-on:

示例(计数器)

html

复制代码
<div id="app">
    <h3>计数:{{ count }}</h3>
    <!-- 完整写法:v-on:click -->
    <button v-on:click="increment">+1</button>
    <!-- 简写写法:@click -->
    <button @click="decrement">-1</button>
    <!-- 直接执行代码,无需调用方法 -->
    <button @click="count = 0">重置</button>
</div>

<script>
    new Vue({
        el: "#app",
        data: {
            count: 0
        },
        methods: { // 定义事件处理方法
            increment() {
                this.count++; // 修改 data 数据
            },
            decrement() {
                this.count--;
            }
        }
    });
</script>

5.2 事件修饰符

处理事件冒泡、默认行为等:

html

复制代码
<!-- 阻止事件冒泡 -->
<div @click="outerClick">
    <button @click.stop="innerClick">内部按钮</button>
</div>

<!-- 阻止默认行为(如 a 标签跳转) -->
<a href="http://www.baidu.com" @click.prevent="goTo">百度</a>

6、Vue 双向绑定

6.1 核心指令 v-model

原理:在表单元素(input/select/textarea)上创建双向数据绑定。

  • 视图变 ➡ 数据变
  • 数据变 ➡ 视图变

6.2 基础示例(表单输入)

html

复制代码
<div id="app">
    <!-- 双向绑定:input 输入框与 message 同步 -->
    <input type="text" v-model="message">
    <p>你输入的内容是:{{ message }}</p>

    <!-- 单选按钮 -->
    <input type="radio" value="男" v-model="gender">男
    <input type="radio" value="女" v-model="gender">女
    <p>选中的性别:{{ gender }}</p>
</div>

<script>
    new Vue({
        el: "#app",
        data: {
            message: "",
            gender: ""
        }
    });
</script>

6.3 v-model 修饰符

  • .trim:去除首尾空格
  • .number:转为数字类型
  • .lazy:失去焦点 / 回车时才更新(而非实时同步)

html

复制代码
<input type="text" v-model.trim="name">
<input type="text" v-model.number="age">

7、Vue 组件讲解

7.1 组件核心概念

组件(Component)是 Vue 实现页面复用的最小单元。

  • 全局组件:在所有 Vue 实例中都能使用。
  • 局部组件:仅在当前 Vue 实例挂载的区域内使用。

7.2 全局组件示例(App 标题栏)

html

复制代码
<div id="app">
    <!-- 使用组件 -->
    <my-nav></my-nav>
    <my-nav></my-nav>
</div>

<script>
    // 1. 注册全局组件
    Vue.component("MyNav", {
        // 模板:组件的 HTML 结构(必须有一个根容器)
        template: `
            <div class="nav">
                <h3>这是一个导航组件</h3>
            </div>
        `
    });

    // 2. 挂载 Vue
    new Vue({ el: "#app" });
</script>

7.3 局部组件 + 传值(Props)

组件之间的数据传递,子组件通过 props 接收父组件数据。

html

复制代码
<div id="app">
    <!-- 父组件向子组件传值:title="书籍管理" -->
    <book-item title="Java 编程思想" price="79"></book-item>
    <book-item title="Vue 实战" price="69"></book-item>
</div>

<script>
    // 1. 定义子组件
    let BookItem = {
        // props: 接收父组件传递的属性(需声明类型)
        props: {
            title: {type: String, required: true},
            price: {type: Number, default: 0}
        },
        // 模板中使用 props 数据
        template: `
            <div class="book">
                <h4>{{ title }}</h4>
                <p>价格:{{ price }} 元</p>
            </div>
        `
    };

    // 2. 挂载 Vue,并注册局部组件
    new Vue({
        el: "#app",
        components: {
            // 标签名: 组件对象
            BookItem: BookItem
        }
    });
</script>

7.4 组件生命周期(简述)

组件从创建到销毁的过程,核心钩子函数:

  • created():实例创建完成,DOM 未生成(可发起 AJAX)。
  • mounted():DOM 挂载完成(真实 DOM 操作在这里做)。
  • updated():数据更新导致 DOM 更新。

8、Axios 异步通信

8.1 核心定义

Axios 是 Promise 风格的 HTTP 客户端,是 Vue 官方推荐的异步请求库,用于前端向后端 SSM 接口发起请求、获取 JSON 数据,实现前后端分离。

8.2 核心特性

  • 支持 Promise API,链式调用更优雅
  • 自动转换 JSON 数据,无需手动解析
  • 拦截请求 / 响应,统一处理异常、添加请求头
  • 兼容浏览器和 Node.js,跨平台使用

8.3 基础使用(CDN 引入)

html

复制代码
<!-- 引入 Axios -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

<div id="app">
  <button @click="getBookList">获取书籍列表</button>
  <ul>
    <li v-for="book in books" :key="book.id">{{ book.bookName }}</li>
  </ul>
</div>

<script>
new Vue({
  el: "#app",
  data: {
    books: []
  },
  methods: {
    // 发起 GET 请求,调用 SSM 后端接口
    async getBookList() {
      try {
        const res = await axios.get("http://localhost:8080/book/all");
        this.books = res.data; // 直接获取响应数据
      } catch (err) {
        console.error("请求失败:", err);
      }
    }
  }
});
</script>

8.4 常用请求方式

javascript

复制代码
// GET 请求
axios.get("/user", { params: { id: 1 } });

// POST 请求(提交 JSON 数据)
axios.post("/user", { username: "zhangsan", password: "123456" });

// 通用请求配置
axios({
  method: "post",
  url: "/book/add",
  data: book,
  headers: { "Content-Type": "application/json" }
});

9、计算属性

9.1 核心定义

计算属性(computed)是 Vue 中基于依赖缓存的属性,用于处理复杂的逻辑计算,避免在模板中编写大量表达式,提升性能和可维护性。

9.2 基础示例(总价计算)

html

复制代码
<div id="app">
  <p>商品单价:{{ price }}</p>
  <p>购买数量:<input type="number" v-model.number="count"></p>
  <p>商品总价:{{ totalPrice }}</p>
</div>

<script>
new Vue({
  el: "#app",
  data: {
    price: 99,
    count: 1
  },
  computed: {
    // 计算属性:自动监听依赖(price/count)变化,重新计算
    totalPrice() {
      return this.price * this.count;
    }
  }
});
</script>

9.3 计算属性 vs 方法

特性 计算属性 方法
缓存 有,依赖不变时直接返回缓存值 无,每次调用都重新执行
调用 直接作为属性使用(totalPrice 需加括号调用(getTotal()
适用场景 复杂计算、需要缓存的场景 事件触发、无缓存需求的场景

9.4 计算属性的 setter(双向绑定)

javascript

复制代码
computed: {
  fullName: {
    get() {
      return `${this.firstName} ${this.lastName}`;
    },
    set(val) {
      const names = val.split(" ");
      this.firstName = names[0];
      this.lastName = names[1];
    }
  }
}

10、插槽 slot

10.1 核心定义

插槽(slot)是 Vue 实现组件内容分发的核心机制,让组件的 HTML 结构可自定义,提升组件的复用性和灵活性。

10.2 基础使用(匿名插槽)

html

复制代码
<!-- 定义组件:带插槽 -->
<template id="my-dialog">
  <div class="dialog">
    <div class="dialog-header">
      <h3>弹窗标题</h3>
    </div>
    <div class="dialog-body">
      <!-- 匿名插槽:父组件可插入任意内容 -->
      <slot></slot>
    </div>
  </div>
</template>

<div id="app">
  <!-- 使用组件:在插槽位置插入自定义内容 -->
  <my-dialog>
    <p>这是自定义的弹窗内容</p>
    <button>确认</button>
  </my-dialog>
</div>

<script>
Vue.component("MyDialog", {
  template: "#my-dialog"
});

new Vue({ el: "#app" });
</script>

10.3 具名插槽(v-slot)

给插槽命名,实现多位置内容分发,Vue 2.6+ 推荐语法:

html

复制代码
<!-- 组件模板 -->
<div class="layout">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot> <!-- 匿名插槽 -->
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

<!-- 使用组件 -->
<my-layout>
  <template v-slot:header>
    <h1>页面头部</h1>
  </template>
  <p>页面主体内容</p>
  <template v-slot:footer>
    <p>页面底部</p>
  </template>
</my-layout>

10.4 作用域插槽

让插槽内容能够访问子组件的数据,实现数据双向传递:

html

复制代码
<!-- 子组件 -->
<ul>
  <li v-for="item in list" :key="item.id">
    <slot :item="item"></slot>
  </li>
</ul>

<!-- 父组件 -->
<my-list :list="books">
  <template v-slot="slotProps">
    <span>{{ slotProps.item.bookName }}</span>
  </template>
</my-list>

11、自定义事件内容分发

11.1 核心定义

自定义事件是 Vue 实现子组件向父组件传值 的核心机制:子组件通过 $emit 触发事件,父组件通过 v-on 监听事件,实现组件间通信。

11.2 基础示例(子组件触发事件)

html

复制代码
<!-- 子组件:计数器 -->
<template id="counter">
  <div>
    <button @click="increment">+1</button>
    <p>当前计数:{{ count }}</p>
  </div>
</template>

<script>
Vue.component("Counter", {
  template: "#counter",
  data() {
    return { count: 0 };
  },
  methods: {
    increment() {
      this.count++;
      // 触发自定义事件,向父组件传递数据
      this.$emit("count-change", this.count);
    }
  }
});
</script>

<!-- 父组件:监听事件 -->
<div id="app">
  <counter @count-change="handleCountChange"></counter>
  <p>父组件收到的计数:{{ currentCount }}</p>
</div>

<script>
new Vue({
  el: "#app",
  data: { currentCount: 0 },
  methods: {
    handleCountChange(val) {
      this.currentCount = val;
    }
  }
});
</script>

11.3 事件修饰符 .native

给组件绑定原生 DOM 事件时使用,否则事件不会触发:

html

复制代码
<my-button @click.native="handleClick"></my-button>

12、第一个 vue-cli 程序

12.1 核心定义

Vue CLI 是 Vue 官方提供的项目脚手架工具,用于快速搭建标准化的 Vue 项目,集成 webpack、babel、热更新等工具,无需手动配置环境。

12.2 环境准备

  1. 安装 Node.js(版本 ≥ 14.x)
  2. 全局安装 Vue CLI:

bash

复制代码
npm install -g @vue/cli
# 验证安装
vue --version

12.3 创建项目

bash

复制代码
# 交互式创建项目
vue create ssm-vue-demo

# 选择预设(推荐默认:babel + eslint)
# 等待项目依赖安装完成

12.4 项目结构

plaintext

复制代码
ssm-vue-demo
├── public/          # 静态资源
├── src/
│   ├── assets/      # 项目资源(css、img)
│   ├── components/  # 组件
│   ├── views/       # 页面组件
│   ├── router/      # 路由配置
│   ├── App.vue      # 根组件
│   └── main.js      # 入口文件
├── package.json     # 依赖配置
└── vue.config.js    # Vue CLI 配置

12.5 启动项目

bash

复制代码
cd ssm-vue-demo
npm run serve
# 访问 http://localhost:8080 即可看到项目

13、webpack 学习使用

13.1 核心定义

webpack 是静态模块打包器,是 Vue CLI 的底层核心工具,用于将项目中的 JS、CSS、图片等资源打包成优化后的静态文件,实现模块化开发。

13.2 核心概念

  • 入口(entry):打包的起点文件
  • 出口(output):打包后的文件输出位置
  • loader:处理非 JS 文件(如 CSS、图片),转换为 webpack 可识别的模块
  • 插件(plugin):执行更广泛的任务(如打包优化、资源管理)
  • 模式(mode):开发模式(development)/ 生产模式(production)

13.3 基础配置示例(webpack.config.js)

javascript

复制代码
const path = require("path");

module.exports = {
  entry: "./src/main.js", // 入口
  output: { // 出口
    path: path.resolve(__dirname, "dist"),
    filename: "bundle.js"
  },
  module: { // loader
    rules: [
      { test: /\.css$/, use: ["style-loader", "css-loader"] },
      { test: /\.(png|jpg)$/, use: ["file-loader"] }
    ]
  },
  plugins: [ // 插件
    new HtmlWebpackPlugin({ template: "./public/index.html" })
  ],
  mode: "development"
};

13.4 核心作用

  • 模块化开发,支持 ES6+ 语法
  • 代码压缩、混淆,提升性能
  • 处理资源依赖,自动打包
  • 热更新,提升开发效率

14、vue-router 路由

14.1 核心定义

Vue Router 是 Vue 官方的路由管理器,用于实现单页应用(SPA)的页面跳转,让不同的 URL 对应不同的组件,无需刷新页面切换视图。

14.2 基础使用

  1. 安装依赖:

bash

复制代码
npm install vue-router@3
  1. 路由配置(router/index.js)

javascript

复制代码
import Vue from "vue";
import VueRouter from "vue-router";
import BookList from "../views/BookList.vue";
import AddBook from "../views/AddBook.vue";

Vue.use(VueRouter);

const routes = [
  { path: "/", redirect: "/book/list" },
  { path: "/book/list", component: BookList },
  { path: "/book/add", component: AddBook }
];

const router = new VueRouter({ routes });
export default router;
  1. 根组件(App.vue)

html

复制代码
<template>
  <div id="app">
    <!-- 路由导航 -->
    <router-link to="/book/list">书籍列表</router-link>
    <router-link to="/book/add">添加书籍</router-link>
    <!-- 路由视图:渲染匹配的组件 -->
    <router-view></router-view>
  </div>
</template>
  1. 入口文件(main.js)

javascript

复制代码
import Vue from "vue";
import App from "./App.vue";
import router from "./router";

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

14.3 路由传参

  • params 传参/user/:id,通过 $route.params.id 获取
  • query 传参/user?id=1,通过 $route.query.id 获取

15、vue + elementUI

15.1 核心定义

Element UI 是 基于 Vue 2 的桌面端组件库,提供了丰富的开箱即用的组件(表格、表单、弹窗、导航等),用于快速搭建后台管理系统,大幅提升开发效率。

15.2 安装与引入

bash

复制代码
npm install element-ui

入口文件(main.js)全局引入:

javascript

复制代码
import Vue from "vue";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";

Vue.use(ElementUI);

15.3 基础示例(表格组件)

html

复制代码
<template>
  <el-container>
    <el-header>书籍管理系统</el-header>
    <el-main>
      <!-- 表格组件 -->
      <el-table :data="tableData" border stripe>
        <el-table-column prop="id" label="书籍ID"></el-table-column>
        <el-table-column prop="bookName" label="书名"></el-table-column>
        <el-table-column prop="author" label="作者"></el-table-column>
        <el-table-column prop="price" label="价格"></el-table-column>
      </el-table>
    </el-main>
  </el-container>
</template>

<script>
export default {
  data() {
    return {
      tableData: []
    };
  },
  async mounted() {
    // 调用 Axios 获取数据
    const res = await this.$axios.get("/book/all");
    this.tableData = res.data;
  }
};
</script>

15.4 核心优势

  • 组件丰富,覆盖后台管理全场景
  • 样式美观,交互体验好
  • 文档完善,中文支持好
  • 与 Vue 深度集成,开发效率高

16、路由嵌套

16.1 核心定义

路由嵌套(Nested Routes)用于实现页面内的子路由跳转,让一个父路由下包含多个子路由,适配复杂的页面结构(如后台管理系统的侧边栏 + 主内容区)。

16.2 核心原理

  • 父路由组件中通过 <router-view> 渲染子路由
  • 路由配置中通过 children 属性定义子路由
  • 子路由的 path 无需加 /,会自动继承父路由路径

16.3 完整实现示例

1. 路由配置(router/index.js)

javascript

复制代码
import Vue from 'vue'
import VueRouter from 'vue-router'
import Layout from '@/views/Layout.vue'
import BookList from '@/views/book/BookList.vue'
import AddBook from '@/views/book/AddBook.vue'
import UserList from '@/views/user/UserList.vue'

Vue.use(VueRouter)

const routes = [
  {
    // 父路由:后台布局页
    path: '/admin',
    component: Layout,
    // 子路由:嵌套在 Layout 中
    children: [
      {
        // 子路由路径:/admin/book/list
        path: 'book/list',
        component: BookList,
        meta: { title: '书籍列表' }
      },
      {
        path: 'book/add',
        component: AddBook,
        meta: { title: '添加书籍' }
      },
      {
        path: 'user/list',
        component: UserList,
        meta: { title: '用户列表' }
      },
      // 子路由默认重定向
      { path: '', redirect: '/admin/book/list' }
    ]
  },
  // 根路由重定向
  { path: '/', redirect: '/admin' }
]

const router = new VueRouter({ routes })
export default router
2. 父路由组件(Layout.vue)

vue

复制代码
<template>
  <div class="layout">
    <!-- 侧边栏导航 -->
    <aside class="sidebar">
      <router-link to="/admin/book/list">书籍管理</router-link>
      <router-link to="/admin/user/list">用户管理</router-link>
    </aside>
    <!-- 主内容区:渲染子路由 -->
    <main class="main">
      <router-view></router-view>
    </main>
  </div>
</template>

16.4 核心要点

  • 子路由的 <router-view> 必须写在父路由组件内
  • 子路由 path/ 开头会被视为根路径,不会继承父路径
  • 可通过 meta 给路由添加自定义信息(如标题、权限标识)

17、参数传递及重定向

17.1 路由参数传递的 3 种方式

1. params 传参(RESTful 风格)
  • 路由配置中定义参数占位符 :id
  • 参数会被拼接到 URL 中,刷新页面不丢失
  • 适合资源类请求(如查询书籍详情)

路由配置

javascript

复制代码
{
  path: '/admin/book/detail/:id',
  component: BookDetail
}

跳转与取值

vue

复制代码
<!-- 跳转 -->
<router-link :to="`/admin/book/detail/${book.id}`">详情</router-link>
<!-- 编程式导航 -->
this.$router.push(`/admin/book/detail/${id}`)

<!-- 取值 -->
<p>书籍ID:{{ $route.params.id }}</p>
2. query 传参(传统 URL 参数)
  • 参数以 ?key=value 形式拼接在 URL 后
  • 适合非资源类、可选参数的场景
  • 刷新页面不丢失

跳转与取值

vue

复制代码
<!-- 跳转 -->
<router-link :to="{ path: '/admin/book/list', query: { name: 'Vue' } }">搜索</router-link>
<!-- 编程式导航 -->
this.$router.push({ path: '/admin/book/list', query: { name: 'Vue' } })

<!-- 取值 -->
<p>搜索关键词:{{ $route.query.name }}</p>
3. props 传参(解耦组件)
  • 将路由参数映射为组件的 props,让组件不依赖 $route
  • 提升组件复用性,便于单元测试

路由配置

javascript

复制代码
{
  path: '/admin/book/detail/:id',
  component: BookDetail,
  // 开启 props 映射,params 参数会自动注入组件 props
  props: true
}

组件内使用

vue

复制代码
<script>
export default {
  // 声明 props,接收路由参数
  props: ['id'],
  mounted() {
    console.log('书籍ID:', this.id)
  }
}
</script>

17.2 路由重定向

1. 路由配置中重定向

javascript

复制代码
// 方式1:直接重定向到指定路径
{ path: '/', redirect: '/admin' }
// 方式2:重定向到命名路由
{ path: '/', redirect: { name: 'BookList' } }
// 方式3:动态重定向(根据条件返回目标路径)
{ path: '/', redirect: to => {
  return localStorage.getItem('token') ? '/admin' : '/login'
}}
2. 编程式重定向

javascript

复制代码
// 方式1:push 跳转(可回退)
this.$router.push('/admin')
// 方式2:replace 替换(不可回退,适合登录后跳转)
this.$router.replace('/admin')
// 方式3:go 回退/前进
this.$router.go(-1) // 回退一页

17.3 命名路由

给路由添加 name 属性,通过名称跳转,避免硬编码路径:

javascript

复制代码
{
  path: '/admin/book/list',
  name: 'BookList',
  component: BookList
}

// 跳转
this.$router.push({ name: 'BookList' })

18、404 和路由钩子

18.1 404 页面处理

1. 配置 404 路由
  • 必须放在路由配置的最后一项,否则会拦截所有路由
  • 使用 * 通配符匹配所有未匹配的路径

javascript

复制代码
import NotFound from '@/views/NotFound.vue'

const routes = [
  // ... 其他路由配置
  // 404 路由,必须放在最后
  { path: '*', component: NotFound }
]
2. 404 页面组件(NotFound.vue)

vue

复制代码
<template>
  <div class="not-found">
    <h1>404 - 页面不存在</h1>
    <p>你访问的页面不存在或已删除</p>
    <router-link to="/">返回首页</router-link>
  </div>
</template>

18.2 路由钩子(导航守卫)

路由钩子用于拦截路由跳转,实现权限校验、登录判断、全局 loading 等功能,分为 3 类:

1. 全局守卫
  • 作用于所有路由,是项目权限控制的核心
  • 包括 beforeEach(前置守卫)、afterEach(后置守卫)

javascript

复制代码
router.beforeEach((to, from, next) => {
  // to:目标路由对象
  // from:当前路由对象
  // next:放行函数,必须调用
  const token = localStorage.getItem('token')
  // 登录页直接放行
  if (to.path === '/login') {
    next()
  } else {
    // 其他页面需校验 token
    if (token) {
      next()
    } else {
      next('/login')
    }
  }
})

// 后置守卫:路由跳转完成后执行
router.afterEach((to, from) => {
  // 关闭全局 loading、修改页面标题等
  document.title = to.meta.title || 'SSM-VUE 管理系统'
})
2. 路由独享守卫
  • 写在单个路由配置中,仅作用于当前路由
  • 适合单个路由的权限校验

javascript

复制代码
{
  path: '/admin/user/list',
  component: UserList,
  // 路由独享守卫
  beforeEnter: (to, from, next) => {
    const role = localStorage.getItem('role')
    if (role === 'admin') {
      next()
    } else {
      next('/403')
    }
  }
}
3. 组件内守卫
  • 写在组件内部,仅作用于当前组件的路由
  • 包括 beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave

vue

复制代码
<script>
export default {
  // 进入组件前调用(此时组件实例未创建,无法访问 this)
  beforeRouteEnter(to, from, next) {
    next(vm => {
      // 通过 vm 访问组件实例
      console.log('进入组件:', vm)
    })
  },
  // 路由更新时调用(如 params 变化)
  beforeRouteUpdate(to, from, next) {
    next()
  },
  // 离开组件前调用(可访问 this)
  beforeRouteLeave(to, from, next) {
    if (confirm('确定要离开当前页面吗?')) {
      next()
    } else {
      next(false)
    }
  }
}
</script>

18.3 完整的路由守卫执行顺序

  1. 全局 beforeEach
  2. 路由独享 beforeEnter
  3. 组件内 beforeRouteEnter
  4. 全局 beforeResolve
  5. 全局 afterEach
  6. 组件内 beforeRouteUpdate(路由更新时)
  7. 组件内 beforeRouteLeave(离开时)
相关推荐
一袋米扛几楼981 天前
【网络安全】SIEM -Security Information and Event Management 工具是什么?
前端·安全·web安全
小陈工1 天前
2026年4月7日技术资讯洞察:下一代数据库融合、AI基础设施竞赛与异步编程实战
开发语言·前端·数据库·人工智能·python
Cobyte1 天前
3.响应式系统基础:从发布订阅模式的角度理解 Vue2 的数据响应式原理
前端·javascript·vue.js
竹林8181 天前
从零到一:在React前端中集成The Graph查询Uniswap V3池数据实战
前端·javascript
咖啡忍者1 天前
【SAP CO】4.COPC产品成本控制-3.WIP后台配置
笔记
Mintopia1 天前
别再迷信"优化":大多数性能问题根本不在代码里
前端
倾颜1 天前
接入 MCP,不一定要先平台化:一次 AI Runtime 的实战取舍
前端·后端·mcp
军军君011 天前
Three.js基础功能学习十八:智能黑板实现实例五
前端·javascript·vue.js·3d·typescript·前端框架·threejs
恋猫de小郭1 天前
Android 上为什么主题字体对 Flutter 不生效,对 Compose 生效?Flutter 中文字体问题修复
android·前端·flutter
Moment1 天前
AI全栈入门指南:一文搞清楚NestJs 中的 Controller 和路由
前端·javascript·后端