vue3,你还为状态为何物而发愁吗?(一)

简介: 为啥需要状态?因为组件划分的非常原子化(细腻),所以造成了很多的组件,那么组件之间就需要一种“通讯方式”,这个就是状态了。不仅仅是传递数据,还可以实现事件总线。

技术栈

  • vite2
  • vue 3.0.5
  • vue-router 4.0.6
  • vue-data-state 0.1.1
  • element-plus 1.0.2-beta.39


前情回顾

前面介绍的表单控件和查询控件,都是原子性的,实现自己的功能即可。而这里要介绍的是管理后台里面的各个组件之间的状态关系。

为啥需要状态?因为组件划分的非常原子化(细腻),所以造成了很多的组件,那么组件之间就需要一种“通讯方式”,这个就是状态了。不仅仅是传递数据,还可以实现事件总线。


页面结构


一般的后台管理大体是这样的结构:

5.png

后台页面结构.png

具体项目里页面结构会有一些变化,但是总体结构不会有太大的改变。

做出来的效果大体是这样的:

6.png


一种后台管理的效果

  • 动态菜单 根据用户权限加载需要的菜单。
  • 动态 tab 点击一下左面的菜单,创建一个新的tab,然后加载对应的组件,一般是列表页面(组件),也可以是其他页面(组件)。
  • 查询 各种查询条件那是必备的,总不能没有查询功能吧,查询控件需要提供查询条件。
  • 操作按钮组 里面可以有常见的添加、修改、删除、查看按钮,也可以有自定义的其他按钮。可以“弹窗”也可以直接调用后端API。
  • 列表 显示客户需要的数据,看起来简单,但是要和查询、翻页、添加、修改、删除等功能配合。
  • 分页 这是和列表最接近的一个需求,因为数据有可能很大,不能一次性都显示出来,那么就需要分页处理,所以分页控件和列表控件就是天然CP。
  • 表单(添加、修改) 数据提交之后,为了便于确认数据添加成功,是不是需要通知列表去更新数据呢?总不能填完数据,列表一点变化都没有吧。
  • 删除 数据删掉了,不管是物理删除还是逻辑删除,列表里面都不需要再显示出来了。也就是说删除后要通知列表更新数据。

总之,各个组件直接需要统筹一下状态关系。


视频演示

我们来看一下实际效果。

7.png

活链接


设计状态


我们整理一下需求,用脑图表达出来:

8.png



1使用“轻量级状态管理”定义状态:

/store-ds/index.js

import VuexDataState from'vue-data-state'
exportdefault VuexDataState.createStore({
  global: { // 全局状态
    userOnline: {
      name: 'jyk'//
    }
  },
  local: { // 局部状态
    dataListState () { // 获取列表数据的状态 dataPagerState
      return {
        query: {}, // 查询条件
        pager: { // 分页参数
          pageTotal: 100, // 0:需要统计总数;其他:不需要统计总数
          pageSize: 5, // 一页记录数
          pageIndex: 1, // 第几页的数据,从 1  开始
          orderBy: { id: false } // 排序字段
        },
        choice: { // 列表里面选择的记录
          dataId: '', // 单选,便于修改和删除
          dataIds: [], // 多选,便于批量删除
          row: {}, // 选择的记录数据,仅限于列表里面的。
          rows: [] // 选择的记录数据,仅限于列表里面的。
        },
        hotkey: () => {}, // 处理快捷键的事件,用于操作按钮
        reloadFirstPager: () => {}, // 重新加载第一页,统计总数(添加后)
        reloadCurrentPager: () => {}, // 重新加载当前页,不统计总数(修改后)
        reloadPager: () => {} // 重新加载当前页,统计总数(删除后)
      }
    } 
  },
  init (state) {
  }
})


这里没有使用 Vuex,因为我觉得 Vuex 有点臃肿,还是自己做的清爽。另外,状态里面除了数据之外,还可以有方法(事件总线)。


组件里面使用轻量级状态的方法


// 引入状态
import VueDS from'vue-data-state'
// 访问状态
const { reg, get } = VueDS.useStore()
// 父组件注册列表的状态
const state = reg.dataListState()
// 子组件里面获取父组件注册的状态
const dataListState = get.dataListState()

