递归组合树状结构以及递归组件应用

2018-08-03  本文已影响0人  writeanewworld

1.需求:
数据库中有一张表,表名为itemType,记录的是商品类型,其中有一个字段是父级id,对应的也是本表中的id字段,所以这里类型数据应该是以一种树装结构json来显示的。

结构如图:

image.png image.png

2.json结构图:

image.png

转化后:

image.png

3.控制层代码:(递归)
递归这玩意不懂别去强行理解,多写多练,别指望一次就会用。用的多了自然就会明白了,要不然就直接看源码。

1).初始数据=>  List<ItemType>  itemTypes = ...
2).json格式拼装方法:
    private List<Map<String,Object>>  covertToTree(List<ItemType> itemTypes){
        Map<Integer,ItemType> typeMap = new HashMap<>();
        for(ItemType type:itemTypes){
              typeMap.put(type.getId(),type);
        }
        return recursionCovertToTree(null,typeMap); 
    }

    private recursionCovertToTree(Integer parentId,Map<Integer,ItemType> typeMap){
        List<Map<String,Object>> list = new ArrayList<>();
        for(Integer key : typeMap){
             //通过key拿到单个ItemType实例 
             ItemType type = typeMap.get(key);
             if((parentId==null && type.getParentId()==null) || ()){
                 Map<String,Object> entity = new HashMap<>();
                 entity.put("type",type);
                 List<Map<String,Object>>  children = recursionCovertToTree(type.getId(),typeMap);
                 entity.put("children",children);
                 list.add(entity) ;
             }
        }
          return list;
    }

4.vue递归组件应用场景:


image.png

选择一个类型,如果这个类型有父级就会接着选择。


image.png

无父级之后:

image.png

5.页面布局:

  <div class="form-group" style="width:500px !important;">
  
                <!-- todo -->
                <label>商品类型</label>
                <div id="item-type-container">
                    <item-type v-bind:options="tree" v-bind:id-path="path" v-bind:id-pos="0"></item-type>
                </div>
                
</div>

组件:

Vue.component('item-type', {
template: "" +
"<div style='display: inline-block;'>\n" +
"    <select @change='change($event.target.value)' :disabled='disabled' v-if='showSelector'>\n" +
"        <option value='-1'>请选择</option>\n" +
"        <option v-for='opt in options' :key='opt.type.id' :value='opt.type.id' :selected='idPath[idPos] == opt.type.id'>{{opt.type.typeName}}</option>\n" +
"    </select>\n" +
"    <item-type v-if='childOptions && childOptions.length !== 0' :options='childOptions' :id-path='idPath' :id-pos='idPos + 1' :disabled='disabled'></item-type>\n" +
"</div>",
props: ['options', 'idPath', 'idPos', 'disabled'],
data: function () {
    return {
        childOptions: []
    }
},
computed: {
    showSelector: function () {
        if (!this.disabled) {
            return true
        }
        var curId = this.idPath[this.idPos]
        for (var i = 0, len = this.options.length; i < len; ++i) {
            if (this.options[i].type.id == curId) {
                return true
            }
        }
        return false
    }
},
methods: {
    change: function (id) {
        for (var i = 0, len = this.options.length; i < len; ++i) {
            var opt = this.options[i]
            if (opt.type.id == id) {
                this.$set(this.idPath, this.idPos, id)
                this.childOptions = opt.children
                return
            }
        }
        this.childOptions = []
        this.idPath.splice(this.idPos)
    }
},
mounted: function () {
    this.change(this.idPath[this.idPos])
}
});

实例:

function createItemTypeSelector(id, itemTypeId, itemTypes, onItemTypeChanged) {
new Vue({
    el: id,
    data: function() {
        var path = [];
        this.getPath(path, itemTypeId, itemTypes);
        return {
            tree: itemTypes,
            itemTypeId: itemTypeId,
            path: path
        }
    },

    watch: {
        path: function (value) {
            typeof onItemTypeChanged === 'function' && onItemTypeChanged(value[value.length - 1])
        }
    },

    methods: {
        getPath: function (path, typeId, children) {
            for (var i = 0, len = children.length; i < len; ++i) {
                var child = children[i]
                if (this.getPath(path, typeId, child.children)) {0
                    path.unshift(child.type.id)
                    return true
                } else if (child.type.id == typeId) {
                    path.unshift(child.type.id)
                    return true
                }
            }
            return false
        }
    }
});
}
上一篇 下一篇

猜你喜欢

热点阅读