详解使用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 相关文章推荐
用javascript实现的图片马赛克后显示并切换加文字功能
Apr 21 Javascript
Jquery中find与each方法用法实例
Feb 04 Javascript
jQuery实现Div拖动+键盘控制综合效果的方法
Mar 10 Javascript
JQuery显示隐藏DIV的方法及代码实例
Apr 16 Javascript
用JS写的一个Ajax库(实例代码)
Aug 06 Javascript
详解微信小程序 wx.uploadFile 的编码坑
Jan 23 Javascript
javascript 网页进度条简单实例
Feb 22 Javascript
基于Vue框架vux组件库实现上拉刷新功能
Nov 28 Javascript
angularjs 缓存的使用详解
Mar 19 Javascript
关于Vue源码vm.$watch()内部原理详解
Apr 26 Javascript
JavaScript HTML DOM元素 节点操作汇总
Jul 29 Javascript
quickjs 封装 JavaScript 沙箱详情
Nov 02 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求两个文件的相对路径
2013/06/20 PHP
windwos下使用php连接oracle数据库的过程分享
2014/05/26 PHP
php常用的安全过滤函数集锦
2014/10/09 PHP
ThinkPHP模型详解
2015/07/27 PHP
PHP FileSystem 文件系统常用api整理总结
2019/07/12 PHP
php日志函数error_log用法实例分析
2019/09/23 PHP
javascript[js]获取url参数的代码
2007/10/17 Javascript
js data日期初始化的5种方法
2013/12/29 Javascript
jquery操作下拉列表、文本框、复选框、单选框集合(收藏)
2014/01/08 Javascript
原生js仿jq判断当前浏览器是否为ie,精确到ie6~8
2014/08/30 Javascript
JavaScript实现窗口抖动效果
2016/10/19 Javascript
javascript显示系统当前时间代码
2016/12/29 Javascript
jQuery实现动态生成表格并为行绑定单击变色动作的方法
2017/04/17 jQuery
JavaScript数组push方法使用注意事项
2017/10/30 Javascript
bootstrap Table的一些小操作
2017/11/01 Javascript
使用Vue-cli3.0创建的项目 如何发布npm包
2019/10/10 Javascript
gearman的安装启动及python API使用实例
2014/07/08 Python
详解Python中类的定义与使用
2017/04/11 Python
Python入门之三角函数tan()函数实例详解
2017/11/08 Python
Python测试人员需要掌握的知识
2018/02/08 Python
Linux(Redhat)安装python3.6虚拟环境(推荐)
2018/05/05 Python
python中的变量如何开辟内存
2018/06/26 Python
快速解决pyqt5窗体关闭后子线程不同时退出的问题
2019/06/19 Python
pytorch 在网络中添加可训练参数,修改预训练权重文件的方法
2019/08/17 Python
Python3 合并二叉树的实现
2019/09/30 Python
Python 生成VOC格式的标签实例
2020/03/10 Python
python开发实例之Python的Twisted框架中Deferred对象的详细用法与实例
2020/03/19 Python
基于CSS3实现图片模糊过滤效果
2015/11/19 HTML / CSS
Keds加拿大官网:购买帆布运动鞋和皮鞋
2019/09/26 全球购物
什么是静态路由,其特点是什么?什么是动态路由,其特点是什么?
2013/07/26 面试题
人事助理岗位职责
2013/11/18 职场文书
经典演讲稿范文
2013/12/30 职场文书
怀念母亲教学反思
2014/04/28 职场文书
毕业实习证明(4篇)
2014/10/28 职场文书
房屋产权共有协议书范本
2014/11/03 职场文书
警示教育观后感
2015/06/17 职场文书