欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于 vue +better scroll滑动切换页面 并支持下拉刷新案例

程序员文章站 2022-06-11 11:17:00
...

也是公司项目 ,内部app的资讯模块整改,改是不可能改的,之前还是用jquery。感觉越改越混乱,还是重做。就仿着今日头条、等资讯页面做了一个dome,话不多说,先看效果!

基于 vue +better scroll滑动切换页面 并支持下拉刷新案例

 效果看完,感觉还行的话,接着就往下看开启爬坑之路!

先打一个无偿广告 上图的gif 是通过LICEcap 软件录屏制作的!下载地址:官网地址,支持window mac ,无插件 无广告 完全免费!确实好用,比起国内的动不动就要会员才能导出的***软件要好的多

一、效果分析

看起来好像很常见,但是这个整体效果完成,对better scroll就比较熟悉了 做平常的滚动导航列表、轮播图、下拉刷新、上拉加载等ui模板都应该小kiss了。页面主要也就三个功能

  1. 顶部的可滑动导航列表
  2. 中间的可滑动切换页 和导航列表有联动效果
  3. 每页列表页都支持下拉刷新、上拉加载

二、功能实现

1.插件安装

基于vue 和better scroll的项目,用vue cli 安装vue的环境搭建 这一块就不多说

better scroll的安装

npm install aaa@qq.com -S 

使用的话就比较简单

 import BScroll from 'better-scroll';

  mounted() {
            this.initBscroll()
        },
  methods: {
           initBscroll() {
                this.bscroll = new BScroll(this.$refs.bsWrapper, {
                    scrollY: true,
                    bounceTime: TIME_BOUNCE,
                    pullDownRefresh: {
                        threshold: THRESHOLD,
                        stop: STOP
                    }
                })           
               this.bscroll.on('scroll', this.scrollHandler)
            },
            scrollHandler(pos) {
                console.log(pos.y)
            },     
       }  

使用的话也就是配置参数 对于这些参数详细解释就 分享一下api链接http://ustbhuangyi.github.io/better-scroll/doc/api.html

重要的标记一下:

一类是属性 在new的时候传入的 如scrollY:true 设置竖直方向可以滚动

一类是方法 就是在用户操作过程中可以调用该方法 如scroll 就是页面滚动中触发的,调用语法如下

this.bscroll.on('scroll', this.scrollHandler)
            
scrollHandler(pos) {
                console.log(pos.y)
            },

上面为实时打印滚动的位置案例

  • eventPassthrough

在属性上 这里要着重介绍 eventPassthrough属性!该属性默认值为'' 可以设置'vertical'、'horizontal'简单解释一下  当eventPassthrough 设置vertical 时 该实例 只会相应水平的滑动事件 竖直方向事件将不会影响它如咱们案例中的 左右切换和下拉刷新就必须设置该属性 ,不让相互影响 整个页面滑动效果就很卡顿

  • scrollToElement(el, time, offsetX, offsetY, easing)

在放方法上也介绍一下scrollToElement,就是滚动到指定元素 ,五个参数(滚动到哪个对象 所需时间 x偏移 y偏移 动画效果)x偏移和y偏移 设置为true是 就会滚动到该元素中心位置

2.顶部滚动导航实现

也提一下滚动原理  虽然黄佚老师讲的很详细了,但是还是提一下,这个主要就是为了页面如何布局,内容区域大于wepper 才可以触发滚动,因此必须控制wrpper的大小,不能让它的大小让子元素撑开

基于 vue +better scroll滑动切换页面 并支持下拉刷新案例

 先是进行页面布局吧

基于 vue +better scroll滑动切换页面 并支持下拉刷新案例

顶部这一块红色标出的就是wrapper 大小固定 ,绿色的就是内容部分 可滚动;

而红色区域的大小就是屏幕的宽度减去两边的宽度 这个实现可以用flex 实现 可以用aclc实现 个人还是倾向于flex

布局完成之后就是 进行better scroll的初始化 对于这个实现就是 需要在**状态下滚动至该元素的最中间直接用scrollToElement实现 整体代码如下:

<template>
    <div class="page" >
        <div class="topcontent">
            <div class="tranbox"></div>
            <div class="tab" ref="linescoll">
                <div class="tabitems" ref="picList">
                    <div v-for="(item,index) in navlist" class="tabitem" :class="item.id==activeitem.id?'tabactived':''" @click="changtab(item)" :key="index">{{item.title}}</div>
                </div>
            </div>
            <div class="additem">+</div>
        </div>
    </div>
</template>

