nuxt.js 进行项目重构-配置事件总线、底部tabbar、better-scroll

首页的基础布局已经完成 接下来 接下来还要配置一些通用的模块

tabbar 底部导航

本质

在  webApp 中底部导航 其实就是一个 position:fixed 固定定位到页面底部的盒子 里面再使用弹性盒布局 选项

(小程序在对应的 json文件中设置)

引入位置

在 传统 vue-cli 中 在app.vue 根目录当中引入

页面通过路由 显示在 router-view 容器当中 tabbat组件在页面下面

还可以根据 配置路由中设置布尔值 决定哪些页面不显示 tabbar

 在nuxt.js中

layout 文件夹中存放的是页面默认布局 default.vue 文件类似于 app.vue

内部封装

外部 tabbar

<template>
  <div id="main">
    <tabbaritem
      :path=tt.path
      :activeTextColor=tt.activeTextColor
      v-for="tt in tabList"
      :num=tt.num
      :key=tt.text>
      <img slot="item-icon" :src=tt.DSrc alt="" >
      <img slot="item-active" :src=tt.ASrc alt="" >
      <div slot="item-text">{
   
   {tt.text}}</div>
    </tabbaritem>
  </div>
</template>

<script>

  import tabbaritem from './Tabbar-item'
  export default {
    data(){
      return{
        tabList:[
          {
            path:'/home',
            activeTextColor:'#f64257',
            DSrc:'http://www.wsg3096.com/ass/tabbar/home-deactive.svg',
            ASrc:'http://www.wsg3096.com/ass/tabbar/home-active.svg',
            text:'首页'
          },
          {
            path:'/class',
            activeTextColor:'#f64257',
            DSrc:'http://www.wsg3096.com/ass/tabbar/class-deactive.svg',
            ASrc:'http://www.wsg3096.com/ass/tabbar/class-active.svg',
            text:'分类'
          },
          {
            path:'/car',
            activeTextColor:'#f64257',
            DSrc:'http://www.wsg3096.com/ass/tabbar/car-deactive.svg',
            ASrc:'http://www.wsg3096.com/ass/tabbar/car-active.svg',
            text:'购物车',
            num:true
          },
          {
            path:'/profile',
            activeTextColor:'#f64257',
            DSrc:'http://www.wsg3096.com/ass/tabbar/me-deactive.svg',
            ASrc:'http://www.wsg3096.com/ass/tabbar/me-active.svg',
            text:'我的'
          }
        ]
      }
    },

    name: "Main-tabbar",
    components:{
      tabbaritem
    }
  }
</script>

<style scoped>
#main{
  display: flex;
  box-shadow: 1px -1px rgba(88,88,88,0.1);
  background: #f0f0f0;
  position: fixed;
  left: 0;
  bottom: 0;
  width: 100%;
}
</style>

 根据数据 v-for 渲染 内部tabbaritem

细节1 查找自己的 path 属性 是否存在于当前路由中 来显示高亮效果

isActive(){
  return this.$route.path.indexOf(this.path) !== -1
}

细节二 根据需要显示右上角 信息小标

这里只有一项需求 购物车哪一项显示当前购物车内商品数量 默认不显示

购物车这一项 新增 num:true

{
  path:'/car',
  activeTextColor:'#f64257',
  DSrc:'http://www.wsg3096.com/ass/tabbar/car-deactive.svg',
  ASrc:'http://www.wsg3096.com/ass/tabbar/car-active.svg',
  text:'购物车',
  num:true
},
<div class="item-num" v-if="num">
  {
   
   {numss}}
