SpringBoot+VUE前后端分离项目学习笔记 - 【12 Vue使用路由】

news2024/11/16 3:18:22

整体代码结构

在这里插入图片描述

Manage.vue

HomeView.vue改名为Manage.vue,用以管理其他view页面【通过import 】
在这里插入图片描述

<template>
  <el-container style="min-height: 100vh">

    <el-aside :width="sideWidth + 'px'" style="box-shadow: 2px 0 6px rgb(0 21 41 / 35%);">
      <Aside :isCollapse="isCollapse" :logoTextShow="logoTextShow" />
    </el-aside>

    <el-container>
      <el-header style="border-bottom: 1px solid #ccc;">
        <Header :collapseBtnClass="collapseBtnClass" :collapse="isCollapse" />
      </el-header>

      <el-main>
<!--        表示当前页面的子路由会在 <router-view /> 里面展示-->
        <router-view />
      </el-main>

    </el-container>
  </el-container>
</template>

<script>

import Aside from "@/components/Aside";
import Header from "@/components/Header";

export default {
  name: 'Home',
  data() {
    return {
      collapseBtnClass: 'el-icon-s-fold',
      isCollapse: false,
      sideWidth: 200,
      logoTextShow: true,
    }
  },
  components: {
    Aside,
    Header
  },
  methods: {
    collapse() {  // 点击收缩按钮触发
      this.isCollapse = !this.isCollapse
      if (this.isCollapse) {  // 收缩
        this.sideWidth = 64
        this.collapseBtnClass = 'el-icon-s-unfold'
        this.logoTextShow = false
      } else {   // 展开
        this.sideWidth = 200
        this.collapseBtnClass = 'el-icon-s-fold'
        this.logoTextShow = true
      }
    }
  }
}
</script>

Aside.vue

把原来Home.vue之前的菜单栏封装在这里

<template>
  <el-menu :default-openeds="['1', '3']" style="min-height: 100%; overflow-x: hidden"
           background-color="rgb(48, 65, 86)"
           text-color="#fff"
           active-text-color="#ffd04b"
           :collapse-transition="false"
           :collapse="isCollapse"
           router
  >
    <div style="height: 60px; line-height: 60px; text-align: center">
      <img src="../assets/logo.png" alt="" style="width: 20px; position: relative; top: 5px; right: 5px">
      <b style="color: white" v-show="logoTextShow">后台管理系统</b>
    </div>
    <el-menu-item index="/home">
      <template slot="title">
        <i class="el-icon-house"></i>
        <span slot="title">主页</span>
      </template>
    </el-menu-item>
    <el-submenu index="2">
      <template slot="title">
        <i class="el-icon-menu"></i>
        <span slot="title">系统管理</span>
      </template>
      <el-menu-item index="/user">
        <i class="el-icon-s-custom"></i>
        <span slot="title">用户管理</span>
      </el-menu-item>
    </el-submenu>
  </el-menu>
</template>

<script>
export default {
  name: "Aside",
  props: {
    isCollapse: Boolean,
    logoTextShow: Boolean
  }
}
</script>

<style scoped>

</style>

Header.vue

把顶部栏分到Header里

<template>
  <div style="line-height: 60px; display: flex">
    <div style="flex: 1;">
      <span :class="collapseBtnClass" style="cursor: pointer; font-size: 18px" @click="collapse"></span>

      <el-breadcrumb separator="/" style="display: inline-block; margin-left: 10px">
        <el-breadcrumb-item :to="'/'">首页</el-breadcrumb-item>
        <el-breadcrumb-item>{{ currentPathName }}</el-breadcrumb-item>
      </el-breadcrumb>
    </div>
    <el-dropdown style="width: 70px; cursor: pointer">
      <span>王小虎</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i>
      <el-dropdown-menu slot="dropdown" style="width: 100px; text-align: center">
        <el-dropdown-item style="font-size: 14px; padding: 5px 0">个人信息</el-dropdown-item>
        <el-dropdown-item style="font-size: 14px; padding: 5px 0">退出</el-dropdown-item>
      </el-dropdown-menu>
    </el-dropdown>
  </div>
</template>