<script>
    import BScroll from 'better-scroll';

    export default {
        data() {
            return {

                navlist:[
                    {title:'要闻', action:'', type:'', from:'ezx',id:1},
                    {title:'7*24', action:'', type:'', from:'ezx',id:2},
                    {title:'自选股', action:'', type:'', from:'ezx',id:3},
                    {title:'公司研报', action:'', type:'', from:'zz',id:4},
                    {title:'行业研究', action:'', type:'', from:'zz',id:5},
                    {title:'新三板新闻', action:'', type:'', from:'zz',id:6},
                    {title:'期货研究', action:'', type:'', from:'zz',id:7},
                ],
                activeitem: {},
            };
        },
        watch:{
            activeitem:function(val) {
                let idx;
                this.navlist.map((item,index)=>{
                        if(item.id == val.id){
                            idx =  index
                        }
                    }
                );
                this.changetitle(val,idx);
            }
        },
        mounted(){
            this.init();
            this.activeitem =  {title:'7*24', action:'', type:'', from:'ezx',id:2};
        },
        methods: {
            init() {
                this.$nextTick(()=>{
                    //设置顶部滚动 navlist
                    this.scrollmethod = new BScroll(this.$refs.linescoll, {
                        bounce: true,
                        eventPassthrough: 'vertical',
                        scrollX: true,
                        scrollY: false,
                        preventDefault: false
                    });
                });
            },
            changetitle(item,index){
                let idx = index+1;
                let dom = document.querySelector('.tabitems .tabitem:nth-child(' + idx + ')');
                this.$nextTick(() => {
                    //标题滚动到对应位置
                    // 五个参数 滚动到元素 时间  水平偏移 竖直偏移  后两个为true 则是中心位置 最后一个 设置动画效果
                    this.scrollmethod.scrollToElement(dom, null, true, true);
                })
            },
            changtab(item) {
                this.activeitem = item;
            }
        }

    };
</script>

<style lang="scss"  scoped>
    .page{
        display: flex;
        flex-direction: column;
        width: 100%;
        height: 100%;
        overflow: hidden;
        background-color: rgba(247, 247, 247, 1);
        .topcontent {
            z-index: 999;
            display: flex;
            .tranbox{
                width: 10px;
                background-color: #fff;
                z-index: 999;
            }
            .tab{
                background-color: #fff;
                flex: 1;
                overflow: hidden;
                .tabitems{
                    display: inline-flex;
                    width: auto;
                    .tabitem{
                        flex: 1;
                        font-size: 15px;
                        line-height: 24px;
                        padding:10px 17px;
                        color: #333333;
                        text-align: center;
                        display: inline-flex;
                        justify-content: center;
                        box-sizing: border-box;
                        flex-wrap: nowrap;
                        white-space: nowrap;
                    }
                    .tabactived{
                        color:#F14D44;
                        position: relative;
                        font-size: 17px;
                        line-height: 24px;
                        &:after{
                            position: absolute;
                            content: "";
                            bottom: 0;
                            left: 20%;
                            width: 60%;
                            height: 3px;
                            background-color: #F14D44;
                        }
                    }
                }
            }
            .additem{
                height: 100%;
                width: 45px;
                display: flex;
                justify-content: center;
                align-items: center;
                background-color: #fff;
                font-size: 20px;
                line-height: 24px;
                padding:10px 0;
                color: #888;
                box-shadow: 0 -5px 5px #ddd;
                z-index: 999;

            }
        }
    }
</style>

复制代码就可以实现以下效果 算是一个 简单的滚动导航条了吧

基于 vue +better scroll滑动切换页面 并支持下拉刷新案例

2. 滑动切换slider实现

用better scroll实现slider也是相当方便 直接就slider这个对象属性,初始化时候添加进来就好,而这个页面布局如下

基于 vue +better scroll滑动切换页面 并支持下拉刷新案例

 根据咱们的项目 添加一些初始数据 在init 中在初始化一下 slider

