This is the third day of my participation in the More text Challenge. For details, see more text Challenge
preface
Read the series in order before reading, for better results!
It is said that the series of articles is difficult to be popular, because the knowledge point baggage is not enough, so we are not willing to collect in the future, but it doesn’t matter, the benefit of the series of articles is to look comfortable, fragmental time is soon finished, isn’t it?
1. Common page
As explained in the previous sections, if we need to complete our low-code list design, then the design of common components is a must.
1.1 Flexible dynamic Components
We designed the CommonLayout Component to accomplish common functions, but of course it has very little content except the introduction of the Component.
Here is an excerpt from the Vue documentation:
Sometimes it is useful to switch between components dynamically, such as in a multi-tag interface, by adding a special is attribute to the element of Vue:.
<! -- Component changes when 'currentTabComponent' changes -->
<component v-bind:is="currentTabComponent"></component>
Copy the code
In the example above, the currentTabComponent can include either the name of the registered component, or an option object for a component.
Because this component corresponds to multiple routes, its created method is only called once due to vUE optimization. Therefore, we need to complete the loading work during route switchover.
1.2 Awkward asynchronous API calls
The implementation of the previous section was problematic because it involved API calls, and this asynchronous approach resulted in a less timely state refresh when the page was updated, so the components in the previous section needed to be optimized so that they could load the data smoothly.
- So let’s control the display, let’s introduce it here
initCom
Variable, do not display the component until it is ready. Doing this will have a little time page blank ~~~ not found a suitable solution temporarily;
<template>
<div class="app-container">
<keep-alive v-if="initCom">
<component :is="realCompoonent" v-if="realCompoonent" :guid="guid" />
<common-layout v-else :guid="guid" />
</keep-alive>
</div>
</template>
Copy the code
- API requests are then controlled to load the list definition model data before switching routes. Once loaded, vuEX data is refreshed and the actual components are loaded
beforeRouteEnter(to, from, next) {
next(vm= > {
vm.guid = vm.getGuid(to)
if (vm.hasExpire(vm.udf, vm.guid)) {
const http = new Http()
http.fetch({
url: `/Tools/GetModelDefine/${vm.guid}`.method: 'get',
}).then(data= > {
vm.$store.dispatch('udf/setUdfModelData', { guid: vm.guid, data })
vm.init(to)
})
} else {
vm.init(to)
}
})
},
init(route) {
const path = route.path
try {
this.realCompoonent = require(`@/views${path}`).default
// this.$router.push(this.realCompoonent)
} catch (ex) {
console.log(`load sub com [${path}] failed. ${ex}`)
this.realCompoonent = null
}
this.initCom = true
},
Copy the code
According to this modification, finally in the page refresh, menu back and forth when the performance is normal.
2. com monLayout components
When the realCompoonent component page is not defined, we automatically display it using the CommonLayout component.
2.1 This table is a little ugly
It mainly shows the form we define in the form of a list, and the effect is as follows:
2.2 Model metadata
It is mainly according to the definition of the model, the analysis and display.Through the Common page component, we have successfully obtained the model definition data and put it in VUEX. Therefore, this component only needs to get the GUID parameter and then query the data in VUEX.
2.3 Then we define a GUID attribute first.
export default {
name: 'CommonLayout'.mixins: [mixClass],
props: {
guid: { type: String.default: ' '}},data() {
return{}}},Copy the code
2.4 Import mapGetters to obtain VUEX data.
import { mapGetters } from 'vuex'.computed: {
...mapGetters(['udf']),
templateModel() {
// console.log(this.udf.get(this.guid))
return this.udf.get(this.guid)
},
showSummary() {
const index = this.templateModel.listTemplate.findIndex(
item= > item.isSum == 1.)returnindex ! = -1}},Copy the code
2.5 To get the backend list data, we refer to the Mixins extension class.
Mixins provide a very flexible way to distribute reusable functionality in Vue components. A mixin object can contain any component option. When a component uses a mixin object, all the options for the mixin object are “mixed” into the component’s own options. When components and mixins have options with the same name, these options are “merged” in the appropriate manner. Refer to the VUE documentation for more consolidation rules.
In the mixin class, we invoke the paging data API by convention.
getlistApi(params) {
const model = this.templateModel.model.modelName
return this.$http.fetch({
url: ` /${model}/Get${model}Page`.method: 'post'.params: params,
})
},
Copy the code
2.6 Similarly, we monitor $route to ensure that data is loaded
Monitor $Rout to refresh data when the created method is not called.
watch: {
$route: function(to, from) {
this.reset()
this.fetchData()
},
},
Copy the code
2.7 According to the model definition, we show or hide the ordinal number and multi-checkbox columns of the table.
<el-table-column
v-if="templateModel.model.listShowSelect == 1"
type="selection"
width="55"
/>
<el-table-column
v-if="templateModel.model.listShowNo == 1"
type="index"
align="center"
width="50"
label="#"
:index="table_index"
/>
Copy the code
2.8 Add the sorting function and merging function of lists
<el-table
v-loading="listLoading"
:data="list"
element-loading-text="Loading"
border
fit
highlight-current-row
:show-summary="showSummary"
:summary-method="getSummaries"
@current-change="handleCurrentChange"
@sort-change="sortList"
>
Copy the code
2.9 List total function
The merge functionality needs to be displayed according to the column Settings, so you need to customize the getSummaries method. The implementation method is as follows:
getSummaries(param) {
const list = this.templateModel.listTemplate
const { columns, data } = param
const sums = []
columns.forEach((column, index) = > {
if (index === 0) {
sums[index] = 'together'
return
}
if (column.property) {
const item = list.find(o= > o.fieldName.toLowerCase() == column.property.toLowerCase())
console.log(item)
if (item && item.isSum == 1) {
const values = data.map(item= > Number(item[column.property]))
sums[index] = values.reduce((prev, curr) = > {
const value = Number(curr)
if (!isNaN(value)) {
return prev + curr
} else {
return prev
}
}, 0)
// sums[index]}}})return sums
},
Copy the code
2.10 the column definitions
The column is pulled and displayed according to the list definition of the model. This defines the width, column names, alignment, properties, and formatting the date data. Of course, you can extend by type of control.
<el-table-column
v-for="(item, index) in templateModel.listTemplate"
:key="index"
:label="$t(templateModel.model.modelName + '.' + item.fieldName)"
:width="item.width <= 0 ? 0 : item.width"
:align="item.controlType == 'Number' ? 'right' : 'left'"
:sortable="item.isSort == 1 ? 'custom' : false"
:prop="firstLower(item.fieldName)"
>
<template slot-scope="scope">
<template v-if="item.controlType == 'Text'">
{{ scope.row[firstLower(item.fieldName)] }}
</template>
<template v-else-if="item.controlType == 'DateTime'">
{{ scope.row[firstLower(item.fieldName)] | formatDate }}
</template>
<template v-else>
{{ scope.row[firstLower(item.fieldName)] }}
</template>
</template>
</el-table-column>
Copy the code
2.11 Paging components can also be displayed as configured.
<el-pagination
v-if="templateModel.model.listShowPage == 1"
background
layout="total, sizes, prev, pager, next, jumper"
:page-sizes="[10, 20, 50, 100, 500]"
:page-size="listQuery.limit"
:total="total"
@size-change="changeSize"
@current-change="fetchPage"
@prev-click="fetchPrev"
@next-click="fetchNext"
/>
Copy the code
2.12 One of the remaining problems is column name reclamation
Column name reclamation is a problem because if the front end does not intervene, the reclamation work needs to be completely in the back end. After the resource file is defined, the front end obtains the resource through the interface and automatically merges it into the resource dictionary.
2.13 The second remaining problem is button customization
If you need to expand a new button, then the previously designed model needs to add button metadata, which is still under design, and will be shared when there is time.
3. Summary
The basic function of the list of customization has been realized, through the introduction of these several times, have you learned?
In low-code projects, customizing lists and forms is usually a no-go. If you have a better idea, leave a comment.