详解使用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 相关文章推荐
用roll.js实现的图片自动滚动+鼠标触动的特效
Mar 18 Javascript
javascript 密码强弱度检测万能插件
Feb 25 Javascript
写给想学习Javascript的朋友一点学习经验小结
Nov 23 Javascript
js 静态动态成员 and 信息的封装和隐藏
May 29 Javascript
调用innerHTML之后onclick失效问题的解决方法
Jan 28 Javascript
EasyUi combotree 实现动态加载树节点
Apr 01 Javascript
详解Angular4 路由设置相关
Aug 26 Javascript
jQuery选择器之属性筛选选择器用法详解
Sep 19 jQuery
js获取文件里面的所有文件名(实例)
Oct 17 Javascript
深入浅析js原型链和vue构造函数
Oct 25 Javascript
package.json各个属性说明详解
Mar 11 Javascript
基于PHP pthreads实现多线程代码实例
Jun 24 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实现一维数组与二维数组去重功能示例
2018/05/24 PHP
学习YUI.Ext 第六天--关于树TreePanel(Part 1)
2007/03/10 Javascript
使用javascript实现有效时间的控制,并显示将要过期的时间
2014/01/02 Javascript
IE浏览器IFrame对象内存不释放问题解决方法
2014/08/22 Javascript
封装好的js判断操作系统与浏览器代码分享
2015/01/09 Javascript
扒一扒JavaScript 预解释
2015/01/28 Javascript
js实现仿QQ秀换装效果的方法
2015/03/04 Javascript
JavaScript调用客户端Java程序的方法
2015/07/27 Javascript
PHP捕捉异常中断的方法
2016/10/24 Javascript
用angular实现多选按钮的全选与反选实例代码
2017/05/23 Javascript
Node.js 使用request模块下载文件的实例
2018/09/05 Javascript
浅谈Vue.js中如何实现自定义下拉菜单指令
2019/01/06 Javascript
nodemon实现Typescript项目热更新的示例代码
2019/11/19 Javascript
详解JavaScript执行模型
2020/11/16 Javascript
[04:22]DSPL第二期精彩集锦:残血反杀!
2014/12/10 DOTA
Python编程实现二叉树及七种遍历方法详解
2017/06/02 Python
解决python 无法加载downsample模型的问题
2018/10/25 Python
解决Python运行文件出现out of memory框的问题
2018/12/03 Python
pybind11和numpy进行交互的方法
2019/07/04 Python
德国PC硬件网站:CASEKING
2016/10/20 全球购物
Marmot土拨鼠官网:美国专业户外运动品牌
2018/01/11 全球购物
英国家庭和商业健身器材购物网站:Fitness Options
2018/07/05 全球购物
Hotels.com英国:全球领先的酒店住宿提供商
2019/01/24 全球购物
毕业生文员求职信
2013/11/03 职场文书
25岁生日感言
2014/01/13 职场文书
学校师德师风整改方案
2014/10/28 职场文书
匿名检举信范文
2015/03/02 职场文书
客服专员岗位职责范本
2015/04/07 职场文书
收入证明范本
2015/06/12 职场文书
2015年高中生国庆节演讲稿
2015/07/30 职场文书
2016年大学生寒假社会实践心得体会
2015/10/09 职场文书
MySQL系列之十五 MySQL常用配置和性能压力测试
2021/07/02 MySQL
实现AJAX异步调用和局部刷新的基本步骤
2022/03/17 Javascript
angular4实现带搜索的下拉框
2022/03/25 Javascript
阿里云ECS云服务器快照的概念以及如何使用
2022/04/21 Servers
python中 Flask Web 表单的使用方法
2022/05/20 Python