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

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

 微信扫码预览

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

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

一、效果分析

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

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

二、功能实现

1.插件安装

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

better scroll的安装

npm install better-scroll@next -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的大小,不能让它的大小让子元素撑开

 先是进行页面布局吧

顶部这一块红色标出的就是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>

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

2. 滑动切换slider实现

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

 根据咱们的项目 添加一些初始数据 在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 中实现,这样保证了数据变化就可以触发 实现了上下联动效果 效果如下

 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 复制进去就可以跑起来 感觉更方便一些!

 

发布了28 篇原创文章 · 获赞 18 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章