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> {{item.agreeCount}}
</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