Vue - 嵌套组件不会更新其数据并重新渲染

Posted

技术标签:

【中文标题】Vue - 嵌套组件不会更新其数据并重新渲染【英文标题】:Vue - Nested component won't update its data and re-render 【发布时间】:2020-07-09 15:45:13 【问题描述】:

这里是场景。我可以上传一个LiteratureReview,每个可以包含一个或多个Quote。所以我拥有的是LiteratureReview(Parent) 和Quote(Child) 组件。我使用 Axios 获取和发布数据。我的后端是 Laravel。

LiteratureReviewQuote 从应用实例中获取数据。发送 post 请求后,LiteratureReview 将更新并重新呈现页面。但是当我想在其文献综述中添加Quote时,它并没有更新,我需要刷新页面。

app.js(或 main.js)

export const app = new Vue(
    el: '#app',

    data: function () 
        return 
            literatureReviews: [],
            quotes: [],
        
    ,
    mounted() 
        axios.all([
            axios.get('/literature-review'),
            axios.get('/quote')
        ]).then(axios.spread((first_response, second_response) => 
            this.literatureReviews = first_response.data
            this.quotes = second_response.data
        ))
    
);

index.blade.php

<literature-review v-for="(literatureReview, index) in literatureReviews" v-bind:loop="index + 1"
            v-bind:key="literatureReview.id" v-bind:literature_review_id="literatureReview.id"
            v-bind:topic="literatureReview.topic" v-bind:type="literatureReview.type"
            v-bind:year="literatureReview.year" v-bind:link="literatureReview.link"></literature-review>

文学评论(组件;父级)

<template>
    <div class="literature-card mb-5 rounded">
        .
        .
        .
        <quote v-for="quote in filterByLiteratureReview(quotes, literature_review_id)" v-bind:key="quote.id"
            v-bind:literature_review_id="literature_review_id" v-bind:quote="quote.quote" v-bind:page="quote.page"></quote>
    </div>
</template>

<script>
    import  app  from '../app.js'
    import  store  from '../app.js'

    export default 
        props: ['loop', 'literature_review_id', 'topic', 'type', 'year', 'link'],
        data() 
            return 
                quotes: app.quotes,
                sharedObject: store,
            
        ,
        methods: 
            filterByLiteratureReview(quotes, literature_review_id) 
                return this.quotes.filter(quote => quote.literature_review_id == literature_review_id)
            ,
            updateLitIdForAddingQuote(value) 
                this.sharedObject.setLiteratureReviewIdAction(value)
            ,
        
    
</script>

引用(组件;子)

<template>
    <div>
        <div class="row no-gutters px-3 pt-3">
            <div class="col" style="white-space: pre-wrap;"> quote </div>
        </div>
        <div class="row no-gutters" style="border-bottom: solid black 2px;">
            <div class="col py-4 pr-3 text-right">Pg  page </div>
        </div>
    </div>
</template>

<script>
    export default 
        props: ['id', 'literature_review_id', 'quote', 'page'],
    
</script>

Axios 发表文献评论

axios.post('/literature-review', 
    topic: this.topic,
    type: this.type,
    year: this.year,
    link: this.link,
).then( response => 
    $('#addSourceModal').modal('hide')
).finally(
    axios.get('/literature-review').then(response => app.literatureReviews = response.data)
)

Axios 发布报价

axios.post('/quote', 
    literature_review_id: this.sharedObject.state.literature_review_id,
    quote: this.quote,
    page: this.page
).then( response => 
    console.log(response)
    $('#addQuoteModal').modal('hide')
    // location.reload();
).finally(
    axios.get('/quote').then(response => app.quotes = response.data)
)

【问题讨论】:

当您发出帖子请求时,您是否在literature-review 中获得更新的道具? 我从一个弹出模式更新数据,它本身是一个组件但与这两个无关 我的意思是,发完帖子后,你能在literature-review componet 看到更新的道具吗? 哦,对于 literature-review 是的,但对于 quote 不是,尽管方法相同 这是由于您的 filterByLiteratureReview 方法而发生的。当数据发生变化时,它不知道再次运行。您可以尝试将其转换为计算属性。或者您需要传递一个key,它会在您发帖时更新。当key改变时,会强制Quote重新渲染。 【参考方案1】:

这个article 在某种程度上帮助我解决了这个问题。所以基本上,数据是从弹出模式的提交按钮更新的。我制作了这个按钮来向根this.$root.$emit('forceRerender') 发出一个事件,该事件在创建时由LiteratureReviewthis.$root.$on('forceRerender', this.forceRerender) 接收。 LiteratureReview 组件然后运行其包含axios.get('/quote').then(response =&gt; this.quotes = response.data)forceRerender()

模态

<script>
    export default 
        props: ['target'],
        methods: 
            submit() 
                this.$emit('submit')
                this.$root.$emit('forceRerender')
            
        
    
</script>

文学评论部分

<script>
    import 
        app
     from '../app.js'
    import 
        store
     from '../app.js'

    export default 
        props: ['loop', 'literature_review_id', 'topic', 'type', 'year', 'link'],
        data() 
            return 
                quotes: app.quotes,
                sharedObject: store,
            
        ,
        created() 
            this.$root.$on('forceRerender', this.forceRerender)
        ,
        methods: 
            filterByLiteratureReview(quotes, literature_review_id) 
                return this.quotes.filter(quote => quote.literature_review_id == literature_review_id)
            ,
            updateLitIdForAddingQuote(value) 
                this.sharedObject.setLiteratureReviewIdAction(value)
            ,
            forceRerender() 
                axios.get('/quote').then(response => this.quotes = response.data)
            
        
    
</script>

【讨论】:

以上是关于Vue - 嵌套组件不会更新其数据并重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

Vuex 全局状态更改不会触发 Nuxt 中 v-for 循环中的重新渲染组件

vue异步渲染

Vue 计算属性已更新,但组件未重新渲染

嵌套反应路由器组件不会在页面重新加载时加载/渲染?

如何将参数传递给Vue组件并在组件模板中重新使用其值

高阶组件状态正在正确更新,但接收道具的包装组件不会在状态更改时重新渲染