【问题标题】:How can I show data from 2 level child component by clicking a button in the main instance?如何通过单击主实例中的按钮来显示来自 2 级子组件的数据?
【发布时间】:2018-02-15 03:14:32
【问题描述】:

假设我有一个主实例,一个名为“movie-card”的子组件和另一个名为“link-btn”的“movie-card”子组件。问题是我想用 v-for 构建一个循环“link-btn”组件的选择器,而且我想在主实例中有一个按钮,显示每个“link-btn”组件选择的数据。代码如下:

HTML:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
        <title>Test</title>
    </head>
    <body>
        <div id="app">
            <movie-card
                v-for="(movie, index) in movies"
                key="index"
                :movie="movie"
                :title="movie.title"
                :description="movie.desc"
                :review="movie.review">
            </movie-card>
            <a>BUTTON TO SHOW REVIEWS SELECTED</a>
        </div>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
        <script src="https://unpkg.com/vuex@2.4.0/dist/vuex.js"></script>
        <script src="app.js"></script>
    </body>
</html>

JS:

Vue.component('movie-card', {
    props: ['movie', 'title', 'description', 'review'],
    template: `
        <div>
            <h2>{{ title }}</h2>
            <p>{{ description }}</p>
            <link-btn
                v-for="(review, index) in movie.reviews"
                :index="index"
                :review="review"
                key="review"
                @updateIndex="updateI($event)"
                @updateReview="updateR($event)">
            </link-btn>
            <pre>{{ $data }}</pre>
        </div>
    `,
    data() {
        return {
            selectedIndex: '',
            selectedReview: ''
        }
    },
    methods: {
        updateI(e) {
            if(e + 1 === this.selectedIndex) {
                this.selectedIndex = ''
            } else {
                this.selectedIndex = e + 1
            }
        },
        updateR(e) {
            if(e.id === this.selectedReview.id) {
                this.selectedReview = ''
            } else {
                this.selectedReview = e
            }
        }
    }
})

Vue.component('link-btn', {
    props: ['index', 'review'],
    template: `
        <a @click="change">{{ review.content }}</a>
    `,
    methods: {
        change() {
            this.$emit('updateIndex', this.index)
            this.$emit('updateReview', this.review)
        }
    }
})

new Vue({
    el: '#app',
    data: {
        added: [],
        movies: [
            {
                title: 'Regreso al futuro',
                desc: 'Esto es la descripción de Regreso al futuro',
                reviews: [
                    { id: 1, content: 'Blabla...', stars: 2, active: false },
                    { id: 2, content: 'Blabla...', stars: 3, active: false },
                    { id: 3, content: 'Blabla...', stars: 1, active: false }
                ]
            },
            {
                title: 'Titanic',
                desc: 'Esto es la descripción de Titanic',
                reviews: [
                    { id: 1, content: 'Blabla...', stars: 2, active: false },
                    { id: 2, content: 'Blabla...', stars: 3, active: false },
                    { id: 3, content: 'Blabla...', stars: 1, active: false }
                ]
            },
            {
                title: 'Blade Runner',
                desc: 'Esto es la descripción de Blade Runner',
                reviews: [
                    { id: 1, content: 'Blabla...', stars: 2, active: false },
                    { id: 2, content: 'Blabla...', stars: 3, active: false },
                    { id: 3, content: 'Blabla...', stars: 1, active: false }
                ]
            }
        ]
    }
})

【问题讨论】:

    标签: javascript arrays vue.js


    【解决方案1】:

    您需要将所选评论冒泡到顶层。我在updateR 方法中添加了一个$emit,并在movie-card 标记上添加了一个处理程序,该处理程序调用了一个新方法updateReview,它填充了added 的适当元素。

    我只是让它显示added,但你可以让你的按钮显示/隐藏一个包含added的div。

    Vue.component('movie-card', {
      props: ['movie', 'title', 'description', 'review'],
      template: `
            <div>
                <h2>{{ title }}</h2>
                <p>{{ description }}</p>
                <link-btn
                    v-for="(review, index) in movie.reviews"
                    :index="index"
                    :review="review"
                    key="review"
                    @updateIndex="updateI($event)"
                    @updateReview="updateR($event)">
                </link-btn>
                <pre>{{ $data }}</pre>
            </div>
        `,
      data() {
        return {
          selectedIndex: '',
          selectedReview: ''
        }
      },
      methods: {
        updateI(e) {
          if (e + 1 === this.selectedIndex) {
            this.selectedIndex = ''
          } else {
            this.selectedIndex = e + 1
          }
        },
        updateR(e) {
          if (e.id === this.selectedReview.id) {
            this.selectedReview = ''
          } else {
            this.selectedReview = e
          }
          this.$emit('update-review', this.selectedReview);
        }
      }
    })
    
    Vue.component('link-btn', {
      props: ['index', 'review'],
      template: `
            <a @click="change">{{ review.content }}</a>
        `,
      methods: {
        change() {
          this.$emit('updateIndex', this.index)
          this.$emit('updateReview', this.review)
        }
      }
    })
    
    new Vue({
      el: '#app',
      data: {
        added: [],
        movies: [{
            title: 'Regreso al futuro',
            desc: 'Esto es la descripción de Regreso al futuro',
            reviews: [{
                id: 1,
                content: 'Blabla...',
                stars: 2,
                active: false
              },
              {
                id: 2,
                content: 'Blabla...',
                stars: 3,
                active: false
              },
              {
                id: 3,
                content: 'Blabla...',
                stars: 1,
                active: false
              }
            ]
          },
          {
            title: 'Titanic',
            desc: 'Esto es la descripción de Titanic',
            reviews: [{
                id: 1,
                content: 'Blabla...',
                stars: 2,
                active: false
              },
              {
                id: 2,
                content: 'Blabla...',
                stars: 3,
                active: false
              },
              {
                id: 3,
                content: 'Blabla...',
                stars: 1,
                active: false
              }
            ]
          },
          {
            title: 'Blade Runner',
            desc: 'Esto es la descripción de Blade Runner',
            reviews: [{
                id: 1,
                content: 'Blabla...',
                stars: 2,
                active: false
              },
              {
                id: 2,
                content: 'Blabla...',
                stars: 3,
                active: false
              },
              {
                id: 3,
                content: 'Blabla...',
                stars: 1,
                active: false
              }
            ]
          }
        ]
      },
      methods: {
        updateReview(index, review) {
          while (this.added.length < index) {
            this.added.push(null);
          }
          this.added.splice(index, 1, review);
          
        }
      }
    });
    <script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
    <div id="app">
      <movie-card v-for="(movie, index) in movies" key="index" :movie="movie" :title="movie.title" :description="movie.desc" :review="movie.review" @update-review="updateReview(index, $event)">
      </movie-card>
      <a>BUTTON TO SHOW REVIEWS SELECTED</a>
      <div v-for="r, i in added">
        {{i}}: {{r}}
      </div>
    </div>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-02
      • 1970-01-01
      • 2015-06-25
      • 1970-01-01
      • 2021-12-12
      • 1970-01-01
      相关资源
      最近更新 更多