</div>
props:{
  num:{
    type:Boolean,
    default:false
  }

<template>
  <div class="tab-bat-item" @click="barclick">
    <div v-if="isActive">
      <slot name="item-active"></slot>
    </div>
    <div v-else>
      <slot name="item-icon"></slot>
    </div>
    <div :style="activeStyle">
      <slot name="item-text"></slot>
    </div>
    <div class="item-num" v-if="num">
      {
   
   {numss}}
    </div>
  </div>
</template>

<script>
  import {mapGetters} from 'vuex'
  export default {
    name: "Tabbar-item",
    props:{
      path:String,
      activeTextColor:{
        type:String,
        default:'#f64257'
      },
      num:{
        type:Boolean,
        default:false
      }
    },
    data(){
      return{
        //isActive:true,
      }
    },
    computed:{
      isActive(){
        // /home -> item1(/home) = true
        // /home -> item1(/class) = false
        // /home -> item1(/car) = false
        // /home -> item1(/profile) = false
        return this.$route.path.indexOf(this.path) !== -1
        // 返回 活跃的路由的path 是不是我这个路由  !== -1(不等于负一) 就是找到了  找到了 isActive 就是true
      },
      activeStyle(){
        return this.isActive ? {color:this.activeTextColor} : {}
        //   isActive是true的话返回 父组件传过来的数据  父组件没有传这个数据就用默认的
      },
        ...mapGetters('car',['numss'])
    },
    methods:{
      barclick(){
        this.$router.push(this.path);
        //console.log('00');
      }
    }
  }
</script>

<style scoped>
  .tab-bat-item{
    flex: 1;
    text-align: center;
    height: 49px;
    font-size: 14px;
    color: #b3b3b3;
    padding-top: 3px;
    box-sizing: border-box;
    position: relative;
  }

  .tab-bat-item img{
    width: 24px;
    height: 24px;
    vertical-align:middle;
  }

  .item-num{
    position: absolute;
    right: 6px;
    top: 0px;
    width: 24px;
    height: 24px;
    border-radius: 12px;
    background: #ff3355;
    color: white;
    font-size: 14px;
    line-height: 24px;
    text-align: center;
  }
</style>

效果:

 挂载事件总线

步骤

pulgin/bus.js

import Vue from 'vue'
Vue.prototype.$bus = new Vue()

nuxt.config.js中配置

plugins: [
  '@plugins/bus',
  '@plugins/better-scroll',
],

Better-scroll

使用这个插件会使 移动端手指触屏滑动  更加丝滑

先安装
npm install [email protected]

 pulgin/better-scroll.js :

import Bscroll from 'better-scroll'

然后在 nuxt.config.js中配置 上面已经写到

封装组件:

模板部分:

wrapper  和  content 为固定结构

预留插槽 使用方法 使用此组件包裹 想要滚动的元素

<template>
  <div content="wrapper" ref="wrapper">
    <div class="content">
      <slot></slot>
    </div>
  </div>
</template>

 在mounted 生命周期中  new 一个 Bscroll 实例 增加相关配置

click 添加内部的点击事件

probeType 记录滚动的位置  可选择值 0 1 2

当 probeType 为 1 的时候,会非实时(屏幕滑动超过一定时间后)派发scroll 事件;

当 probeType 为 2 的时候,会在屏幕滑动的过程中实时的派发 scroll 事件;(在手指滚动的过程中侦测,手指离开后的惯性滚动过程中不侦测。)

当 probeType 为 3 的时候,不仅在屏幕滑动的过程中,而且在 momentum 滚动动画运行过程中实时派发 scroll 事件。( 就是我们用手用力滑动的时候,手放开之后,屏幕还在滑动,这就叫momentum 滚动动画 )
————————————————
版权声明:本文为CSDN博主「阿清呀.」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wzg0817/article/details/108013765

 pullUpLoad 上拉加载更多

mounted() {
  //创建 scroll 对象
  this.scroll =new Bscroll(this.$refs.wrapper,{
    click:true, // 
    probeType:this.probeType,
    pullUpLoad:this.pullUpLoad,
  })
  // probeType 是2 或者3 监听滚动的位置
  if (this.probeType ===2 || this.probeType ===3){
    this.scroll.on('scroll' ,(position)=>{
      this.$emit('scrollpos',position)
    })
  }

  //监听滚动到底部
  this.scroll.on('pullingUp',()=>{
    this.$emit('ToDown')
  })
},

组件内部的方法 外部可以通过 $refs.xxx 调用 

methods:{
// 0.5杪返回到滚动顶部
  scrollTo(x,y,time=500){
    this.scroll.scrollTo(x,y,time)
  },
// 重新刷新 计算滚动高度
  refresh(){
    this.scroll.refresh()
  },
// 获取组件距离 页面最顶部的距离
  getScrollY(){
    return this.scroll ? this.scroll.y : 0
  }
}

在首页当中使用 

传入 probeType= 3 需要记录滚动的位置

pullUpLoad= true  开启下拉加载更多

给类名 content  需要有一个 限定高度 (减去底部 tabbar的高度)

.content{
  overflow: hidden;
  height: calc(100vh - 49px);
}
<scroll
    class="content"
    ref="scroll"
    @scrollpos="scrollpos"
    :probeType="3"
    :pullUpLoad="true"
    @ToDown="ToDown">
.....
  </scroll>

接收实时滚动的事件 scrollpos   和 滚动到底部的事件 ToDown

//监听位置 到1000了 显示返回顶部按钮
scrollpos(position){
  this.isShow = (-position.y) >1000
  // 到一定位置了goods按钮贴合顶部
  this.isgoodfix = (-position.y) > this.$refs.goodbtns2.$el.offsetTop
},
//到底部时做什么
ToDown(){
  console.log('我是有底线的');
  //this.GetGoods(this.current.type)
},

到1000了 显示返回顶部按钮

.backtop{
  position: fixed;
  bottom: 68px;
  right: 6%;
}

 点击时返回顶部

backtop(){
  this.$refs.scroll.scrollTo(0,0)
},

调用的还是scroll组件内部的方法

还可以  返回首页的时候 停留在上次 离开的位置

//进入组件时做什么
activated() {
  this.$refs.scroll.scrollTo(0,this.saveY,0)
  this.$refs.scroll.refresh()
},
// 离开组件时做什么
deactivated() {
  //记录离开时的Y位置
  this.saveY = this.$refs.scroll.getScrollY()

  //取消商品列表图片加载时间的监听
  this.$bus.$off('goodsimgload',this.goodsimglisten)
}

猜你喜欢

转载自blog.csdn.net/benlalagang/article/details/127464152
今日推荐