preface

Recursion is familiar to many of you, and we often use recursion in algorithms to solve problems. Like the classic: find a combination of all numbers in an array that adds up to the target number. And the idea is not that hard, you loop through the array, you add them recursively until you satisfy the target number condition. Recursion solves most of the problems, but the downside is that it’s easy to write code that doesn’t loop, causing the stack to explode. Let’s take a look at the application of recursion in a VUE component in my actual business scenario.

Used in vue

To complete a complete recursion, I personally think there are two most important points:

  1. Determine the conditions for entering the recursion;
  2. Determine the conditions for breaking out of recursion;

One of the most important is to determine when to break out of recursion. A recursive component is actually very simple, is A component A call A component, the formation of A recursive. Take the following business I encountered as an example. One day, I received a demand to select target users from a bunch of users according to the combination of different label conditions. Therefore, I have the following design drawing:

At first glance, may be muddled, but in fact, as long as after careful analysis, found that it is not very difficult, look at the picture many students will feel, a bit like we often say the doll, a layer of a layer. For this kind of graph, we first analyze which is the smallest unit, and it’s easy to see in the figure above that the smallest is this one. The large structure in the diagram is basically made up of this small piece, as long as the implementation of this piece, the rest of the data is recursively rendered layer by layer.

The next step is to determine the data structure and, if there are no subtrees, simply render the project. If an item contains a subtree, the component must be rerendered to pass in the subtree data. So the idea is very simple. Let’s say our data structure looks like this:

{
  type: 'or'.valueList: [{condition: 'Login Number in last 7 days'.login: '! = '.value: 45
    },
    {	
      condition: 'Login Number in last 7 days'.login: '! = '.value: 45
    },
    {
      type: 'and'
      valueList: [{condition: 'Login Number in last 7 days'.login: '! = '.value: 45}]}]}Copy the code

The data structure above is clear, and you can see that when a subitem in the array contains a valueList, it indicates that a small piece of the component described in the figure above needs to be rerendered. Therefore, we can simply code as follows (the following code can be optimized) :

<template>
  <div class="label-list">
    <el-tag type="primary" size="mini" class="logic">{{ typeDict[treedata.type] }}</el-tag>
    <template v-for="(item, index) in treedata.valueList">
      <ul v-if=! "" item.hasOwnProperty('valueList')" :key="'rule_' + index">
        <li>{{ item.condition }} {{ item.logic }} {{ item.value }}</li>
      </ul>
    </template>
    <template v-for="(item, index) in treedata.valueList">
      <! Call this component again to render the subitem -->
      <label-shows-view v-if="item.hasOwnProperty('valueList')" :key="'tree_' + index" :treedata="item"></label-shows-view>
    </template>
  </div>
</template>
<script>
const _TYPE = {
  'and': 'and'.'or': 'or'
}
export default {
  name: 'LabelShowsView'.props: {
    treedata: {
      type: Object.required: true}},data() {
    return {
      typeDict: _TYPE
    }
  }
}
</script>
Copy the code

As you can see, it’s all about analyzing and finding the repetitive parts of the data structure and rendering them layer by layer. In fact, the above example is relatively easy to understand for pure demonstration, if the data interaction is added, it needs extra attention. If the recursion level is very deep, event transmission, data change, etc., need to be handled carefully. For example, the author encountered the following figure when completing the above visual configuration to filter the customer group:

You can add and remove children, and you can drag and drop each group to adjust its position. In this case, you can take advantage of a similar bubbling approach, where the child component either fires an event or accepts an event. For example, when deleting a set of conditions, the parent component needs to be notified which item of the child data to delete, as follows:

<! -- labelRulesView.vue --> <! -- This custom component is a recursive component --><label-rules-view v-if="item.hasOwnProperty('valueList')" :label-list="labelList" :treedata="item" :current-index="index" @delGroup="funDelGroup"></label-rules-view><! -- This component listens for delGroup events --><el-button size="mini" type="danger" icon="el-icon-delete" class="operate-btn" @click="handleDelNewGroup(currentIndex)"></el-button>

// Delete a group
handleDelNewGroup(index) {
  this.$emit('delGroup', index) // Fires events to upper-layer components
},
funDelGroup(index) {
  this.treedata.valueList.splice(index, 1)},Copy the code

In a recursive component, many times the component acts as both a child and a parent. Therefore, it is necessary to control the interaction between data, otherwise it is easy to cause data disorder

summary

This article is the author in the actual business scenario encountered and conveniently recorded, using recursive components, we can even complete some more complex graphics display. I hope I can help you to broaden your thoughts. If I can help you, I still want to be careful (I must [doge] next time I refuse).