详解使用vue实现tab 切换操作


Posted in Javascript onJuly 03, 2017

在使用jQuery类库实现tab功能时,是获取鼠标在mousenter或click时的index值,然后切换到当前的标题和内容,把其他的标题和内容的状态去掉:

$('.tab .title').find('.item')
 .removeClass('current').eq(index).addClass('current'); // 为index位置的title添加current
$('.tab .content').find('.item')
 .hide().eq(index).show(); // 显示index位置的内容

那么在使用vue实现tab功能时,就不是像jQuery这种直接操作DOM了。我这里总结了下实现tab功能的3个思路,仅供参考。

1. 切换content或者直接切换内容

这种思路下,我们首先把结构搭建起来,然后用一个变量selected表示tab当前展示的位置,给li标签添加mouseenter或click事件,将当前的index传递进去:

html代码:

<div class="hd">
 <ul class="clearfix">
  <li v-for="(item, index) of list" :class="{active:selected==index}" @mouseenter="change(index)">{{item.title}}</li>
 </ul>
</div>
<div v-for="(item, index) of list" :class="{active:selected==index, item:true}" v-html="item.content"></div>

js代码:

var app = new Vue({
 el: '#app',
 data: {
  selected: 0, //当前位置
  list: [
   {
    title: '11111',
    content: '11111content'
   },
   {
    title: '22222',
    content: '222222content'
   },
   {
    title: '33333',
    content: `<div>
        <span style="color:#f00">hello world</span>
        <p><input type="text" v-model="message"></p>
        <p>{{message}}</p>
       </div>`
   }
  ]
 },
 methods: {
  change(index) {
   this.selected = index;
  }
 }
})

绑定的change(index)事件,每次都将index给了selected,然后tab就会切换到对应的标签。

上面的代码里,我们是通过切换div的显示与隐藏来进行执行的。tab中的content里如果只有纯html内容,我们可以直接把list[selected].content展示到.bd中:

<div class='bd' v-html="list[selected].content"></div>

每次selected变换时,bd的内容都会发生变化。

2. 使用currentView

在上面的实现方式中,第3个tab里有个输入框与p标签双向绑定,但是没有效果,因为vue是把list中的内容作为html元素填充到页面中的,message并没有作为vue的属性绑定给input。那么使用组建和currentView就能弥补这个缺陷。

无论使用全局注册还是局部注册的组件,思路都是一样的,我们暂时使用全局注册的组件来实现。

每个组件里展示的是一个tab里的内容,先注册3个组件:

// tab0
Vue.component('item0',{
 template : '<div>1111111content</div>'
});
// tab1
Vue.component('item1',{
 template : '<div>222222content</div>'
})
// tab2
Vue.component('item2',{
 data(){
  return{
   message : ''
  }
 },
 template : `<div>
     <span style="color:#f00">hello world</span>
     <p><input type="text" v-model="message"></p>
     <p>{{message}}</p>
    </div>`
})

然后在html中使用component来展示对应组件的内容,title的展示方式不变:

<div class="hd">
 <ul class="clearfix">
  <li v-for="(item, index) of list" :class="{active:selected==index}" @mouseenter="change(index)">{{item.title}}</li>
 </ul>
</div>
<component :is="currentView"></component>

currentView属性可以让多个组件可以使用同一个挂载点,并动态切换:

var app = new Vue({
 el: '#app',
 data: {
  selected: 0,
  currentView : 'item0',
  list: [
   {
    title: '11111'
   },
   {
    title: '22222'
   },
   {
    title: '33333'
   }
  ]
 },
 methods: {
  change(index) {
   this.selected = index;
   this.currentView = 'item'+index; // 切换currentView
  }
 }
})

这样 message 在组件里就是一个独立的data属性,能在tab里也使用vue绑定事件了.

3. 使用slot方式等

使用slot方式进行内容分发或者一个独立的组件,可以让我们把代码整合到一块,对外提供一个数据接口,只要按照既定的格式填写数据即可。

3.1 slot

用slot方式写一个子组件:

Vue.component('my-slot-tab', {
 props : ['list', 'selected'],
 template : `<div class="tab">
     <div class="hd">
      <ul class="clearfix">
       <slot name="title" v-for="(item, index) in list" :index="index" :text="item.title"> </slot>
      </ul>
     </div>
     <div class="bd">
      <slot name="content" :content="list[selected].content"></slot>
     </div>
    </div>`
});

父组件模板:

<my-slot-tab :list="list" :selected="selected">
 <template slot="title" scope="props">
  <li :class="{active:selected==props.index, item:true}" @mouseenter="change(props.index)">{{ props.text }}</li>
 </template>
 <template slot="content" scope="props">
  <div v-html="props.content"></div>
 </template>
</my-slot-tab>

父组件中slot="title"会替换子组件中name="title"的slot,父组件中slot="content"会替换子组件中name="content"的slot.最终渲染出来的tab结构与上面之前的代码一样。

3.2 其他组件方式

还有一种方式就是把所有的模板都写到组件中。

子组件:

