Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >使用局部状态(轻量级状态)优化博客代码

使用局部状态(轻量级状态)优化博客代码

作者头像
用户1174620
发布于 2021-05-13 09:29:48
发布于 2021-05-13 09:29:48
44600
代码可运行
举报
运行总次数:0
代码可运行

上两篇介绍了如何用vite2 + Vue3 搭建一个博客网站,以及轻量级状态的基础使用,那么二者结合起来会发生什么呢?

做个开源博客学习Vite2 + Vue3 (四)实现博客功能 https://cloud.tencent.com/developer/article/1817830

制作一个轻量级的状态管理插件:Vue-data-state https://cloud.tencent.com/developer/article/1818999

回顾博客代码

博客代码里面有三个列表:首页的博文列表、编辑博文里面的博文列表以及讨论列表。

三个列表的写了三份代码,但是对比看一下就会发现,这三份代码大同小异嘛。

其共同点就是:查询条件、分页要求、数据容器

那么是不是可以针对这几个共同点抽象一下,做成一个共用的函数呢?

这个就需要用到轻量级状态里面的局部状态了。

为啥一定要用状态管理呢?那是因为可以把不同的功能分布到不同的组件里面,而不用拘泥在一个组件内实现全部功能。

比如把查询条件的表单放在单独的组件里面,这样可以简化列表组件的代码,更容易进行管理。

定义用于列表需求的局部状态

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// store-ds/index.js
import VuexDataState from 'vue-data-state'

// 设置全局状态和局部状态
export default VuexDataState.createStore({
  global: { // 全局状态
    onlineUser: { // 当前登录用户
      name:'jyk' //
    }
  },
  local: { // 局部状态
    // 数据列表,使用前需要先注册
    dataListState() { // 显示数据列表的状态
      return { // 确保不会重复
        findKind: {}, // 查询方式,仅容器,不用写具体的查询字段
        find: {}, // 查询关键字,还是容器
        page: { // 分页参数
          pageTotal: 100,
          pageSize: 2,
          pageIndex: 1,  // 其实主要是用这个
          orderBy: { id: false } // 排序字段,可以写多个
        },
        _query: {}, // 缓存的查询条件,翻页的时候使用
        isReload: false // 重新加载数据,需要统计总数
      }
    }
  },
  init(state) {
    // 初始化
  }
}) 
  • dataListState 定义一个数据列表用的状态,局部状态的优点就是可以在“多套”业务组件里复用,而且可以保证局部状态不会相互影响,博文列表组件、讨论列表组件都可以用这个状态,而不用定义多个。
  • findKind 查询方式,这个只定义一个容器,具体的内容在后面的代码里面实现。
  • find 查询关键字,记录用户输入的查询内容。具体内容还是在后面的代码里面实现。
  • Page 分页信息,这里主要使用 pageIndex,其他的算是附赠吧,毕竟一般都是配套出现的。
  • _query 缓存查询条件,用户进行查询的时候需要记录查询条件,然后翻页的时候就可以直接拿出来使用了。 缓存起来也便于确定需要哪些查询条件。
  • init 初始化状态,这个是给全局状态用的。

MVC 的 Control

然后我们可以借鉴MVC的思路,做一个control,控制model的加载、状态的变化等功能。

建立一个 src/control 文件夹,统一管理相关的代码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// control/data-list.js
import { watch, reactive } from 'vue'
// 状态
import VueDS from 'vue-data-state'
// webSQL
import { webSQLVue } from 'nf-web-storage'
// 获取配置
// eslint-disable-next-line import/no-absolute-path
import blogListInfo from '/config/bloglist.config.json'

/**
 * 数据列表的通用管理类
 * * 查询条件
 * * 分页信息
 * * 加载数据
 * * 注入局部状态
 */
