Vue.js组件实现选项卡以及切换特效


Posted in Javascript onJuly 24, 2019

Vue.js组件实现选项卡以及切换动画特效,供大家参考,具体内容如下

最近在学习Vue,当看梁灏大神写的《Vue.js实战》时看到了关于用组件实现选项卡功能,我也根据课后的练习加上自己的理解重新编写了一下。

组件分为pane.jstabs.js两个部分,话不多说,直接上代码。

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <link rel="stylesheet" href="style.css" rel="external nofollow" >
 <title>Document</title>
</head>

<body>
 <div id="app">
  <tabs v-model="activeKey">
   //transiton是Vue自带封装的,不懂的同学可以去找文档,主要是可以实现动画
   <transition name="slide-fade"> 
    <pane label="标签一" name="1">
     标签一的内容
    </pane>
   </transition>
   <transition name="slide-fade">
    <pane label=" 标签二" name="2">
     标签二的内容
    </pane>
   </transition>
   <transition name="slide-fade">
    <pane label="标签三" name="3">
     标签三的内容
    </pane>
   </transition>

  </tabs>
 </div>


 <script src="vue/vue.js"></script>
 <script src="pane.js"></script>
 <script src="tabs.js"></script>
 <script src="text.js"></script>
</body>

</html>
//tabs.js
Vue.component('tabs', {
 template: `
 <div class="tabs">
  <div class="tabs-bar">
  <div :class="tabCls(item)" v-for="(item, index) in navList" @click="handleChange(index)">
   {{item.label}}
  </div>
  <button @click="removePane()"> 关闭/打开 </button>
  </div>

  <div class="tabs-content">
    <slot></slot> 
  </div>
 </div>
 `,
 props: {
  value: {
   type: [String, Number],
  },
 },
 data: function () {
  return {
   currentValue: this.value,
   navList: [],
  };
 },
 methods: {
  tabCls: function (item) {
   return [
    'tabs-tab',
    {
     'tabs-tab-active': item.name === this.currentValue,
    },
   ];
  },
  getTabs() {
   return this.$children.filter(function (item) {
    return item.$options.name === 'pane';
   });
  },
  updateNav() {
   this.navList = [];
   var _this = this;

   this.getTabs().forEach(function (pane, index) {
    _this.navList.push({
     label: pane.label,
     name: pane.name || index,
     bool: pane.closable,
    });
    if (!pane.name) pane.name = index;
    if (index === 0) {
     if (!_this.currentValue) {
      _this.currentValue = pane.name || index;
     }
    }
   });
   this.updateStatus();
  },
  updateStatus() {
   var tabs = this.getTabs();
   var _this = this;
   tabs.forEach(function (tab) {
    return (tab.show = tab.name === _this.currentValue);
   });
  },
  handleChange: function (index) {
   var nav = this.navList[index];
   var name = nav.name;

   this.currentValue = name;
   this.$emit('input', name);
   // this.$emit('on-click', name);
  },
  removePane: function () {
   var bool = this.navList[1].bool;
   console.log(bool);
   if (bool) {
    this.navList[1].bool = false;
    this.currentValue = '0';
   }
   if (!bool) {
    this.navList[1].bool = true;
    this.currentValue = '1';
    this.$emit('input', '1');
   }
  },
 },
 watch: {
  value: function (val) {
   this.currentValue = val;
  },
  currentValue: function () {
   console.log('demo');
   this.updateStatus();
  },
 },
});
//pane.js
Vue.component('pane', {
 name: 'pane',
 template: `
 <div class="pane" v-if="show">
  <slot> </slot>
 </div>
 `,
 props: {
  name: {
   type: String
  },
  label: {
   type: String,
   default: ''
  },
  closable: {
   type: Boolean,
   default: true
  }
 },

 data: function () {
  return {
   show: true
  }
 },
 methods: {
  updateNav() {
   this.$parent.updateNav();
  }
 },
 watch: {
  label() {
   this.updateNav();
  }
 },
 mounted() {
  this.updateNav();
 }
})
//style.css
.tabs {
 font-size: 14px;
 color: black;
}

.tabs-bar:after {
 content: '';
 display: block;
 width: 100%;
 height: 1px;
 position: relative;
 background: rgba(78, 81, 128, 0.5);
}

.tabs-tab {
 display: inline-block;
 padding: 4px 16px;
 margin-right: 6px;
 color: rgba(0, 0, 0, 0.6);
 background: rgba(134, 134, 131, 0.137);
 border: 1px solid rgba(154, 214, 248, 0.856);
 cursor: pointer;
 position: relative;
}

.tabs-tab-active {
 background: rgb(252, 251, 251);
 color: rgba(0, 0, 0, 1);
 border-top: 1px solid rgba(154, 214, 248, 0.856);
 border-bottom: 1px solid white;
}

/* .tabs-tab-active:before {
 content: '';
 display: block;
 height: 5px;
 background: grey;
 position: absolute;
 top: 0;
 left: 0;
 right: 0;
} */

.tabs-content {
 position: relative;
 left: 10px;
 top: 30px;
 padding: 8px 0;
}

