vue axios 异步请求数据时 better-scroll不能初始化成功

发布于 2022-09-06 11:48:10 字数 7206 浏览 13 评论 0

1、vue 项目中使用axios异步请求数据
2、slide 图片滚动使用的是better-scroll插件
3、使用的vue slot插槽封装了better-scroll slide方法
4、第一次初始化不成功 获取不到滚动的width
5、父组件代码:

<template>
    <div>
        <div class="slide-wrap">
            <slide :homelist.sync="homelist" :autoPlay="isAutoPlay" :loop="isLoop" :showDot="isShowDot" :interval="interval" :threshold="threshold" :speed="speed">
              <div v-for="(item,index) in homelist" :key="index">
                  <a :href="item.advContent">
                    <img class="needsclick" :src="item.advTitle" alt="">
                  </a>
              </div>
            </slide>
        </div>
     </div>

</template>
<script>
    import { getCommonAdv} from '@/api'
    import slide from '@/components/pageRender/slideRender'

    export default {
        data(){
            return {
                homelist: [],
                newslist: [],
                isAutoPlay: true,
                isLoop: true,
                isShowDot: true,
                speed: 400,
                threshold: 0.3,
                interval: 4000
            }
        },
        created() {
           this.getIndexBanner();    
        },
          methods: {
              getIndexBanner() {
                  let params = {apGradeno:'index_adv'}
                getCommonAdv(params).then(res => {  //此处是封装axios API请求
                        this.homelist = res.adv_list
                        console.log('11111')
                  }).catch(e => {
                      console.log(e);
                  });
                }
          },
        components: {
            slide
        }
    }
</script>

6、子组件代码

<template>
  <div class="slider" ref="slide">
    <div class="slider-group" ref="group">
      <slot></slot>
      <!--slot插槽说明 
        外部引用slide时,slider包裹的DOM会被插入进这个slot插槽部分 
        eg:
         在相关页面需要引用slide组件的地方写下如下代码:
         <slide>
            <div>...这里写循环的内容与结构....</div>
         </slide>
      -->
    </div>
    <div class="dots">
      <span class="dot" v-for="(item, index) in dots" :class="{active: currentPageIndex === index}"></span>
    </div>
  </div>
</template>
<script>
import BScroll from 'better-scroll'
import { addClass } from '@/utils/dom'

/** 
 * slide 基于better-scroll实现,监听了它的几个事件{snap,snapLoop,snapThreshold,snapSpeed }  
 * 注:better-scroll因为版本原因,以上几个事件会有出入,请参考官方文档
 **/
const COMPONENT_NAME = 'slide'
export default {
  name: COMPONENT_NAME,
  data() {
    return {
      dots: [], // 定义一个名为dots的数组,小圆点数组
      currentPageIndex: 0 // 当前的页码
    }
  },
  //定义可在外部控制的属性
  props: { 
    loop: { // 是否是循环轮播
      type: Boolean,
      default: true
    },
    autoPlay: { // 自动播放
      type: Boolean,
      default: true
    },
    interval: { // 自动轮播间隔
      type: Number,
      default: 4000
    },
    showDot: { //显示dot
      type: Boolean,
      default: true
    },
    threshold: { //表示可滚动到下一个的阈值
      type: Number,
      default: 0.3
    },
    speed: {  //滚动速度
      type: Number,
      default: 400
    },
    homelist: { // 列表的数据 
      type: Array, 
      default: null 
    }
  },
  mounted() {
    this.update()
    //当调整浏览器窗口的大小时,发生 resize 事件。
    window.addEventListener('resize', () => {
      console.log('resize')
      if (!this.slide || !this.slide.enabled) {
        return
      }
      clearTimeout(this.resizeTimer)
      this.resizeTimer = setTimeout(() => {
        if (this.slide.isInTransition) {
          this.onScrollEnd()
        } else {
          if (this.autoPlay) {
            this.play()
          }
        }
        this.refresh()
      }, 60)
    })
  }, 
  methods: {
    update() {
      // 初始化 better-scroll时机(*一般初始化better-scroll不成功,使用vue $nextTick方法 或者better-scroll推荐的settimeout延时20秒)
      this.$nextTick(() => {
        this.init()
      })
    },
    refresh() {
      this.setSlideWidth(true)
      this.slide.refresh()
    },
    init() {
      console.log('2222')
      // clearTimeout(this.timer)
      this.currentPageIndex = 0
      this.setSlideWidth()
      if (this.showDot) {
        this.initDots()
      }  
      this.initSlider()
      if (this.autoPlay) {
        this.play()
      }
    },
    // 因为是横向滚动,需计算slide 的宽度并且赋值
    setSlideWidth(isResize) {
      this.children = this.$refs.group.children // 获取整个列表有多少个元素
      console.log('group元素:')
      console.log(this.children)
      console.log('获取整个列表有多少个元素:' + this.children.length)
      let width = 0 // 总的宽度
      let slideWidth = this.$refs.slide.clientWidth // slide 父元素的宽度
      for (let i = 0; i < this.children.length; i++) {
        let child = this.children[i] // 获取每个子元素
        addClass(child, 'slider-item') // 添加名为slider-item的类名

        child.style.width = slideWidth + 'px'
        width += slideWidth
      }
      if (this.loop && !isResize) { // 如果slide是需要循环的话,slide会在左右两侧copy两个子元素从而保证循环切换
        width += 2 * slideWidth
      }
      this.$refs.group.style.width = width + 'px'
    },
    //初始化dot
    initDots() {
      this.dots = new Array(this.children.length)
      console.log('获取dots:' + this.dots.length)
    },
    //初始化slide
    initSlider() { 
      console.log(this.threshold)
      this.slide = new BScroll(this.$refs.slide, {
        scrollX: true, // 横向滚动
        scrollY: false, // 不允许纵向滚动
        momentum: false, // 是否开启动量动画,关闭可以提升效率
        snap: {
          loop: this.loop,
          threshold: 0.3,
          speed: 400
        }
      })
      this.slide.on('scrollEnd', () => {
        // 参考文档 https://ustbhuangyi.github.io/better-scroll/doc/zh-hans/api-specific.html#getcurrentpage
        let pageIndex = this.slide.getCurrentPage().pageX
        if (this.loop) {
          pageIndex -= 1 // 因为设置自动播放之后,会自动在左右两侧copy两个子元素,所以在设置pageIndex时应减一
        }
        this.currentPageIndex = pageIndex
        if (this.autoPlay) {
          this.play()
        }
      })
      // 参考文档 https://ustbhuangyi.github.io/better-scroll/doc/zh-hans/events.html#beforescrollstart
      this.slide.on('beforeScrollStart', () => {
        if (this.autoPlay) {
          clearTimeout(this.timer)
        }
      })
    },
    onScrollEnd() {
      let pageIndex = this.slide.getCurrentPage().pageX
      this.currentPageIndex = pageIndex
      if (this.autoPlay) {
        this.play()
      }
    },
    play() {
      clearTimeout(this.timer)
        this.timer = setTimeout(() => {
          this.slide.next()
        }, this.interval)
    },
    watch: {
      // 监听数据的变化,调用refresh方法重新计算,保证滚动效果正常
      homelist() {
        setTimeout(() => {
          this.refresh()
        }, 20)
      }
    }
  }
}

</script>

7、group元素能打印出数组,但是长度却是0
图片描述

图片描述

8、调试了下 发现在axios异步请求没有返回数据的时候走了slide的初始化
9、子组件修改之后是可以正确加载的,只是初始化不行,请帮我看看是哪个环节出现的问题

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文