先引入状态,然后在父组件注册(也就是注入)状态,然后在子组件就可以获取状态。函数名就是 /store-ds/index.js 里面定义的名称。

然后我们还可以仿照 MVC 的 Controllar ,做一个控制类,当然也可以叫做管理类。叫什么不是重点,重点是实现了什么功能。


列表的管理类

我们可以为列表的状态写一个状态的管理类。这个类是在单独的 js 文件里面,并不需要像 Vuex 那样去设置 action 或者 module。

/control/data-list.js

import { watch, reactive } from'vue'
// 状态
import VueDS from'vue-data-state'
// 仿后端API
import service from'../api/dataList-service.js'
/**
 * * 数据列表的通用管理类
 * * 注册列表的状态
 * * 关联获取数据的方式
 * * 设置快捷键
 * @param {string} modeluId 模块ID
 * @returns 列表状态管理类
 */
exportdefaultfunction dataListControl (modeluId) {
  // 显示数据列表的数组
  const dataList = reactive([])
  // 模拟后端API
  const { loadDataList } = service()
  // 访问状态
  const { reg, get } = VueDS.useStore()
  // 子组件里面获取父组件注册的状态
  const dataListState = get.dataListState()
  // 数据加载中
  let isLoading = false
  /**
   * 父组件注册状态
   * @returns 注册列表状态
   */
  const regDataListState = () => {
    // 注册列表的状态,用于分页、查询、添加、修改、删除等
    const state = reg.dataListState()
    //  重新加载第一页,统计总数(添加、查询后)
    state.reloadFirstPager = () => {
      isLoading = true
      state.pager.pageIndex = 1// 显示第一页
      // 获取数据
      loadDataList(modeluId, state.pager, state.query, true).then((data) => {
        state.pager.pageTotal = data.count
        dataList.length = 0
        dataList.push(...data.list)
        isLoading = false
      })
    }
    // 先执行一下,获取初始数据
    state.reloadFirstPager()
    // 重新加载当前页,不统计总数(修改后)
    state.reloadCurrentPager = () => {
      // 获取数据
      loadDataList(modeluId, state.pager, state.query).then((data) => {
        dataList.length = 0
        dataList.push(...data)
      })
    }
    // 重新加载当前页,统计总数(删除后)
    state.reloadPager = () => {
      // 获取数据
      loadDataList(modeluId, state.pager, state.query, true).then((data) => {
        state.pager.pageTotal = data.count
        dataList.length = 0
        dataList.push(...data.list)
      })
    }
    // 监听,用于翻页控件的翻页。翻页,获取指定页号的数据
    watch(() => state.pager.pageIndex, () => {
      // 避免重复加载
      if (isLoading) {
        // 不获取数据
        return
      }
      // 获取数据
      loadDataList(modeluId, state.pager, state.query).then((data) => {
        dataList.length = 0
        dataList.push(...data)
      })
    })
    return state
  }
  return {
    setHotkey, // 设置快捷键,(后面介绍)
    regDataListState, // 父组件注册状态
    dataList, // 父组件获得列表
    dataListState // 子组件获得状态
  }
}


管理类的功能:

  1. 父组件注册状态
  2. 子组件获取状态
  3. 定义列表数据的容器
  4. 各种监听
  5. 事件总线

1父组件注册状态因为使用的是局部的状态,并不是全局状态,所以在需要使用的时候,首先需要在父组件里面注册一下。看起来似乎没有全局状态简单,但是可以更好的实现复用,更轻松的区分数据,兄弟组件的状态不会混淆。2子组件获取状态因为或者状态必须在vue的直接函数内才行,所以才需要先把状态获取出来,而不能等到触发事件了再获取。3定义列表数据的容器列表数据并没有在状态里面定义,而是在管理类里面定义的,因为主要列表组件才需要这个列表数据,其他的组件并不关心列表数据。4监听:

  • 监听页号的变化,依据当前的查询条件获取新的记录,用于翻页,不用重新统计总数。

5事件:

  • 统计总数并且翻到第一页,用于查询条件变化,添加新记录。
  • 重新获取当前页号的列表数据,用于修改数据后的更新。
  • 重新获取当前页号的列表数据,并且统计总记录数,用于删除数据后的更新。

