• Vue2 实战 基于 Elmenet-UI 的 单页面开发 用户信息增删改查 | 支持分页查询 | 自动登录


    案例介绍

    为了熟悉 Vue2 框架 的使用,现采用 Vue2的基础知识、Router路由、Vuex 管理仓库来实现一个可对用户进行增删改查的小案例。数据存储在浏览器的 localStorage 本地缓存中,方便模拟从后端获取数据,不过这里仅有前端部分,没有涉及 axios 请求相关的内容。
    技术栈:Vue2 + ElementUI + Vue Router + Vuex
    【注:本案例只是作为初学者的分享,里面的设计思路不一定适合特定场景,可能存在许多不足,仅供参考】

    案例地址:https://gitee.com/ccuni/vue-easy-user-crud

    一、相关知识


    1.1 Vue

    Vue 是国人大牛【尤雨溪】开发的一套用于构建用户界面的开源的渐进式框架,支持 MVVM架构,具有易用、灵活和高效的特点,是前端领域比较火热的框架,不过目前最流行的前端框架还是 React,React框架在国外使用量最多,这里简单提一下。
    目前 Vue2 是大多数使用企业中的主流版本(据说),而 Vue3 带来了更高性能,增加了一些新特性,在这里我以Vue 2 为主,先掌握 Vue2 的使用,之后有时间再继续学习 Vue3。

    1.2 Vue-Router

    Vue-Router 是 Vue官方提供的路由插件。
    使用 Vue 开发的 Web 项目支持 SPA 页面的渲染,即 Single Page Web Application,单页面的web应用。
    单页面可以提升页面切换速度,每次切换都是局部加载页面,提升网站的响应速度,减少服务器压力,支持组件化构建。
    而 Vue-Router 简单来说就是支持我们定义不同的 URL 请求地址,跳转到不同的路由组件,在本次案例中,我没有使用到路由守卫、元数据等内容,只是简单的配置了一下页面和路由组件的映射,适合初学者入门。

    1.3 Vuex

    Vuex 也是 Vue官方提供的插件,采用集中式存储管理应用的所有组件的状态,主要分为三层,分别是 action 响应层,mutations 数据处理层,store 存储层。
    对于这三层,我们可以类比 MVC架构里的 Controller、Service和 DAO, 但是这里是有区别的,可以从 mutations 直接到 store,而不经过 action。
    在本次案例中,我使用 Vuex 来保存处理用户信息的所有业务代码,这样其他的所有路由组件都可以调用,可有效的降低代码耦合度,而用户的信息也存储在了 Vuex 的 store 层,方便任意组件获取数据。
    在这里插入图片描述

    1.4 VueCLI

    Vue CLI 又称脚手架,是搭建 Vue项目的工具,在我们做 Vue 项目的开发时,不可能每次都从零开始创建项目文件,这样效率是比较低的,而官方提供的基于 Node.js 的脚手架可以很好的解决这个问题,我本次的案例是基于脚手架开发的,其中有许多文件都是默认生成的,不用自己手动去配置,降低了开发难度。

    1.5 Element-UI

    Element 是国内【饿了么】开发团队为开发者、设计师和产品经历准备的基于 Vue 的开源的桌面端组件库,有支持 Vue2的版本,同时也有支持 Vue3 的对应版本,用了这个神奇的框架,我们可以快速搭建前端页面,实现想要的效果,除此之外,该框架提供了一系列基于 Vue 实现的功能,大大降低了开发难度。

    二、页面展示


    2.1 注册页面

    因为没有连接后端,故目前没有写注册功能

    在这里插入图片描述

    2.2 登录页面

    在这里插入图片描述

    2.3 管理页面

    在这里插入图片描述

    2.4 查看用户详情

    在这里插入图片描述

    2.5 编辑指定的用户

    在这里插入图片描述

    2.6 批量删除用户

    在这里插入图片描述

    2.7 退出登录

    在这里插入图片描述

    2.8 条件查询+分页

    在这里插入图片描述

    2.9 添加用户

    在这里插入图片描述

    三、思路整理


    3.1 项目结构

    本案例使用 Vue-CLI 脚手架进行创建,其中有一些是默认创建的文件

    案例项目的整体结构
    在这里插入图片描述

    父项目各个组件的分配
    在这里插入图片描述

    用户路由组件包括它的子组件
    在这里插入图片描述

    理清项目结构后,接下来就是关键功能实现的描述,稍微记录一下,将来可以做个优化。

    3.2 自动登录

    自动登录功能的实现是在 Vue各个生命周期钩子函数中的 mounted() ,即已挂载函数里执行。

    在 Vue2 中,当页面渲染完毕则会执行这个函数,此时我们就可以在这个方法里执行自动登录。

    自动登录的实现方式有很多,以前学到的就是读取浏览器中的cookie,然后用cookie里的用户信息向服务端发送登录的请求,这是比较传统的方式了,后来听说有了 token 凭证的方法,在 JavaWeb应用中称为 JWT,即 JSON Web Token,本质上就是一种字符串,规定好格式的字符串,它相比cookie安全很多,因为其中用到了加密算法,加密的密钥是由服务端设置的,在这里暂时不做深入,了解有这么一个技术即可。

    在本次案例中我使用的是 localStorage 本地缓存,因为我们的浏览器中也是有数据库存在的,存储 Cookie、缓存这类信息,这里我就将用户登录的信息存储到本地缓存,然后在自动登录时读取这个缓存,因为没有后端,得到信息后就直接执行登录的方法,判断是否登录成功即可,整体来说逻辑还是比较简单的。

    mounted(){
      // 读取本地缓存中的 userInfo,并转为 Object 对象
      let userInfo = JSON.parse(localStorage.getItem('userInfo'))
      // 如果对象存在则执行登录的逻辑
      if(userInfo) this.autoLogin(userInfo)
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    自动登录则先向 Vuex 中的 actions 层的 login 方法发送请求,同时传入需要登录的用户信息,由于 action层方法是不会返回指定的参数的,所以我采取使用 Vuex 中 state 层的一个变量来记录是否登录成功,然后在当前登录组件中,只需要用 计算属性 就能获取并同步与 state 层用户登录状态了

    computed:{
      loginState(){
        return this.$store.state.user.loginState | false
      }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Vuex 中登录的方法实现如下:

    // actions 响应层
    actions: {
      login(context, user){
      // 模拟获取正确的用户信息
      let u = { username: 'admin', password: 'admin'}
      if(user.username === u.username && user.password === u.password){
        context.commit('login', user)
      }
      else
        context.commit('logout')
      }
    },
    // mutations 数据处理层
    mutations: {
      login(state, user){
        state.userInfo = user
        state.loginState = true
      },  
    },
    // state 数据存储层
    state: {
      loginState: false,
      // 当前登录用户的信息(每次都默认读缓存,如果缓存不存在则指定为测试的账号和密码)
      userInfo: 
        JSON.parse(localStorage.getItem('userInfo'))
          || {
                username: 'admin',
                password: 'admin',
                isLogin: false
             },  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    登录组件自动登录的方法实现如下:

    autoLogin(userInfo){
      this.$store.dispatch('user/login', userInfo)
      if(this.loginState){
        this.$notify({
          title: '温馨提示',
          type: 'success',
          message: '欢迎访问~',
          showClose: false,
          duration: 1500
        });
        this.$router.push('/admin/user')
      }else {
        message.error('自动登录失败')
      }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这里用到了 Element-UI 提供的提示窗,只需要调用 this.$notify() 这个方法,就会出现相应的页面效果了。

    3.3 分页显示

    关于分页显示,前端页面直接使用 Element-UI 提供的组件就行,在这里比较复杂就是当切换页面时,数据的变换以及浏览器 URL的变化,这就设计了 vue-router 路由的相关知识,不过其实也只是用到了路由传参。
    关于路由传参,当我们点击下一页时,则采用动态的编程路由,指定跳转到下一页的 URL,当然这不会导致页面刷新,因为是 SPA 单页面开发,但为了给用户带来较好的视觉体验,所以需要实现路由组件的刷新,点击下一页过后,有一个刷新效果,而且在刷新过程中也可以发送 axios 请求获取真实的数据(为之后的开发做准备)。
    在这里插入图片描述

    切换页面或切换页面尺寸执行的方法:

    // 切换页面尺寸(尺寸修改后, 页面固定为第一页)
    handleSizeChange(value){
      this.$router.push({
        path: '/admin/user',
        query: {
          size: value,
          p: 1
        }
      })
      this.reloadRouterView()
    },
      // 切换页面
      handleCurrentChange(value){
        this.$router.push({
          path: '/admin/user',
          query: {
            size: this.pageInfo.size,
            p: value,
          }
        })
        this.reloadRouterView()
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    这里直接采取动态路由的方式修改当前的路由组件,我们先来看看关于刷新路由组件的实现逻辑:
    引入组件的HTML部分:

    <router-view v-if="routerViewVisible" :reloadRouterView="reloadRouterView"></router-view>
    
    • 1

    实现刷新的 JS部分

    // 刷新视图
    reloadRouterView(){
      this.routerViewVisible = false
      this.$nextTick(function() {
        this.routerViewVisible = true
      })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这个方法并不在用户列表的组件里,而是在引入了用户列表组件的父组件,在调用时通过标签属性直接传参即可,如:

    <UserList :reloadRouterView="reloadRouterView"/>
    
    • 1

    然后在 UserList 子组件里通过 props 属性接收参数,如:

    props: ['reloadRouterView']
    
    • 1

    这样一来,用户列表组件就可以直接自身,来实现加载效果了。

    路由的关键配置如下:

    {
      path: '/admin',
      component: () => import('@/pages/admin/admin'),
        children:[
          {
            path: 'user',
            component: () => import('@/pages/admin/user'),
          },
        ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    如此一来,我们的用户列表组件便收到了当前的分页参数,那么如何显示对应的数据呢?答案是可通过计算属性,由于没有后端,所以关于用户的信息都存储在 Vuex 的 store 层,这里使用简单的几行语句就可以实现了。

    computed:{
      pageInfo(){
        return {
          p: parseInt(this.$route.query.p) || 1,
          size: parseInt(this.$route.query.size) || 5
        }
      },
        userList(){
          console.log(this.pageInfo)
          let L = (this.pageInfo.p - 1) * this.pageInfo.size
          let R = L + this.pageInfo.size
          return this.$store.state.user.userList.slice(L, R)
        },
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    ElasticSearch Python API教程
    阿里云混合云首席架构师张晓丹:政企混合云技术架构的演进和发展
    GCC + Vscode 搭建 nRF52xxx 开发环境
    大数据与AI:解析智慧城市的幕后英雄
    组合索引实例
    生产环境TiDB集群缩容TiKV操作步骤
    【操作系统】内存管理
    C/C++进程超详细详解【中部分】(系统性学习day07)
    25 张图详解交换机:秒懂二层交换机的 16 个问题
    Redis 笔记 01:入门篇
  • 原文地址:https://blog.csdn.net/Unirithe/article/details/125819283