美文网首页
递归组合树状结构以及递归组件应用

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

作者: writeanewworld | 来源:发表于2018-08-03 15:48 被阅读0次

    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
            }
        }
    });
    }
    

    相关文章

      网友评论

          本文标题:递归组合树状结构以及递归组件应用

          本文链接:https://www.haomeiwen.com/subject/xknyvftx.html