无限极分类,简单来说就是一个人类可以繁衍出多个后代,后代又可以分多个后代,这样无限繁衍下去。
那么这种层级结构也成为树结构在日常开发需求李也是很常见的,例如:商城项目的分类,课程的目录章节,以及论坛里的帖子回复等等。
我们后台利用Django来写一个能够返回增肌结构数据的结构,接口将该数据已json的形式返回前端,vue.js组件进行展示数据。
首先,打开django项目中的models。py。新建一个模型类。
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数据库中存入一些测试数据,我们访问接口,他会以json的形式返回了层级结构。
接口没问题!我们把目光转移到前端,打开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>
当然了,vue组件也可以间接的调用自己实现递归,这涉及到组件之间的循环引用,这样比较麻烦,可读性也间接的降低了不少。