了解VueJS中的组件嵌套

时间:2018-10-09 23:02:22

标签: vue.js vue-component

学习VueJS并通过在线学习一些教程,包括vuejs.org上的指南,我真是费劲地了解如何嵌套组件并使它们通过道具进行通信。

一个简单的示例似乎还可以,但是以下代码(稍有调整,但在VueJS指南中却有很多内容)给我带来麻烦。

我似乎无法在'blog-items'中嵌套'blog-item'。

如果有人可以解释如何使用v-for指令嵌套组件,那我将不胜感激。

我已经阅读了许多教程,并且所有内容似乎都可以正常工作,该组件嵌套在提供数据的顶级“应用”组件中,但是我似乎无法将其转换为以下场景。

作为新手,我可能会错过一个关键概念,或者完全不了解Vue:)

希望可以为您提供帮助。

谢谢

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Components Basics - from vuejs.org</title>
    <!-- development version, includes helpful console warnings -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>

  <body>
    <div id="app">

      <!-- This works. I get it. -->
      <div id="components-demo">
        <button-counter></button-counter>
        <button-counter></button-counter>
        <button-counter></button-counter>
      </div>

      <hr>

      <!-- This works too and I get it. -->
      <div id="blog-post-demo-simple">
        <blog-post-simple title="My journey with Vue"></blog-post-simple>
        <blog-post-simple title="Blogging with Vue"></blog-post-simple>
        <blog-post-simple title="Why Vue is so fun"></blog-post-simple>
      </div>

      <hr>

      <!-- This is where I'm totally confused -->
      <!-- How do I structure this to make sure blog-items is binding the 'post'  -->
      <!-- correctly? What is not clear to me is where the directives should be placed -->
      <!-- Vue keeps complainig with the following: -->
      <!-- Property or method "posts" is not defined on the instance but referenced during render -->
      <blog-items>
        <blog-item
          v-for="post in posts"
          v-bind:key="post.id"
          v-bind:post="post">
        </blog-item>
      </blog-items>

      <hr>

    </div>

    <script>

      // Define a new component called button-counter. Cool. No problem here.
      Vue.component('button-counter', {
        data: function () {
          return {
            count: 0
          }
        },
        template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
      })

      // This is also clear.
      Vue.component('blog-post-simple', {
        template:
        '<h3>{{title}}</h3>',
        props: {
          title: {
            type: String,
            required: true
          }
        }
      })

      Vue.component('blog-items', {
        data() { return {
            posts: [
              { id: 1, title: '1. My journey with Vue' },
              { id: 2, title: '2. Blogging with Vue' },
              { id: 3, title: '3. Why Vue is so fun' }
            ]
          }
        }
      })

      Vue.component('blog-item', {
        template:
        '<h2>{{post.title}}</h2>',
        props: ['post']
      })

      var app = new Vue({
        el: '#app'
      })

    </script>
  </body>
</html>

1 个答案:

答案 0 :(得分:2)

请记住,当您访问模板中的属性时,您是从使用该模板的组件中获取该属性的。在这种情况下,它是您的根#app组件。由于该组件没有名称为posts的属性或方法,因此Vue会抱怨。您需要做的就是在blog-items组件的模板中移动该部分,因为该组件正在保存您的帖子。

所以你需要做的是这个..

    <!-- This is where I'm totally confused -->
    <!-- How do I structure this to make sure blog-items is binding the 'post'  -->
    <!-- correctly? What is not clear to me is where the directives should be placed -->
    <!-- Vue keeps complainig with the following: -->
    <!-- Property or method "posts" is not defined on the instance but referenced during render -->
    <blog-items></blog-items>

Vue.component('blog-items', {
    template: `
    <div>
        <blog-item v-for="post in posts" v-bind:key="post.id" v-bind:post="post" />
    </div>
    `,
    data() {
        return {
            posts: [
            { id: 1, title: '1. My journey with Vue' },
            { id: 2, title: '2. Blogging with Vue' },
            { id: 3, title: '3. Why Vue is so fun' }
            ]
        }
    }
})

否则,您将不得不使用Scoped Slots,它允许您将子组件的作用域中的属性/方法公开给父组件。

<blog-items>
    <template slot-scope="{ posts }">
        <blog-item v-for="post in posts" v-bind:key="post.id" v-bind:post="post">
        </blog-item>
    </template>
</blog-items>

Vue.component('blog-items', {
    template:`
    <div>
        <slot :posts="posts"></slot>
    </div>`,
    data() {
        return {
            posts: [
            { id: 1, title: '1. My journey with Vue' },
            { id: 2, title: '2. Blogging with Vue' },
            { id: 3, title: '3. Why Vue is so fun' }
            ]
        }
    }
})

我发现this对于理解作用域插槽的工作方式特别有用。