export default function dataListControl (jsonFlag) {
  // 显示数据列表的数组
  const _dataList = reactive([])

  // 访问 webSQL
  const { help } = webSQLVue.useHelp()

  // 访问状态
  const { reg, get } = VueDS.useStore()
  // 子组件里面获取状态
  const dataListState = get.dataListState()

  // 父组件注册状态
  const regDataListState = () => {
    // 注入获取列表需要的状态,便于查询、分页里面修改
    const state = reg.dataListState()
    // 需要的配置信息
    const listInfo = blogListInfo[jsonFlag]
    if (typeof listInfo === 'undefined') {
      // 没有设置对应的信息
      return state
    }

    // 设置具体的查询条件和查询方式
    state.find = listInfo.find
    state.findKind = listInfo.findKind
    state.page = listInfo.page

    // 重新加载数据
    watch(() => state.isReload, () => {
      const _query = {}
      // 设置查询条件
      for (const key in state.find) {
        const value = state.find[key]
        const kind = state.findKind[key]
        if (value && value.length > 0 && value > 0) {
          _query[key] = [kind, value]
        }
      }
      // 缓存查询条件,分页的时候可以直接使用
      state._query = _query
      state.page.pageIndex = 1 // 显示第一页
      // 统计总数
      help.selectCount(listInfo.tableName, _query).then((count) => {
        // 设置分页
        state.page.pageTotal = count
      })
      // 获取数据
      help.select(listInfo.tableName, listInfo.listCol, _query, state.page).then((data) => {
        _dataList.length = 0
        _dataList.push(...data)
      })
    })

    // 翻页,依据缓存的查询条件,获取其他页号的数据
    watch(() => state.page.pageIndex, () => {
      // 获取数据
      help.select(listInfo.tableName, listInfo.listCol, state._query, state.page).then((data) => {
        _dataList.length = 0
        _dataList.push(...data)
      })
    })
    return state
  }

  return {
    regDataListState, // 父组件注册状态
    dataList: _dataList, // 父组件获得列表
    dataListState // 子组件获得状态
  }
}

虽然代码多了一点,但是这里处理好各种需求,组件里面就可以轻松使用了。

  • 读取配置信息 blogListInfo 因为博文列表、讨论列表需要的信息都是不一样的,所以不同的信息都放在了一个json文件里面,这里用了vite2 的 import 方式读取,然后按照参数(jsonFlag)获取对应的信息。
  • VueDS.useStore 获取轻量级状态的注册等函数。
  • 子组件里面获取状态 因为 vue 的 inject 必须在 vue 的 setup 的进程里面才可以获取,而在事件的进程里面无法获取,所以只好在这里先把需要的状态获取出来,如果是父组件的话,当然取不出来。
  • regDataListState 父组件注册局部状态的函数。从配置信息里面提取对应的信息,设置给 find、findKind、query。
  • 监听 state.isReload isReload 主要针对查询需求,设置好查询条件后对 isReload 取反,就会触发watch,然后这里执行获取数据的操作。在线演示用的是webSQL,正式项目可以使用 axios 向后端申请数据。然后获取数据设置给 dataList。 这里需要统计总记录数,而下面的翻页事件里就不需要统计总记录数了。
  • 监听 page.pageIndex 这个是应对翻页的需求的。分成两个来监听,目的是区分要不要统计总记录数。 如果数据量不大的话,统计总数没啥问题,每次翻页都统计一下用户也不会有啥感觉。 但是如果数据量大的话,还是每次翻页都去统计一下总数,那么就太浪费性能了。

所以这里做了一下区分,翻页的时候不统计总数,重置查询条件的时候才会统计总数。

父组件的使用方法

我们先来看一个简单情况,讨论列表的使用方式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
  <el-card shadow="hover"
    v-for="(item, index) in dataList"
    :key="'discusslist_' + index"
    :id="'discuss_'+ item.ID"
  >
    <template #header>
      <div class="card-header">
        {{item.discusser}}
        <span class="button">({{dateFormat(item.addTime).format('YYYY-MM-DD')}})</span>
      </div>
    </template>
    <!--简介-->
    <div class="text item" v-html="item.concent" :id="'discuss1_'+ item.ID"></div>
    <hr>
    <i class="el-icon-circle-check"></i>&nbsp;{{item.agreeCount}}&nbsp;&nbsp;
  </el-card>
  <!--没有找到数据-->
  <el-empty description="没有讨论呢,抢个沙发呗。" v-if="dataList.length === 0"></el-empty>
   <!--分页-->
  <pager/>
  <!--讨论表单-->
  <discussForm :id="id"/>
</template>

把分页和讨论的表单都分布出去做成了单独的组件,这样模板里面可以专注讨论列表的设置了。

集中目标不分心。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 组件
import { ref } from 'vue'
// 组件
import discussForm from '../components/discuss-form.vue'
import pager from '../components/pager.vue'

// 数据列表的状态
import dataListControl from '../control/data-list'

// 日期格式化
const dateFormat = dayjs

// 组件的属性,获取博文ID
const props = defineProps({
  id: String
})

// 获取注册函数和数据容器,
const { regDataListState, dataList } = dataListControl('discussList')