6是否重新统计总数可能你会发现上面获取数据里面有一个明显的区别,那就是是否需要统计总数。在数据量非常大的情况下,如果每次翻页都重新统计总数,那么会严重影响性能!其实仔细考虑一下,一些情况是不用重新统计总数的,比如翻页、修改后的更新等,这些操作都不会影响总记录数(不考虑并发操作),那么我们也就不必每次都重新统计。



相关文章
|
2月前
|
JavaScript 前端开发 安全
Vue 3
Vue 3以组合式API、Proxy响应式系统和全面TypeScript支持,重构前端开发范式。性能优化与生态协同并进,兼顾易用性与工程化,引领Web开发迈向高效、可维护的新纪元。(238字)
529 139
|
2月前
|
缓存 JavaScript 算法
Vue 3性能优化
Vue 3 通过 Proxy 和编译优化提升性能,但仍需遵循最佳实践。合理使用 v-if、key、computed,避免深度监听,利用懒加载与虚拟列表,结合打包优化,方可充分发挥其性能优势。(239字)
248 1
|
7月前
|
缓存 JavaScript PHP
斩获开发者口碑!SnowAdmin:基于 Vue3 的高颜值后台管理系统,3 步极速上手!
SnowAdmin 是一款基于 Vue3/TypeScript/Arco Design 的开源后台管理框架,以“清新优雅、开箱即用”为核心设计理念。提供角色权限精细化管理、多主题与暗黑模式切换、动态路由与页面缓存等功能,支持代码规范自动化校验及丰富组件库。通过模块化设计与前沿技术栈(Vite5/Pinia),显著提升开发效率,适合团队协作与长期维护。项目地址:[GitHub](https://github.com/WANG-Fan0912/SnowAdmin)。
1006 5
|
3月前
|
开发工具 iOS开发 MacOS
基于Vite7.1+Vue3+Pinia3+ArcoDesign网页版webos后台模板
最新版研发vite7+vue3.5+pinia3+arco-design仿macos/windows风格网页版OS系统Vite-Vue3-WebOS。
406 11
|
2月前
|
JavaScript 安全
vue3使用ts传参教程
Vue 3结合TypeScript实现组件传参,提升类型安全与开发效率。涵盖Props、Emits、v-model双向绑定及useAttrs透传属性,建议明确声明类型,保障代码质量。
276 0
|
4月前
|
缓存 前端开发 大数据
虚拟列表在Vue3中的具体应用场景有哪些?
虚拟列表在 Vue3 中通过仅渲染可视区域内容,显著提升大数据列表性能,适用于 ERP 表格、聊天界面、社交媒体、阅读器、日历及树形结构等场景,结合 `vue-virtual-scroller` 等工具可实现高效滚动与交互体验。
462 1
|
4月前
|
缓存 JavaScript UED
除了循环引用,Vue3还有哪些常见的性能优化技巧?
除了循环引用,Vue3还有哪些常见的性能优化技巧?
272 0
|
5月前
|
JavaScript
vue3循环引用自已实现
当渲染大量数据列表时,使用虚拟列表只渲染可视区域的内容,显著减少 DOM 节点数量。
143 0
|
7月前
|
JavaScript API 容器
Vue 3 中的 nextTick 使用详解与实战案例
Vue 3 中的 nextTick 使用详解与实战案例 在 Vue 3 的日常开发中,我们经常需要在数据变化后等待 DOM 更新完成再执行某些操作。此时,nextTick 就成了一个不可或缺的工具。本文将介绍 nextTick 的基本用法,并通过三个实战案例,展示它在表单验证、弹窗动画、自动聚焦等场景中的实际应用。
620 17
|
7月前
|
JavaScript 前端开发 API
Vue 2 与 Vue 3 的区别:深度对比与迁移指南
Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架,在过去的几年里,Vue 2 一直是前端开发中的重要工具。而 Vue 3 作为其升级版本,带来了许多显著的改进和新特性。在本文中,我们将深入比较 Vue 2 和 Vue 3 的主要区别,帮助开发者更好地理解这两个版本之间的变化,并提供迁移建议。 1. Vue 3 的新特性概述 Vue 3 引入了许多新特性,使得开发体验更加流畅、灵活。以下是 Vue 3 的一些关键改进: 1.1 Composition API Composition API 是 Vue 3 的核心新特性之一。它改变了 Vue 组件的代码结构,使得逻辑组
1789 0