mpvue之滑动切换页面

2018 年 11 月 02 日 • 阅读数: 146

mpvue之滑动切换页面

简介

滑动切换页面是现在的一个非常普遍的需求,在微信小程序中实现这一点也比较简单,下面给出我的一套基于mpvue的滑动切换页面的解决方案

功能实现

这里呢,主要可以把上面的页面看出两个部分(最下面的导航栏可以不管),一个就是顶部导航栏,一个就是中间的内容区域

先来说说主页面的实现

可以看出,左右滚动部分使用的微信小程序的内置组件 swiper ,其中 duration 表示页面的滑动速度,然后该组件必须指定一个高度,这个高度我们必须根据窗口的高度来动态设定,change 在页面切换的时候触发,animationfinish 在页面切换完成后触发

<template>
  <div>
    <div class="nav-bar">
      <block v-for="(item, index) in tabs" :key="index">
        <div :id="index" class="nav-bar-item" @click="tabClick">
          <div class="nav-bar-title" :class="{'nav-bar-on':activeIndex==index}">
              {{item.name}}</div>
        </div>
      </block>
      <div class="nav-bar-slider" :class="navBarSliderClass"></div>
    </div>
    <div class="swiper-content">
      <swiper class="content" duration="500" 
              :style="{height:contentHeight}" 
              :current="currentTab" 
              @change="swiperChange"
              @animationfinish="onAnimationFinish">
        <swiper-item>
          <index-attention :winHeight="winHeight"></index-attention>
        </swiper-item>
        <swiper-item>
          <index-recommend :winHeight="winHeight"></index-recommend>
        </swiper-item>
        <swiper-item>
          <index-approximately :winHeight="winHeight"></index-approximately>
        </swiper-item>
      </swiper>
    </div>
  </div>
</template>

js部分

需要注意的是,在页面加载的时候,我们就需要获取到页面的高度,然后当我们滑动内容区域的时候,同时改变顶部导航栏,点击导航栏的时候,同时改变内容区域

<script>
/* eslint-disable */
import IndexApproximately from './components/approximately'
import IndexAttention from './components/attention'
import IndexRecommend from './components/recommend'

export default {
  components: {
    IndexApproximately,
    IndexAttention,
    IndexRecommend,
  },
  data() {
    return {
      tabs: [
        { name: '关注', type: 1, checked: true },
        { name: '推荐', type: 2, checked: true },
        { name: '约拍', type: 3, checked: true },
      ],
      activeIndex: 1,
      currentTab: 1,
      winWidth: 0,
      winHeight: 0,
    };
  },
  computed: {
    // 动态绑定导航栏滚动条的样式
    navBarSliderClass() {
      if (this.activeIndex == 0) {
        return "nav-bar-slider-0";
      }
      if (this.activeIndex == 1) {
        return "nav-bar-slider-1";
      }
      if (this.activeIndex == 2) {
        return "nav-bar-slider-2";
      }
    },
    // 动态设置滑动区域的高度
    contentHeight() {
      return this.winHeight + "px";
    },
  },
  methods: {
    // 获取系统信息,主要是获取窗口的高度
    getSystemInfo() {
      let that = this;
      wx.getSystemInfo({
        success(res) {
          that.winHeight = res.windowHeight;
        }
      })
    },
    // 导航栏点击的回调函数
    tabClick(e) {
      this.activeIndex = e.currentTarget.id;
      this.currentTab = this.activeIndex;
    },
    // 左右滑动的回调函数
    swiperChange(e) {
      this.currentTab = e.mp.detail.current;
      this.activeIndex = this.currentTab;
    },
    // 滑动完成的回调函数
    onAnimationFinish() {
      console.log("滑动完成.....")
    },
  },
  onLoad() {
    this.getSystemInfo();
  },
};
</script>

css部分

这部分没什么好说的,动画方面我也不是很了解,主要说下 rpx 这个单位,它可以根据屏幕宽度进行自适应,规定屏幕宽为750rpx,比如所上面我们有3个导航栏,那么每个导航栏的宽度就该是 250rpx ,而如果使用 px 的话这个宽度就是不能确定的,应为不同的手机宽度是不同的,但 rpx 都是 750

<style scoped>
  .nav-bar {
    display: -webkit-box;
    display: -webkit-flex;
    display: flex;
    position: fixed;
    z-index: 500;
    top: 0;
    height: 50px;
    width: 100%;
    box-shadow: 0 1rpx 6rpx #ccc;
  }
  .nav-bar-item {
    position: relative;
    display: block;
    -webkit-box-flex: 1;
    -webkit-flex: 1;
    flex: 1;
    padding: 13px 0;
    text-align: center;
    font-size: 0;
  }
  .nav-bar-title {
    color: black;
    font-weight: 500;
    display: inline-block;
    font-size: 15px;
    max-width: 8em;
    width: auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    word-wrap: normal;
  }
  .nav-bar-on {
    color: #89c5de;
  }

  .nav-bar-slider {
    position: absolute;
    content: " ";
    left: 0;
    bottom: 0;
    width: 100rpx;
    height: 3px;
    background-color: #89c5de;
    -webkit-transition: -webkit-transform 0.1s;
    transition: -webkit-transform 0.1s;
    transition: transform 0.1s, -webkit-transform 0.1s;
  }

  .nav-bar-slider-0 {
    left: 75rpx;
    transform: translateX(0);
  }

  .nav-bar-slider-1 {
    left: 75rpx;
    transform: translateX(250rpx);
  }

  .nav-bar-slider-2 {
    left: 75rpx;
    transform: translateX(500rpx);
  }

  .content {
    box-sizing: border-box;
    padding-top: 50px;
    background-color: #f9f9f9;
    -webkit-overflow-scrolling: touch;
  }
</style>

子组件的实现都是一样的,这里只任意介绍一个

子组件要实现的主要就是页面的滚动,这里我们直接使用微信小程序的 scroll-view 组件

其中的参数 scroll-y 就表示允许垂直滚动,需要注意的是,该组件必须指定一个高度,而这个高度我们已经在前面获取到了,并且通过父组件传递过来了,只不过这里需要减去顶部导航栏的高度

<template>
  <div>
    <scroll-view scroll-y :style="{height:contentHeight}">
      <i-card class="card-item" v-for="(item,index) in cardList" 
              :key="index" full="true" title="Title" :extra="item">
        <div style="height: 100px" slot="content">关注</div>
        <div slot="footer">尾部内容</div>
      </i-card>
    </scroll-view>
  </div>
</template>

<script>
export default {
  name: 'attention',
  props: {
    winHeight: Number
  },
  data() {
    return {
      cardList: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
    };
  },
  computed: {
    contentHeight() {
      return this.winHeight - 50 + "px";
    },
  },
};
</script>

注意: 这里使用的 i-card 是第三方的组件库,关于第三方组件库,这里不过多介绍

标签: mpvue

召唤伊斯特瓦尔