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 相关文章推荐
JavaScript中的类继承
Nov 25 Javascript
jquery插件jTimer(jquery定时器)使用方法
Dec 23 Javascript
Jquery Post处理后不进入回调的原因及解决方法
Jul 15 Javascript
Javascript获取CSS伪元素属性的实现代码
Sep 28 Javascript
javascript将数字转换整数金额大写的方法
Jan 27 Javascript
jquery实现带缩略图的全屏图片画廊效果实例
Jun 25 Javascript
jQuery中的ready函数与window.onload谁先执行
Jun 21 Javascript
JavaScript实现移动端滑动选择日期功能
Jun 21 Javascript
JS+CSS3实现超炫的散列画廊特效
Jul 16 Javascript
详解Angular 4.x NgIf 的用法
May 22 Javascript
记一次Vue.js混入mixin的使用(分权限管理页面)
Apr 17 Javascript
微信小程序实现聊天室
Aug 21 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
html中select语句读取mysql表中内容
2006/10/09 PHP
php设计模式之单例模式使用示例
2014/01/20 PHP
PHP聚合式迭代器接口IteratorAggregate用法分析
2017/12/28 PHP
js调用flash的效果代码
2008/04/26 Javascript
JQUERY复选框CHECKBOX全选,取消全选
2008/08/30 Javascript
javascript 面向对象全新理练之数据的封装
2009/12/03 Javascript
Select标签下拉列表二级联动级联实例代码
2014/02/07 Javascript
2014年最火的Node.JS后端框架推荐
2014/10/27 Javascript
基于jQuery实现滚动刷新效果
2017/01/09 Javascript
Angular.js前台传list数组由后台spring MVC接收数组示例代码
2017/07/31 Javascript
基于Vue实现后台系统权限控制的示例代码
2017/08/29 Javascript
PHPStorm中如何对nodejs项目进行单元测试详解
2019/02/28 NodeJs
vue相同路由跳转强制刷新该路由组件操作
2020/08/05 Javascript
python 调用c语言函数的方法
2017/09/29 Python
python使用pycharm环境调用opencv库
2018/02/11 Python
python找出一个列表中相同元素的多个索引实例
2019/06/11 Python
python格式化输出保留2位小数的实现方法
2019/07/02 Python
python英语单词测试小程序代码实例
2019/09/09 Python
python的命名规则知识点总结
2019/10/04 Python
python安装dlib库报错问题及解决方法
2020/03/16 Python
Django-xadmin+rule对象级权限的实现方式
2020/03/30 Python
python中turtle库的简单使用教程
2020/11/11 Python
CSS3 mask 遮罩的具体使用方法
2017/11/03 HTML / CSS
全球最大的跑步用品商店:Road Runner Sports
2016/09/11 全球购物
速卖通欧盟:Aliexpress EU
2020/08/19 全球购物
工地标语大全
2014/06/18 职场文书
国庆65周年演讲稿:回首往昔,展望未来
2014/09/21 职场文书
住宿生擅自离校检讨书
2014/09/22 职场文书
交通事故和解协议书
2014/09/25 职场文书
会计求职自荐信范文
2015/03/04 职场文书
建国大业观后感
2015/06/01 职场文书
全家福照片寄语怎么写?
2019/04/02 职场文书
加薪申请书应该这样写!
2019/07/04 职场文书
python 如何在list中找Topk的数值和索引
2021/05/20 Python
海贼王十大潜力果实,路飞仅排第十,第一可毁世界(震震果实)
2022/03/18 日漫
MySQL数据库实验实现简单数据库应用系统设计
2022/06/21 MySQL