简体   繁体   中英

Why is this data not correctly passing from parent component to child component, in vue.js?

I have a vue component responsible for pagination, so that only 20 items are shown per page. Everything is working except for the one value that I need passed down from the parent component, the 'count' value that returns the total number of items.

I use the 'count' value to calculate whether the "Next Page" button is active or not and what the total number of pages should be. Using console.log I can see that the 'count' value returns correctly in to the parent component, but it always comes back as undefined in the child pagination component. Please advise how I can fix this.

(I'm not sure if using watch here is correct; I thought it would solve the problem, but it changed nothing.)

EDIT : I've posted more of both the child and parent component for better context.

Here is the script of the child component:

<script>
  export default {
    name: 'Pagination',
    props: ['count'],
    watch: {
      count: function (val, oldVal) {}
    },
    data () {
      return {
        currentPage: 1,
        limit: 20,
        paginationVisible: true,
        firstPageIsCurrent: true,
        prevEllipsisVisible: false,
        pageLink1: 2,
        pageLink1Visible: true,
        pageLink1IsCurrent: false,
        pageLink2: 3,
        pageLink2Visible: true,
        pageLink2IsCurrent: false,
        pageLink3: 4,
        pageLink3Visible: true,
        pageLink3IsCurrent: false,
        nextEllipsisVisible: true,
        lastPageVisible: true,
        lastPageIsCurrent: false,
        prevDisabled: true,
        nextDisabled: false,
        lastPage: 1
      }
    },
    methods: {
      handlePrev () {
        if (!this.prevDisabled) {
          this.currentPage -= 1
          this.paginate()
        }
      },
      handleNext () {
        if ((this.currentPage * this.limit) < this.count) {
          this.currentPage += 1
          this.paginate()
        }
      },
      handleFirstPage () {
        if (this.currentPage !== 1) {
          this.currentPage = 1
          this.paginate()
        }
      },
      handlePageLink1 () {
        if (this.currentPage !== this.pageLink1) {
          this.currentPage = this.pageLink1
          this.paginate()
        }
      },
      handlePageLink2 () {
        if (this.currentPage !== this.pageLink2) {
          this.currentPage = this.pageLink2
          this.paginate()
        }
      },
      handlePageLink3 () {
        if (this.currentPage !== this.pageLink3) {
          this.currentPage = this.pageLink3
          this.paginate()
        }
      },
      handleLastPage () {
        if (this.currentPage < this.lastPage) {
          this.currentPage = this.lastPage
          this.paginate()
        }
      },
      paginateAdjust () {
        console.log(this.count)
        // adjust pagination bar and previous/next buttons
        this.nextDisabled = ((this.currentPage * this.limit) >= this.count)
        this.prevDisabled = (this.currentPage === 1)
        const pageCount = Math.ceil(this.count / this.limit)
        // console.log(pageCount + ', cp: ' + this.currentPage)
        if (pageCount === 1) {
          this.paginationVisible = false
        } else {
          this.paginationVisible = true
          // first page link
          this.firstPageIsCurrent = this.currentPage === 1
          // previous ellipsis
          this.prevEllipsisVisible = this.currentPage > 3 && pageCount > 5
          // first page link
          this.pageLink2Visible = pageCount > 2
          if (this.currentPage < 4) {
            this.pageLink1 = 2
          } else if ((pageCount - this.currentPage) < 3) {
            this.pageLink1 = pageCount - 3
          } else {
            this.pageLink1 = this.currentPage - 1
          }
          this.pageLink1IsCurrent = this.pageLink1 === this.currentPage
          // second page link
          this.pageLink2Visible = pageCount > 3
          if (this.currentPage < 4) {
            this.pageLink2 = 3
           } else if ((pageCount - this.currentPage) < 3) {
            this.pageLink2 = pageCount - 2
          } else {
            this.pageLink2 = this.currentPage
          }
           this.pageLink2IsCurrent = this.pageLink2 === this.currentPage
          // third page link
          this.pageLink3Visible = pageCount > 4
          if (this.currentPage < 4) {
            this.pageLink3 = 4
          } else if ((pageCount - this.currentPage) < 3) {
            this.pageLink3 = pageCount - 1
          } else {
            this.pageLink3 = this.currentPage + 1
          }
          this.pageLink3IsCurrent = this.pageLink3 === this.currentPage
          // next ellipsis
          this.nextEllipsisVisible = ((pageCount - this.currentPage) >= 3) && pageCount > 5
          // last page
          this.lastPage = pageCount
          this.lastPageIsCurrent = this.currentPage === pageCount
        }
      },
      emitMSQ () {
        this.$emit('msq', this.currentPage, this.limit)
      },
      paginate () {
        this.paginateAdjust()
        this.emitMSQ()
      }
    },
    created () {
      this.paginate()
    }
  }
</script>

Here is the (relevant) script from the parent component:

export default {
  name: 'index',
  components: {Pagination},
  computed: {
    apps () {
      return this.$store.state.apps
    }
  },
  data () {
    return {
      apps: [],
      count: 0,
      searchAddress: ''
    }
  },
  methods: {
    onSearch () {
      if (this.searchAddress.length === 12 || this.searchAddress.length === 0) {
        this.currentPage = 1
        this.makeServerQuery()
      }
    },
    makeServerQuery (cp, pp) {
      let queryStr = '?uid=' + this.$auth.user().id + '&cp=' + cp + '&pp=' + pp
      if (this.searchAddress.length === 12) {
        queryStr += '&se=' + this.searchAddress
      }
      this.$http.get('/apps' + queryStr).then(res => {
        this.apps = res.data.apps
        this.count = res.data.count
        console.log(this.count + ' msq()')
      })
    },

The emit, server query, and actual pagination elements all work fine. But my next page button is wrong and the last page button displays NaN because it can't run the correct calculations when count === undefined .

Thanks in advance for the help.

From your comments, it looks like you are not really passing anything to your component's prop.

As @Dan suggested, your count prop is undefined because nothing is being passed to it from the parent. To pass the count data property from the parent to the child you need to use a template binding <child v-bind:count="count"></child> or its shorthand <child :count="count"></child> .

The official documentation is a good starting point for understanding props.

Here's a minimal example.

 Vue.config.productionTip = false; Vue.component('child', { template: ` <div class="child"> from parent: {{count}} <br> <button :disabled="!enableNext" @click="onNext">Next</button> </div> `, props: ['count'], computed: { enableNext() { return this.count && this.count > 0; } }, methods: { onNext() { console.log('Go to page ' + this.count + 1) } } }) new Vue({ el: '#app', template: ` <div class="parent"> Parent count: {{ count }} <child :count="count" /> <br> <button @click="count++">Increment count</button> </div> `, data:() => ({ count: 0 }) });
 div { border: solid 1px black; padding: 1em; } .child { background: lightgray; } button:disabled, button[disabled]{ border: 1px solid #999999; background-color: #cccccc; color: #666666; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"></div>

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