/* 可以设置不同的进入和离开动画 */
/* 设置持续时间和动画函数 */
.slide-fade-enter-active {
 transition: all 1.3s ease;
}

.slide-fade-leave-active {
 transition: all 1.8s cubic-bezier(1, 0.5, 0.8, 1);
}

.slide-fade-enter,
.slide-fade-leave-to

/* .slide-fade-leave-active for below version 2.1.8 */
 {
 transform: translateY(30px);
 opacity: 0;
}
//text.js
var app = new Vue({
 el: '#app',
 data: {
  activeKey: '1',
 },
})

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js实现addClass,removeClass,hasClass的函数代码
Jul 13 Javascript
JQuery Highcharts 动态生成图表的方法
Nov 15 Javascript
原生js获取宽高与jquery获取宽高的方法关系对比
Apr 04 Javascript
模拟用户点击弹出新页面不会被浏览器拦截
Apr 08 Javascript
JavaScript原生对象之Number对象的属性和方法详解
Mar 13 Javascript
JavaScript编程中window的location与history对象详解
Oct 26 Javascript
jquery封装插件时匿名函数形参和实参的写法解释
Feb 14 Javascript
js放到head中失效的原因与解决方法
Mar 07 Javascript
vue实现长图垂直居上 vue实现短图垂直居中
Oct 18 Javascript
vue组件实践之可搜索下拉框功能
Nov 25 Javascript
通过js给网页加上水印背景实例
Jun 17 Javascript
微信小程序动态添加和删除组件的现实
Feb 28 Javascript
javascript中call,apply,callee,caller用法实例分析
Jul 24 #Javascript
javascript关于“时间”的一次探索
Jul 24 #Javascript
javascript面向对象三大特征之封装实例详解
Jul 24 #Javascript
解决vue-cli webpack打包开启Gzip 报错问题
Jul 24 #Javascript
Vue  webpack 项目自动打包压缩成zip文件的方法
Jul 24 #Javascript
JavaScript面向对象中接口实现方法详解
Jul 24 #Javascript
IE11下处理Promise及Vue的单项数据流问题
Jul 24 #Javascript
You might like
PHP去掉json字符串中的反斜杠\及去掉双引号前的反斜杠
2015/09/30 PHP
PHP 网站修改默认访问文件的nginx配置
2017/05/27 PHP
PHP判断是否微信访问的方法示例
2019/03/27 PHP
thinkphp5.1框架模板赋值与变量输出示例
2020/05/25 PHP
Alliance vs Liquid BO3 第三场2.13
2021/03/10 DOTA
JavaScript入门教程(11) js事件处理
2009/01/31 Javascript
jQuery dialog 异步调用ashx,webservice数据的代码
2010/08/03 Javascript
JS HTML5 音乐天气播放器(Ajax获取天气信息)
2013/05/26 Javascript
JavaScript中constructor()方法的使用简介
2015/06/05 Javascript
js利用正则表达式检验输入内容是否为网址
2016/07/05 Javascript
vue快捷键与基础指令详解
2017/06/01 Javascript
JS实现自动轮播图效果(自适应屏幕宽度+手机触屏滑动)
2017/06/19 Javascript
vue router demo详解
2017/10/13 Javascript
傻瓜式解读koa中间件处理模块koa-compose的使用
2018/10/30 Javascript
在vue中使用echarts(折线图的demo,markline用法)
2020/07/20 Javascript
[52:15]2014 DOTA2国际邀请赛中国区预选赛5.21 HGT VS LGD-GAMING
2014/05/23 DOTA
[04:44]显微镜下的DOTA2第二期——你所没有注意到的细节
2014/06/20 DOTA
[56:17]NB vs Infamous 2019国际邀请赛淘汰赛 败者组 BO3 第三场 8.22
2019/09/05 DOTA
Python 执行字符串表达式函数(eval exec execfile)
2014/08/11 Python
Python对象体系深入分析
2014/10/28 Python
Python下rrdtool模块的基本使用方法
2015/11/13 Python
教你用Type Hint提高Python程序开发效率
2016/08/08 Python
Python 实现文件的全备份和差异备份详解
2016/12/27 Python
基于scrapy的redis安装和配置方法
2018/06/13 Python
Python不同目录间进行模块调用的实现方法
2019/01/29 Python
pandas的相关系数与协方差实例
2019/12/27 Python
Python换行与不换行的输出实例
2020/02/19 Python
python爬虫开发之Request模块从安装到详细使用方法与实例全解
2020/03/09 Python
CSS3实现swap交换动画
2016/01/19 HTML / CSS
澳大利亚Mocha官方网站:包、钱包、珠宝和配饰
2019/07/18 全球购物
初一家长会邀请函
2014/01/31 职场文书
网络管理专业求职信
2014/03/15 职场文书
咖啡厅里的创业计划书
2019/08/21 职场文书
K8s部署发布Golang应用程序的实现方法
2021/07/16 Golang
java中用float时,数字后面加f,这样是为什么你知道吗
2021/09/04 Java/Android
python热力图实现的完整实例
2022/06/25 Python