vue 插件tab选项卡(转载)

摘要:
StartTransX:0、transX:0,//元素样式偏移。CssX:0//css在动作中实际完成的偏移量。
<template>
    <tab :options="tabOpt" :state.sync="stateIndex"></tab>
</template>
<script type="text/babel">
    import tab from 'components/tab_touch';
    export default {
        data(){
            tabOpt:undefined,
            stateIndex:0
        },
        components:{
        "tab":tab
        },
        ready(){
            this.tabOpt={
                count: 2.3,
                pin:true,
                htmls:[
                    "<span>白日登山</span>",
                    "<span>望烽火</span>",
                    "<span>黄昏饮马</span>",
                    "<span>傍交河</span>",
                    "<span>行人刁斗</span>",
                    "<span>风沙暗</span>",
                    "<span>公主琵琶</span>",
                    "<span>幽怨多</span>",
                    "<span>野营万里</span>",
                    "<span>无城郭</span>",
                    "<span>雨雪纷纷</span>",
                    "<span>连大漠</span>"
                ],
                slideCallback:function (dex) {
                    console.log(dex);
                },
                tabClassName:"tab",
                tabActiveClassName: "active"
            }
        }
    }
</script>

options参数释义

参数名简称是否必填类型含义默认值其它
count展示tab数必填项数值|一屏中露出tab的个数| 无   
pin是否固定到顶部可选项布尔当垂直滚动时,该组件即将超出屏幕时是否固定到头部false 
htmlstab内容必填项数组[字符串]在tab中显示的html 
tabClassNametabClassName可选项字符串单个tab的class名一般用于自定义样式
tabActiveClassNametabActiveClassName可选项字符串

激活的tab的class名

<template>
    <div class="fixWrap">
        <div   :id="tabsWrapID"
             v-touch:pan="onPan">
            <div   :style="wrapStyle">
                <div   v-for="item in options.htmls" track-by="$index" :style="''+tWidth+'px'"
                     @click.stop="this.state=$index"
                     :class="[options.tabClassName,$index==state?options.tabActiveClassName:'']">
                    {{{item}}}
                </div>
            </div>
        </div>
    </div>
</template>
<style lang="sass" rel="stylesheet/sass">
    @import "tab.sass"
