I apologize in advance, but it’s been a month since I wrote my last article. I have had too many things to do in the past month, and I am not in good physical condition. Every weekend, I always think that I should write an article, but then I think that no one will read it, so why do I have to be so tired? Until a few days ago, when I saw some friends leave messages urging me to do more, I realized that since I was writing a series of articles, there is no reason to give up halfway, only to finish it with energy. In fact, I just write technical articles of the new, come up to write a series of articles, is really not a good choice; Fortunately, as this series comes to an end, the next few articles are examples of real world scenarios that can serve as a reference for vUE forms practices.
Code address: gitee.com/wyh-19/supe… This article is based on the following code: Essay-9
Series of articles:
- Vue + Element Large Forms solution (1)– Overview
- Vue + Element Large Forms solution (2)– Form splitting
- Vue + Element Large Forms Solution (3)– Anchor Components (part 1)
- Vue + Element Large Form Solution (4)– Anchor Component (2)
- Vue + Element Large Forms solution (5)– Validation identifier
- Vue + Element Large Forms solution (6)– Automatic identification
- Vue + Element Large Forms solution (7)– Form form
- Vue + Element Large Form Solution (8)– Data comparison (1)
- Vue + Element Large Form Solution (9)– Data comparison (2)
- Vue + Element Large Forms solution (10)– Form communication and dynamic forms
preface
The last one realized the basic data comparison, but the scene is relatively simple, comparison is the data of the text class control. This paper will supplement the data comparison of some complex controls, such as SELECT, radio, checkbox, etc., all of which have a common feature, that is, value is not suitable for direct display, and can only be compared after it is converted into corresponding text.
The preparatory work
Go to the form1.vue file and add some common complex controls as follows:
<el-form-item label="Degree" class="field-wrapper">
<el-select v-model="formData.education" v-compare:education="oldFormData">
<el-option v-for="item in educationList" :key="item.value" :value="item.value"
:label="item.label"></el-option>
</el-select>
</el-form-item>
<el-form-item label="Gender" class="field-wrapper">
<el-radio-group v-model="formData.gender" v-compare:gender="oldFormData">
<el-radio :label="1">female</el-radio>
<el-radio :label="2">male</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="Hobby" class="field-wrapper">
<el-checkbox-group v-model="formData.hobby" v-compare:hobby="oldFormData">
<el-checkbox v-for="item in hobbyList" :key="item.value" :label="item.value">
{{ item.label }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
Copy the code
Add the required responsive data to the corresponding data:
educationList: [
{
label: 'Graduate student'.value: 1
},
{
label: 'bachelor'.value: 2
},
{
label: 'college'.value: 3}].hobbyList: [{label: 'read'.value: 1
},
{
label: 'Play games'.value: 2
},
{
label: 'movement'.value: 3}].Copy the code
Find the demo.js file and add the test data to return as follows:
export function ajaxGetData() {... Omit the resolve ({name: 'wyh'.age: 30.education: 1.gender: 1.hobby: [1.3].company: 'aaa'
}
)
...省略
}
export function ajaxGetOldData() {... Omit the resolve ({name: 'wyh19'.age: 30.education: 2.gender: 2.hobby: [2.3].company: 'bbb'
}
)
...省略
}
Copy the code
In the form assembly file index.vue, find the resolveDataToMap method and add field handling:
resolveDataToMap(data) {
const form1 = {
name: data.name,
age: data.age,
education: data.education,
gender: data.gender,
hobby: data.hobby } ... Omit}Copy the code
After the preparation, enter the comparison page and the effect is as follows:
Obviously, these value-type data comparison results are not satisfactory, which is exactly the problem to be solved in this paper. Let’s start formally.
Implementation approach
By comparing the old value with the new value, we can distinguish whether the data has changed or not. However, the text content cannot be directly displayed like the field of the text class, and the text needs to be derived according to the value. Therefore, the function of text parsing needs to be added in the instruction. V -compare: field name =”oldFormData” is not enough information, we need to expand to add additional information, such as v-compare: field name. Comparison method =”{oldFormData, other information}”. As it involves the internal instructions, some fields need to be fixed into norms. For example, in the current example, select and radio need to map value to label for display, and map is used for comparison, and map is also used as the field name for other information fields. Map =”{oldFormData,map:{… }} “.
The specific implementation
The realization of the radio
Radio is relatively the simplest, so start from here to realize the above ideas. To change the gender of this field the comparison instruction uses the code:
<el-radio-group v-model="formData.gender"
v-compare:gender.map={oldFormData,map:{1:' female ',2:' male '}}">
<el-radio :label="1">female</el-radio>
<el-radio :label="2">male</el-radio>
</el-radio-group>
Copy the code
In this case, enter the v-compare.js file and add the map type processing. Since the use form of the instruction is different from the previous one, and I do not want to change the original writing method, I need to isolate the instruction inside and keep the original logic unchanged. Remove the modifiers from the binding parameter and determine which logic to use based on their content as follows:
componentUpdated(el, binding, vnode) {
const { value, oldValue, arg, modifiers } = binding
if (modifiers.map) {
// Map type logic is implemented here
} else {
// === the original text type alignment logic remains unchanged ====
// oldFormData is compared only when there is data from no data
// Avoid too many invalid alignments
if(! oldValue && value) {// The comparison function is available when entering this if judgment
// The latest data, that is, the current binding value in the V-model
const lastModel = vnode.data.model.value
// oldFormData[arg]
const beforeModel = value[arg]
// If the two data are different, it is not used here! = =
if(lastModel ! == beforeModel) {// Label it
markDiffrent(el, beforeModel)
}
}
}
}
Copy the code
Write a similar comparison logic code in the map’s judgment body as follows:
if (modifiers.map) {
// Map type logic is implemented here
// Get oldFormData before and after the directive update
const oldV = oldValue.oldFormData
const v = value.oldFormData
// Get the map information
const map = value.map
// Compare oldFormData twice to avoid unnecessary invalid comparisons
if(! oldV && v) {const lastModel = vnode.data.model.value
const beforeModel = v[arg]
if(lastModel ! == beforeModel) {// Map directly from the map to the corresponding text
markDiffrent(el, map[beforeModel])
}
}
}
Copy the code
At this point, we can see that the radio has realized the comparison effect, as shown below (the style problem is not discussed here, you can adjust it according to your needs) :
The realization of the select
In this example, radio and SELECT are essentially the same, the only difference being that the radio options are enumerated and the SELECT options are iterated, so the main work here is to get the map information. In the super-form-mixin.js file, write a public method that handles the conversion as follows:
/ * * * convert the select options for comparison instruction need to map type *, for example: [{value: 1, the label: 'a'}] = = = > {1} : a * /
composeOptions(options = [], value = 'value', label = 'label') {
const map = {}
options.forEach(item= > {
map[item[value]] = item[label]
})
return map
},
Copy the code
At this time to modify the select compare instructions for v – compare: education. The map = “{oldFormData, map: composeOptions (educationList)}” when comparing the results as follows:
The realization of the checkbox
Checkbox = arrayMap = arrayMap = arrayMap = arrayMap = arrayMap = arrayMap = arrayMap Checkbox comparison instruction using code v – compare: hobby. ArrayMap = “{oldFormData, map: composeOptions (hobbyList)} in modifiers. The map following add new branches, the code is as follows:
else if (modifiers.arrayMap) {
// arrayMap type logic is implemented here
// Get oldFormData before and after the directive update
const oldV = oldValue.oldFormData
const v = value.oldFormData
// Get the map information
const map = value.map
// Compare oldFormData twice to avoid unnecessary invalid comparisons
if(! oldV && v) {const lastModel = vnode.data.model.value
const beforeModel = v[arg]
if(! compareEasyArray(lastModel, beforeModel)) {// Map directly from the map to the corresponding text
markDiffrent(el, getArrayMapResult(beforeModel, map))
}
}
}
Copy the code
I did not optimize the code for the convenience of writing here. You can use switch branch to expand and optimize the duplicate code according to your own habits. The difference with the previous comparison is that:
- It’s not easy to use
lastModel ! == beforeModel
To see if two values are different, we usecompareEasyArray
Method, the requirement here is to determine whether the array is different not in order, but whether there are different items. - Not easy
map[beforeModel]
Get the text, but use itgetArrayMapResult
methods
The following implements both methods:
function compareEasyArray(arr1, arr2) {
// Each item in the array is of a simple type and does not compare in order
const arr1ToString = arr1.sort().join(', ')
const arr2ToString = arr2.sort().join(', ')
return arr1ToString === arr2ToString
}
function getArrayMapResult(arr, map) {
const result = arr.map(item= > map[item])
return result.join(', ')}Copy the code
The effect is as follows:
At this point we have basically achieved our goal, if you want to do more perfect, just need to use the current thinking and their own fantastic ideas.
Expand supplementary
In practice, there are far more than these comparison types, and the following code is not demonstrated in the demo, but is simply a note for quick lookup if needed later.
- Value field, but the back end directly returns the corresponding label, or the front end finds laebL and does not want to map inside the instruction, then the label comparison method can be added
V - compare: the field name. The label = "{oldFormData, label: xxLabel}"
Corresponding instruction parsing method:
if (modifiers.label) {
const oldV = oldValue.oldFormData
const v = value.oldFormData
const label = value.label
if(! oldV && v) {const lastModel = vnode.data.model.value
const beforeModel = v[arg]
if(lastModel ! == beforeModel) { markDiffrent(el, label) } } }Copy the code
- Select-tree control data, need to recursively search the tree node
<v-tree-select v-model="formData.respUnitId"
v-compare:respUnitId.tree="{oldFormData,tree:{options:$store.state.base.unitUserTreeData,id:'id',label:'name',children:'childList'}}"
:options="$store.state.base.unitUserTreeData"
no-results-text="There is no such department."
:normalizer="(node)=>({id:node.id,label:node.name,children:node.childList})" />
Copy the code
Corresponding instruction parsing code:
if (modifiers.tree) {
const oldV = oldValue.oldFormData
const v = value.oldFormData
const tree = value.tree
if(! oldV && v) {const lastModel = vnode.data.model.value
const beforeModel = v[arg]
if(lastModel ! == beforeModel) {const { options, id, label, children } = tree
const beforeLabel = getLabelFromTree(beforeModel, options, id, label, children)
markDiffrent(el, beforeLabel)
}
}
}
Copy the code
Implement getLabelFromTree recursively:
function getLabelFromTree(value, tree, idKey, labelKey, childrenKey) {
let result = ' '
if(! value || ! tree || ! tree.length) {return result
}
for (let i = 0; i < tree.length; i++) {
if (tree[i][idKey] === value) {
result = tree[i][labelKey]
} else {
result = getLabelFromTree(value, tree[i][childrenKey], idKey, labelKey, childrenKey)
}
if (result) {
break}}return result
}
Copy the code
Through the above example, I want to illustrate that any complex value control can be converted into a comparison result that can be displayed. If it is really difficult to solve the situation, you can actively obtain the label in the outer layer and pass the label into the form of display.
At this point, the field alignment function of a normal form has been fully implemented. I’ll show you how some complex types of forms can be implemented and how they can communicate interactively across forms. Thank you for reading, and your comments are welcome!