栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > Web开发 > Vue.js

看JQ时代过来的前端,如何转换思路用Vue打造选项卡组件

Vue.js 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

看JQ时代过来的前端,如何转换思路用Vue打造选项卡组件

前言

在Vue还未流行的时候,我们都是用JQuery来封装一个选项卡插件,如今Vue当道,让我们一起来看看从JQ时代过来的前端是如何转换思路,用数据驱动DOM的思想打造一个Vue选项卡组件。

接下来,正文从这开始~

先来看一下用Vue写的选项卡组件在浏览器上的展示效果:

其实,你在浏览器上看到的UI界面效果也就是那么回事,中规中矩。当点开Chrome的Devtools下面的Elements选项,你看到的dom节点其实和jQuery的dom节点如出一辙,不同的是,现在你看到的dom树是在Vue组件生命周期mounted之后渲染得到的真实DOM

首先我们来聊一聊关于选项卡组件的业务需求,每个标签页的主体内容是由使用组件的父级控制,所以这部分应该是一个slot。slot的数量决定了标签切换按钮的数量。假设我们有3个标签页,点击每个标签按钮时,另外的两个标签对应的slot将被隐藏掉。

先来贴出html结构:

 1 
 2      
 3      
 4   

标签一的内容

5
6 7

标签二的内容

8
9 10

标签三的内容

11
12
13

由html结构可知,我们需要定义两个组件tabs和子组件pane,pane嵌套在标签组件tabs里面。由于tabs和pane两个组件是分离的,但是tabs的组件上的标题应该由pane组件来定义,因为slot是写在pane里,因此在组件初始化(以及标签标题动态改变)时,tabs要从pane里获取标题,并保存起来,自己使用。

接下来,先初始化各个组件:

Vue.component('tabs',{
    template:`
 
     
  
     
     
  
  
     
 
    `
})
Vue.component('pane',{
    name:'pane',
    template:`
 
     
 
    `,
    data:function(){
 return {
     show:true
 }
    }
})

pane组件中需要控制标签页内容的显示与隐藏,所以设置一个data:show,并且用v-show指令来控制元素。

如果你是用jQuery写过选项卡,应该知道,在写完控制tabs标题显示与隐藏后,接下来该控制tabs内容的显示与隐藏了。那么如果要点击对应的标签页标题显示对应的标签页内容,此时应该有一个唯一的值来标识这个pane,我们可以设置一个prop:name让用户来设置,其实这个name也就是索引index。除了name,还需要设置标签页的标题prop:label。

props:{
     name:{
 type:String
     },
 label:{
     type:String,
     default:''
     }
}

上面的标题prop:label 用户是可以动态调整的,所以在pane初始化及label更新时,都要通知父组件也更新,因为是独立独立组件,我们可以直接通过this.$parent访问tabs组件的实例来调用它的方法更新标题,这个方法名暂定为updateNav:

methods:{
    updateNav(){
 this.$parent.updateNav();
    }
},
watch:{
    label(){
 this.updateNav();
    }
},
mounted(){
    this.updateNav();
}

通过以上代码可以看到,在生命周期mounted,也就是pane初始化时,调用一遍tabs的updateNav方法,同时监听了prop:label,在label更新时,同样调用。

说完了pane组件,剩下的任务就是完成tabs组件。

首先就是需要把pane组件设置的标题动态渲染出来,也就是当pane触发tabs的updateNav方法时,更新标题内容。

 Vue.component('tabs',{
 template:`
     
  
      
   {{item.label}}
      
  
  
      
  
     
 `,
 props:{
          // 这里的value是为了可以使用v-model
     value:{
  type:[String, Number]
     }
 },
 data:function(){
     return {
            // 因为不能修改value,所以复制一份自己维护
  currentValue:this.value,
  navList:[]  // 用于渲染tabs的标题
     }
 },
 methods:{
     tabCls:function(item){
  return [
      'tabs-tab',
      {
                 // 给当前选中的tab加一个class
   'tabs-tab-active': item.name === this.currentValue
      }
  ]
     },
     getTabs(){
  // 通过遍历子组件,得到所有的pane组件
  return this.$children.filter(function(item){
      return item.$options.name === 'pane';
  });
     },
     updateNav(){
  this.navList=[];
  // 设置对this的引用,在function回调里,this指向的并不是vue实例
  var _this = this;

  this.getTabs().forEach(function(pane,index){
      _this.navList.push({
   label:pane.label,
   name:pane.name || index
      });
      // 如果没有给pane设置那么,默认设置它的索引
      if(!pane.name) pane.name = index;
      // 设置当前选中的tab的索引
      if(index === 0){
   if(!_this.currentValue){
_this.currentValue = pane.name || index;
   }
      }
  });
  // console.log(this.navList);

  this.updateStatus();
     },
     updateStatus(){
  var tabs = this.getTabs();
  // console.log(tabs);
  var _this = this;
  // 显示当前选中的tab对应的pane组件,隐藏没有选中的
  tabs.forEach(function(tab){
      // console.log(tab.name === _this.currentValue);
      return tab.show = tab.name === _this.currentValue;
  })
     },
          // 点击tab标题时触发
     handleChange:function(index){
  var nav = this.navList[index];
  var name = nav.name;
  console.log(name);
            // 改变当前选中的tab,并触发下面的watch
  this.currentValue = name;
     }
 },
 watch:{
     value:function(val){
  this.currentValue = val;
     },
     currentValue:function(){
  this.updateStatus();
     }
 }
    })    

getTabs是一个公用的方法,使用this.$children来拿到所有的pane组件实例。在遍历了每一个pane组件后,把他的label和name提取出来,构建成一个Object并添加到数据navList数组里。拿到navList后,就可以用v-for把tab的标题渲染出来,并且判断每个tab当前的状态。

通过以上代码,大家可以看到,在使用v-for指令循环显示tab标题时,使用v-bind:class指向了一个名为tabCls的methods来动态设置class名称。

点击每个tab标题时,会触发handleChange方法来改变当前选中的tab的索引,也就是pane组件的name。在watch选项里,我们监听了currentValue,当其发生变化时,触发了updateStatus方法来更新了pane组件的显示状态。

后记

总结一下:该选项卡组件,使用了组件嵌套的方式,将一系列pane组件作为tabs组件的slot;tabs组件和pane组件通信上,使用了$parent 和 $children 的方法访问父链和子链;定义了prop:value 和 data: currentValue。

以上就是Vue标签页组件的所有实现过程。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/241344.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号