详解使用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 判断浏览器类型及版本
Feb 21 Javascript
JavaScript面向对象知识串结(读JavaScript高级程序设计(第三版))
Jul 17 Javascript
jquery 定位input元素的几种方法小结
Jul 28 Javascript
js 触发select onchange事件代码
Mar 20 Javascript
jquery显示隐藏input对象
Jul 21 Javascript
Javascript对象字面量的理解
Jun 22 Javascript
利用jquery实现下拉框的禁用与启用
Dec 07 Javascript
详解VUE的状态控制与延时加载刷新
Mar 27 Javascript
vue 动态修改a标签的样式的方法
Jan 18 Javascript
vue 使用eventBus实现同级组件的通讯
Mar 02 Javascript
在Mac下彻底卸载node和npm的方法
May 16 Javascript
全面解析Vue中的$nextTick
Dec 24 Vue.js
关于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 操作文件的一些FAQ总结
2009/02/12 PHP
xss防御之php利用httponly防xss攻击
2014/03/21 PHP
PHP常用正则表达式集锦
2014/08/17 PHP
thinkPHP5.0框架API优化后的友好性分析
2017/03/17 PHP
简单的php购物车代码
2020/06/05 PHP
来自国外的14个图片放大编辑的jQuery插件整理
2010/10/20 Javascript
flexigrid 参数说明
2010/11/23 Javascript
JQuery 操作/获取table具体代码
2013/06/13 Javascript
jQuery分页插件jquery.pagination.js使用方法解析
2017/02/09 Javascript
JQuery判断正整数整理小结
2017/08/21 jQuery
Vue组件的使用教程详解
2018/01/05 Javascript
原生JS+HTML5实现的可调节写字板功能示例
2018/08/30 Javascript
Angular 实现输入框中显示文章标签的实例代码
2018/11/07 Javascript
Angular脚手架开发的实现步骤
2019/04/09 Javascript
vue中datepicker的使用教程实例代码详解
2019/07/08 Javascript
Vue项目中数据的深度监听或对象属性的监听实例
2020/07/17 Javascript
JS中锚点链接点击平滑滚动并自由调整到顶部位置
2021/02/06 Javascript
python字典序问题实例
2014/09/26 Python
python 使用sys.stdin和fileinput读入标准输入的方法
2018/10/17 Python
python用opencv批量截取图像指定区域的方法
2019/01/24 Python
Django的models中on_delete参数详解
2019/07/16 Python
python创建学生成绩管理系统
2019/11/22 Python
Python中如何将一个类方法变为多个方法
2019/12/30 Python
Python 剪绳子的多种思路实现(动态规划和贪心)
2020/02/24 Python
Python线程协作threading.Condition实现过程解析
2020/03/12 Python
Selenium 安装和简单使用的实现
2020/12/04 Python
使用 css3 实现圆形进度条的示例
2017/07/05 HTML / CSS
ASOS比利时:英国线上零售商及自有品牌
2018/07/29 全球购物
迪卡侬波兰体育用品商店:Decathlon波兰
2020/03/31 全球购物
在DELPHI中调用存储过程和使用内嵌SQL哪种方式更好
2016/11/22 面试题
应届生求职信
2014/05/31 职场文书
镇创先争优活动总结
2014/08/28 职场文书
《詹天佑》教学反思
2016/02/20 职场文书
因个人工作失误检讨书
2019/06/21 职场文书
基于Python实现的购物商城管理系统
2021/04/27 Python
Python&Matlab实现樱花的绘制
2022/04/07 Python