5

使用Python3.7+Django2.0.4配合vue.js2.0的组件递归来实现无限级分类(递归层级结构)

 1 year ago
source link: https://v3u.cn/a_id_133
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

使用Python3.7+Django2.0.4配合vue.js2.0的组件递归来实现无限级分类(递归层级结构)

首页 - Python/2020-03-03
使用Python3.7+Django2.0.4配合vue.js2.0的组件递归来实现无限级分类(递归层级结构)

    所谓的无限极分类是啥?其实简单点说就是一个人类可以繁衍出多个后代,然后一个后代又可以分另外多个后代这样无限繁衍下去(可以想象神奇动物在哪里2里面莱斯特兰奇的家族族谱),就好象linux系统你可以新建一个文件夹,然后在这个文件夹里又可以建一些个文件夹,在文件夹底下还可以建一些文件夹一样,随后使用tree命令就可以查看文件夹目录层级。

    那么这种层级结构也成为树结构在日常的开发需求里也是很常见的,比如美多商城系统的商品分类,课程的目录章节,以及以及论坛里的帖子回复等等,本次我们后台利用Django来写一个能够返回层级结构数据的接口,接口将该数据以json的形式返回前端,前端使用vue的组件递归来展示数据。

    首先,打开django项目中的models.py,新建一个类别的模型类,这里我们以最简单的parentid的形式来建立

class Cate(models.Model):

    #主键 通过参数声明主键
    id = models.AutoField(primary_key=True)
    #分类名称
    name = models.CharField(max_length=500)
    #父级id
    pid = models.IntegerField()

    #表名
    class Meta:
        db_table = 'cate'

     由于我们的项目基于drf框架,所以要增加一个序列器类,如果你的项目没有用drf,可以直接用json模块来进行序列化

from rest_framework import serializers
from myapp.models import Cate


class CateSer(serializers.ModelSerializer):
    class Meta:
        model = Cate
        fields = "__all__"

     由于django序列化出来的类不具备层级结构,所以我们提前写好一个用来递归的方法:

def xTree(datas):
    lists=[]
    tree={}
    parent_id=''
    for i in datas:
        item=i
        tree[item['id']]=item
    root=None
    for i in datas:
        obj=i
        if not obj['pid']:
            root=tree[obj['id']]
            lists.append(root)
        else:
            parent_id=obj['pid']
            if 'childlist' not in tree[parent_id]:   
                tree[parent_id]['childlist']=[]
            tree[parent_id]['childlist'].append(tree[obj['id']])
    return lists

     此时我们写一个视图接口,用来从数据库中读取数据

class MyTree(APIView):
    def get(self,request):


        #获取订单列表
        catelist = Cate.objects.filter()
        #序列化
        catelist_ser = CateSer(catelist,many=True)

        mylist= xTree(catelist_ser.data)


        return Response(mylist)

     请在mysql库里存一些测试数据

    

20200303114306_78562.png

    测试一下接口,看看是否以json的形式返回了层级结构

    

20200303114400_23346.png

    ok,接口没有问题,现在我们把目光投向前端,打开vue项目,新建一个Reply.vue组件

    所谓递归组件: 就是组件可以在它们自己的模板中调用自身,不过它们只能通过 name 选项来做这件事,例如给组件设置属性 name: 'Reply',然后在模板中就可以使用 Reply 调用自己进行递归调用了

<template>

    <div>

            <li >
                    <div :class="[data.id==0 ? 'root': '', 'reply']">{{ data.name }}</div>
            
                    <ul v-if="data.childlist && data.childlist.length>0">
                        <Reply v-for="child in data.childlist" :key="child.id" :data="child"/>
                    </ul>
                </li>

        </div>
</template>
    
    <script>
    export default {
        name: 'Reply', // 递归组件需要设置 name 属性,才能在模板中调用自己
        props:['data'],
    };
    </script>
    
    <style >
    .reply {
        padding-left: 4px;
        border-left: 1px solid #eee;
    }

    ul {
            padding-left: 20px;
            list-style: none;
        }

        .root { display: none; }

    

    </style>

     然后在其他任意组件中调用该Reply.vue组件,传入刚刚写好的接口数据

<template>
        <div>
                
                <Reply :data="data" />
    
        </div>
    </template>
       
      <script>
    
        import {config,formatXml} from '../config.js';
        import mh_test from './mh_test.vue';
        import Reply from './Reply.vue';
    
        import md5 from 'js-md5';
    
    
      export default {
        data () {
          return {
              data:{},
            online: 0
          }
        },
        components: {
            //'mh_test':mh_test
            Reply
      },
    
        //钩子方法
        mounted:function(){
            
                this.get_token();
        },
        //绑定事件
        methods:{
    
            get_token(){
    
             this.axios.get('http://localhost:8000/mytree/').then((result) =>{
            console.log(result);
            var mytree = {'id':0,name:'123'};
            mytree['childlist'] = result.data;
            this.data = mytree;


            console.log(this.data);

            });

            },
       
    
        }
      }
      </script>
       
    <style>
    
    .on {
                background: #cdcbff;
            }
    .off {
        background: #fefdff;
    
    }
    
    </style>

     最后请求页面,可以看到展示的效果:

    

20200303114749_87796.png

    当然了,vue组件也可以间接的调用自己实现递归,这涉及到组件之间的循环引用,这样比较麻烦,可读性也间接的降低了不少。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK