详解使用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 Undefined,Null类型和NaN值区别
Oct 22 Javascript
根据对象的某一属性进行排序的js代码(如:name,age)
Aug 10 Javascript
js判断输入是否为数字的具体实例
Aug 03 Javascript
Python脚本后台运行的几种方式
Mar 09 Javascript
jsMind通过鼠标拖拽的方式调整节点位置
Apr 13 Javascript
微信小程序 animation API详解及实例代码
Oct 08 Javascript
easyui combotree加载静态数据问题(选不上)解决方法
Dec 26 Javascript
jQuery时间验证和转换为标准格式的时间格式
Mar 06 Javascript
简单实现jQuery手风琴效果
Aug 18 jQuery
JS获取url参数,JS发送json格式的POST请求方法
Mar 29 Javascript
如何正确解决VuePress本地访问出现资源报错404的问题
Dec 03 Vue.js
Vue与React的区别和优势对比
Dec 18 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
我的论坛源代码(一)
2006/10/09 PHP
php带密码功能并下载远程文件保存本地指定目录 修改加强版
2010/05/16 PHP
php对象在内存中的存在形式分析
2015/02/03 PHP
php使用CURL模拟GET与POST向微信接口提交及获取数据的方法
2016/09/23 PHP
ecshop适应在PHP7的修改方法解决报错的实现
2016/11/01 PHP
Python中使用django form表单验证的方法
2017/01/16 PHP
tp5(thinkPHP5框架)captcha验证码配置及验证操作示例
2019/05/28 PHP
PHP Ajax跨域问题解决方案代码实例
2020/08/01 PHP
Javascript 判断 object 的特定类转载
2007/02/01 Javascript
基于jQuery的消息提示插件 DivAlert之旅(二)
2010/04/01 Javascript
FileUpload 控件 禁止手动输入或粘贴的实现代码
2010/04/07 Javascript
javascript模块化是什么及其优缺点介绍
2013/09/02 Javascript
跟我学Node.js(四)---Node.js的模块载入方式与机制
2014/06/04 Javascript
js创建一个input数组并绑定click事件的方法
2014/06/12 Javascript
简介JavaScript中toUpperCase()方法的使用
2015/06/06 Javascript
javascript中FOREACH数组方法使用示例
2016/03/01 Javascript
JS实现将数字金额转换为大写人民币汉字的方法
2016/08/02 Javascript
javascript基础知识讲解
2017/01/11 Javascript
微信小程序实现跳转的几种方式总结(推荐)
2019/04/24 Javascript
vue滚动固定顶部及修改样式的实例代码
2019/05/30 Javascript
如何提升vue.js中大型数据的性能
2019/06/21 Javascript
python判断数字是否是超级素数幂
2018/09/27 Python
python实现将文件夹下面的不是以py文件结尾的文件都过滤掉的方法
2018/10/21 Python
Python使用POP3和SMTP协议收发邮件的示例代码
2019/04/16 Python
Django 表单模型选择框如何使用分组
2019/05/16 Python
使用django的ORM框架按月统计近一年内的数据方法
2019/07/18 Python
python中Ansible模块的Playbook的具体使用
2020/05/28 Python
基于Python绘制个人足迹地图
2020/06/01 Python
Django web自定义通用权限控制实现方法
2020/11/24 Python
CSS实现限制字数功能当对象内文本溢出时显示省略标记
2014/08/20 HTML / CSS
html5在移动端的屏幕适应问题示例探讨
2014/06/15 HTML / CSS
中专药剂专业应届毕的自我评价
2013/12/27 职场文书
舞蹈专业大学生职业规划范文
2014/03/12 职场文书
酒店工程部岗位职责
2015/02/12 职场文书
职工趣味运动会开幕词
2016/03/04 职场文书
python3 字符串str和bytes相互转换
2022/03/23 Python