vue-carousel goToPage 以编程方式更改到选定页面

vue-carousel goToPage to programmatically change to selected page

我正在将一组位置传递到 vue-carousel。我在页面上的其他几个地方使用相同的集合,将选定的位置发送到 eventHub 中的根,这是存储位置和选定位置的位置。

棘手的部分是让轮播移动到正确的页面 - 我使用 perPageCustom 选项在较大的视口中一次显示三个位置,在较小的视口中只显示一个。我在 laravel 中的 api 中创建键并根据 window 的大小,我正在移动到正确的页面并且一切正常,但是当它加载时我得到一个错误因为当 watcher 第一次启动时 ref 不存在。我知道这就是问题所在,但我不确定如何在位置发生变化时设置观察器,它不会在页面加载时观察...也许使用挂载?

我的组件:

<template>
    <div>
        <h3>Locations ({{locations.length}})</h3>
        <p class="lead">Serving California in the greater Sacramento and Los Angeles areas.</p>
        <carousel v-if="locations.length > 0" ref="locations-carousel" :scrollPerPage="true" :perPage="1" :perPageCustom="[[480, 1], [768, 3]]" v-on:pageChange="pageChange">
          <slide v-for="loc in locations" :key="loc.id">
            <div class="card" style="width: 18rem;" v-bind:class="{ closest: loc.is_closest,  active: loc.id == location.id }">
              <img v-on:click="changeLocation(loc.id)" v-if="loc.is_comingsoon === 0" class="card-img-top" :src="'/assets/images/location_'+loc.pathname+'.jpg'" alt="Card image cap">
              <img v-on:click="changeLocation(loc.id)" v-if="loc.is_comingsoon === 1" class="card-img-top" :src="'/assets/images/coming-soon.png'" alt="Card image cap">
              <div class="card-body">
                <h5 class="card-title" v-on:click="changeLocation(loc.id)">{{ loc.name }}</h5>
                <p class="card-text">{{ loc.address }}<br>{{ loc.city_name }}<br>{{ loc.phone | phone }}</p>
                <div class="btn-group" role="group" aria-label="Location Buttons">
                  <a class="btn btn-outline btn-default" :href="'tel:'+ loc.phone"><font-awesome-icon icon="phone"></font-awesome-icon> call</a>
                  <a class="btn btn-outline btn-default" :href="loc.map"><font-awesome-icon icon="globe"></font-awesome-icon> map</a>
                  <a class="btn btn-outline btn-default" v-on:click="changeLocation(loc)" v-bind:class="{ active: loc.id == location.id }"><font-awesome-icon icon="star"></font-awesome-icon> pick</a>
                </div>
                <p class="card-text">{{ loc.note }}</p>
                <span class="badge badge-closest" v-if="loc.is_closest"><font-awesome-icon icon="map-marker"></font-awesome-icon> closest detected</span>
                <span class="badge badge-active" v-if="loc.id == location.id"><font-awesome-icon icon="star"></font-awesome-icon> selected <font-awesome-icon icon="angle-double-down" :style="{ color: 'white' }"></font-awesome-icon></span>
              </div>
            </div>
          </slide>
        </carousel>
        <font-awesome-icon icon="spinner" size="lg" v-if="locations.length < 1"></font-awesome-icon>
    </div>
</template>
<script>
    Vue.filter('phone', function (phone) {
        return phone.replace(/[^0-9]/g, '')
                    .replace(/(\d{3})(\d{3})(\d{4})/, '() -');
    });
    import { Carousel, Slide } from 'vue-carousel';
    var axios = require("axios");
    export default {
        name: 'locations-carousel',
        props: ['location', 'pg', 'locations'],
        components: {
            Carousel,
            Slide
        },
        data() {
            return {
                debounce: null,
                subs: {},
                clear: 0
            };
        },
        watch: { 
            location: function(newVal, oldVal) { // watch it
                console.log('Prop changed: ', newVal, ' | was: ', oldVal)
                console.log('key: '+this.location.key);
                if( window.innerWidth > 481 ) {
                    if( this.location.pg == 1 ) {
                        this.$refs['locations-carousel'].goToPage(-0);
                    } else {
                        this.$refs['locations-carousel'].goToPage(1);
                    }   
                } else {
                    this.$refs['locations-carousel'].goToPage(this.location.key);
                }
            }
        },
        methods: {
            pageChange(i){ 
                console.log('current Index', i); 
            },
            changeLocation(location) {
                this.$eventHub.$emit('location-loaded', location);              
            }
        }
    }

</script>

我遇到的错误:

[Vue warn]: Error in callback for watcher "location": "TypeError: 
Cannot read property 'goToPage' of undefined"

found in

---> <LocationsCarousel> at resources/assets/js/components/LocationsCarousel.vue
   <Root>

TypeError: Cannot read property 'goToPage' of undefined
at VueComponent.location (app.js?v=0.1:53288)
at Watcher.run (app.js?v=0.1:3937)
at flushSchedulerQueue (app.js?v=0.1:3685)
at Array.<anonymous> (app.js?v=0.1:2541)
at flushCallbacks (app.js?v=0.1:2462)

也许你可以先检查一下 this.$refs['locations-carousel'] 是否存在,然后再访问它的 properties/methods ..

watch: {
  location: function(newVal, oldVal) { // watch it
    console.log('Prop changed: ', newVal, ' | was: ', oldVal)
    console.log('key: ' + this.location.key);
    const locationsCarousel = this.$refs['locations-carousel']
    if (window.innerWidth > 481) {
      if (this.location.pg == 1) {
        locationsCarousel && locationsCarousel.goToPage(-0);
      } else {
        locationsCarousel && locationsCarousel.goToPage(1);
      }
    } else {
      locationsCarousel && locationsCarousel.goToPage(this.location.key);
    }
  }
},