</style>
<script lang="babel" type="text/babel">
    var VueTouch = require ('vue-touch');
    Vue.use (VueTouch);
    import requestAnimFrame  from "utils/requestAnimFrame"
    const sign = (num)=> {
        return num >= 0 ? 1 : -1
    }
    export default {
        props: ["options", "state"],
        data(){
            return {
                tabsWrapID: undefined,//外容器ID
                wrapWidth: "", //外容器宽度
                tWidth: 0, //每一个选项卡应该有多宽
                 0, //宽度。
                startTransX: 0,
                transX: 0, //元素样式偏移。
                cssX: 0 //动作中css实际完成的偏移。
            }
        },
        methods: {
            init(){
                this.wrapWidth = document.getElementById (this.tabsWrapID).offsetWidth;
                this.tWidth = this.wrapWidth / this.options.count;
                this.width = this.tWidth * this.options.htmls.length;
                setTimeout(function(){
                    this.$el.style["height"]= this.$el.children[0].clientHeight+"px";
                }.bind(this),0)
                if (this.options.pin) {
                    var elemRect = this.$el.getBoundingClientRect ();
                    var windowOffset = this.getWindowOffset ();
                    var winOffsetY = windowOffset.offsetY;
                    this.elemOffsetY = elemRect.top + winOffsetY;
                    document.addEventListener ('scroll', this.isTop);
                }
            },
            onPan(event){
                if (this.options.disPan) return;
                this.transX = event.deltaX + this.startTransX;
                this.cssX = this.transX;
                if (event.eventType == 4) {
                    this.transX = -Math.round (-this.transX / this.tWidth) * this.tWidth; //整格滑动
                    var start = null;
                    if (this.transX > 0) {
                        // 头部回弹
                        this.transX = 0;
                        var speed = 24;
                        requestAnimFrame (step.bind (this));
                        function step (timestamp) {
                            this.cssX -= speed;
                            if (this.cssX > this.transX) requestAnimFrame (step.bind (this));
                            else this.startTransX = this.cssX = this.transX;
                        };
                    }
                    else if (this.transX < this.wrapWidth - this.width) {
                        // 尾部回弹
                        this.transX = this.wrapWidth - this.width;
                        var speed = 24;
                        requestAnimFrame (step.bind (this));
                        function step (timestamp) {
                            this.cssX += speed;
                            if (this.cssX < this.transX) requestAnimFrame (step.bind (this));
                            else this.startTransX = this.cssX = this.transX;
                        };
                    }
                    else {
                        //整格落位
                        let speed = 6;
                        let _sign = sign (this.cssX - this.transX);
                        if (_sign * (this.cssX - this.transX) > 1) requestAnimFrame (step.bind (this));
                        else this.cssX = this.transX;
                        function step (timestamp) {
                            if (start === null) start = timestamp;
                            let progress = timestamp - start;
                            if (progress < 3000) speed *= 1 - progress / 3000;
                            this.cssX -= _sign * speed;
                            if (_sign * (this.cssX - this.transX) > 1) requestAnimFrame (step.bind (this));
                            else this.cssX = this.transX;
                        };
                    }
                    this.startTransX = this.transX; //滑动结束设置下次滑动起始值。
                }

            },
            slideTo(dex){
                this.state = dex;
                let speed = 10;
                // 开头几个
                if (dex + 1 <= this.options.count) {
                    this.transX = 0; // 设置应到位置。
                    if (this.startTransX < this.transX) {
                        let _sign = sign (this.transX - this.startTransX);
                        this.cssX = this.transX - _sign * this.tWidth;
                        requestAnimFrame (step.bind (this));
                        function step () {
                            this.cssX += _sign * speed;
                            if (_sign * (this.cssX - this.transX) < 0) requestAnimFrame (step.bind (this));
                            else {
                                this.cssX = this.startTransX = this.transX;
                                if (this.options.slideCallback) this.options.slideCallback (dex);
                            }
                            ;
                        };
                    }
                    //无需动画
                    else {
                        this.cssX = this.startTransX = this.transX;
                        if (this.options.slideCallback) this.options.slideCallback (dex);
                    }
                }
                // 结尾几个
                else if (this.options.htmls.length - dex <= this.options.count) {
                    this.transX = this.wrapWidth - this.width;// 设置应到位置。
                    if (this.startTransX > this.transX) {
                        let _sign = sign (this.transX - this.startTransX);
                        this.cssX = this.transX - _sign * this.tWidth;
                        requestAnimFrame (step.bind (this));
                        function step () {
                            this.cssX += _sign * speed;
                            if (_sign * (this.cssX - this.transX) < 0) requestAnimFrame (step.bind (this));
                            else {
                                this.cssX = this.startTransX = this.transX;
                                if (typeof this.options.slideCallback == "function") this.options.slideCallback (dex);
                            }

                        };
                    }
                    else {
                        this.cssX = this.startTransX = this.transX; //无需动画
                        if (typeof this.options.slideCallback == "function") this.options.slideCallback (dex);
                    }
                }
                //
                else {
                    this.transX = -this.tWidth * dex;// 设置应到位置。
                    let _sign = sign (this.transX - this.startTransX);
                    if (this.tWidth * (dex + 0.5 * (1 - _sign)) + this.startTransX >= 0 && this.tWidth * (dex + 0.5 * (1 - _sign)) + this.startTransX <= this.wrapWidth) {
                        //无需动画
                        this.cssX = this.transX = this.startTransX;
                        if (typeof this.options.slideCallback == "function") this.options.slideCallback (dex);
                    }
                    else {
                        //需要动画
                        this.cssX = this.transX - _sign * this.tWidth;
                        requestAnimFrame (step.bind (this));
                        function step () {
                            this.cssX += _sign * speed;
                            if (_sign * (this.cssX - this.transX) < 0) requestAnimFrame (step.bind (this));
                            else {
                                this.cssX = this.startTransX = this.transX;
                                if (typeof this.options.slideCallback == "function") this.options.slideCallback (dex);
                            }
                        };
                    }
                }
            },
            isTop(){
                var windowOffset = this.getWindowOffset (),
                        winOffsetY = windowOffset.offsetY,
                        isTop;
                isTop = this.elemOffsetY <= winOffsetY;
                if (isTop) {
                    this.$el.children[0].style['position'] = 'fixed';
                    this.$el.children[0].style['top'] = '0';
                    this.$el.children[0].style['left'] = '0';
                }
                else {
                    this.$el.children[0].style['position']='relative';
                }
                return isTop;
            },
            getWindowOffset(){
                var t;
                var win = window;
                var pageXOffset = (typeof win.pageXOffset == 'number') ? win.pageXOffset : (((t = doc.documentElement) || (t = body.parentNode)) && typeof t.ScrollLeft == 'number' ? t : body).ScrollLeft;
                var pageYOffset = (typeof win.pageYOffset == 'number') ? win.pageYOffset : (((t = doc.documentElement) || (t = body.parentNode)) && typeof t.ScrollTop == 'number' ? t : body).ScrollTop;
                return {
                    offsetX: pageXOffset,
                    offsetY: pageYOffset
                };
            },
        },
        watch: {
            options(){
                this.tabsWrapID = parseInt (Math.random () * 1e10);
                setTimeout (this.init.bind (this), 10);
            },
            state(val){
                this.slideTo(val)
            }
        },
        computed: {
            wrapStyle(){
                var _str = "";
                if (this.width) _str += `${this.width}px;`;//宽度
                _str += `-webkit-transform:translateX(${this.cssX}px);` //位移。
                _str += `transform:translateX(${this.cssX}px);` //位移。
                return _str
            }
        }
    }