<template>
    <div class="page" >
        <div class="topcontent">
            <div class="tranbox"></div>
            <div class="tab" ref="linescoll">
                <div class="tabitems" ref="picList">
                    <div v-for="(item,index) in navlist" class="tabitem" :class="item.id==activeitem.id?'tabactived':''" @click="changtab(item)" :key="index">{{item.title}}</div>
                </div>
            </div>
            <div class="additem">+</div>
        </div>
        <div class="center">
            <div class="slide-banner-scroll" ref="slide">
                <div class="slide-banner-wrapper">
                    <div class="slide-item"  v-for="item in navlist" :key="item.id">
                        <div class="zxlinelistbox" :class="'page'+item.id">
                            <div class="zxcontentbox">
                                <zxlist :zxlist="listdata" :readId="readId" @zxitemclick="zxitemclick"></zxlist>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    import BScroll from 'better-scroll';
    import zxlist from '../components/zxlist'
    export default {
        components:{
            zxlist:zxlist
        },
        data() {
            return {
                listdata:[],
                navlist:[
                    {title:'要闻', action:'', type:'', from:'ezx',id:1},
                    {title:'7*24', action:'', type:'', from:'ezx',id:2},
                    {title:'自选股', action:'', type:'', from:'ezx',id:3},
                    {title:'公司研报', action:'', type:'', from:'zz',id:4},
                    {title:'行业研究', action:'', type:'', from:'zz',id:5},
                    {title:'新三板新闻', action:'', type:'', from:'zz',id:6},
                    {title:'期货研究', action:'', type:'', from:'zz',id:7},
                ],
                activeitem: {},
            };
        },
        watch:{
            activeitem:function(val) {
                let idx;
                this.navlist.map((item,index)=>{
                        if(item.id == val.id){
                            idx =  index
                        }
                    }
                );
                this.changetitle(val,idx);
            }
        },
        created(){
            let data = {"code":0,
                "message":"SUCCESS",
                "data":[
                    {"item_title":"央行开展1年期MLF操作3000亿元 操作利率3.25%","author":["吴晓辉"],"img":[],"is_original":"1","is_top":"0","is_red":"1","is_recom":"1","creat_time":"2020-01-15 10:03:57","news_type":"11","item_id":"552942","label":[]},
                    {"item_title":"2019年业绩续亏跌停 时代万恒打响保壳战","author":["孙宪超"],"img":["https://resource-e2-oss.egsea.com/upload/2020/0115/09/20130419044553.jpg?x-oss-process=image/resize,m_fixed,h_150,w_200"],"is_original":"1","is_top":"0","is_red":"0","is_recom":"1","creat_time":"2020-01-15 10:03:44","news_type":"11","item_id":"552945","label":["600241"]},
                    {"item_title":"上海:将完善居转户政策 加快建设国际人才高地","author":["彭飞"],"img":[],"is_original":"1","is_top":"0","is_red":"0","is_recom":"0","creat_time":"2020-01-15 09:59:13","news_type":"11","item_id":"552965","label":[]},{"item_title":"上海市市长应勇:加快建设全球性人民币产品创新、交易、定价和清算中心","author":["陈文斌"],"img":[],"is_original":"1","is_top":"0","is_red":"1","is_recom":"1","creat_time":"2020-01-15 09:58:12","news_type":"11","item_id":"552949","label":[]},{"item_title":"【e公司微访谈】雄塑科技:“小管道”有大商机 市政工程打开新增长空间","author":["陈文斌"],"img":[],"is_original":"1","is_top":"0","is_red":"1","is_recom":"1","creat_time":"2020-01-15 09:56:41","news_type":"11","item_id":"552824","label":["300599"]},{"item_title":"区块链概念股盘中拉升 联络互动、智度股份等涨停","author":["陈文斌"],"img":[],"is_original":"1","is_top":"0","is_red":"0","is_recom":"0","creat_time":"2020-01-15 09:55:41","news_type":"11","item_id":"552959","label":["000676","002280","603888"]},{"item_title":"上海市市长应勇:全面实施集成电路、人工智能、生物医药“上海方案”","author":["陈文斌"],"img":[],"is_original":"1","is_top":"0","is_red":"1","is_recom":"1","creat_time":"2020-01-15 09:55:28","news_type":"11","item_id":"552962","label":["000975"]},{"item_title":"上海市市长应勇:2019年科创板70家企业成功上市 筹资额达到824亿元","author":["彭飞"],"img":[],"is_original":"1","is_top":"0","is_red":"0","is_recom":"1","creat_time":"2020-01-15 09:51:34","news_type":"11","item_id":"552848","label":[]},{"item_title":"上海市市长应勇:上海房地产市场保持平稳健康发展","author":["彭飞"],"img":[],"is_original":"1","is_top":"0","is_red":"0","is_recom":"0","creat_time":"2020-01-15 09:51:19","news_type":"11","item_id":"552872","label":[]},{"item_title":"上海市市长应勇:支持和鼓励更多科创企业上市","author":["陈文斌"],"img":[],"is_original":"1","is_top":"0","is_red":"1","is_recom":"1","creat_time":"2020-01-15 09:51:02","news_type":"11","item_id":"552932","label":[]}],
                "pageinfo":{"pageNum":1,"pageSize":10,"totalCount":3497,"totalPages":350}
            }
            this.listdata = data.data
        },
        mounted(){
            this.init();
            this.activeitem =  {title:'7*24', action:'', type:'', from:'ezx',id:2};
        },
        methods: {
            init() {
                this.$nextTick(()=>{
                    //设置顶部滚动 navlist
                    this.scrollmethod = new BScroll(this.$refs.linescoll, {
                        bounce: true,
                        eventPassthrough: 'vertical',
                        scrollX: true,
                        scrollY: false,
                        preventDefault: false
                    });

                    //设置轮播页面
                    this.slide = new BScroll(this.$refs.slide, {
                        scrollX: true,
                        scrollY: false,
                        slide: {
                            loop: false,
                            threshold: 100
                        },
                        eventPassthrough:"vertical",
                        momentum: false,
                        // bounce: true,
                    })
                    this.slide.on('scrollEnd', this._onScrollEnd)
                });
            },

            _onScrollEnd() {
                console.log('endssssss')
                let index = this.slide.getCurrentPage().pageX;
                let item  =  this.navlist[index];
                this.activeitem = item;
            },

            changetitle(item,index){
                let idx = index+1;
                let dom = document.querySelector('.tabitems .tabitem:nth-child(' + idx + ')');
                this.$nextTick(() => {
                    //标题滚动到对应位置
                    // 五个参数 滚动到元素 时间  水平偏移 竖直偏移  后两个为true 则是中心位置 最后一个 设置动画效果
                    this.scrollmethod.scrollToElement(dom, null, true, true);
                    this.scrollmethod.refresh();
                    //详情页滚动到对应页面
                    this.slide.goToPage(index);
                })
            },
            changtab(item) {
                this.activeitem = item;
            }
        }

    };
</script>

<style lang="scss"  scoped>
    .page{
        display: flex;
        flex-direction: column;
        width: 100%;
        height: 100%;
        overflow: hidden;
        background-color: rgba(247, 247, 247, 1);
        .topcontent {
            z-index: 999;
            display: flex;
            .tranbox{
                width: 10px;
                background-color: #fff;
                z-index: 999;
            }
            .tab{
                background-color: #fff;
                flex: 1;
                overflow: hidden;
                .tabitems{
                    display: inline-flex;
                    width: auto;
                    .tabitem{
                        flex: 1;
                        font-size: 15px;
                        line-height: 24px;
                        padding:10px 17px;
                        color: #333333;
                        text-align: center;
                        display: inline-flex;
                        justify-content: center;
                        box-sizing: border-box;
                        flex-wrap: nowrap;
                        white-space: nowrap;
                    }
                    .tabactived{
                        color:#F14D44;
                        position: relative;
                        font-size: 17px;
                        line-height: 24px;
                        &:after{
                            position: absolute;
                            content: "";
                            bottom: 0;
                            left: 20%;
                            width: 60%;
                            height: 3px;
                            background-color: #F14D44;
                        }
                    }
                }
            }
            .additem{
                height: 100%;
                width: 45px;
                display: flex;
                justify-content: center;
                align-items: center;
                background-color: #fff;
                font-size: 20px;
                line-height: 24px;
                padding:10px 0;
                color: #888;
                box-shadow: 0 -5px 5px #ddd;
                z-index: 999;

            }
        }
        .center {
            flex: 1;
            overflow-y: auto;
            margin-top: -1px;
            -webkit-overflow-scrolling: touch;
            .slide-banner-scroll{
                width: 100%;
                height: 100%;
                touch-action: none;
                .slide-banner-wrapper{
                    height: 100%;
                    .slide-item{
                        width: 100%;
                        height: 100%;
                        display: inline-block;
                        position: relative;
                        .zxlinelistbox{
                            height: 100%;
                            .zxcontentbox{
                                padding-bottom: 20px;
                            }
                        }
                    }
                }
            }
        }
    }
</style>

其中silder有个方法就是 goToPage

this.slide.goToPage(index);

传入页码 自动滚动至对应页数 所用的变化都在watch 中实现,这样保证了数据变化就可以触发 实现了上下联动效果 效果如下

基于 vue +better scroll滑动切换页面 并支持下拉刷新案例

 4.实现下拉刷新 上拉加载更多

现在是水平方向有多个页面 要实现下拉刷新 上拉加载,为了保证每个页面的独立性,在每个页面**后 给该页面增加该效果,就在watch中添加,为了防止其他页面干扰 切换前先清除下拉 scroll 为了防止和slider干扰 设置一下eventPassthrough:"horizontal" 保证水平方向不干扰别人 slider 也设置eventPassthrough:"vertical", 保证竖直方向不干扰别人。

实现下拉效果和加载更多效果在初始化的时候还需要设置pullUpLoad 和 pullDownRefresh

初始化如下

