详解使用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里使用Dom操作Xml
Jan 22 Javascript
调用DOM对象的focus使文本框获得焦点
Feb 19 Javascript
JS实现至少包含字母、大小写数字、字符的密码等级的两种方法
Feb 03 Javascript
简介JavaScript中的unshift()方法的使用
Jun 09 Javascript
javascript使用闭包模拟对象的私有属性和方法
Oct 05 Javascript
jQuery和JavaScript节点插入元素的方法对比
Nov 18 Javascript
js控制一个按钮是否可点击(可使用)disabled的实例
Feb 14 Javascript
bootstrap的工具提示实例代码
May 17 Javascript
js 监控iframe URL的变化实例代码
Jul 12 Javascript
JS实现在文本指定位置插入内容的简单示例
Dec 22 Javascript
JS事件流与事件处理程序实例分析
Aug 16 Javascript
JS addEventListener()和attachEvent()方法实现注册事件
Jan 11 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 计算两个时间戳相隔的时间的函数(小时)
2009/12/18 PHP
php session 写入数据库
2016/02/13 PHP
详解PHP处理字符串类似indexof的方法函数
2017/06/11 PHP
php使用QueryList轻松采集js动态渲染页面方法
2018/09/11 PHP
Yii2框架配置文件(Application属性)与调试技巧实例分析
2019/05/27 PHP
php封装的page分页类完整实例代码
2020/02/01 PHP
发现的以前不知道的函数
2006/09/19 Javascript
关于JavaScript的gzip静态压缩方法
2007/01/05 Javascript
Jquery乱码的一次解决过程 图解教程
2010/02/20 Javascript
JQuery循环滚动图片代码
2011/12/08 Javascript
IE6下拉框图层问题探讨及解决
2014/01/03 Javascript
jQuery文字提示与图片提示效果实现方法
2016/07/04 Javascript
全屏滚动插件fullPage.js使用实例解析
2016/10/21 Javascript
Chrome浏览器的alert弹窗禁止再次弹出后恢复的方法
2016/12/30 Javascript
详解Javascript 中的 class、构造函数、工厂函数
2017/12/20 Javascript
使用vuex的state状态对象的5种方式
2018/04/19 Javascript
详解vue中组件参数
2018/07/09 Javascript
原生JS实现天气预报
2020/06/16 Javascript
全面解析Vue中的$nextTick
2020/12/24 Vue.js
Python实现1-9数组形成的结果为100的所有运算式的示例
2017/11/03 Python
python Matplotlib画图之调整字体大小的示例
2017/11/20 Python
使用C++扩展Python的功能详解
2018/01/12 Python
python快速建立超简单的web服务器的实现方法
2018/02/17 Python
Python多线程threading模块用法实例分析
2019/05/22 Python
python基于Selenium的web自动化框架
2019/07/14 Python
python 修改本地网络配置的方法
2019/08/14 Python
Python获取二维数组的行列数的2种方法
2020/02/11 Python
python 写函数在一定条件下需要调用自身时的写法说明
2020/06/01 Python
什么是python的函数体
2020/06/19 Python
互联网创业计划书写作技巧攻略
2014/03/23 职场文书
预备党员群众路线思想汇报2014
2014/10/25 职场文书
劳动争议和解协议书范本
2014/11/20 职场文书
大学教师个人总结
2015/02/10 职场文书
机器人总动员观后感
2015/06/09 职场文书
webpack介绍使用配置教程详解webpack介绍和使用
2022/06/25 Javascript
DQL数据查询语句使用示例
2022/12/24 MySQL