<script>
export default {
  name: "Header",
  props: {
    collapseBtnClass: String,
    collapse: Boolean,
  },
  computed: {
    currentPathName () {
      return this.$store.state.currentPathName;  //需要监听的数据
    }
  }
}
</script>

<style scoped>

</style>

User.vue

把查询栏以及加载的数据表放在这里

<template>
  <div>
    <div style="margin: 10px 0">
      <el-input style="width: 200px" placeholder="请输入名称" suffix-icon="el-icon-search" v-model="username"></el-input>
      <el-input style="width: 200px" placeholder="请输入邮箱" suffix-icon="el-icon-message" class="ml-5" v-model="email"></el-input>
      <el-input style="width: 200px" placeholder="请输入地址" suffix-icon="el-icon-position" class="ml-5" v-model="address"></el-input>
      <el-button class="ml-5" type="primary" @click="load">搜索</el-button>
      <el-button type="warning" @click="reset">重置</el-button>
    </div>

    <div style="margin: 10px 0">
      <el-button type="primary" @click="handleAdd">新增 <i class="el-icon-circle-plus-outline"></i></el-button>
      <el-popconfirm
          class="ml-5"
          confirm-button-text='确定'
          cancel-button-text='我再想想'
          icon="el-icon-info"
          icon-color="red"
          title="您确定批量删除这些数据吗?"
          @confirm="delBatch"
      >
        <el-button type="danger" slot="reference">批量删除 <i class="el-icon-remove-outline"></i></el-button>
      </el-popconfirm>
      <el-button type="primary" class="ml-5">导入 <i class="el-icon-bottom"></i></el-button>
      <el-button type="primary">导出 <i class="el-icon-top"></i></el-button>
    </div>

    <el-table :data="tableData" border stripe :header-cell-class-name="'headerBg'"  @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55"></el-table-column>
      <el-table-column prop="id" label="ID" width="80"></el-table-column>
      <el-table-column prop="username" label="用户名" width="140"></el-table-column>
      <el-table-column prop="nickname" label="昵称" width="120"></el-table-column>
      <el-table-column prop="email" label="邮箱"></el-table-column>
      <el-table-column prop="phone" label="电话"></el-table-column>
      <el-table-column prop="address" label="地址"></el-table-column>
      <el-table-column label="操作"  width="200" align="center">
        <template slot-scope="scope">
          <el-button type="success" @click="handleEdit(scope.row)">编辑 <i class="el-icon-edit"></i></el-button>
          <el-popconfirm
              class="ml-5"
              confirm-button-text='确定'
              cancel-button-text='我再想想'
              icon="el-icon-info"
              icon-color="red"
              title="您确定删除吗?"
              @confirm="del(scope.row.id)"
          >
            <el-button type="danger" slot="reference">删除 <i class="el-icon-remove-outline"></i></el-button>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
    <div style="padding: 10px 0">
      <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="pageNum"
          :page-sizes="[2, 5, 10, 20]"
          :page-size="pageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total">
      </el-pagination>
    </div>

    <el-dialog title="用户信息" :visible.sync="dialogFormVisible" width="30%" >
      <el-form label-width="80px" size="small">
        <el-form-item label="用户名">
          <el-input v-model="form.username" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="昵称">
          <el-input v-model="form.nickname" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="邮箱">
          <el-input v-model="form.email" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="电话">
          <el-input v-model="form.phone" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="地址">
          <el-input v-model="form.address" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="save">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: "User",
  data() {
    return {
      tableData: [],
      total: 0,
      pageNum: 1,
      pageSize: 2,
      username: "",
      email: "",
      address: "",
      form: {},
      dialogFormVisible: false,
      multipleSelection: []
    }
  },
  created() {
    this.load()
  },
  methods: {
    load() {
      this.request.get("/user/page", {
        params: {
          pageNum: this.pageNum,
          pageSize: this.pageSize,
          username: this.username,
          email: this.email,
          address: this.address,
        }
      }).then(res => {
        console.log(res)

        this.tableData = res.records
        this.total = res.total

      })
    },
    save() {
      this.request.post("/user", this.form).then(res => {
        if (res) {
          this.$message.success("保存成功")
          this.dialogFormVisible = false
          this.load()
        } else {
          this.$message.error("保存失败")
        }
      })
    },
    handleAdd() {
      this.dialogFormVisible = true
      this.form = {}
    },
    handleEdit(row) {
      this.form = row
      this.dialogFormVisible = true
    },
    del(id) {
      this.request.delete("/user/" + id).then(res => {
        if (res) {
          this.$message.success("删除成功")
          this.load()
        } else {
          this.$message.error("删除失败")
        }
      })
    },
    handleSelectionChange(val) {
      console.log(val)
      this.multipleSelection = val
    },
    delBatch() {
      let ids = this.multipleSelection.map(v => v.id)  // [{}, {}, {}] => [1,2,3]
      this.request.post("/user/del/batch", ids).then(res => {
        if (res) {
          this.$message.success("批量删除成功")
          this.load()
        } else {
          this.$message.error("批量删除失败")
        }
      })
    },
    reset() {
      this.username = ""
      this.email = ""
      this.address = ""
      this.load()
    },
    handleSizeChange(pageSize) {
      console.log(pageSize)
      this.pageSize = pageSize
      this.load()
    },
    handleCurrentChange(pageNum) {
      console.log(pageNum)
      this.pageNum = pageNum
      this.load()
    }
  }
}
</script>


