关于vue组件递归的个人理解

       vue近来是前端最热门的框架之一,不久之前,在做项目的时候,遇到一个问题,就是vue组件递归的问题,经过研究,总结出以下几点,若有不同见解,欢迎各位大佬纠正.

一.需求实现(这里用的是vue的脚手架搭建的项目总体框架)

    各大论坛,相信大家都知道,其中针对每个人发的帖子需要进行回复的操作,针对第一个人回复的内容,第二个回复人也可以回复第一个人的回复,依次类推,这就需要递归显示每条帖子后面的所有评论信息,下面我们就一起来看看实现的方式

二.组件的创建

    首先,在项目中新建一个组件,这里我命名为set.vue(名字随便起的,不要在意),在main.js中导入


      书写set.vue的内容模板(注:set.vue这个组件就是用于显示论坛帖子评论的组件)


这个是论坛的模板部分,其中responseTopic是个数组,我们一起来看看这个数组的结构是怎么样的

replyList: [
{
id: 5,
cusomer: {
id: 1,
aliasName: null,
nickName: null,
realName: null,
loginName: null,
status: null
},
createTime: "2018-06-30 15:29:20",
content: "+1+1+1+1+1+1+1+1+1+1",
anonymous: "0",
replyList: [
{
id: 8,
cusomer: {
id: 1,
aliasName: null,
nickName: null,
realName: null,
loginName: null,
status: null
},
createTime: "2018-06-30 15:52:35",
content: "+1+2+3",
anonymous: "0",
replyList: null
}
]
}
]
},
{
id: 6,
cusomer: {
id: 1,
aliasName: null,
nickName: null,
realName: null,
loginName: null,
status: null
},
createTime: "2018-06-30 15:46:03",
content: "+1+2+3",
anonymous: "0",
replyList: null
},
{
id: 7,
cusomer: {
id: 1,
aliasName: null,
nickName: null,
realName: null,
loginName: null,
status: null
},
createTime: "2018-06-30 15:50:51",
content: "+1+2+3",
anonymous: "0",
replyList: null
}
]

可以看到这些数据将来是后台接口返回给我们的,每一层数据,对应一条用户的评论,我门需要对这些数据进行递归展示,就必须要考虑到数据的合理性和共性,观察这些数据我们可以看到每一层都是相同的字段,并且有一个顶层数据,这就让我想到,要想把这些数据全部展示到页面上,单纯的v-for是不够的,因为你不知道,将来这里面到底有多少层数据,接下来,我就根据数据来介绍一下,vue组件之间的通讯原理.


我们知道,vue父子组件之间通讯,若父组件想把自己本身的数据发送到子组件身上,就必须要在引用子组件的时候通过vue的数据绑定v-bind(或者':')将需要的数据绑定到子组件身上,本例中在引用子组件的时候,通过绑定

:responseTopic=" responseTopic"
把自身上的数据传递到子组件内部,子组件要想拿到父组件传过来的数据,就必须要定义一个叫props的对象或者数组 ,然后把父组件中绑定的数据定义到这里面,就可以直接使用了  .   下面这是我在home.vue页面中(也就是用于显示评论组件的父组件)引用刚刚创建的组件,我们知道一个组件只能展示一条用户评论,那么,怎么才能让组件展示出所有的数据呢?通过上面的观察的数据结构发现,只要每层数据中有replyList字段,就证明,这层评论下面还有评论,那么既然这样的话,我们可以在刚刚创建的set.vue这个组件中,引入自己,见下图


对的,你没看错,就是自己引用自己,根据数据结构,一层结构对应一层数据,每层需要的数据,已经通过vue组件绑定数据传递到了它的子组件身上,而组件嵌套,正好对应了每层数据结构,它的作用也就是解析所有层的评论对象,到这里,你应该会问,那么一直这样嵌套下去,不会导致死循环嘛,是的,如果真的一直循环下去不管在强大的框架也是吃不消的,这时候,就需要我们有一个停止嵌套的条件,这里我用的是v-if,v-if后面的表达式为true时才会显示,也就是说当replyList为null或''时,就不会继续嵌套下去了,这就达到我所要的效果,下图是该案例实现的效果图


