The last two articles covered how to build a blog site with Vite2 + Vue3 and the basic use of lightweight state, so what happens when you combine the two?

Do an open source blog learning Vite2 + Vue3 (four) to achieve blog functions juejin.cn/post/695455…

Create a lightweight state management plugin: vue-data-state juejin.cn/post/695541…

Review the blog code

There are three lists in the blog code: the home blog list, the edit blog list and the discussion list. The three lists write three pieces of code, but if you look at them, they’re pretty much the same. They have in common: query conditions, paging requirements, data containers.

So can we abstract these common points and make a common function?

This requires the use of the local state inside the lightweight state.

Why do you have to use state management? That’s because different functions can be distributed across different components rather than being stuck in a single component.

For example, putting the query criteria form in a separate component can simplify the list component code and make it easier to manage.

Defines local state for list requirements

// store-ds/index.js
import VuexDataState from 'vue-data-state'

// Set global state and local state
export default VuexDataState.createStore({
  global: { // Global status
    onlineUser: { // Current login user
      name:'jyk' //}},local: { // Local state
    // List of data, which needs to be registered before use
    dataListState() { // Displays the status of the data list
      return { // Make sure there are no duplicates
        findKind: {}, // Query mode, only container, do not write specific query field
        find: {}, // query keyword, or container
        page: { // Paging parameters
          pageTotal: 100.pageSize: 2.pageIndex: 1.// This is the main one
          orderBy: { id: false } // Sort the field
        },
        _query: {}, // Cache query criteria, used when turning pages
        isReload: false // Reload the data and count the total}}},init(state) {
    / / initialization}})Copy the code
  • dataListState

Define a state for a data list. The advantage of local state is that it can be reused in “multiple sets” of business components without affecting each other. A blog list component, a discussion list component, can use this state instead of defining multiple.

  • findKind

Query mode, this only defines a container, the specific content in the following code implementation.

  • find

Query keyword: records the search content entered by users. Specific content or in the following code to achieve.

  • Page

Page information, here the main use of pageIndex, the other is a bonus bar, after all, are generally matched.

  • _query

Cache query conditions, users need to record the query conditions, and then turn the page when you can directly take out the use. Caching also makes it easy to determine which query criteria are needed.

  • init

Initialize state. This is for global state.

The Control of the MVC

Then we can learn from MVC ideas and make a control to control model loading and state changes. Create a SRC /control folder to centrally manage the relevant code.

// control/data-list.js
import { watch, reactive } from 'vue'
/ / state
import VueDS from 'vue-data-state'
// webSQL
import { webSQLVue } from 'nf-web-storage'
// Get the configuration
// eslint-disable-next-line import/no-absolute-path
import blogListInfo from '/config/bloglist.config.json'

/** * General management class for data lists ** query criteria ** paging information ** load data ** Inject local state */
export default function dataListControl (jsonFlag) {
  // Displays an array of data lists
  const _dataList = reactive([])

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

  // Access status
  const { reg, get } = VueDS.useStore()
  // Get the state from the child component
  const dataListState = get.dataListState()

  // Parent component registration status
  const regDataListState = () = > {
    // Inject the state needed to get the list, easy to query, pagination inside the modification
    const state = reg.dataListState()
    // Required configuration information
    const listInfo = blogListInfo[jsonFlag]
    if (typeof listInfo === 'undefined') {
      // The corresponding information is not set
      return state
    }

    // Set specific search conditions and search methods
    state.find = listInfo.find
    state.findKind = listInfo.findKind
    state.page = listInfo.page

    // Reload the data
    watch(() = > state.isReload, () = > {
      const _query = {}
      // Set search criteria
      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]
        }
      }
      // Cache query criteria, can be used directly when paging
      state._query = _query
      state.page.pageIndex = 1 // Display the first page
      // Count the total number
      help.selectCount(listInfo.tableName, _query).then((count) = > {
        // Set paging
        state.page.pageTotal = count
      })
      // Get data
      help.select(listInfo.tableName, listInfo.listCol, _query, state.page).then((data) = > {
        _dataList.length = 0_dataList.push(... data) }) })// Turn pages to obtain data of other page numbers according to the query conditions in the cache
    watch(() = > state.page.pageIndex, () = > {
      // Get data
      help.select(listInfo.tableName, listInfo.listCol, state._query, state.page).then((data) = > {
        _dataList.length = 0_dataList.push(... data) }) })return state
  }

  return {
    regDataListState, // Parent component registration status
    dataList: _dataList, // The parent gets the list
    dataListState // The child component gets state}}Copy the code

There’s a bit more code, but the requirements are handled here and the components are easy to use.

  • Read configuration information at blogListInfo

Since the information required for the blog list and discussion list is different, different information is stored in a JSON file, which is read by vite2 import mode, and then obtains the corresponding information according to the parameter (jsonFlag).

  • VueDS.useStore

Functions such as registration to get lightweight state.

  • Get state from child components

Since vue inject must be available in the vue setup process, but not in the event process, so we have to get the required state here, if it is the parent component, of course, not available.

  • regDataListState

The parent component registers local state functions. Extract the corresponding information from the configuration information and set it to find, findKind, and Query.

  • To monitor the state isReload

IsReload is mainly for query requirements. After setting the query conditions, reverse isReload will trigger watch, and then the operation of data acquisition will be performed here. The online demo uses webSQL, and formal projects can request data from the back end using AXIOS. Then get the data set to dataList. The total number of records is required here, but not in the following page-turning events.

  • Listening to the page. PageIndex

This is for the need to turn pages. Divide into two to monitor, the purpose is to distinguish whether to count the total number of records. If the amount of data is small, there’s nothing wrong with counting the total, and counting users every time you turn a page won’t feel bad. However, if there is a large amount of data, it is a waste of performance to count the total every time you turn a page.

So the distinction here is that the total is not counted when the page is turned, but is counted when the query criteria are reset.

How to use the parent component

Let’s start with a simple case to discuss how lists can be used:

<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>
    <! - introduction -- - >
    <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>
  <! -- no data found -->
  <el-empty description="No discussion. Grab a couch." v-if="dataList.length === 0"></el-empty>
   <! - page - >
  <pager/>
  <! Discuss the form -->
  <discussForm :id="id"/>
</template>
Copy the code

Split the pagination and discussion forms into separate components so that the template can focus on discussion list Settings. Focus on your goals and don’t get distracted.

/ / component
import { ref } from 'vue'
/ / component
import discussForm from '.. /components/discuss-form.vue'
import pager from '.. /components/pager.vue'

// The state of the data list
import dataListControl from '.. /control/data-list'

// Format the date
const dateFormat = dayjs

// Component property to get the blog ID
const props = defineProps({
  id: String
})

// Get the registry function and the data container,
const { regDataListState, dataList } = dataListControl('discussList')

// Register status, set blog ID as query condition, get blog discussion data.
constdiscussState = regDataListState() discussState.find.blogId = props.id discussState.isReload = ! discussState.isReloadCopy the code

How’s that? Isn’t that neat?

  • Used in the parent component

Control /data-list is introduced first, then the state is obtained, and the query conditions are set according to the requirements. Finally, don’t forget to use the dataList binding template.

  • Paging control usage

Paging is made into a separate, shareable component where local state can be fetched directly and el-Pagination is set so that the parent component doesn’t have to worry about it. /src/components/pager.vue

<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>
Copy the code

Get the status and bind the template.

// Unified data list paging component
import { defineProps } from 'vue'
// The state of the data list
import dataListControl from '.. /control/data-list'
// Get the local state of the list
const { dataListState } = dataListControl()
Copy the code

The page number will change when turning the page, triggering the monitoring of watch, so as to realize the effect of turning the page to obtain data.

How to use child components

This is the same step, but you don’t need to register. Instead, you get the status of the parent component, and then modify it where necessary. This makes the code inside the component very simple. Like the paging component above.

Let’s take a look at the components that discuss forms. The template part is a normal form, so skip the JS part:

import { reactive, watch } from 'vue'
// The state of the data list
import dataListControl from '.. /control/data-list'
// Form management
import discussFromControl from '.. /control/data-form'

// Get the status of the discussion list
const { dataListState } = dataListControl('discussList')
// Form management
const { discussModel, addNewDiscuss } = discussFromControl()
 
// Format the date
const dateFormat = dayjs

// Component properties
const props = defineProps({
  id: String
})

// Publish the discussion
const submit = () = > {
  discussModel.blogId = props.id
  addNewDiscuss().then((id) = > {
    // Notification listdataListState.isReload = ! dataListState.isReload }) }Copy the code

It gets the state of the discussion list, and then invokes the state of the discussion list when the discussion is published successfully, triggering the discussion list to reload the discussion data.

Other code is not introduced, if you are interested in gitee to see the source code.

Lightweight state vue-data-state

The lightweight state has been published to NPM and can be installed using YARN Add VUe-data-state.

The source code

  • Lightweight state vue-data-state

Gitee.com/naturefw/vu…

  • blog

Gitee.com/naturefw/vu…

The online demo

State naturefw. Gitee. IO/vue – data – st…

Blog naturefw. Gitee. IO/vue3 – blog