<style>
.headerBg {
  background: #eee!important;
}
</style>

vuex安装

npm i -S vuex@3.6.2

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
    state: {
        currentPathName: ''
    },
    mutations: {
        setPath (state) {
            state.currentPathName = localStorage.getItem("currentPathName")
        }
    }
})

export default store

main.js引入vuex

在源代码加上下面内容

import store from './store'

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

router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import store from "@/store";

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    component: () => import('../views/Manage.vue'),
    redirect: "/home",
    children: [
      { path: 'home', name: '首页', component: () => import('../views/Home.vue')},
      { path: 'user', name: '用户管理', component: () => import('../views/User.vue')},
    ]
  },
  {
    path: '/about',
    name: 'About',
    component: () => import('../views/About.vue')
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('../views/Login.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

// 路由守卫
router.beforeEach((to, from, next) => {
  localStorage.setItem("currentPathName", to.name)  // 设置当前的路由名称,为了在Header组件中去使用
  store.commit("setPath")  // 触发store的数据更新
  next()  // 放行路由
})

export default router

Header.vue

涉及到的store引入部分


computed: {
    currentPathName () {
      return this.$store.state.currentPathName;  //需要监听的数据
    }
  },
  watch: {
    currentPathName (newVal, oldVal) {
      console.log(newVal)
    }
  },
  
  // 使用
  <el-breadcrumb separator="/" style="display: inline-block; margin-left: 10px">
      <el-breadcrumb-item :to="'/'">首页</el-breadcrumb-item>
      <el-breadcrumb-item>{{ currentPathName }}</el-breadcrumb-item>
  </el-breadcrumb>
  

完整代码

<template>
  <div style="line-height: 60px; display: flex">
    <div style="flex: 1;">
      <span :class="collapseBtnClass" style="cursor: pointer; font-size: 18px" @click="collapse"></span>

      <el-breadcrumb separator="/" style="display: inline-block; margin-left: 10px">
        <el-breadcrumb-item :to="'/'">首页</el-breadcrumb-item>
        <el-breadcrumb-item>{{ currentPathName }}</el-breadcrumb-item>
      </el-breadcrumb>
    </div>

    <el-dropdown style="width: 70px; cursor: pointer">
      <span>王小虎</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i>
      <el-dropdown-menu slot="dropdown" style="width: 100px; text-align: center">
        <el-dropdown-item style="font-size: 14px; padding: 5px 0">个人信息</el-dropdown-item>
        <el-dropdown-item style="font-size: 14px; padding: 5px 0">退出</el-dropdown-item>
      </el-dropdown-menu>
    </el-dropdown>
  </div>
</template>

<script>
export default {
  name: "Header",
  props: {
    collapseBtnClass: String,
    collapse: Boolean,
  },
  computed: {
    currentPathName () {
      return this.$store.state.currentPathName;  //需要监听的数据
    }
  },
  watch: {
    currentPathName(newVal, oldVal) {
      console.log(newVal)
    }
  },

}
</script>

<style scoped>

</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/140664.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

年终盘点:元宇宙产业委多项成果荣登元宇宙行业影响力榜单

在经过了2021年元宇宙概念落地和普及后&#xff0c;2022年成为元宇宙相关产业井喷式发展的一年。元宇宙产业委在2022年多项成果荣登行业影响力榜单。 2021-2022元宇宙科技传播图书影响力榜发布&#xff0c;元宇宙产业委好书上榜 2022年9月&#xff0c;两办印发《关于新时代进一…

Internet Download Manager2023最新永久版下载及功能介绍

提到下载工具&#xff0c;大多数国人映入脑海的或许是迅雷。没错&#xff0c;当今随着互联网的迅猛发展&#xff0c;不少早期积累大量用户的国内外下载工具尽显疲态&#xff0c;止步不前&#xff0c;纷纷掉队&#xff0c;如网络快车、FDM、脱兔等等。一款名叫Internet Download…

Anaconda(python)安装教程以及创建新环境

文章目录一. Anaconda简介二. Anacoda安装1. Anacondad下载2. 安装方式三.通过conda创建新的环境四.conda常用命令一. Anaconda简介 Anaconda介绍&#xff1a;开源的Python发行版本。Anaconda指的是一个开源的Python发行版本&#xff0c;其包含了conda、Python等180多个科学包…

make_shared与new

假设有这么个类&#xff1a; class A {private:int b;public:A(int c):b(c) { cout << "call constructor..." << endl;}~A() { cout << "call destructor..." << endl;}int getValue() { return b;} }; 当创建指向 A 对象的智能…

【测绘程序设计】——附合导线近似平差

附合导线(Connecting Traverse,CT)近似平差是测绘专业九大核心专业基础课——《数字地形测量学》中的重点内容,其程序设计也是测绘学子必修的课程设计之一。本文分享了测绘程序设计——附合导线近似平差(C++/MFC版),相关源代码(完整工程,包含测试数据)及使用示例(结果…

CLion开发环境的完全解析(QT开发?STM32?顺便速通cmake

文章目录下载与安装主题推荐编辑器与clang-format设置鼠标滚轮改变字体大小clang-format的使用我的 .clang-format 配置编译工具链设置编译工具链的添加与解释cmake配置项的添加与解释cmake的使用与实战常用的cmake变量&#xff08;入门&#xff09;常用的cmake命令&#xff08…

融合通信系统建设建议(华脉智联内参一)

各行业融合通信系统建设建议 让通信融合信息无阻 题记&#xff1a;目前各个行业都已建设了视频监控系统、内部电话系统、无线对讲机系统、公共广播系统、会场音频系统、视频会议系统等。这些通信系统各自解决不同的用户需求&#xff0c;随着技术的发展&#xff0c;以及融合通信…

腾讯安全连续三年列为Gartner在线反欺诈市场指南全球代表厂商

近日&#xff0c;全球研究机构Gartner发布了2022《在线反欺诈市场指南》&#xff08;Market Guide for Online Fraud Detection&#xff09;。腾讯安全凭借天御&#xff08;TenDI&#xff09;金融风控被列为全球代表性厂商&#xff0c;这也是腾讯安全连续第三次被列入该报告。随…

洛谷千题详解 | P1031 [NOIP2002 提高组] 均分纸牌【C/C++、pascal、Java语言】

博主主页&#xff1a;Yu仙笙 专栏地址&#xff1a;洛谷千题详解 目录 题目描述 输入格式 输出格式 输入输出样例 解析&#xff1a; C源码&#xff1a; pascal源码&#xff1a; pascal源码2&#xff1a; Java源码&#xff1a; ------------------------------------------------…

很穷的top2农村男博士要不要嫁?

这个问题最近在知乎上面很火&#xff0c;经常能刷到&#xff0c;具体背景如下&#xff1a;我自己家也是农村的&#xff0c;家里比较穷&#xff0c;我就读的学校肯定比不上top2&#xff0c;但也还不错&#xff0c;是个C9&#xff0c;所以这个问题想和大家简单聊一下我的看法。知…

JavaScript刷LeetCode拿offer-栈相关题目

1. 栈是什么&#xff1f; 一种先进后出的数据结构&#xff1b;JavaScript没有栈的结构&#xff1b;可以用array实现栈的功能 入栈 push(x);出栈 pop(); const stack [];// 入栈 stack.push(1); stack.push(2);// 出栈 const item1 stack.pop(); const item2 stack.pop();2…

GC日志分析

1.写在前面 前段时间一位读者面了阿里&#xff0c;在二面中被问到 GC 日志分析&#xff0c;感觉回答的不是很好&#xff0c;过来找我复盘&#xff0c;大致听了他的回答&#xff0c;虽然回答出了部分&#xff0c;但是没抓到重点。 GC 日志分析算是 JVM 调优中比较难的部分&…

【python数据分析】对淘商品类母婴购物数据进行分析(含完整源码)

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 又到了学Python时刻~ 一、数据集 ​ 今天我们来看一个来着阿里云天池的数据集:淘母婴购物数据,有两个csv文件: 1、mum_baby.csv 它包含了953个孩子的生日和性别信息&#xff0c;这些信息是由淘或tian猫的消费者提供的…

足球视频AI(四)——队伍与裁判人员分类

一、基础概念 足球比赛中人员为&#xff1a;A队11人、B队11人、裁判&#xff0c;其中我们暂时不研究守门员。 需要将球场中的人员分类&#xff0c;并呈现在2D看板中。 1.1识别目标&#xff1a; 1&#xff09;球场中的白队 2&#xff09;球场中的蓝队 3&#xff09;球场中的…

剑指offer----C语言版----第九天

目录 1. 剪绳子 1.1 题目描述 1.2 基础知识 1.2.1 动态规划 1.2.2 贪婪算法 1.3 思路一&#xff1a;动态规划 1.4 思路二&#xff1a;贪婪算法 1.5 思路一的优化 1. 剪绳子 原题链接&#xff1a;剑指 Offer 14- I. 剪绳子 - 力扣&#xff08;LeetCode&#xff09;http…

无约束优化:Hessian-Free Optimization 拟牛顿类算法(BFGS,L-BFGS)

文章目录无约束优化&#xff1a;Hessian-Free Optimization 拟牛顿类算法&#xff08;BFGS&#xff0c;L-BFGS&#xff09;为什么要用拟牛顿算法割线方程严格凸且光滑函数的BFGS算法非凸但光滑函数的BFGS算法L-BFGS算法非凸非光滑函数的BFGS算法参考文献无约束优化&#xff1a;…

LInux僵尸进程的解决方法

文章目录僵尸进程是如何出现的&#xff1f;如何防止僵尸进程产生&#xff1f;使用wait函数使用waitpid函数阻塞等待非阻塞等待——轮询僵尸进程出现后如何解决&#xff1f;僵尸进程是如何出现的&#xff1f; 一个进程在退出后&#xff0c;操作系统会释放该进程对应的资源&…

网络舆情监测管理制度及处置机制,网络舆情监测服务项目实时方案?

舆情监测通常包括搜集、分析和报告舆论信息的过程。搜集信息的途径包括网络新闻、社交媒体、博客、论坛等&#xff0c;分析信息的方法包括自然语言处理、数据挖掘、模糊属性决策分析等。接下来TOOM舆情监测小编带您简单了解网络舆情监测管理制度及处置机制&#xff0c;网络舆情…

奈奎斯特采样定理(Nyquist)

采样定理在1928年由美国电信工程师H.奈奎斯特首先提出来的&#xff0c;因此称为奈奎斯特采样定理。1933年由苏联工程师科捷利尼科夫首次用公式严格地表述这一定理&#xff0c;因此在苏联文献中称为科捷利尼科夫采样定理。1948年信息论的创始人C.E.香农对这一定理加以明确地说明…

VirtualBox+Vagrant快速搭建linux虚拟环境

VirtualBoxVagrant快速搭建linux虚拟环境 1.下载安装VirtualBox 下载 Virtual Box 官网: https://www.virtualbox.org/ 2.BIOS 里修改设置开启虚拟化设备支持(f2, f10) 参考: https://jingyan.baidu.com/article/ab0b56305f2882c15afa7dda.html 3.安装 Virtual Box&#xff…