this.bscroll = new BScroll(scldom, {
                        click: true,
                        scrollX: false,
                        scrollY: true,
                        // momentum:false,
                        bounceTime: 800,
                        pullUpLoad:{
                            threshold: 70,
                        },
                        pullDownRefresh: {
                            threshold: 20,
                            stop:56
                        },
                        eventPassthrough:"horizontal"
                    });
                }
this.bscroll.on('pullingDown', this.pullingDownHandler)
this.bscroll.on('pullingUp', this.pullingUpHandler)

修复问题:在页面来回切换过程中 发现下拉刷新 的定时器没有清除 导致 下拉刷新没有重置 因此在初始化时加了一下判断

    initscrldata(){
                this.loadingtxt='下拉刷新';
                this.dragTip={
                    text:"释放刷新",
                        translate:-50,
                        showLoding:false
                },
                this.beforePullDown=true;
                this.isPullingDown= false;
                this.isPullUpLoad=true;
                this.canloading=true;
                if(this.bscroll){
                    this.bscroll.finishPullDown()
                    this.bscroll.finishPullUp();
                    this.bscroll.destroy();
                }
                if(this.timer2){
                    let vm = this;
                    clearTimeout(vm.timer2)
                }
                if(this.timer){
                    let vm = this;
                    clearTimeout(vm.timer)
                }
                if(this.timer1){
                    let vm = this;
                    clearTimeout(vm.timer1)
                }
                this.bscroll = null;
            },

 最终代码如下。复制即可使用!

<template>
    <div class="page" ref="page">
        <div class="topcontent" style="">
            <div class="tranbox"></div>
            <div class="tab" ref="linescoll">
                <!--11 快讯(e 线)、12 解读、13 情报(131 早知道、132 涨停板、133 龙虎榜、134 数 说 A 股)、21 新三板、22 科创板-->
                <div class="tabitems" ref="picList">
                    <div v-for="(item,index) in navlist" class="tabitem" :class="item.id==activeitem.id?'tabactived':''" @click="changtab(item)" :key="index">{{item.title}}</div>
                </div>
            </div>
            <div class="additem">+</div>
        </div>
        <div class="center">
            <div class="slide-banner-scroll" ref="slide">
                <div class="slide-banner-wrapper">
                    <div class="slide-item"  v-for="item in navlist" :key="item.id">
                        <div class="zxlinelistbox" :class="'page'+item.id">
                            <div class="zxcontentbox">
                                <div class="pulldown-wrapper">
                                    <div v-show="beforePullDown">
                                        <span>松开刷新</span>
                                    </div>
                                    <div v-show="!beforePullDown">
                                        <div v-show="isPullingDown">
                                            <span>刷新中...</span>
                                        </div>
                                        <div v-show="!isPullingDown"><span>刷新成功</span></div>
                                    </div>
                                </div>
                                <div class="zxcollist">
                                    <div class="zxcolitem" v-for="(item,index) in listdata" :key="index">
                                        <label :class="readId.indexOf(item.item_id)!=-1?'readed':''">
                                            <div v-if="item.item_title && item.item_title.length<30">{{item.item_title}}</div>
                                            <div v-else>{{item.item_title.slice(0,30)}}...</div>
                                            <div>{{item.creat_time}}</div>
                                        </label>
                                        <label v-if="item.img && item.img[0]" class="itemimg">
                                            <img :src="item.img[0]">
                                        </label>
                                    </div>
                                </div>
                                <div class="pullup-wrapper" v-if="canloading && listdata.length>0">
                                    <div v-if="!isPullUpLoad" class="before-trigger">
                                        <span class="pullup-txt">上拉加载更多</span>
                                    </div>
                                    <div v-else class="after-trigger">
                                        <span class="pullup-txt">加载中...</span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>

                </div>
            </div>
        </div>
    </div>
</template>