Vue.component('my-tab', {
 props : ['list'],
 template : `<div class="tab">
     <div class="hd">
      <ul class="clearfix">
       <li v-for="(item, index) in list" :class="{active:selected==index, item:true}" @mouseenter="change(index)">{{item.title}}</li>
      </ul>
     </div>
     <div class="bd">
      <div v-for="(item, index) of list" :class="{active:selected==index, item:true}" v-html="item.content"></div>
     </div>
    </div>`,
 data(){
  return{
   selected:0
  }
 },
 methods : {
  change(index){
   this.selected = index;
  }
 }
});

父组件:

<my-tab :list="list"></my-tab>

 这种只需要传递一个list即可。

对比这两种方法,slot中可以自定义更多的内容,而下面的方法使用起来更加简单,只是自定义的东西比较少。

4. 总结

上面讲解了几种实现tab功能的方式,没有说哪种方式最好,选择最适合自己项目需求的方式就是最好的。文中有哪有错误或不足,欢迎批评指正。也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Microsoft Ajax Minifier 压缩javascript的方法
Mar 05 Javascript
JS 如果改变span标签的是否隐藏属性
Oct 06 Javascript
js时间比较示例分享(日期比较)
Mar 05 Javascript
页面js遇到乱码问题的解决方法是和无法转码的情况
Apr 30 Javascript
从零学jquery之如何使用回调函数
May 16 Javascript
php简单数据库操作类的封装
Jun 08 Javascript
Vue之Watcher源码解析(1)
Jul 19 Javascript
JS排序算法之冒泡排序,选择排序与插入排序实例分析
Dec 13 Javascript
vue 之 .sync 修饰符示例详解
Apr 21 Javascript
Javascript的console['']常用输入方法汇总
Apr 26 Javascript
Vue的生命周期操作示例
Sep 17 Javascript
测量JavaScript函数的性能各种方式对比
Apr 27 Javascript
关于jQuery.ajax()的jsonp碰上post详解
Jul 02 #jQuery
Angular4项目中添加i18n国际化插件ngx-translate的步骤详解
Jul 02 #Javascript
React学习笔记之事件处理(二)
Jul 02 #Javascript
React学习笔记之条件渲染(一)
Jul 02 #Javascript
vue.js学习之vue-cli定制脚手架详解
Jul 02 #Javascript
如何通过非数字与字符的方式实现PHP WebShell详解
Jul 02 #Javascript
关于使用axios的一些心得技巧分享
Jul 02 #Javascript
You might like
PHP基础学习小结
2011/04/17 PHP
深入phpMyAdmin的安装与配置的详细步骤
2013/05/07 PHP
为PHP安装imagick时出现Cannot locate header file MagickWand.h错误的解决方法
2014/11/03 PHP
php给图片加文字水印
2015/07/31 PHP
Yii2针对指定url的生成及图片等的引入方法小结
2016/07/18 PHP
浅谈PHP中pack、unpack的详细用法
2018/03/12 PHP
根据鼠标的位置动态的控制层的位置
2009/11/24 Javascript
Javascript面向对象编程(二) 构造函数的继承
2011/08/28 Javascript
模拟电子签章盖章效果的jQuery插件源码
2013/06/24 Javascript
jQuery图片切换插件jquery.cycle.js使用示例
2014/06/16 Javascript
JavaScript AJAX之惰性载入函数
2014/08/27 Javascript
Javascript 运动中Offset的bug解决方案
2014/12/24 Javascript
jquery获取文档高度和窗口高度汇总
2016/01/25 Javascript
JS实现随页面滚动显示/隐藏窗口固定位置元素
2016/02/26 Javascript
基于jquery实现即时检查格式是否正确的表单
2016/05/06 Javascript
javascript工厂模式和构造函数模式创建对象方法解析
2016/12/30 Javascript
Vue.js 2.0窥探之Virtual DOM到底是什么?
2017/02/10 Javascript
Bootstrap Paginator+PageHelper实现分页效果
2018/12/29 Javascript
JS大坑之19位数的Number型精度丢失问题详解
2019/04/22 Javascript
vue element 生成无线级左侧菜单的实现代码
2019/08/21 Javascript
VueX模块的具体使用(小白教程)
2020/06/05 Javascript
Python中fnmatch模块的使用详情
2018/11/30 Python
如何获取Python简单for循环索引
2019/11/21 Python
python yield和Generator函数用法详解
2020/02/10 Python
python excel和yaml文件的读取封装
2021/01/12 Python
html5页面结构_动力节点Java学院整理
2017/07/10 HTML / CSS
MVMT手表官方网站:时尚又实惠的高品质手表
2016/12/04 全球购物
解释一下Windows的消息机制
2014/01/30 面试题
汇智创新科技发展有限公司
2015/12/06 面试题
.NET常见笔试题集
2012/12/01 面试题
数控专业个人求职信范例
2013/11/29 职场文书
2014年会演讲稿范文
2014/01/06 职场文书
初中体育教学反思
2014/01/14 职场文书
运动员获奖感言
2014/08/15 职场文书
2016年幼儿园庆六一开幕词
2016/03/04 职场文书
vue 数字翻牌器动态加载数据
2022/04/20 Vue.js