在vue2中,v-for嵌套组件道具在父项中删除元素后不会更新

时间:2016-11-27 10:28:57

标签: vue.js vuejs2

对于我的应用,我使用了两个Vue组件。一个提供"天"的列表并且为每个"日提供一个" "位置列表"。例如"第1天和第34天;可以拥有位置" Berlin"," London"," New York"。

在删除"第1天"从视图未被更正的日期列表中。这就是:

  1. 已删除当天的标题 ​​- >正确
  2. 删除的日期内容未被替换 - >不正确
  3. 
    
    Vue.component('day-list', {
      props: ['days'],
      template: '<div><div v-for="(day, index) in dayItems">{{ day.name }} <a href="#" @click.prevent="remove(index)">Remove day</a><location-list :locations="day.locations"></location-list><br/></div></div>',
      data: function() {
        return {
          dayItems: this.days
        }
      },
      methods: {
        remove(index) {
          this.dayItems.splice(index, 1);
        }
      }
    });
    
    Vue.component('location-list', {
      props: ['locations', 'services'],
      template: '<div><div v-for="(location, index) in locationItems">{{ location.name }} <a href="#" @click.prevent="remove(index)"</div></div>',
      data: function() {
        return {
          locationItems: this.locations
        }
      },
      methods: {
        remove(index) {
          this.locationItems.splice(index, 1);
        }
      }
    });
    
    const app = window.app = new Vue({
      el: '#app',
    
      data: function() {
      	return {
        	days: [
            {
              name: 'Day 1',
              locations: [
                {name: 'Berlin'}, 
                {name: 'London'}, 
                {name: 'New York'}
              ]
            },
            {
              name: 'Day 2',
              locations: [
                {name: 'Moscow'}, 
                {name: 'Seul'}, 
                {name: 'Paris'}
              ]
            }
          ]
        }
      },
    
      methods: {}
    });
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.3/vue.js"></script>
    
    
    <div id="app">
      <day-list :days="days"></day-list>
    </div>
    &#13;
    &#13;
    &#13;

1 个答案:

答案 0 :(得分:0)

如果您尚未使用,请使用Vue-devtools。它清楚地显示了问题,如下图所示:

Screenshot from Vue devtools

如上所示,您的day-list组件包含原始列表中的所有日期,其中的位置直接列出。您需要在其间再添加一个组件,将其称为day-details,这将呈现特定日期的信息。您可能在location-list内有day-details

以下是更新后的代码:

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.3/vue.js"></script>

<div id="app">
    <day-list :days="days"></day-list>
</div>
Vue.component('day-list', {
    props: ['days'],
    template: `
        <div>
            <day-details :day="day" v-for="(day, index) in days">
                <a href="#" @click.prevent="remove(index)">Remove day</a>
            </day-details>
        </div>`,
    methods: {
        remove(index) {
            this.days.splice(index, 1);
        }
    }
});

Vue.component('day-details', {
    props: ['day'],
    template: `
        <div>
            {{ day.name }}
            <slot></slot>
            <location-list :locations="day.locations"></location-list>
            <br/>
        </div>`
});

Vue.component('location-list', {
    props: ['locations', 'services'],
    template: `
        <div>
            <div v-for="(location, index) in locations">
                {{ location.name }}
                <a href="#" @click.prevent="remove(index)">[x]</a>
            </div>
        </div>
    `,
    methods: {
        remove(index) {
            this.locations.splice(index, 1);
        }
    }
});

const app = window.app = new Vue({
    el: '#app',

    data: function() {
        return {
            days: [{
                name: 'Day 1',
                locations: [{
                    name: 'Berlin'
                }, {
                    name: 'London'
                }, {
                    name: 'New York'
                }]
            }, {
                name: 'Day 2',
                locations: [{
                    name: 'Moscow'
                }, {
                    name: 'Seul'
                }, {
                    name: 'Paris'
                }]
            }]
        }
    },

    methods: {}
});

另一件事 - location-list的模板有错误 - 您没有关闭<a>元素。您可以使用反引号运算符来获取多行模板,如上例所示,以避免模板错误。

此外,您不应该更改通过props传递的对象。它在这里工作,因为您传递的是通过引用传递的对象。但是在子组件中修改的字符串对象将导致此错误:

  

[Vue警告]:避免直接改变道具......

如果您收到此错误,可以使用事件机制,如此问题的答案中所述:Delete a Vue child component