为什么侧边滚动条不能拉动?header为什么不是红色?

来源:1-1 Header和侧栏

soso_crazy

2019-08-07 19:34:41

//scroll\index.vue
<template>
 <!--ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。-->
 <swiper :options="swiperOption" ref="swiper">
 <!--作为一个滚动条,仅需要一个swiper-slide,将内容放在插槽内-->
 <div class="mine-scroll-pull-down" v-if="pullDown">
      <me-loading :text="pullDownText" inline ref="pullDownLoading"></me-loading>
    </div>
    <swiper-slide>
      <slot></slot>
    </swiper-slide>
    <div class="mine-scroll-pull-up" v-if="pullUp">
      <me-loading :text="pullUpText" inline ref="pullUpLoading"></me-loading>
    </div>
 <!--控制是否有scrollbar-->
 <div class="swiper-scrollbar" v-if="scrollbar" slot="scrollbar"></div>
  </swiper>
</template>

<script>
 // 引入swiper插件作为滚动条
 import {swiper, swiperSlide} from 'vue-awesome-swiper';

 // 引入loading小图标来做加载动画
 import MeLoading from 'base/loading';

 // 引入scroll文件夹的配置文件中暴露的常量
 import {
    PULL_DOWN_HEIGHT,
 PULL_DOWN_TEXT_INIT,
 PULL_DOWN_TEXT_START,
 PULL_DOWN_TEXT_ING,
 PULL_DOWN_TEXT_END,
 PULL_UP_HEIGHT,
 PULL_UP_TEXT_INIT,
 PULL_UP_TEXT_START,
 PULL_UP_TEXT_ING,
 PULL_UP_TEXT_END
  } from './config';

 export default {
    name: 'MeScroll',
 components: {
      swiper,
 swiperSlide,
 MeLoading
    },
 props: {
      scrollbar: {
        type: Boolean,
 default: true
 },
 // 接收home\index.vue父组件传给子组件的参数data,<me-scroll :data="recommends">
 data: {
        type: [Array, Object]
      },
 pullDown: {
        type: Boolean,
 default: false
 },
 pullUp: {
        type: Boolean,
 default: false
 }
    },
 // watch监听的是父组件传递的属性data: <me-scroll :data="recommends" pullDown>,watch中会将属性写为同名函数进行监听:props:{data: {type: [Array, Object]},}。watch里的data()要与props里的data同名。因为是父组件里的:data
 watch: {
      // watch作用是用来监听数据的变化的,在watch中要定义成函数。
 // watch中的data它是父组件传递的,然后子组件props中接收的,当父组件传递的data有变化,就触发update方法更新滚动条
 data() {
        this.update();
 }
    },
 created() {
      this.init();
 },
 methods: {
      update() {
        // <swiper ref="swiper"> 查看swiper的api更新滚动条是swiper实例.update()。$refs对象有已注册过ref的所有子组件。
 console.log(this.$refs.swiper); // 里面有所需的swiper实例对象,swiper:Swiper。this.$refs.swiper指注册过的子组件
 // vue-awsome-swiper的api有swiper实例.update()方法更新滚动条
 // this.$refs.swiper.swiper指Swiper实例对象
 this.$refs.swiper && this.$refs.swiper.swiper.update();
 },

 scrollToTop(speed, runCallbacks) {
        // slideTo是swiper插件提供的方法控制返回第几个幻灯片。因为这里只有一个<swiper-slide>,所以会返回幻灯片的最顶部
 this.$refs.swiper && this.$refs.swiper.swiper.slideTo(0, speed, runCallbacks);
 },

 // 将swiper的参数放在init方法内只需要初始化一次,避免放在data内随时监听变化渲染导致浪费
 init() {
        // swiper插件参数http://idangero.us/swiper/api/#events
 this.swiperOption = {
          direction: 'vertical',
 slidesPerView: 'auto', // 一页幻灯片显示多少张
 freeMode: true, // 自由滑动,不强制滑动显示一张幻灯片大小
 setWrapperSize: true, // 将计算后的高度设置swiper-wrapper的height
 scrollbar: {
            el: this.scrollbar ? '.swiper-scrollbar' : null,
 hide: true // 是否自动隐藏scrollbar
 },
 // on参数是注册事件处理程序
 on: {
            // sliderMove是swiper插件API的events,当用户触摸并将手指移过Swiper并移动它时,将触发事件。这里是触发methods中的scroll方法
 sliderMove: this.scroll,
 // touchEnd是swiper插件的事件,当用户触碰并释放Swiper时将触发事件。接收'touchend'事件作为参数。这里是执行methods中的touchEnd方法
 touchEnd: this.touchEnd,
 // swiper插件提供transitionEnd事件让我们监听
 transitionEnd: this.scrollEnd
 }
        };
 this.pullDownText = PULL_DOWN_TEXT_INIT;
 this.pullUpText = PULL_UP_TEXT_INIT;
 // 正在上拉或正在下拉标志位
 this.pulling = false;
 },
 scroll() {
        // 用常量保存swiper对象实例
 const swiper = this.$refs.swiper.swiper;

 this.$emit('scroll', swiper.translate, this.$refs.swiper.swiper);

 // 如果正在上拉或者正在下拉,不做任何操作
 if (this.pulling) return;

 // 下拉
 if (swiper.translate > 0) {
          // 没有开启下拉的布尔值,就不做任何操作
 if (!this.pullDown) return;
 if (swiper.translate > PULL_DOWN_HEIGHT) {
            this.$refs.pullDownLoading.setText(PULL_DOWN_TEXT_START);
 } else {
            // 拉完文字又变回初始文字
 this.$refs.pullDownLoading.setText(PULL_DOWN_TEXT_INIT);
 }
        } else if (swiper.isEnd) { // 判断是否拉到底部。swiper属性isEnd,如果位于最右和最底部,值为true
          // 没有开启下拉,直接返回<div class="mine-scroll-pull-up" v-if="pullUp">
 if (!this.pullUp) return;

 // 是否达到上拉加载的触发条件,是否下拉超过设置的pull_up_height的50。swiper.$warpperEl表示可滚动区域的外层元素,在swiper实例下的属性。
 const isPullUp = Math.abs(swiper.translate) + swiper.height - PULL_UP_HEIGHT > parseInt(swiper.$wrapperEl.css('height'));
 if (isPullUp) {
            this.$refs.pullUpLoading.setText(PULL_UP_TEXT_START);
 } else {
            this.$refs.pullUpLoading.setText(PULL_UP_TEXT_INIT);
 }
        }
      },
 scrollEnd() {
        // 向父组件传递scroll-end事件,传递插件移动的距离,和swiper实例
 this.$emit('scroll-end', this.$refs.swiper.swiper.translate, this.$refs.swiper.swiper, this.pulling);
 },
 // 松手刷新内容
 touchEnd() {
        // 如果正在上拉或者正在下拉,不做任何操作
 if (this.pulling) return;

 // 用常量保存swiper对象实例
 const swiper = this.$refs.swiper.swiper;
 if (swiper.translate > PULL_DOWN_HEIGHT) { // 滑动距离超过下拉高度时可以下拉
 // 没有开启下拉的布尔值,就不做任何操作

 this.pulling = true;

 if (!this.pullDown) return;
 // 在加载过程中禁止触摸
 swiper.allowTouchMove = false; // 禁止触摸
 // 设置动画速度
 swiper.setTransition(swiper.params.speed);
 // 移动到设定的位置。如果下拉拉过长,会回到设定的位置
 swiper.setTranslate(PULL_DOWN_HEIGHT);
 swiper.params.virtualTranslate = true; // 定住不给回弹
 this.$refs.pullDownLoading.setText(PULL_DOWN_TEXT_ING);
 // 当下拉的过程完毕,子组件传递pull-down事件,并且传递pullDownEnd方法给父组件
 this.$emit('pull-down', this.pullDownEnd);
 } else if (swiper.isEnd) { // 判断是否到底部
 // swiper.$warpperEl表示可滚动区域的外层元素。在swiper实例下的属性
 const totalHeight = parseInt(swiper.$wrapperEl.css('height'));
 // 判断是否满足上拉加载的条件:滚动距离swiper.translate加上显示区域的高度swiper.height减去一个定的值PULL_UP_HEIGHT,如果大于所有滚动内容的总高度,那么就表示用户正在上拉页面, 需要需要加载数据了。
 const isPullUp = Math.abs(swiper.translate) + swiper.height - PULL_UP_HEIGHT > totalHeight;

 // swiper.translate这个属性可以获取到wrapper的位移,其实可以理解为滚动条滚动的距离
 // swiper.height这个属性获取swiper容器的高度, 也就是显示区域的高度
 // PULL_UP_HEIGHT是我们设置的一个值。为了让页面不是到达最低部的时候,可以提前加载内容
 // totalHeight是通过wrapper的HTML元素的height属性, 也就是所有内容的高度
 // 滚动距离加上显示区域的高度减去一个定的值,如果大于所有滚动内容的总高度,那么就表示用户正在上拉页面,需要需要加载数据了

 if (isPullUp) {
            if (!this.PullUp) {
              return;
 }
            this.pulling = true;
 swiper.allowTouchMove = false; // 禁止触摸
 swiper.setTransition(swiper.params.speed);
 // swiper.height是swiper的参数,代表swiper的高度
 // 拉超过PULL_UP_HEIGHT的高度需要回弹到PULL_UP_HEIGHT的高度,然后定住不回弹
 // 所有内容的整体高度加上我们设定的值,减去可显示区域的高度,也就是此时滚动条需要滚动的距离,通过swiper提供的方法setTranslate设置位移。 因为是上拉, 所以需要设置位移为负值。
 swiper.setTranslate(-(totalHeight + PULL_UP_HEIGHT - swiper.height));
 swiper.params.virtualTranslate = true; // 定住不回弹
 this.$refs.pullUpLoading.setText(PULL_UP_TEXT_ING);
 this.$emit('pull-up', this.pullUpEnd);
 }
        }
      },
 // pullDownEnd方法就是加载完成之后,改变touchEnd事件中文字和swiper组件移动的位置等变回原来的样子
 pullDownEnd() {
        // 用常量保存swiper对象实例
 const swiper = this.$refs.swiper.swiper;

 // 加载完成之后,设置标志位可以进行下一次的上拉或下拉
 this.pulling = false;

 this.$refs.pullDownLoading.setText(PULL_DOWN_TEXT_END);
 swiper.params.virtualTranslate = false; // 可以回弹
 swiper.allowTouchMove = true; // 可以触摸
 // 设置动画速度
 swiper.setTransition(swiper.params.speed);
 // 回到0的位置
 swiper.setTranslate(0);
 // 当下拉完成后,header又重新出现,需要下拉完成后发送pull-down-transition-end事件监听然后使header重新出现
 setTimeout(() => {
          this.$emit('pull-down-transition-end');
 }, swiper.params.speed);
 },
 pullUpEnd() {
        const swiper = this.$refs.swiper.swiper;
 // 将不允许触摸和不回弹还原,设置标志位允许下一次下拉
 this.pulling = false;
 this.$refs.pullUpLoading.setText(PULL_DOWN_TEXT_END);
 swiper.params.virtualTranslate = false; // 可以回弹
 swiper.allowTouchMove = true; // 可以触摸
 }
    }
  };
