Recently, I wrote an open source project about a pain point in the front-end development process of my company, which respectively extended the form components of Element-UI and iView. I would like to introduce it to you and hope you can support it more.
Our company is engaged in the project of TO B, the Vue selected by the framework. Compared with the Internet to C project, to B is based on the management background, without too many complex interactions, and is basically the increase, deletion, change and check of the page, only one point is large amount! Large amount of! Large amount of! For example, we have a scenario where we need to implement form editing. Scene: the address
scenario
Quite simply, this page can be done using the Element-UI form component. Then you need a form detail function.
The edit page and details page above are identical except one for editing and one for display. The editing page is developed with Element-UI, and we need to develop another set of detail pages. According to this development mode, there will be the following problems:
The problem
- Coding problem
The edit page needs to be written once, and the details page needs to be written twice.
- The styling
The edit page is an off-the-shelf form component that doesn’t need to be styled, and the detail page needs to be rewritten in the same style as the form component.
- Number of questions
A front-end project on our side might have 20 to 40 groups of these pages, whereas a management system consists of 10 front-end projects and more than 10 back-end projects. So a complete management system would have more than 200 sets of edit detail pages.
- Maintenance problems
Well, as you all know, requirements change, design changes. When a form item is added or subtracted, the edit page should be changed again, and the details page should be changed again. When the form layout is changed from a two-column row to a three-column row, the edit page is changed again, and the details page is changed again.
One or two pages are fine, but the to B project is massive! Large amount of! Large amount of! It’s very painful to maintain.
The solution
Would it be better if they were written into a file? A colleague started to combine the edit page and detail page into a file, and realized the judgment of edit and detail through V-if, as follows:
<el-form ref="form" :model="form">
<el-form-item label="Activity Name">
<template v-if="state='edit'">
<el-input v-model="form.name" />
</template>
<template v-else>
<div class="form-item--detail"> <label> Activity name </label> <div class="form-item__content">{{ form.name }}</div>
</div>
</template>
</el-form-item>
...
</el-form>
Copy the code
As a result, the amount of code in this file increases dramatically, and readability and maintainability decrease significantly. One or two of these files are fine to maintain, but if you think about hundreds or thousands of these files, it’s a disaster to maintain.
So I wrote an extension for the form component, tentatively named the component distributor (portal), and went straight to the code.
In the case of element-UI, we wrote the form (edit page) like this:
<template>
<el-form ref="form" :model="form">
<el-form-item label="Activity Name">
<el-input v-model="form.name" />
</el-form-item>
...
</el-form>
</template>
Copy the code
The dispenser could be written like this:
<template>
<el-form ref="form" :model="form">
<el-form-item label="Activity Name">
<el-input-dispatcher v-model="form.name" />
</el-form-item>
...
</el-form>
</template>
<script>
export default {
provide () {
return {
rwDispatcherProvider: this
}
},
data () {
return {
rwDispatcherState: 'write'. } } } </script>Copy the code
There are only three more steps using the dispenser than using the form:
-
Add the provide attribute, where the rwDispatcherProvider value points to itself
-
Add rwDispatcherState to data property for state management (read or write)
-
The label of the original form element is appended with a -dispatcher suffix, and the rest of the configuration remains the same as for the form component
This completes the form-to-dispenser code migration, which we understand as follows:
Edit page with form component implementation, is write state;
The details page cannot be edited, so it is in read state.
So, replace the component generator with the form component and manage the reads and writes with state parameters. The dispenser renders the component as a form component in the write state and as a detail component in the read state. This implements a set of code maintenance edit and detail pages.
Every potter praises his pot. Why is the dispenser recommended? It has the following features:
- Support for multiple component libraries
Element-ui and iView both have distributors.
- Using a simple
Only three more steps.
- Full customization
A variety of configurations are provided, and the rendering functions are freely customized according to the actual needs of the project.
application
Speaking of which, where exactly can you use it? I’ve summarized the following scenarios
- A set of code implements the editing and detailing (preview) functions of the form
- Double-click a cell in the table to edit it directly
- Switch to edit mode directly in the card
Realize the principle of
The implementation principle of the dispenser is vUE provide/inject and render functions.
According to the state parameters provided, each dispenser enters the corresponding rendering function to realize the corresponding rendering logic. Start (* ^ – ^ *) is welcome, thank you!
Here are other related links:
The document
Example element-UI dispenser
Iview dispenser example
thinking
The render function has two parameters (h, context), for example el-input-Dispatcher, which it passes to the el-Input data object (class, style, attrs, props, ON, directives, Slot, REF, etc.), The implementation code is very simple:
. render (h, context) { const { data, children } = contextreturn h('el-input', data, children)
},
...
Copy the code
However, as the project went further, I found some problems with the rendering function. The biggest problem is that it has no life cycle, and there is no way to communicate with other components during rendering. For example, the size attribute of form elements can be set in the form component itself. If the size attribute on the el-Form-item is not set, the El-form-item will not continue to look up the El-Form. There is no way to do this with context.parent in the render function.
Vue 3.0 is coming soon. I’ll write another version then, haha.