// 注册状态,设置博文ID为查询条件,获取博文的讨论数据。
const discussState = regDataListState()
discussState.find.blogId = props.id
discussState.isReload = !discussState.isReload

怎么样?是不是很简洁。

  • 父组件里面使用 首先引入 control/data-list,然后获取状态,根据需求设置好查询条件。 最后别忘了使用 dataList 绑定模板。
  • 分页控件使用 分页做成了单独且可以共享的组件,在组件里面可以直接获取局部状态,给 el-pagination 设置属性,这样就不需要父组件操心了。 /src/components/pager.vue
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
  <el-pagination
    background
    layout="prev, pager, next"
    v-model:currentPage="dataListState.page.pageIndex"
    :page-size="dataListState.page.pageSize"
    :total="dataListState.page.pageTotal">
  </el-pagination>
</template>

获取状态,绑定模板。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 统一的数据列表的分页组件
import { defineProps } from 'vue'
// 数据列表的状态
import dataListControl from '../control/data-list'
// 获取列表的局部状态
const { dataListState } = dataListControl()

翻页的时候页号会变化,触发 watch 的监听,从而实现翻页获取数据的效果。

子组件的使用方法

也是一样的步骤,只是不需要注册,而是获取父组件注册的状态,得到状态后,在需要的地方修改即可。

这样组件里面的代码就非常简单了。比如上面那个分页组件。

我们来看一下讨论表单的组件,模板部分就是一个普通的表单,跳过直接看js部分:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { reactive, watch } from 'vue'
// 数据列表的状态
import dataListControl from '../control/data-list'
// 表单管理
import discussFromControl from '../control/data-form'

// 获取讨论列表的状态
const { dataListState } = dataListControl('discussList')
// 表单管理
const { discussModel, addNewDiscuss } = discussFromControl()
 
// 日期格式化
const dateFormat = dayjs

// 组件的属性
const props = defineProps({
  id: String
})

// 发布讨论
const submit = () => {
  discussModel.blogId = props.id
  addNewDiscuss().then((id) => {
    // 通知列表
    dataListState.isReload = !dataListState.isReload
  })
}

先获取讨论列表的状态,然后发布讨论成功后,调用讨论列表的状态,从而触发讨论列表重新加载讨论数据。

其他代码就不一一介绍了,感兴趣的话可以到 gitee 看源码。

轻量级状态 vue-data-state

轻量级状态已经发布到 npm ,可以使用yarn add vue-data-state 来安装。

源码

在线演示

状态

https://naturefw.gitee.io/vue-data-state/

博客

https://naturefw.gitee.io/vue3-blog

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
vue3,后台管理列表页面各组件之间的状态关系 管理类的功能:查询分页添加、修改删除
前面介绍的表单控件和查询控件,都是原子性的,实现自己的功能即可。 而这里要介绍的是管理后台里面的各个组件之间的状态关系。
用户1174620
2021/07/13
2.1K0
制作一个轻量级的状态管理插件:Vue-data-state
Vuex 是针对 Vue2 来设计的,因为 option API 本身有很多缺点,所以 Vuex 只好做各种补丁弥补这些缺点,于是变得比较“复杂”。
用户1174620
2021/04/28
8720
制作一个轻量级的状态管理插件:Vue-data-state
结合 Vuex 和 Pinia 做一个适合自己的状态管理 nf-state
结合 Vuex 和 Pinia, 保留需要的功能,去掉不需要的功能,修改一下看着不习惯的使用方法,最后得到了一个满足自己需要的轻量级状态管理 —— nf - state。
用户1174620
2022/05/12
9580
结合 Vuex 和 Pinia 做一个适合自己的状态管理 nf-state
做个开源博客学习Vite2 + Vue3 (四)实现博客功能 管理类文件结构config设置路由设置网页入口代码入口首页、博文列表表单 发布博文博文内容 + 讨论博文分组博文列表,编
Composition API,就是组合API的意思,那么是不是应该把js代码分离出来,做成独立的管理类的形式呢?
用户1174620
2021/04/26
8810
做个开源博客学习Vite2 + Vue3 (四)实现博客功能
    




管理类文件结构config设置路由设置网页入口代码入口首页、博文列表表单 发布博文博文内容 + 讨论博文分组博文列表,编
做个开源博客学习Vite2 + Vue3 (三)博客设计和代码设计 功能设计代码设计model设计model代码状态设计
项目搭建好了之后是不是可以编码了呢? 等等不要着急,我们是不是应该先设计一下?比如博客的功能等?
用户1174620
2021/04/26
3890
做个开源博客学习Vite2 + Vue3 (三)博客设计和代码设计
    