</script>
<style lang="sass" rel="stylesheet/sass" type="sass">
.fixWrap
  z-index: 999
  position: relative
.component-tabsWrap
   100%
  overflow: hidden
  min-height: .1rem
  position: relative
  background: #fff
  .component-tabs
    height: 100%
    display: table
    .component-tab
      display: table-cell
      box-sizing: border-box
      text-align: center
      vertical-align: middle
</style>

来源:http://blog.csdn.net/keliyxyz/article/details/52208484

免责声明:文章转载自《vue 插件tab选项卡(转载)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇JS水仙花数Android 4.0 SDK的离线方式安装(转)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

vue组件的inheritAttrs属性

vue官网对于inheritAttrs的属性解释:如果你不希望组件的根元素继承特性,你可以在组件的选项中设置 inheritAttrs: false。 可能不是很好理解,我们可以举个例子来验证一下。 父组件 parent-component.vue <template>  <div class="parent">     <...

vue JSON数据导出为 多个sheet表的excel文件

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />...

【Vue后台管理三】集成echarts图表

集成echarts图标 路一步步走,代码得一个个敲,今天自己来集成了echarts图标,为什么要集成echarts了? 图表表示数据,应该是最清晰直白了,所以很多管理页面的首页都集成了。 首先看看效果 下面应该还有一个关于每月销量收入的图表,明天在加上。 站在巨人的肩膀上 我个人没真实做过后台管理项目,所以了这些后台的样子,是参考我公司后台管理样式和一些...

vue官网总结

1.Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:2.在 Vue 里,一个组件本质上是一个拥有预定义选项的一个 Vue 实例。 所有的 Vue 组件都是 Vue 实例,并且接受相同的选项对象 (一些根实例特有的选项除外)3.只有当实例被创建时就已经存在于 data 中的属性才是响应式的,vm.b = 不会触发视图的...

无限加载 vue用infinite-loading插件和阿波罗请求

1.npm install vue-infinite-loading --save 2.npm install --save vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag   (https://akryum.gi...

跨平台响应式开发框架DevExtreme——支持Vue 3

DevExpress技术交流群3:700924826欢迎一起进群讨论 DevExtreme拥有高性能的HTML5 / JavaScript小部件集合,使您可以利用现代Web开发堆栈(包括React,Angular,ASP.NET Core,jQuery,Knockout等)构建交互式的Web应用程序。从Angular和Reac,到ASP.NET Core或...