<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  
htmls tab内容 必填项 数组[字符串] 在tab中显示的html  
tabClassName tabClassName 可选项 字符串 单个tab的class名 一般用于自定义样式
tabActiveClassName tabActiveClassName 可选项 字符串

激活的tab的class名

<template>
<div class="fixWrap">
<div class="component-tabsWrap" :id="tabsWrapID"
v-touch:pan="onPan">
<div class="component-tabs" :style="wrapStyle">
<div class="component-tab" v-for="item in options.htmls" track-by="$index" :style="'width:'+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, //每一个选项卡应该有多宽
width: 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 += `width:${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
width: 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选项卡(转载)的更多相关文章

  1. 微信小程序的wx-charts插件-tab选项卡

    微信小程序的wx-charts插件-tab选项卡 效果: //index.js var wxCharts = require('../../utils/wxcharts-min.js'); const ...

  2. vue实现tab选项卡切换效果

    tab选项卡切换效果: 通过点击事件传入参数,然后通过v-show来进行切换显示 <template> <div class="box"> <div ...

  3. Vue实现tab选项卡

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. vue实现tab选项卡切换

    上代码: <template>   <div class="push">     //点击按钮     <div class="tab&qu ...

  5. 使用jQuery开发tab选项卡插件(可以右键关闭多个标签)

    在前一篇“使用jQuery开发tab选项卡插件”的基础上添加了tab标签右键关闭菜单功能,菜单主要包括:关闭当前标签.关闭左侧标签.关闭右侧标签.关闭其他.关闭全部. 一.插件效果 二.实现思路 为w ...

  6. 使用jQuery开发tab选项卡插件

    为了复习巩固jQuery的插件开发.HTML和CSS方面的知识,做了一个简单的tab选项卡插件,简单记录一下开发.使用的过程,以备日后使用. 一.插件效果 tab选项卡插件常用的功能均已实现,包括:动 ...

  7. 微信小程序-滚动Tab选项卡

    前言:今天呢 给大家详细讲解一下滚动Tab选项卡:左右可滑动切换的效果,希望对大家做项目时候有用! 以前也遇到过这个,但是没有做记录.转载来源于:https://www.jianshu.com/p/9 ...

  8. 很全的vue插件汇总,赶紧收藏下(转)

    Vue是一个构建数据驱动的 web 界面的渐进式框架.Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件特别整理了常用的vue插件,来了个大汇总,方便查找使用,便于工作 ...

  9. 可轮播滚动的Tab选项卡

    前段时间有试着搭建个后台主题ui框架,有用到可支持滚动的Tab选项卡,模仿着H+后台主题ui框架中的代码造轮子改造了下,可惜代码在公司,不能把代码外发出来(感觉这样被限制了很多,对于这样的公司没办法, ...

随机推荐

  1. 读书笔记 C# 接口之浅析

    一.接口可以包含 属性.方法.事件和索引器: 二.接口不能被实例化: 三.一个类可以继承多个接口: 四.接口不能包含方法的实现: 五.继承接口的类必须实现接口中所有成员: 六.显式实现接口的成员,不能 ...

  2. PHP和Mysql事物处理

    这几天做支付的时候,又用到了事物,为了方便自己以后查看,今天闲的没事就把以前的东西整理下.(其中引用别人的东西,在这里谢谢他们贡献的代码!) 一.事务处理概述: 事务:是若干事件的集合 事务处理:当所 ...

  3. 小程序之setData特殊情况 三种情况的wx:if

    比如data{ “a”:{}, "b":{} } 你想完成这样的结构 //创建一个对象 var readyData={} //对象[key] =另一个对象 readyData[ke ...

  4. 网口扫盲二:Mac与Phy组成原理的简单分析(转)

    1. general 下图是网口结构简图.网口由CPU.MAC和PHY三部分组成.DMA控制器通常属于CPU的一部分,用虚线放在这里是为了表示DMA控制器可能会参与到网口数据传输中. 对于上述的三部分 ...

  5. Class file collision

    ecplise报错,提示:Class file collision (类文件冲突) 原因是:文件保存(编译)后,生成了class文件起了冲突,windows 系统认为Test.class 和test. ...

  6. MERGE INTO 解决大数据量 10w 更新缓慢的问题

    有个同事处理更新数据缓慢的问题,数据量超10w的量,更新速度太慢耗时较长,然后改成了 MERGE INTO 效率显著提高. 使用方法如下 MERGE INTO 表A USING 表B ON 关联条件 ...

  7. Oracle function和procedure

    1.返回值的区别 函数有1个返回值,而存储过程是通过参数返回的,可以有多个或者没有 2. 调用的区别,函数可以在查询语句中直接调用,而存储过程必须单独调用. 函数:一般情况下是用来计算并返回一个计算结 ...

  8. shell脚本实例-mysql多机部署

    今天我给大家分享shell 安装mysql 多机部署的实例,本次实验是基于各个主机的公钥已经配置好了,如果还不会推送公钥的同学,可以看看我以前写的文章,那里面有写推公钥的实例,mysql 多机部署一般 ...

  9. python 递归进阶操作方法

    递归 在函数内部,可以调用其他函数; 如果一个函数在内部调用自身本身,这个函数就是递归函数. 例如,我们来计算阶乘: n! = 1 x 2 x 3 x ... x n, 用函数f1(n)表示,可以看出 ...

  10. ipython output logging:使用日志记录输出

    通常使用ipython的%logstart日志功能时,仅开启输入的记录. 例如在ipython中开启%logstart后,记录的日志文件内容如下: #!/usr/bin/env python # 20 ...