简体   繁体   中英

Nested components not re-rendering properly: VueJs

I'm new to Vue and I'm building this forum kind of thing which can add nested comments in it. In here there are two components. PostForum and Comment. PostForum contains an input box and parent Comments. And inside each comment, I added child comments recursively.

When I adding comments, It works fine. But when deleting, it sends the ajax req but there's no re-rendering. So this is how I designed it. When deleting a comment, I emit a global event and in PostForum component I listen to that event and deleting that comment from its data. So isn't that supposed to re-render all the comments accordingly? Can anyone tell me what am I doing wrong here?

PostForum.vue

<template>
  <!-- comment box here -->

  <comment
    v-for="(comment, index) in comments" 
    v-if="!comment.parent_id"
    :reply="true" 
    :initialChildren="getChildren(comment.id)" 
    :key="index" 
    :comment="comment">
  </comment>
</template>

<script>
export default {
  data () {
    return {
      comments: [], // all comments
        comment: { // new comment [at comment box]
            body: '',
            parent_id: 0,
        },
    }
  },
  methods: {
    deleteComment (node) {
        axios.delete(`/comments/${node.id}`)
            .then(res => {
                this.comments.splice(node.key, 1)
            })
            .catch(err => {
                console.log(err)
            })
    },
    getChildren: function (parent_id) {
        return this.comments.filter(child => parent_id == child.parent_id)
    },
  },
  mounted: function () {
    window.Event.$on('comment-deleted', (node) => this.deleteComment(node))
  }
}
</script>

Comment.vue

<template>
  <button @click="deleteComment">X</button>

  <!-- comment body goes here -->

  <comment v-for="(child, i) in children" :key="i" :reply="false" :comment="child"></comment>

  <!-- reply form here -->
</template>

<script>
export default {
  props: ['initialChildren']
  data: function () {
    return {
        newComment: {
            body: '',
            parent_id: this.comment.id,
        },
        children: this.initialChildren,
    }
  },
  methods: {
    deleteComment () {
        window.Event.$emit('comment-deleted', {key: this.$vnode.key, id: this.comment.id})
    },
  }
}
</script>

I've tried this:

This code is just an example that may help you. In my case, child component is comment component in your case, and each child component has its own @action listener for his child component. So, he can use that to modify his own childrens .

Here is an example on codesandbox: https://codesandbox.io/s/qzrp4p3qw9

ParentComponent

<template>
    <div>
        <Child v-for="(children,index) in childrens" :child="children" :key="index" :parent="0" :pos="index"></Child>
    </div>
</template>
import Child from './child'; 
export default {
    data() {
        return {
            childrens:[
                {
                    name:"a",
                    childrens:[
                        {
                            name:'aa',
                        },
                        {
                            name:'ba',
                            childrens:[
                                {
                                    name:'baa',
                                    childrens:[
                                        {
                                            name:'baaa',
                                        },
                                        {
                                            name:'baab',
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                },
                {
                    name:"a",
                    childrens:[
                        {
                            name:'aa',
                        },
                        {
                            name:'ab',
                            childrens:[
                                {
                                    name:'aba',
                                    childrens:[
                                        {
                                            name:'abaa',
                                            childrens:[
                                                {
                                                    name:'baa',
                                                    childrens:[
                                                        {
                                                            name:'baaa',
                                                        },
                                                        {
                                                            name:'baa',
                                                        }
                                                    ]
                                                }
                                            ]
                                        },
                                        {
                                            name:'abab',
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    },
    components:{
        Child
    }
}

ChildComponent

<template>
    <div>
        <div style="padding:5px">
            {{ child.name }}
            <button @click="deleteComment(child)">x</button>
        </div> 
        <child @delete="deleteSubComment" style="padding-left:15px" v-if="typeof child.childrens !== 'undefined'" v-for="(children,index) in child.childrens" :child="children" :pos="index" :key="index" :parent="children.parent"></child>
    </div>
</template>
export default {
    name:"child",
    props:['child','parent',"pos"],
    methods:{
        deleteComment(child) {
            this.$emit('delete',child);
        },
        deleteSubComment(obj) {

            this.child.childrens.splice(this.child.childrens.indexOf(obj),1);
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM