nuxt + swiper实现官网上下翻页效果及菜单跳转封装

2,107 阅读3分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

一、前言

本篇主要介绍如何使用nuxt + swiper实现官网的上下翻页效果以及通过菜单跳转对应滚动画面,并进行组件封装,以后开发类似的网站就可以只填充其中页面组件了。

关键技术: nuxt2 、 swiper5.4、vue-awesome-swiper4.1.1

二、实现方式

1.创建nuxt项目

确保安装了 npx(npx 在 NPM 版本 5.2.0 默认安装了):

npx create-nuxt-app <项目名>
// or 
yarn create nuxt-app <项目名>

创建过程会有选择UI框架、集成的服务器端框架等选择,我基本都是一路回车,敲过来的。

之后我们启动项目,如图所示

image.png

之后我们先将页面结构调整成我们需要的上下翻页的结构样式。

具体项目目录如下

image.png

这里我们将项目页面分成了两部分,第一部分是页面的header头部,用于放标题和菜单;第二部分是主体内容页面,可翻页显示。咱们今天主要讲翻页部分内容。

2.上下翻页效果的实现

首先我们先引入swiper

yarn add swiper@5.4

yarn add vue-awesome-swiper@4.1.1

之后我们还要在 plugins 文件夹下,添加swiper.js文件,文件内容如下

import Vue from 'vue'
import VueAwesomeSwiper from 'vue-awesome-swiper'
Vue.use(VueAwesomeSwiper)

因为引入了插件,我们还需要在nuxt.config.js文件中进行如下配置

css: [
    'vant/lib/index.css',
    'swiper/css/swiper.css' // 加入swiper样式
],
plugins: [
    '@/plugins/vant',
    {src: "@/plugins/swiper", ssr: false} // 组件这里配置下swiper插件
],

然后就可以去上面说的第二部分主体,搭建翻页主体了。

这里我们先创建我们需要的数据在vuex中,首先我们如果要实现指定页面的滚动,我们需要一个当前页面的变量,另外我们说要做一个封装,所以有多少个页面我们也不知道,所以我们需要动态计算出有多少个页面,就需要一个变量承载有多少个页面。所以store中的数据声明如下

// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export const state = () => ({
    activePage: '',
    menuList: []
})
const mutations = {
  changeActivePage(state, option) {
    console.log('changeActivePage===', state, option)
    state.activePage = option
  },
  setMenuList(state, option) {
    console.log('setMenuList=====', state, option)
    state.menuList = option
  }
}
export default {
  state,
  mutations
}

那我们应该怎么去计算有多少个页面呢?首先要把这些页面放到一个地方统一管理,我们将页面放到component/swiperPage这个文件夹下面,之后在项目初始画的时候去动态计算有多少个组件。 代码如下

// pages/index.vue
<template>
  <div class="main-content">
    <PageHeader />
    <MainWrapper/>
  </div>
</template>

<script>
// 自动创建组件
import '../plugins/autoCreateCom'
import { mapMutations } from 'vuex'
export default {
  name: 'IndexPage',
  mounted () {
    // 这里计算出有多少个页面,并组织称咱们需要的格式 -- start --
    let files = require.context('../components/swiperPage', true, /\.vue$/);
    let list = [], components = {};
    files.keys().forEach((key) => {
      const component = files(key).default;
      components[component.name] = component;
      list.push({ name: component.desc, value: component.name })
    });
    // 这里计算出有多少个页面,并组织称咱们需要的格式 -- end --
    // 将值存入到vuex的中
    this.setMenuList(list)
  },
  methods: {
    ...mapMutations(['setMenuList']),
  }
}
</script>
<style lang="less" scoped>
.main-content {
  width: 100%;
  height: 100%;
  position: relative;
}
</style>

这里要说明一下,因为在nuxt项目中,component文件中的一级文件会自动声明为全局组件,但是在其之下的文件夹中,就不会自动声明了, 这里咱们需要手动声明。

// /plugins/autoCreateCom.js

import Vue from 'vue';
const components = {};
 
let files = require.context('../components/swiperPage', true, /\.vue$/);

files.keys().forEach((key) => {
  const component = files(key).default;
  components[component.name] = component;
});

 
Object.keys(components).forEach((key) => Vue.component(key, components[key]));

创建好声明文件后,在入口文件中引入一下,如上代码

然后我们就可以搭建页面了,内容如下点击查看swiper参数配置

// MainWrapper.vue

<template>
  <div class="main-wrapper">
    <client-only>
      <swiper :options="swiperOption" ref="mySwiper" class="swiper">
        <swiper-slide :key="banner.value" v-for="banner in menuList">
          <component :is="banner.value" />
        </swiper-slide>
        <div class="swiper-scrollbar"></div>
      </swiper>
    </client-only>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex'
export default {
  name: 'MainWrapper',
  data() {
    return {
      // swiper的选项配置
      swiperOption: {
        centeredSlides: false,
        spaceBetween: 0,
        grabCursor: true,
        autoplay: false, // 是否自动打开
        loop: false, // 关闭无限循环
        slidesPerView: 1,
        direction : 'vertical', // 滑动方向
        navigation: {
          nextEl: '.swiper-button-next',
          prevEl: '.swiper-button-prev'
        },
        mousewheel: true, // 支持滚轮翻页
        mousewheel: {
          sensitivity : 0.2,
        }
      }
    };
  },
  computed: {
    // 这里我们将当前在那个页面activePage、页面list存到了vuex中
    ...mapState(['activePage', 'menuList']),
    swiper() { // swiper实例
      return this.$refs.mySwiper.$swiper
    }
  },
  watch: {
    activePage (val) { // 监听当前页面变化,若有变化,将当前页面替换至对应index
      let index = this.menuList.findIndex(item => item.value === val)
      this.swiper.slideTo(index)
    }
  }
}
</script>
<style lang="less" scoped>
.main-wrapper {
  position: relative;
  width: 100%;
  height: 100%;
  z-index: 10;
}
.swiper {
  width: 100%;
  height: 100%;
  .swiper-slide {
    font-size: 18px;
    background: #fff;
    display: flex;
    justify-content: center;
    align-items: center;
    
  }
}
</style>

之后我们就在创建好每一页的文件就好啦,就可以上下翻动了

image.png

3.点击菜单翻动到对应页面

这部分菜单我们一般放在头部,点击后从左侧弹出,代码如下

// PageHeader.vue
<template>
  <div class="page-header">
    <div class="logo">
      <img src="~/assets/images/shout.svg" alt="">
    </div>
    <div class="menu-tablet">
      <div v-for="item in menuList" :key="item.value" @click="clickSearch(item.value)" style="cursor: pointer;">
        {{item.name}}
      </div>
    </div>
    <div class="menu-mobile" @click="show = true">
      menu
    </div>
    <van-popup v-model="show" position="right" class="vanPop">
      <ul class="right-nav">
        <li v-for="item in menuList" :key="item.value" @click="clickSearch(item.value)">
          {{item.name}}
        </li>
      </ul>
    </van-popup>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex'
export default {
  name: 'PageHeader',
  data () {
    return {
      show: false
    }
  },
  computed: {
    ...mapState(['menuList']),
  },
  methods: {
    ...mapMutations(['changeActivePage']),
    // 这里出发点击事件,修改对应的ActivePage
    clickSearch(value) {
      this.changeActivePage(value)
      this.show = false
    },
  },
  mounted () {
  }
}
</script>

<style lang="less" scoped>
.page-header {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  padding: 0 12px;
  height: 56px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
  z-index: 11;
  box-sizing: border-box;
  background: #3a4c80;
  color: #fff;
}
.vanPop {
  width: 120px;
  height: 100%;
  background: #3a4c80;
  color: #fff;
  transition: all .5s;
}
.right-nav {
  width: 100%;
  height: 100%;
  padding-top: 24px;
  box-sizing: border-box;

  li {
    width: 100%;
    height: 75px;
    line-height: 75px;
    font-size: 14px;
    padding-left: 12px;
    box-sizing: border-box;
    border-bottom: 1px solid hsla(0,0%,100%,.2);
    cursor: pointer;
  }
}
.menu-tablet {
  display: flex;
  width: 50%;
  justify-content: space-around;
}
@media screen and (max-width: 1180px) {
  .page-header .menu-tablet.dark {
    color: #595758;
  }
  .menu-mobile {
    display: none;
  }
}


@media screen and (max-width: 1440px){
  .page-header .menu-tablet.dark {
    color: #595758;
  }
  .menu-mobile {
    display: none;
  }
}

@media screen and (max-width: 688px) {
  .page-header .menu-tablet {
    display: none;
  }
  .menu-mobile {
    display: block;
  }
}

</style>

以上我们就实现了对nuxt + swiper官网上下翻页效果及菜单跳转封装。

三、后记

做这个主要是为了以后遇到类似的官网项目可以直接复用源码仓库

本篇完结! 撒花! 感谢观看! 希望能帮助到你!