下面贴出该案例完整代码

1.路由配置页面


2.home.vue页面


< script >
import set from "./set.vue";
export default {
data() {
return {
isAdmin: false,
scrollTop: 0,
isShow: false,
isActive: false,
isTop: false,
pageSizes: [ 10, 20, 30, 40],
pageSize: 10,
currentPage: 1,
total: 0,
topicId: this. $route. query. topicId,
defaultMsg: "请输入回复内容",
topicDetail: [], //存放帖子详情数据
responseTopic: [
{
id: 1,
cusomer: {
id: 1,
aliasName: null,
nickName: null,
realName: null,
loginName: null,
status: null
},
createTime: "2018-06-30 14:51:58",
content: "这帖子为ID为1的第一条评论",
anonymous: "0",
replyList: [
{
id: 4,
cusomer: {
id: 1,
aliasName: null,
nickName: null,
realName: null,
loginName: null,
status: null
},
createTime: "2018-06-30 15:08:43",
content: "不要沉,我给你顶起来。",
anonymous: "0",
replyList: [
{
id: 5,
cusomer: {
id: 1,
aliasName: null,
nickName: null,
realName: null,
loginName: null,
status: null
},
createTime: "2018-06-30 15:29:20",
content: "+1+1+1+1+1+1+1+1+1+1",
anonymous: "0",
replyList: [
{
id: 8,
cusomer: {
id: 1,
aliasName: null,
nickName: null,
realName: null,
loginName: null,
status: null
},
createTime: "2018-06-30 15:52:35",
content: "+1+2+3",
anonymous: "0",
replyList: null
}
]
}
]
},
{
id: 6,
cusomer: {
id: 1,
aliasName: null,
nickName: null,
realName: null,
loginName: null,
status: null
},
createTime: "2018-06-30 15:46:03",
content: "+1+2+3",
anonymous: "0",
replyList: null
},
{
id: 7,
cusomer: {
id: 1,
aliasName: null,
nickName: null,
realName: null,
loginName: null,
status: null
},
createTime: "2018-06-30 15:50:51",
content: "+1+2+3",
anonymous: "0",
replyList: null
}
]
}
], //存放回复帖子列表
};
},
methods: {
// 控制收藏逻辑
show() {
this. isActive = ! this. isActive;
},
handleSizeChange() {},
handleCurrentChange() {}
},
components: {
set
}
};
</ script >
< style scoped >
.forum-container {
width: 80%;
margin: 0 auto;
padding: 2% 6%;
clear: both;
position: relative;
}
.forum-all .blocks {
position: fixed;
margin-left: 81%;
margin-top: 10%;
z-index: 99;
transition: all ease 0.8s;
}
.forum-all .blocks span {
display: block;
width: 40px;
height: 40px;
font: 14px "microsoft yahei";
color: #fff;
z-index: 1;
box-sizing: border-box;
margin-bottom: 10px;
text-align: center;
cursor: pointer;
}
.forum-all .blocks span.one {
line-height: 40px;
background-color: #10a386;
}
.forum-all .blocks span.two {
line-height: 40px;
background-color: #0084ff;
}
.forum-all .blocks span.three {
background-color: #008fd5;
}
.forum-all .blocks span.back {
/* margin-top: 350px; */
background-color: #008fd5;
}
.toTOP {
margin-top: -10% !important;
}