<script>
    import BScroll from 'better-scroll';
    export default {
        data() {
            return {
                loadingtxt:'下拉刷新',
                dragTip:{
                    text:"释放刷新",
                    translate:-50,
                    showLoding:false
                },
                beforePullDown: true,
                isPullingDown: false,
                isPullUpLoad:true,
                canloading:true,
                navlist:[
                    {title:'要闻', action:'', type:'', from:'ezx',id:1},
                    {title:'7*24', action:'', type:'', from:'ezx',id:2},
                    {title:'自选股', action:'', type:'', from:'ezx',id:3},
                    {title:'公司研报', action:'', type:'', from:'zz',id:4},
                    {title:'行业研究', action:'', type:'', from:'zz',id:5},
                    {title:'新三板新闻', action:'', type:'', from:'zz',id:6},
                    {title:'期货研究', action:'', type:'', from:'zz',id:7},
                ],
                activeitem: {},
                listdata:[],  //数据
                readId:['552942']
            };
        },
        watch:{
            activeitem:function(val) {
                let idx;
                this.navlist.map((item,index)=>{
                        if(item.id == val.id){
                            idx =  index
                        }
                    }
                );
                this.changetitle(val,idx);
            }
        },
        created(){
            let data = {"code":0,
                "message":"SUCCESS",
                "data":[
                    {"item_title":"央行开展1年期MLF操作3000亿元 操作利率3.25%","author":["吴晓辉"],"img":[],"is_original":"1","is_top":"0","is_red":"1","is_recom":"1","creat_time":"2020-01-15 10:03:57","news_type":"11","item_id":"552942","label":[]},
                    {"item_title":"2019年业绩续亏跌停 时代万恒打响保壳战","author":["孙宪超"],"img":["https://resource-e2-oss.egsea.com/upload/2020/0115/09/20130419044553.jpg?x-oss-process=image/resize,m_fixed,h_150,w_200"],"is_original":"1","is_top":"0","is_red":"0","is_recom":"1","creat_time":"2020-01-15 10:03:44","news_type":"11","item_id":"552945","label":["600241"]},
                    {"item_title":"上海:将完善居转户政策 加快建设国际人才高地","author":["彭飞"],"img":[],"is_original":"1","is_top":"0","is_red":"0","is_recom":"0","creat_time":"2020-01-15 09:59:13","news_type":"11","item_id":"552965","label":[]},{"item_title":"上海市市长应勇:加快建设全球性人民币产品创新、交易、定价和清算中心","author":["陈文斌"],"img":[],"is_original":"1","is_top":"0","is_red":"1","is_recom":"1","creat_time":"2020-01-15 09:58:12","news_type":"11","item_id":"552949","label":[]},{"item_title":"【e公司微访谈】雄塑科技:“小管道”有大商机 市政工程打开新增长空间","author":["陈文斌"],"img":[],"is_original":"1","is_top":"0","is_red":"1","is_recom":"1","creat_time":"2020-01-15 09:56:41","news_type":"11","item_id":"552824","label":["300599"]},{"item_title":"区块链概念股盘中拉升 联络互动、智度股份等涨停","author":["陈文斌"],"img":[],"is_original":"1","is_top":"0","is_red":"0","is_recom":"0","creat_time":"2020-01-15 09:55:41","news_type":"11","item_id":"552959","label":["000676","002280","603888"]},{"item_title":"上海市市长应勇:全面实施集成电路、人工智能、生物医药“上海方案”","author":["陈文斌"],"img":[],"is_original":"1","is_top":"0","is_red":"1","is_recom":"1","creat_time":"2020-01-15 09:55:28","news_type":"11","item_id":"552962","label":["000975"]},{"item_title":"上海市市长应勇:2019年科创板70家企业成功上市 筹资额达到824亿元","author":["彭飞"],"img":[],"is_original":"1","is_top":"0","is_red":"0","is_recom":"1","creat_time":"2020-01-15 09:51:34","news_type":"11","item_id":"552848","label":[]},{"item_title":"上海市市长应勇:上海房地产市场保持平稳健康发展","author":["彭飞"],"img":[],"is_original":"1","is_top":"0","is_red":"0","is_recom":"0","creat_time":"2020-01-15 09:51:19","news_type":"11","item_id":"552872","label":[]},{"item_title":"上海市市长应勇:支持和鼓励更多科创企业上市","author":["陈文斌"],"img":[],"is_original":"1","is_top":"0","is_red":"1","is_recom":"1","creat_time":"2020-01-15 09:51:02","news_type":"11","item_id":"552932","label":[]}],
                "pageinfo":{"pageNum":1,"pageSize":10,"totalCount":3497,"totalPages":350}
            }
            this.listdata = data.data
        },
        mounted(){
            this.init();
            this.activeitem =  {title:'7*24', action:'', type:'', from:'ezx',id:2};
        },
        methods: {
            init() {
                this.$nextTick(()=>{
                    //设置顶部滚动 navlist
                    this.scrollmethod = new BScroll(this.$refs.linescoll, {
                        bounce: true,
                        eventPassthrough: 'vertical',
                        scrollX: true,
                        scrollY: false,
                        preventDefault: false
                    });
                    //设置轮播页面
                    this.slide = new BScroll(this.$refs.slide, {
                        scrollX: true,
                        scrollY: false,
                        slide: {
                            loop: false,
                            threshold: 100
                        },
                        eventPassthrough:"vertical",
                        momentum: false,
                        // bounce: true,
                    })
                    this.slide.on('scrollEnd', this._onScrollEnd)
                });
            },
            _onScrollEnd() {
                console.log('endssssss')
                let index = this.slide.getCurrentPage().pageX;
                let item  =  this.navlist[index];
                this.activeitem = item;
            },
            initscrldata(){
                this.loadingtxt='下拉刷新';
                this.dragTip={
                    text:"释放刷新",
                    translate:-50,
                    showLoding:false
                },
                    this.beforePullDown=true;
                this.isPullingDown= false;
                this.isPullUpLoad=true;
                this.canloading=true;
                if(this.bscroll){
                    this.bscroll.finishPullDown()
                    this.bscroll.finishPullUp();
                    this.bscroll.destroy();
                }
                if(this.timer2){
                    let vm = this;
                    clearTimeout(vm.timer2)
                }
                if(this.timer){
                    let vm = this;
                    clearTimeout(vm.timer)
                }
                if(this.timer1){
                    let vm = this;
                    clearTimeout(vm.timer1)
                }
                this.bscroll = null;
            },
            _initScroll() {
                var refstr  =  'page'+ this.activeitem.id;
                console.log(refstr)
                this.initscrldata();
                var scldom = document.querySelector('.'+refstr);
                if(this.bscroll){
                    this.bscroll.finishPullDown()
                    this.bscroll.finishPullUp();
                    this.bscroll.refresh();
                }else {
                    console.log('nesssssss')
                    this.bscroll = new BScroll(scldom, {
                        click: true,
                        scrollX: false,
                        scrollY: true,
                        // momentum:false,
                        bounceTime: 800,
                        pullUpLoad:{
                            threshold: 70,
                        },
                        pullDownRefresh: {
                            threshold: 20,
                            stop:56
                        },
                        eventPassthrough:"horizontal"
                    });
                }
                this.bscroll.on('pullingDown', this.pullingDownHandler)
                this.bscroll.on('pullingUp', this.pullingUpHandler)
            },
            async pullingUpHandler() {
                // if(!this.canloading || this.zxlist.length ===0){
                //     return
                // }
                console.log("babababaabaaaaa");
                this.isPullUpLoad = true;
                // this.page++;
                // await this.getzxdata();
                setTimeout(()=>{
                    this.listdata.push({"item_title":"央行开展1年期MLF操作3000亿元 操作利率3.25%","author":["吴晓辉"],"img":[],"is_original":"1","is_top":"0","is_red":"1","is_recom":"1","creat_time":"2020-01-15 10:03:57","news_type":"11","item_id":"552942","label":[]})
                    this.listdata.push({"item_title":"2019年业绩续亏跌停 时代万恒打响保壳战","author":["孙宪超"],"img":["https://resource-e2-oss.egsea.com/upload/2020/0115/09/20130419044553.jpg?x-oss-process=image/resize,m_fixed,h_150,w_200"],"is_original":"1","is_top":"0","is_red":"0","is_recom":"1","creat_time":"2020-01-15 10:03:44","news_type":"11","item_id":"552945","label":["600241"]})
                    this.$nextTick(()=>{
                        this.bscroll.finishPullUp();
                        this.bscroll.refresh();
                        this.isPullUpLoad = false
                    });
                } ,1000)

            },
            async pullingDownHandler() {
                this.beforePullDown = false
                this.isPullingDown = true
                // STEP += 10
                this.timer =  setTimeout(() =>{
                    this.isPullingDown = false;
                    this.finishPullDown()
                },5000);

                // await this.getzxdata();
                // this.getbannerdata().then(() =>{
                //     this.getkjzxdata()
                // }).then(() =>{
                //     this.loadIcons();
                //     this.isPullingDown = false;
                //     this.finishPullDown()
                // });

            },
            async finishPullDown() {
                let vm =this;
                const stopTime = 600
                await new Promise(resolve => {
                    vm.timer1 =   setTimeout(() => {
                        this.bscroll.finishPullDown()
                        resolve()
                    }, stopTime)
                })
                vm.timer2 = setTimeout(() => {
                    console.log("刷新完成!!!!!!!!!!!!")
                    this.beforePullDown = true
                    this.bscroll.refresh()
                }, 600)
            },
            changetitle(item,index){
                let idx = index+1
                let dom = document.querySelector('.tabitems .tabitem:nth-child(' + idx + ')');
                this.$nextTick(() => {
                    //标题滚动到对应位置
                    // 五个参数 滚动到元素 时间  水平偏移 竖直偏移  后两个为true 则是中心位置 最后
                    this.scrollmethod.scrollToElement(dom, null, true, true);
                    this.scrollmethod.refresh();
                    //详情页滚动到对应页面
                    this.slide.goToPage(index);
                    //对应页加载 上拉下拉事件

                    this._initScroll();
                })
            },

            changtab(item) {
                this.activeitem = item;
            }
        }

    };