</script>

<style lang="scss" scoped>
 /*swiper-container设置100%是可视区域的高度。是由里面的swiper-slide内容撑开的。*/
 .swiper-container {
    overflow: hidden;
 height: 100%;
 width: 100%;
 }

  /*内容比容器高才能滚动*/
 .swiper-slide {
    height: auto;
 }

  .mine-scroll-pull-down,
 .mine-scroll-pull-up {
    position: absolute;
 left: 0;
 width: 100%;
 }

  .mine-scroll-pull-down {
    bottom: 100%;
 height: 80px;
 }

  .mine-scroll-pull-up {
    top: 100%;
 height: 30px;
 }
</style>


//category\header.vue

<template>
<me-navbar>
 <div slot="center">搜索框</div>
 <i class="iconfont icon-msg" slot="right"></i>
</me-navbar>
</template>

<script>
import MeNavbar from 'base/navbar';

export default {
   name: 'CategoryHeader',
components: {
     MeNavbar
   }
 };
</script>

<style lang="scss" scoped>
@import "~assets/scss/mixins";

/*为了加重css权重显示 class="header mine-navbar"*/
.header{
   &.mine-navbar{
     background-color: $header-bgc-translucent;
}

   .iconfont{
     color: $icon-color-default;
font-size: $icon-font-size;
}
 }