功能设计代码设计model设计model代码状态设计
做个开源博客学习Vite2 + Vue3 (一)搭建项目
不会 webpack,遇到报错就一头雾水,完全不知道怎么办,而且体积还大速度还慢。 所以尤雨溪做了 vite 后就很向往,只是知道自己水平有限还是等大佬先趟趟坑,等差不多了在跳。
用户1174620
2021/04/23
8540
基于 element-plus 封装一个依赖 json 动态渲染的查询控件 文本数字单选组的查询勾选和开关级联选择日期年、年月、年周的查询日期时间的查询快速查询自定义查询方案更多查询
使用 vue3 + element-plus 封装了一个查询控件,专为管理后台量身打造,支持各种查询需求:
用户1174620
2021/06/09
2.2K0
基于 element-plus 封装一个依赖 json 动态渲染的查询控件
    




文本数字单选组的查询勾选和开关级联选择日期年、年月、年周的查询日期时间的查询快速查询自定义查询方案更多查询
【玩转腾讯云】手把手教你使用Vue/React/Angular三大框架开发Pagination分页组件
19世纪著名的印象派画家莫奈,喜欢对着同一处景物,分别画出对象在不同时间,不同光线下的色彩变化。
Kagol
2021/04/20
7.9K0
【第五篇】商城系统-商品属性管理
SPU是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。通俗点讲,属性值、特性相同的商品就可以称为一个SPU。
用户4919348
2022/09/16
8480
【第五篇】商城系统-商品属性管理
前端系列14集-Vue3-setup
页面浏览量(Page View,PV)和访客数(Unique Visitors,UV)
达达前端
2023/10/08
5070
前端系列14集-Vue3-setup
我自己写的一个分页控件(源码和演示代码)PostBack分页版 for vs2003、SQL Server
温馨提示: asp.net分页控件已经升级了,基于.net2.0 ,支持多种数据库。 正式命名为:QuickPager Asp.net 2.0 分页控件。 网站:www.natureFW.com 下载:http://www.naturefw.com/down/List1.aspx 在线演示:http://demo.naturefw.com 上一篇随笔: 我的分页控件(未完,待续)——控件件介绍及思路 一、分页控件的工作层次     如果按照三层的划分方式来说,应该算作工作在 UI层 和 逻辑层
用户1174620
2018/02/08
1K0
SSM 单体框架 - 前端开发:课程和广告模块
使用 Element UI 表格进行数据展示:https://element.eleme.cn/#/zh-CN/component/table
RendaZhang
2020/10/09
1.3K0
SSM 单体框架 - 前端开发:课程和广告模块
从零玩转系列之微信支付实战PC端装修我的订单页面 | 技术创作特训营第一期
欢迎来到本期的博客!本篇文章是PC篇幅的倒数第二的文章啦,前面经历过九个章节到本章节刚刚好十章节感谢观看我的文章,后续期待我们的Uniapp之旅吧,那么接下来我们将要编写的是我的订单页面. GGBOM!
杨不易呀
2023/08/18
6110
从零玩转系列之微信支付实战PC端装修我的订单页面 | 技术创作特训营第一期
【摸鱼神器】UI库秒变LowCode工具——列表篇(一)设计与实现
如果基于原生HTML来实现显示数据列表的功能的话,那么需考虑如何创建 table,如何设置css等。 如果直接使用UI库的话,那么可以简单很多,只需要设置各种属性,然后绑定数据即可。 以 el-table 为例:
用户1174620
2022/06/12
1.8K0
【摸鱼神器】UI库秒变LowCode工具——列表篇(一)设计与实现
【自然框架】QuickPager分页控件的总体介绍和在线演示
QuickPager分页控件的特点  两种运行方式:自动运行、手动运行。前者便捷,后者灵活。  多种分页方式:Postback、Postback伪URL、URL、URL重写、Ajax For服务器控件伪URL。  多种分页算法:Max、颠倒Top(优化版)、Row_Number、自动适应等。可以应对多种数据库和各种需求。  支持多种数据显示控件:GridView、DataList、Repeater等控件。有DataSource和DataBind()的控件都支持。  不需要存储过程,但是仍然可以保证高效率!
用户1174620
2018/02/26
1.1K0
告别Vuex,发挥compositionAPI的优势,打造Vue3专用的轻量级状态 定义main.jscontroller组件设置监听和钩子局部状态
Vuex 是基于 Vue2 的 option API 设计的,因为 optionAPI 的一些先天问题,所以导致 Vuex 不得不用各种方式来补救,于是就出现了 getter、mutations、action、module、mapXXX 这些绕圈圈的使用方式。想要使用 Vuex 就必须先把这些额外的函数给弄明白。
用户1174620
2021/10/20
1.1K0
【自然框架】QuickPagerSQL——专门生成分页用的SQL的类库
   分享一个生成分页用SQL的函数库   一般一提到分页,大家就会想到存储过程,而大多数情况都是在存储过程里面拼接SQL,我觉得与其在存储过程里面拼接,还不如写个程序来拼接。这样更便于维护,而且效率也不差多少。   所以我就写了这个类库—— QuickPagerSQL。   一开始这个功能是在QuickPager分页控件内部的,但是放在一起的话,违反了单一职责。所以把它独立了出来。现在QuickPagerSQL是一个独立的类库,可以单独调用。   他的目的很明确,就是根据已知条件,依据分页算法,来拼接需