.forum-all {
width: 100%;
background-color: #fff;
border: 1px solid #eee;
overflow: hidden;
position: relative;
}
.forum-all .btn {
float: right;
box-sizing: border-box;
position: absolute;
top: 8px;
right: 26px;
}
/* ????��???? */
.fontcolorblue {
color: #0285ff;
}
.imgBg-skyblue-radius {
display: block;
width: 40px;
height: 40px;
background-color: #86c0e4;
position: relative;
border-radius: 50%;
}
.colorblue {
color: #369eff;
}
.colorgreen {
color: #42b69f;
}
.colorred {
color: #e04639;
}
/* ???��???? */
.breadLink {
width: 40%;
/* padding: 20px 20px */
}
/* ???????? */
.detaiContent {
width: 70%;
overflow: hidden;
padding: 0 20px;
float: left;
}
.detaiContent .intro {
width: 100%;
padding: 20px;
border: 1px solid #eee;
overflow: hidden;
box-sizing: border-box;
margin-bottom: 20px;
}
.detaiContent .intro .introtitle {
width: 100%;
overflow: hidden;
border-bottom: 1px solid #eee;
}
.detaiContent .intro .left {
width: 60%;
float: left;
}
.detaiContent .intro .left h1 {
margin: 0;
font: 16px "microsoft yahei";
text-align: left;
position: relative;
}
.detaiContent .intro .left h1 div.subtitle {
position: absolute;
top: 0;
left: 70%;
}
.detaiContent .intro .left h1 div.subtitle span {
display: block;
text-align: center;
font: 12px "microsoft yahei";
color: #fff;
line-height: 24px;
width: 60px;
float: left;
margin: 0;
border-radius: 8px;
}
.detaiContent .intro .left h1 div.subtitle span.top {
background-color: #0084ff;
}
.detaiContent .intro .left h1 div.subtitle span.main {
margin-left: 8px;
background-color: #ff3040;
}
.detaiContent .intro .left p {
text-align: left;
}
.detaiContent .intro .left p span {
font: 14px/ 28px "microsoft yahei";
}
.detaiContent .intro .left p span i {
font-style: normal;
color: #0084ff;
margin-left: 8px;
}
/* .detaiContent .intro .left p span.distance {
margin-left: 8px
} */
.detaiContent .intro .right {
float: right;
text-align: right;
}
.detaiContent .intro .right .star {
display: block;
width: 32px;
height: 32px;
font: 24px/ 32px "microsoft yahei";
text-align: center;
background-color: #f2f4f7;
margin-left: 86px;
cursor: pointer;
}
.fontcolororange {
color: #ffba00;
}
.detaiContent .intro .right .operator {
font: 14px/ 28px "microsoft yahei";
}
/* .detaiContent .intro .right .operator span.distance {
margin-left: 14px;
} */
.detaiContent .intro .introbody {
width: 100%;
padding-top: 28px;
}
.detaiContent .intro .introbody h3 {
font: 14px/ 28px "microsoft yahei";
text-align: left;
}
.detaiContent .intro .introbody .desc {
font: 14px/ 28px "microsoft yahei";
text-align: left;
text-indent: 2em;
margin-bottom: 20px;
}

.detaiContent .comment {
width: 100%;
/* padding: 20px; */
border: 1px solid #eee;
overflow: hidden;
box-sizing: border-box;
margin-bottom: 20px;
}
.invitation-content {
width: 100%;
/* border: 1px solid #eee; */
overflow: hidden;
/* margin-bottom: 40px; */
}
.invitation-title {
width: 100%;
padding: 10px 10px;
height: 40px;
line-height: 40px;
overflow: hidden;
position: relative;
border-bottom: 1px solid #eee;
box-sizing: border-box;
}
.invitation-title span {
width: 60px;
display: inline-block;
cursor: pointer;
float: left;
text-align: center;
font: 14px "microsoft yahei";
}
.invitation-title #new {
border-right: 1px solid #eee;
}
.active {
color: #0084ff;
/* background-color: #0084ff; */
}
.comment-bodys {
width: 100%;
/* overflow: hidden;
padding: 0 20px;
box-sizing: border-box */
}
.comment-body {
width: 100%;
overflow: hidden;
padding: 0 20px;
box-sizing: border-box;
}
.comment-body-first {
width: 100%;
overflow: hidden;
padding: 0 0 0 30px;
box-sizing: border-box;
}
.invitation-body {
width: 100%;
height: 80px;
padding: 20px;
border-bottom: 1px solid #eee;
box-sizing: border-box;
overflow: hidden;
}
.head-portrait {
width: 10%;
float: left;
text-align: left;
padding-left: 10px;
}
.head-portrait img {
position: absolute;
top: 5px;
left: 5px;
width: 30px;
height: 30px;
border-radius: 50%;
}
.theme {
width: 53%;
margin-left: 2%;
float: left;
margin: 0;
text-align: left;
}
.theme .commendtitle {
font: 14px "microsoft yahei";
text-align: left;
margin: 0;
cursor: pointer;
}
.theme p {
font: 12px "microsoft yahei";
margin-top: 6px;
text-align: left;
}
.theme p span.distance i {
color: skyblue;
}
.distance {
margin-left: 8px;
}
.state {
float: right;
}
.state .floor {
display: block;
text-align: right;
font: 14px/ 20px "microsoft yahei";
}
.state .commendoperator {
}
.state .commendoperator span {
display: block;
float: left;
cursor: pointer;
font: 14px/ 20px "microsoft yahei";
}
.footerPage {
padding-right: 10px;
}
.footerPage .el-pagination {
margin: 20px 0;
float: right;
}
.publish {
width: 100%;
padding: 10px 10px 10px 60px;
box-sizing: border-box;
border: 1px solid #eee;
overflow: hidden;
position: relative;
margin-bottom: 20px;
}
.uedit {
margin-bottom: 10px;
}
.btnGroup {
width: 100px;
}
.user-portrait {
position: absolute;
top: 16px;
left: 4px;
}
.user-portrait img {
width: 40px;
height: 40px;
border-radius: 50%;
}

