Vue2.5仿去哪儿app笔记二——swiper的自动构建 发送ajax请求 父子组件传值 兄弟组件间数据传递

swiper的自动构建 发送ajax请求 父子组件传值 兄弟组件间数据传递

swiper的自动构建

在首页的icon页面下,默认一个页面中包括8个图标。而我们希望若当页面中有9个图标时,可以左右拖动,形成轮播图的效果。而且我们希望页面能够自动计算和适配图标与轮播图,当图标数目变化时,轮播图也跟着相应变化。
所以应该设定两个v-for指令。分别遍历页面与图标。
<swiper-slide v-for="(page,index) of pages" :key="index">
<div class="icon" v-for="item of page" :key="item.id">

<div class="icons">
  <swiper>
    <swiper-slide v-for="(page,index) of pages" :key="index">
      <!--包括两个v-for指令,第一个是根据页面数,在pages中遍历每一个轮播图页面。-->
      <div class="icon"
           v-for="item of page"
           :key="item.id">
           <!--第二个是在一个页面(page)内遍历8个图标-->
        <div class="icon-img">
          <img class="icon-img-content" :src='item.imgUrl' alt="">
        </div>
        <p class="icon-text">{{item.icontext}}</p>
      </div>
    </swiper-slide>
  </swiper>
</div>

利用计算属性,来实现根据图标数目自动构建页码,实现多页切换的轮播图效果。

computed: {
  pages () {
    const pages = []
    this.iconList.forEach((item, index) => {
      const page = Math.floor(index / 8)//向下取整
      // 计算当前index所处页面page,一个页面包括8个icons
      if (!pages[page]) {
        pages[page] = []
        // 当前page溢出,新建页面
      }
      pages[page].push(item)
    })
    return pages
    // 根据数据自动构建页码,实现多页切换的轮播图
  }
}

使用axios发送ajax请求

axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端

对于home页面来说,每一个组件都有自己的数据,但为避免多次请求降低性能,所以希望整个首页只发送一个ajax请求,并且home.vue发送一个ajax请求在获取数据之后,能分别把数据传给每一个子组件。

//home.vue
methods: {
  getHomeInfo () {
    axios.get('/api/index.json').then(this.getHomeInfoSucc)
    //这里的get路径为'/api/index.json'
    //但本地的模拟数据在'/static/mock'目录下,需要借助路径代理
  },
  getHomeInfoSucc (res) {
    res = res.data
    //获取数据
    if (res.ret && res.data) {
      //后端正确返回结果
      const data = res.data
      this.city = data.city
      this.swiperList = data.swiperList
      this.iconList = data.iconList
      this.recommendList = data.recommendList
      this.weekendList = data.weekendList
      //传递数据
    }
  }
},
mounted () {
  this.getHomeInfo()
  //借助mounted生命周期函数,让页面挂载好之后执行该函数
}

因为只有在/static目录下的内容可以被外部访问到,所以将本地模拟数据放在./static/mock目录下,并且在配置项中添加代理路径

//index.js
proxyTable: {
  '/api': {
    target: 'http://localhost:8080',
    pathRewrite: {
      '^/api': '/static/mock'
    }
  }
},

父子组件间传值

在父组件中,声明引入子组件,并传入子组件内需要的值

//home.vue
data () {
  //初始化数据
  return {
    city: '',
    swiperList: [],
    iconList: [],
    recommendList: [],
    weekendList: []
  }
},

子组件接收数据,注册props

//component.vue
props: {
  recommendList: Array
  //或 city: String
}

在主页面绑定每个组件

<!--home.vue-->
<!--父组件用属性的方式向子组件传值-->
<div class="">
  <home-header :city="city"></home-header>
  <home-swiper :list='swiperList'></home-swiper>
  <!--把父组件获取到的数据赋给子组件-->
  <home-icons :iconList='iconList'></home-icons>
  <home-recommend :recommendList='recommendList'></home-recommend>
  <home-weekend :weekendList='weekendList'></home-weekend>
</div>

swiper轮播图默认显示最后一张图片问题

当使用axios发送ajax请求后,会发现当页面加载完成后,轮播图默认会显示最后一张图片
这是因为页面还没有获取ajax数据时,props的list接收的是外部空数组,即最初创建时是通过空数组创建,获取完成ajax后,获取真正的数据,才重新渲染新数据。

解决方法:
让swiper的初次创建由完整的数据创建,而不使用空数组创建。
即当List为空数组时,不显示轮播图。

<swiper :options="swiperOption" v-if="showSwiper">
  ...
</swiper>
computed: {
  showSwiper () {
    return this.list.length
    //也可直接使用v-if="list.length"
    //但尽量不在模板内添加逻辑性的代码,所以添加一个计算属性来判断数据
  }
}

兄弟组件间数据传递

实现右侧字母列表与城市列表同步

要实现当点击某个字母时,页面自动跳转到该字母对应的城市列表,需实现Alphabet.vuelist.vue这两个兄弟组件间的数据传递。
对于非父子组件传值,可借助父组件进行间接传递,即先将Alphabet.vue传给city.vuecity.vue再转发给list.vue

Alphabet.vue传给city.vue(子组件向父组件传值)

//Alphabet.vue
handleClick (e) {
  this.$emit('change', e.target.innerText)
  //为字母绑定一个click事件,当点击时向外触发事件,事件的名字为‘change’,携带的内容即为这个字母
}

向外触发事件后,父组件city.vue监听这个事件
<cityAlphabet :cities="cities" @change="handleClick"></cityAlphabet>

handleClick (letter) {
  this.letter = letter
  //接收Alphabet.vue传递过来的letter
}

city.vue将接收到的letter转发给list.vue(父组件向子组件传值)

<!--city.vue-->
<list :cities="cities" :hotCities="hotCities" :letter="letter"></list>

在list.vue中,借助监听器watch来监听letter的变化,并使页面随letter的改变而改变
<div class="area" v-for="(item,key) of cities" :key="key" :ref="key">

watch: {
  letter () {
    if (this.letter) {
      // const element = this.$refs[this.letter]
      // 此时element是一个数组,而不是一个DOM元素
      const element = this.$refs[this.letter][0]
      this.scroll.scrollToElement(element)
      //让滚动区自动滚动到element对应的DOM元素上
    }
  }
}

其中

ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 r e f s D O M 使 D O M . refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例. 而 refs是一个对象,即持有注册过ref特性的所有DOM元素和组件实例。

猜你喜欢

转载自blog.csdn.net/wantingtr/article/details/83588327
今日推荐