用户1174620
2018/02/26
7200
【自然框架】QuickPagerSQL——专门生成分页用的SQL的类库
测试开发:Python + Flask 实现接口接收 Disk 信息
今天分享的内容是基于:测试开发:Python + Flask 实现接口接收内存信息 来进一步分享如何使用 Python + Flask 实现接收 Disk 的信息。
Wu_Candy
2022/07/04
3420
测试开发:Python + Flask 实现接口接收 Disk 信息
Flask与Vue分页功能实现
在本篇文章中,我们将实现一个简单的分页功能,后端使用 Flask 提供数据,前端使用 Vue.js 显示数据,并且通过 Element UI 进行分页组件的交互。具体实现包括 Flask 视图函数的分页逻辑、Vue 前端分页组件的实现和前后端数据交互。
晓松
2024/12/26
1100
Flask与Vue分页功能实现
黑马vue电商后台管理系统总结[通俗易懂]
后端是已经写好了的,采用 express 搭建的 API 服务,返回的数据是 JSON 格式的数据,只需要导入数据库,并配置一下数据库信息,就可以跑起来了,也有对应的api文档
全栈程序员站长
2022/07/01
2.4K0
黑马vue电商后台管理系统总结[通俗易懂]
推荐阅读
vue3,后台管理列表页面各组件之间的状态关系 管理类的功能:查询分页添加、修改删除
2.1K0
制作一个轻量级的状态管理插件:Vue-data-state
8720
结合 Vuex 和 Pinia 做一个适合自己的状态管理 nf-state
9580
做个开源博客学习Vite2 + Vue3 (四)实现博客功能 管理类文件结构config设置路由设置网页入口代码入口首页、博文列表表单 发布博文博文内容 + 讨论博文分组博文列表,编
8810
做个开源博客学习Vite2 + Vue3 (三)博客设计和代码设计 功能设计代码设计model设计model代码状态设计
3890
做个开源博客学习Vite2 + Vue3 (一)搭建项目
8540
基于 element-plus 封装一个依赖 json 动态渲染的查询控件 文本数字单选组的查询勾选和开关级联选择日期年、年月、年周的查询日期时间的查询快速查询自定义查询方案更多查询
2.2K0
【玩转腾讯云】手把手教你使用Vue/React/Angular三大框架开发Pagination分页组件
7.9K0
【第五篇】商城系统-商品属性管理
8480
前端系列14集-Vue3-setup
5070
我自己写的一个分页控件(源码和演示代码)PostBack分页版 for vs2003、SQL Server
1K0
SSM 单体框架 - 前端开发:课程和广告模块
1.3K0
从零玩转系列之微信支付实战PC端装修我的订单页面 | 技术创作特训营第一期
6110
【摸鱼神器】UI库秒变LowCode工具——列表篇(一)设计与实现
1.8K0
【自然框架】QuickPager分页控件的总体介绍和在线演示
1.1K0
告别Vuex,发挥compositionAPI的优势,打造Vue3专用的轻量级状态 定义main.jscontroller组件设置监听和钩子局部状态
1.1K0
【自然框架】QuickPagerSQL——专门生成分页用的SQL的类库
7200
测试开发:Python + Flask 实现接口接收 Disk 信息
3420
Flask与Vue分页功能实现
1100
黑马vue电商后台管理系统总结[通俗易懂]
2.4K0
相关推荐
vue3,后台管理列表页面各组件之间的状态关系 管理类的功能:查询分页添加、修改删除
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验