.detailRight {
width: 26%;
float: left;
padding: 0 20px 0 0;
box-sizing: border-box;
/* margin-right: 1%; */
}
.detailRight .usercontent {
width: 100%;
border: 1px solid #eee;
box-sizing: border-box;
margin-bottom: 10px;
}
.detailRight .usercontent .userImage {
background-color: #ebeef5;
width: 70px;
height: 70px;
border-radius: 50%;
box-sizing: border-box;
padding-top: 5px;
margin: 20px auto;
}
.detailRight .usercontent .userImage img {
width: 60px;
height: 60px;
border-radius: 50%;
cursor: pointer;
}
.detailRight .usercontent .userbody {
width: 100%;
margin: 0 auto;
overflow: hidden;
display: flex;
justify-content: center;
margin-bottom: 40px;
}
.detailRight .usercontent .userbody span {
display: block;
width: 60px;
font: 14px "microsoft yahei";
text-align: center;
float: left;
cursor: pointer;
}
.detailRight .usercontent .userbody span.border {
border-right: 1px solid #eee;
}
.detailRight .usercontent .userbody span i {
font-style: normal;
color: #2d97ff;
}
.detailRight .usercontent h3 {
font: 600 14px "microsoft yahei";
}
.detailRight .dynamic {
border: 1px solid #eee;
box-sizing: border-box;
}
.detailRight .dynamic h3 {
height: 40px;
background-color: #f7f8fa;
font: 600 14px/ 28px "microsoft yahei";
line-height: 40px;
text-align: center;
margin: 0;
border-bottom: 1px solid #eee;
}
.detailRight .dynamic .article span {
display: block;
font: 14px "microsoft yahei";
cursor: pointer;
height: 40px;
line-height: 40px;
text-align: center;
border-bottom: 1px solid #eee;
}
.detailRight .dynamic .article span:last-of-type {
border-bottom: none;
}
.detailRight .dynamic .article span:hover {
color: #0084ff;
text-decoration: underline;
}
</ style >

3.set.vue(评论组件)页面



</ script >
< style scoped >
.forum-container {
width: 80%;
margin: 0 auto;
padding: 2% 6%;
clear: both;
position: relative;
}
.forum-all .blocks {
position: fixed;
margin-left: 81%;
margin-top: 10%;
z-index: 99;
transition: all ease 0.8s;
}
.forum-all .blocks span {
display: block;
width: 40px;
height: 40px;
font: 14px "microsoft yahei";
color: #fff;
z-index: 1;
box-sizing: border-box;
margin-bottom: 10px;
text-align: center;
cursor: pointer;
}
.forum-all .blocks span.one {
line-height: 40px;
background-color: #10a386;
}
.forum-all .blocks span.two {
line-height: 40px;
background-color: #0084ff;
}
.forum-all .blocks span.three {
background-color: #008fd5;
}
.forum-all .blocks span.back {
/* margin-top: 350px; */
background-color: #008fd5;
}
.toTOP {
margin-top: -10% !important;
}

