使用组件
< TreeNode v-for = " (node, index) in nodes" :key = " index" :node = " node" />
JSON数据
let nodes= [
{
"id" : 2030 ,
"show_id" : "MC1813024492270223360" ,
"detail_type" : 1 ,
"title" : "1" ,
"description" : "" ,
"class_hour" : 10 ,
"children" : [
{
"id" : 2031 ,
"show_id" : "MC1813024625619734528" ,
"detail_type" : 1 ,
"title" : "2" ,
"description" : "" ,
"class_hour" : 2 ,
"children" : [
{
"id" : 1940 ,
"show_id" : "MC1813024654644314112" ,
"detail_type" : 2 ,
"title" : "31" ,
"description" : "我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介" ,
"class_hour" : 0 ,
"children" : null ,
"study_status_str" : "未学习" ,
"lesson_number" : 0 ,
"level" : 3
}
] ,
"study_status_str" : "" ,
"lesson_number" : 0 ,
"level" : 2
}
] ,
"study_status_str" : "" ,
"lesson_number" : 1 ,
"level" : 1
}
]
组件
< template>
< div :style = " { paddingLeft: level * 20 + 'px' }" class = " tree-node" >
< div
@click = " toggle"
class = " tree-node-header"
:class = " { 'first-level': node.level == 1 }"
>
< img :src = " node.level == 1 ? imgs.group : imgs.dot" alt = " " />
< span class = " title" > {{ node.title }}</ span>
< template v-if = " node.level == 1" >
< span class = " class-hour all-hour" > 总学时 {{ node.class_hour }}</ span>
< span class = " class-hour" > 视频课{{ node.lesson_number }}</ span>
</ template>
< template v-if = " !node.children && node.detail_type == 2" >
< span @click = " handleClassHour(node)" class = " class-hour play"
> < i class = " iconfont" >  </ i> 视频课</ span
>
< span class = " class-hour schedule" > {{ node.study_status_str }}</ span>
</ template>
< span v-if = " hasChildren" class = " arrow" >
< i v-show = " isOpen" class = " el-icon-arrow-up" />
< i v-show = " !isOpen" class = " el-icon-arrow-down" />
</ span>
</ div>
< div class = " content" v-if = " !node.children && node.level != 1" >
{{ node.description }}
</ div>
< transition name = " expand" >
< div v-if = " isOpen" class = " tree-node-children" >
< TreeNode
v-for = " (child, index) in node.children"
:key = " index"
:node = " child"
:level = " level + 1"
/>
</ div>
</ transition>
</ div>
</ template>
< script>
export default {
name : "TreeNode" ,
props : {
node : {
type : Object,
required : true ,
} ,
level : {
type : Number,
default : 1 ,
} ,
} ,
data ( ) {
return {
isOpen : false ,
imgs : {
group : require ( "@/pages/web_site_front/resource_manage/pages/onlineCourses/assets/group.png" ) ,
dot : require ( "@/pages/web_site_front/resource_manage/pages/onlineCourses/assets/dot.png" ) ,
} ,
} ;
} ,
computed : {
hasChildren ( ) {
return ( this . node. children && this . node. children?. length) || 0 ;
} ,
} ,
methods : {
toggle ( ) {
if ( this . hasChildren) {
this . isOpen = ! this . isOpen;
}
} ,
handleClassHour ( node ) {
document. querySelector ( ".main-content" ) . scrollTop = 0 ;
this . $store. dispatch ( "user/setCourseVideoId" , node. id) ;
} ,
} ,
components : {
TreeNode : ( ) => import ( "./treeNode.vue" ) ,
} ,
} ;
</ script>
< style scoped lang = " scss" >
.tree-node {
margin : 5px 0;
.tree-node-header {
cursor : pointer;
padding : 5px;
margin-bottom : 16px;
display : flex;
font-weight : bold;
img {
width : 10px;
align-self : center;
margin : 0 5px;
}
.title {
max-width : calc ( 100% - 160px) ;
overflow : hidden;
white-space : nowrap;
text-overflow : ellipsis;
}
.play {
font-size : 12px;
color : #00ab6b;
line-height : 20px;
height : 20px;
border : 0.5px solid #c3e7da;
border-radius : 4px;
padding : 0 4px;
margin-left : 8px;
display : inline-table;
i {
font-size : 14px;
margin-right : 4px;
}
}
.schedule {
font-size : 12px;
color : #00000040;
margin-left : 8px;
}
.arrow {
flex : 1;
text-align : right;
color : #00ab6b;
margin-right : 31px;
}
}
.first-level {
height : 40px;
line-height : 40px;
display : flex;
margin-bottom : 16px;
background : #fafafa;
border-radius : 8px;
font-weight : bold;
font-size : 16px;
span {
align-self : center;
}
img {
width : 30px;
align-self : center;
}
.class-hour {
color : #000000a6;
line-height : 22px;
padding : 0 8px;
background : #f5f5f5;
border-radius : 2px;
margin-right : 6px;
font-size : 14px;
}
.all-hour {
margin-left : 26px;
}
}
.content {
color : #00000073;
line-height : 22px;
border-bottom : 1px solid #f0f0f0;
padding-bottom : 16px;
margin-left : 26px;
}
}
.tree-node-children {
margin-top : 5px;
// border-left : 2px solid #ccc;
padding-left : 0px;
.tree-node {
padding-left : 20px !important ;
}
}
.expand-enter-active,
.expand-leave-active {
transition : all 0.3s ease;
}
.expand-enter, .expand-leave-to {
height : 0;
opacity : 0;
overflow : hidden;
}
</ style>