</style>


//category\tab.vue

<template>
 <me-scroll :scrollbar="false">
   <ul class="tab">
<!--给当前点击的选项卡添加激活的类-->
<li class="tab-item"
:class="{'tab-item-active'
         :item.id===curId}"
v-for="(item,index) in items"
:key="index"
@click="switchTab(item.id)">{{item.name}}
     </li>
   </ul>
 </me-scroll>
</template>

<script>
// 引入config.js中的数据
import {categoryNames} from './config';
import MeScroll from 'base/scroll';

export default {
   name: 'CategoryTab',
components: {
     MeScroll
   },
data() {
     return {
       curId: ''
};
},
created() {
     this.init();
// 分类页没有点击动作,需要调用一次switchTab方法默认选中第一个选项
this.switchTab(this.items[0].id);
},
methods: {
     init() {
       // 用一个变量引用config.js中的数据
this.items = categoryNames;
},
switchTab(id) {
       // 现在点的选项是当前的选项不做任何操作
if (this.curId === id) {
         return;
}
       // 如果点击选项不是上一次点击的选项卡,就将当前的id更新
this.curId = id;
this.$emit('switch-tab', id);
}
   }
 };
</script>

<style lang="scss" scoped>
@import "~assets/scss/mixins";

$tab-item-height: 46px;