.forum-all {
width: 100%;
background-color: #fff;
border: 1px solid #eee;
overflow: hidden;
position: relative;
}
.forum-all .btn {
float: right;
box-sizing: border-box;
position: absolute;
top: 8px;
right: 26px;
}
/* ????��???? */
.fontcolorblue {
color: #0285ff;
}
.imgBg-skyblue-radius {
display: block;
width: 40px;
height: 40px;
background-color: #86c0e4;
position: relative;
border-radius: 50%;
}
.colorblue {
color: #369eff;
}
.colorgreen {
color: #42b69f;
}
.colorred {
color: #e04639;
}
/* ???��???? */
.breadLink {
width: 40%;
/* padding: 20px 20px */
}
/* ???????? */
.detaiContent {
width: 70%;
overflow: hidden;
padding: 0 20px;
float: left;
}
.detaiContent .intro {
width: 100%;
padding: 20px;
border: 1px solid #eee;
overflow: hidden;
box-sizing: border-box;
margin-bottom: 20px;
}
.detaiContent .intro .introtitle {
width: 100%;
overflow: hidden;
border-bottom: 1px solid #eee;
}
.detaiContent .intro .left {
width: 60%;
float: left;
}
.detaiContent .intro .left h1 {
margin: 0;
font: 16px "microsoft yahei";
text-align: left;
position: relative;
}
.detaiContent .intro .left h1 div.subtitle {
position: absolute;
top: 0;
left: 70%;
}
.detaiContent .intro .left h1 div.subtitle span {
display: block;
text-align: center;
font: 12px "microsoft yahei";
color: #fff;
line-height: 24px;
width: 60px;
float: left;
margin: 0;
border-radius: 8px;
}
.detaiContent .intro .left h1 div.subtitle span.top {
background-color: #0084ff;
}
.detaiContent .intro .left h1 div.subtitle span.main {
margin-left: 8px;
background-color: #ff3040;
}
.detaiContent .intro .left p {
text-align: left;
}
.detaiContent .intro .left p span {
font: 14px/ 28px "microsoft yahei";
}
.detaiContent .intro .left p span i {
font-style: normal;
color: #0084ff;
margin-left: 8px;
}
/* .detaiContent .intro .left p span.distance {
margin-left: 8px
} */
.detaiContent .intro .right {
float: right;
text-align: right;
}
.detaiContent .intro .right .star {
display: block;
width: 32px;
height: 32px;
font: 24px/ 32px "microsoft yahei";
text-align: center;
background-color: #f2f4f7;
margin-left: 86px;
cursor: pointer;
}
.fontcolororange {
color: #ffba00;
}
.detaiContent .intro .right .operator {
font: 14px/ 28px "microsoft yahei";
}
/* .detaiContent .intro .right .operator span.distance {
margin-left: 14px;
} */
.detaiContent .intro .introbody {
width: 100%;
padding-top: 28px;
}
.detaiContent .intro .introbody h3 {
font: 14px/ 28px "microsoft yahei";
text-align: left;
}
.detaiContent .intro .introbody .desc {
font: 14px/ 28px "microsoft yahei";
text-align: left;
text-indent: 2em;
margin-bottom: 20px;
}

