详解使用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 相关文章推荐
利用WebBrowser彻底解决Web打印问题(包括后台打印)
Jun 22 Javascript
jQuery 处理表单元素的代码
Feb 15 Javascript
jquery 之 $().hover(func1, funct2)使用方法
Jun 14 Javascript
jquery实现div阴影效果示例代码
Sep 16 Javascript
JavaScript实现DIV层拖动及动态增加新层的方法
May 12 Javascript
jQuery实现多级下拉菜单jDropMenu的方法
Aug 28 Javascript
JavaScript如何动态创建table表格
Aug 02 Javascript
jquery.cookie.js实现用户登录保存密码功能的方法
Apr 15 Javascript
轻松理解Javascript变量的相关问题
Jan 20 Javascript
Javascript创建类和对象详解
May 31 Javascript
Vue 样式绑定的实现方法
Jan 15 Javascript
jQuery实现简易QQ聊天框
Feb 10 jQuery
关于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 include加载文件两种方式效率比较
2010/08/08 PHP
php5 apache 2.2 webservice 创建与配置(java)
2011/01/27 PHP
PHP安全上传图片的方法
2015/03/21 PHP
在Laravel框架里实现发送邮件实例(邮箱验证)
2016/05/20 PHP
php、mysql查询当天,查询本周,查询本月的数据实例(字段是时间戳)
2017/02/04 PHP
jQuery操作input值的各种方法总结
2013/11/21 Javascript
JavaScript中Function()函数的使用教程
2015/06/04 Javascript
谈谈JavaScript数组常用方法总结
2017/01/24 Javascript
es6+angular1.X+webpack 实现按路由功能打包项目的示例
2017/08/16 Javascript
Nodejs+express+ejs简单使用实例代码
2017/09/18 NodeJs
Vue项目组件化工程开发实践方案
2018/01/09 Javascript
AngularJS 将再发布一个重要版本 然后进入长期支持阶段
2018/01/31 Javascript
微信小程序出现wx.getLocation再次授权问题的解决方法分析
2019/01/16 Javascript
vue2.0中set添加属性后视图不能更新的解决办法
2019/02/22 Javascript
解决layui下拉框监听问题(监听不到值的变化)
2019/09/28 Javascript
vue实现评论列表功能
2019/10/25 Javascript
vue实现数字动态翻牌的效果(开箱即用)
2019/12/08 Javascript
详解vue-router的Import异步加载模块问题的解决方案
2020/05/13 Javascript
vue 导出文件,携带请求头token操作
2020/09/10 Javascript
Python实现的简单文件传输服务器和客户端
2015/04/08 Python
Python内置的HTTP协议服务器SimpleHTTPServer使用指南
2016/03/30 Python
简述Python2与Python3的不同点
2018/01/21 Python
详解tensorflow训练自己的数据集实现CNN图像分类
2018/02/07 Python
python实现随机梯度下降法
2020/03/24 Python
numpy创建单位矩阵和对角矩阵的实例
2019/11/29 Python
HTML5实现文件断点续传的方法
2017/01/04 HTML / CSS
英国最大的割草机购买网站:Just Lawnmowers
2019/11/02 全球购物
枚举和一组预处理的#define有什么不同
2016/09/21 面试题
造型师求职自荐信
2013/09/27 职场文书
银行介绍信范文
2014/01/10 职场文书
儿童生日会策划方案
2014/05/15 职场文书
会计学自荐信
2014/06/03 职场文书
节约用水的口号
2014/06/20 职场文书
2014年小学语文工作总结
2014/12/20 职场文书
springboot集成springCloud中gateway时启动报错的解决
2021/07/16 Java/Android
36个正则表达式(开发效率提高80%)
2021/11/17 Javascript