.tab {
   width: 100%;

&-item {
     height: $tab-item-height;
background-color: #fff;
border-right: 1px solid $border-color;
border-bottom: 1px solid $border-color;
color: #080808;
font-size: $font-size-l;
font-weight: bold;
text-align: center;
line-height: $tab-item-height;
     @include ellipsis();

&:last-child {
       border-bottom: none;
}
   }

   &-item-active {
     background: none;
border-right: none;
color: #f23030;
}
 }
</style>


//category\index.vue

<template>
 <div class="category">
   <header class="g-header-container">
     <category-header></category-header>
   </header>
   <div class="g-content-container">
     <div class="sidebar">
       <category-tab @switch-tab="getCurrentId"></category-tab>
     </div>
     <div class="main">
       <category-content :curId="curId"></category-content>
     </div>
   </div>
 </div>
</template>

<script>
import CategoryHeader from './header';
import CategoryTab from './tab';
import CategoryContent from './content';

export default {
   name: 'category',
components: {
     CategoryHeader,
CategoryTab,
CategoryContent
   },
data() {
     return {
       curId: ''
};
},
methods: {
     getCurrentId(id) {
       this.curId = id;
}
   }
 };
</script>

<style lang="scss" scoped>
@import "~assets/scss/mixins";

.category {
   overflow: hidden;
width: 100%;
height: 100%;
background-color: $bgc-theme;
}

 .g-content-container {
   display: flex;
padding-top: $navbar-height;
}

 /*选项内容是固定宽度80px*/
.sidebar {
   width: 80px;
height: 100%;
}

 /*右侧占领剩下的内容*/
.main {
   flex: 1;
height: 100%;
}
</style>


重新开启项目和重新打开浏览器也没有用,仍然拉动不了侧边栏

写回答

1回答

好帮手慕糖

2019-08-08

同学你好,1、侧边滚动条具体是指哪一块?是指如下这部分的滚动吗?这里使用谷歌浏览测试的,侧边栏是可以滚动的哦。若不是这里,可以详细的描述下,具体指的是哪里哦。

http://img.mukewang.com/climg/5d4b873b0001a9ea00850565.jpg

2、header不是红色是因为,//category\header.vue这个文件中,只设置了样式,但是没有设置类,例:

http://img.mukewang.com/climg/5d4b86420001bc3504380116.jpg

希望能帮助到你,祝学习愉快!

0

0 学习 · 10739 问题

查看课程