.detaiContent .comment {
width: 100%;
/* padding: 20px; */
border: 1px solid #eee;
overflow: hidden;
box-sizing: border-box;
margin-bottom: 20px;
}
.invitation-content {
width: 100%;
/* border: 1px solid #eee; */
overflow: hidden;
/* margin-bottom: 40px; */
}
.invitation-title {
width: 100%;
padding: 10px 10px;
height: 40px;
line-height: 40px;
overflow: hidden;
position: relative;
border-bottom: 1px solid #eee;
box-sizing: border-box;
}
.invitation-title span {
width: 60px;
display: inline-block;
cursor: pointer;
float: left;
text-align: center;
font: 14px "microsoft yahei";
}
.invitation-title #new {
border-right: 1px solid #eee;
}
.active {
color: #0084ff;
/* background-color: #0084ff; */
}
.comment-bodys {
width: 100%;
/* overflow: hidden;
padding: 0 20px;
box-sizing: border-box */
}
.comment-body {
width: 100%;
overflow: hidden;
padding: 0 20px;
box-sizing: border-box;
}
.comment-body-first {
width: 100%;
overflow: hidden;
padding: 0 0 0 30px;
box-sizing: border-box;
}
.invitation-body {
width: 100%;
height: 80px;
padding: 20px;
border-bottom: 1px solid #eee;
box-sizing: border-box;
overflow: hidden;
}
.head-portrait {
width: 10%;
float: left;
text-align: left;
padding-left: 10px;
}
.head-portrait img {
position: absolute;
top: 5px;
left: 5px;
width: 30px;
height: 30px;
border-radius: 50%;
}
.theme {
width: 53%;
margin-left: 2%;
float: left;
margin: 0;
text-align: left;
}
.theme .commendtitle {
font: 14px "microsoft yahei";
text-align: left;
margin: 0;
cursor: pointer;
}
.theme p {
font: 12px "microsoft yahei";
margin-top: 6px;
text-align: left;
}
.theme p span.distance i {
color: skyblue;
}
.distance {
margin-left: 8px;
}
.state {
float: right;
}
.state .floor {
display: block;
text-align: right;
font: 14px/ 20px "microsoft yahei";
}
.state .commendoperator {
}
.state .commendoperator span {
display: block;
float: left;
cursor: pointer;
font: 14px/ 20px "microsoft yahei";
}
.footerPage {
padding-right: 10px;
}
.footerPage .el-pagination {
margin: 20px 0;
float: right;
}
.publish {
width: 100%;
padding: 10px 10px 10px 60px;
box-sizing: border-box;
border: 1px solid #eee;
overflow: hidden;
position: relative;
margin-bottom: 20px;
}
.uedit {
margin-bottom: 10px;
}
.btnGroup {
width: 100px;
}
.user-portrait {
position: absolute;
top: 16px;
left: 4px;
}
.user-portrait img {
width: 40px;
height: 40px;
border-radius: 50%;
}

.detailRight {
width: 26%;
float: left;
padding: 0 20px 0 0;
box-sizing: border-box;
/* margin-right: 1%; */
}
.detailRight .usercontent {
width: 100%;
border: 1px solid #eee;
box-sizing: border-box;
margin-bottom: 10px;
}
.detailRight .usercontent .userImage {
background-color: #ebeef5;
width: 70px;
height: 70px;
border-radius: 50%;
box-sizing: border-box;
padding-top: 5px;
margin: 20px auto;
}
.detailRight .usercontent .userImage img {
width: 60px;
height: 60px;
border-radius: 50%;
cursor: pointer;
}
.detailRight .usercontent .userbody {
width: 100%;
margin: 0 auto;
overflow: hidden;
display: flex;
justify-content: center;
margin-bottom: 40px;
}
.detailRight .usercontent .userbody span {
display: block;
width: 60px;
font: 14px "microsoft yahei";
text-align: center;
float: left;
cursor: pointer;
}
.detailRight .usercontent .userbody span.border {
border-right: 1px solid #eee;
}
.detailRight .usercontent .userbody span i {
font-style: normal;
color: #2d97ff;
}
.detailRight .usercontent h3 {
font: 600 14px "microsoft yahei";
}
.detailRight .dynamic {
border: 1px solid #eee;
box-sizing: border-box;
}
.detailRight .dynamic h3 {
height: 40px;
background-color: #f7f8fa;
font: 600 14px/ 28px "microsoft yahei";
line-height: 40px;
text-align: center;
margin: 0;
border-bottom: 1px solid #eee;
}
.detailRight .dynamic .article span {
display: block;
font: 14px "microsoft yahei";
cursor: pointer;
height: 40px;
line-height: 40px;
text-align: center;
border-bottom: 1px solid #eee;
}
.detailRight .dynamic .article span:last-of-type {
border-bottom: none;
}
.detailRight .dynamic .article span:hover {
color: #0084ff;
text-decoration: underline;
}
</ style >

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值