</script>

<style lang="scss"  scoped>
    .page{
        display: flex;
        flex-direction: column;
        width: 100%;
        height: 100%;
        overflow: hidden;
        background-color: rgba(247, 247, 247, 1);
        .topcontent {
            z-index: 999;
            display: flex;
            .tranbox{
                width: 10px;
                background-color: #fff;
                z-index: 999;
            }
            .tab{
                background-color: #fff;
                flex: 1;
                width: calc(100% - 60px);
                /*display: flex;*/
                /*flex-wrap: nowrap;*/
                .tabitems{
                    display: inline-flex;
                    width: auto;
                    .tabitem{
                        flex: 1;
                        font-size: 15px;
                        line-height: 24px;
                        padding:10px 17px;
                        color: #333333;
                        text-align: center;
                        /*min-width: 22vw;*/
                        display: inline-flex;
                        justify-content: center;
                        box-sizing: border-box;
                        flex-wrap: nowrap;
                        white-space: nowrap;
                    }
                    .tabactived{
                        color: #f14d44;
                        position: relative;
                        font-size: 17px;
                        line-height: 24px;
                        &:after{
                            position: absolute;
                            content: "";
                            bottom: 0;
                            left: 20%;
                            width: 60%;
                            height: 3px;

                            background-color: #f14d44;
                        }
                    }
                }

            }
            .additem{
                height: 100%;
                width: 45px;
                display: flex;
                justify-content: center;
                align-items: center;
                background-color: #fff;
                font-size: 20px;
                line-height: 24px;
                padding:10px 0;
                color: #888;
                box-shadow: 0 -5px 5px #ddd;
                z-index: 999;
            }
        }
        .center {
            flex: 1;
            overflow-y: auto;
            margin-top: -1px;
            -webkit-overflow-scrolling: touch;
            .slide-banner-scroll{
                width: 100%;
                height: 100%;
                touch-action: none;
                .slide-banner-wrapper{
                    height: 100%;
                    .slide-item{
                        width: 100%;
                        height: 100%;
                        display: inline-block;
                        position: relative;
                        .zxlinelistbox{
                            height: 100%;
                            .zxcontentbox{
                                padding-bottom: 20px;
                            }
                            .zxcollist{
                                padding: 0 15px;
                                /*margin-top: 15px;*/
                                .zxcolitem{
                                    margin-top: 10px;
                                    background-color: #fff;
                                    border-radius:8px;
                                    display: flex;
                                    align-items: flex-start;
                                    padding: 15px;
                                    box-sizing: border-box;
                                    label:first-child{
                                        /*padding-right: 20px;*/
                                        box-sizing: border-box;
                                        flex: 1;
                                        color:rgba(33,32,41,1);
                                        display: flex;
                                        flex-direction: column;
                                        justify-content: space-between;
                                        height:75px;
                                        div:first-child{
                                            margin-top: -2px;
                                            font-size:17px;
                                            font-family:PingFang-SC-Medium;
                                            line-height:24px;
                                            letter-spacing:0;
                                            /*text-align: justify;*/
                                        }
                                        div:last-child{
                                            font-size:12px;
                                            font-family:PingFang-SC-Medium;
                                            color:rgba(153,153,153,1);
                                            line-height:12px;
                                            margin-bottom: 2px;
                                        }
                                    }
                                    .itemimg{
                                        width: 120px;
                                        height:75px;
                                        padding-left: 20px;
                                        img{
                                            width:100%;
                                            height:75px;
                                            border-radius:4px;
                                            background-color: #eee;
                                            border: solid 1px #eee;
                                            /*border: none;*/
                                        }
                                    }
                                    .readed{
                                        div:first-child{
                                            color:#888;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        .pulldown-wrapper{
            position: absolute;
            width: 100%;
            padding: 20px;
            box-sizing: border-box;
            transform: translateY(-100%) translateZ(0);
            text-align: center;
            color: #999}
        .pullup-wrapper{
            .before-trigger, .after-trigger{
                padding: 8px;
                font-size:14px;
                color: #888;
                text-align: center;
            }
        }
        .pulldown,.pullup{
            width:100%;
            position:relative;
            div.clear{
                padding:10px 0px;
                font-size:.28rem;
                position:absolute;
                left:50%;
                top:5px;
                transform:translate(-50%,0);
                .list-donetip{
                    text-align:center;
                    line-height:50px;
                    font-size:.28rem;
                }}}
    }
</style>

用的sass 作为css的预编译,作为demo 就没分模块化,也方便快速实现功能 和改造,本来想弄githup上 但是一想光pull 和npm 一下就很费时间 直接贴代码好了 ,只要有sass 和 npm 一下better scroll 创建一个vue 复制进去就可以跑起来 感觉更方便一些!