前端项目框架搭建随笔---Tab组件的编写

栏目: CSS · 发布时间: 5年前

内容简介:低下头看了看自己的手环。距离自己的flag已经跳票3天了。。。不为什么,因为我懒#滑稽 #滑稽#滑稽

低下头看了看自己的手环。距离自己的flag已经跳票3天了。。。

前端项目框架搭建随笔---Tab组件的编写

不为什么,因为我懒#滑稽 #滑稽#滑稽

咳咳,咱们今天进入正题---Tab组件的编写

首先还是先看Tab预览图:

Tab预览图

前端项目框架搭建随笔---Tab组件的编写

很简单的功能,很简洁的UI。

首先还是献上Tab html代码和css代码(我css基础不好 各位可以忽略#滑稽)

为了自由度高一点,我们采用 Tab+TabPanel  的方式制作。这种制作方式也是 大部分UI框架的制作方式

Tab-HTML代码

<template>
  <div class="tab-wrapper">
    <div class="tab__header">
      <div class="tab__header__item">
        <div style="width: 100%;">
          <div class="tab__item">
            <span>验证码登录</span>
          </div>
          <div class="tab__item">
            <span>密码登录</span>
         </div>
        </div>
      </div>
    </div>
    <div class="tab__content">
      <slot></slot>
    </div>
  </div>
</template>复制代码

Tab- CSS代码

<style scoped>
  .iconfont {
    font-size: 1.5rem;
  }

  .tab__header {
    display: flex;
  }

  .tab__header__item {
    margin: 0;
  }

  .tab__header__item > div {
    display: flex;
    flex-direction: row;
    white-space: nowrap;
    transition: transform .3s;
  }

  .tab__item {
    font-size: 1.3rem;
    cursor: pointer;
    margin-right: 1rem;
    flex: 1;
    text-align: center;
  }

  .tab--active > span {
    border-bottom: 2px solid #1890FF;
    color: #1890FF;
    padding-bottom: .5rem;
  }

  .tab__header__btn--left {
    margin-right: .5rem;
    cursor: pointer;
  }

  .tab__header__btn--right {
    margin-left: .5rem;
    cursor: pointer;
  }

  .tab--panel-wrapper {
    display: none;
  }

  .tab--panel-wrapper--active {
    display: block !important;
  }
</style>
复制代码

TabPanel代码:

<template>
  <div class="tab--panel-wrapper" :name="name">
    <div class="tab--panel-content">
      <slot></slot>
    </div>
  </div>
</template>

<script>
  export default {
    name: "ZbTabPanel",
    props: {
      name: { //Tab模块名
        required: true
      }
    }
  }
</script>

<style scoped>

</style>
复制代码

先开始制作基础功能:Tab切换

Tab切换功能的制作

首先一上来就会出现理解性的问题:

以往我们写Tab 头部写头部的东西,内容写内容的东西。两者分开来写。便于理解

但如果是这种组件套组件的方式,看起来用法简单了不少。但是增加了编写难度

还有一点 ,父组件怎么去控制子组件的显示隐藏情况?

那就一步步来呗。

为了方便便于编写起来好理解。我选择内容插入,头部遍历的方式去制作

<template>
  <div class="tab-wrapper">
    <div class="tab__header" ref="tabHeaderItem">
      <div class="tab__header__item">
        <div style="width: 100%;">
          <div class="tab__item"
               @click="tabItemClick(item.name,key)" //tab的点击事件
               @touchstart="tabItemClick(item.name,key)" //tab的移动端点击事件
               v-for="(item,key) in tabList" //循环list
               :class="{'tab--active':activeTab.index===key}"> //如果当前tabtitle的下标 =已激活的tabtitle下标
            <span>{{item.name}}</span> 
          </div>
        </div>
      </div>
    </div>
    <div class="tab__content"
         ref="content">
      <slot></slot>
    </div>
  </div>
</template>

复制代码

js方面:

data() {
  return {
    tabList: [], //tab标题列表
    activeTab: { //已激活的tab信息
      index: 0, //下标
      name: '' //名称
    }
  }
}复制代码

既然是插槽slot,那我们就用点插槽该做的事情 #嘿嘿嘿

于是我在  mounted  函数内,看一下$slot的内容

结果还真的有

前端项目框架搭建随笔---Tab组件的编写

不过出现了一个空插槽值。。。但是无关紧要,我们可以加一层空值判断嘛~~

let self = this; //外层新建变量引用this
this.$slots.default.forEach((components) => { //循环default内的内容
  if (components.tag && components.componentOptions) { //如果子元素tag键&&componentOptions有内容。
    self.tabList.push(components.componentOptions.propsData) 
    // 在components.componentOptions这个键内 有propsDate这个属性。我们可以通过这个属性拿到子组件的props值
  }
});
this.$nextTick(() => { //避免data未更新
  this.activeTab = { //给activeTab赋初始值 
    index: 0, //默认选中第一个
    name: this.tabList[0].name //寻找tabList第一个元素 还有他的名字
  };
});复制代码

这样切换头部功能实现了。但是底部主体内容无动于衷

所以我们在watch函数内,监听一下activeTab变量的数据变化:

watch: {
  activeTab(newValue, oldValue) {
    this.$refs.content.children[oldValue.index].className = "tab--panel-wrapper";
    this.$refs.content.children[newValue.index].className = "tab--panel-wrapper--active";
  }
}复制代码

这样基础内容就大功告成了。

用法参考

<zb-tab>
  <zb-tab-panel name="验证码登录">
    <!--这是验证码登录的内容-->
  </zb-tab-panel>
  <zb-tab-panel name="密码登录">
    <!--这是密码登录的内容-->
  </zb-tab-panel>
</zb-tab>复制代码

因为name属性不能少 所以是必填

这样一来遇到个问题,我们的tab是用flex编写的。但是如果tab多了横向滚动怎么办?

这里安利一个滴滴出行@ustbhuangyi 开发的滚动组件: better-scroll

首先我们先安装他:

better-scroll文档

npm install better-scroll --save复制代码

接着在vue组件内引入:

import BScroll from 'better-scroll'复制代码

这里不做过多介绍。所以我们简单使用。详细使用请看文档

_initScroll: function () {
  new BScroll(this.$refs.tabHeaderItem, {
    scrollX: true, //是否支持X滚动
    bounce: true //是否开启回弹动画
  });
}复制代码

挂载函数内

setTimeout(() => {
  this.$nextTick(() => { //避免data未更新
      this._initScroll();
    }
  )
}, 20)复制代码

如果看到行内样式有css动画。说明就挂载成功了

这样遇到了一个小bug。挂载成功是可以。但是无法滚动。如图

前端项目框架搭建随笔---Tab组件的编写

经查:是因为他挂载的那个元素,我们写个width:100%。导致他丢失了实际长度。无法挂载。

但是去掉width:100%后,元素始终不会平铺开。会左浮动一样的排列

前端项目框架搭建随笔---Tab组件的编写

所以我们为了两种都要,加个props外部控制吧~~

props: {
  floatLeft: { //是否开启左浮动模式
    default: false
  }
}复制代码

html:

<div class="tab__header__item"
     :style="floatLeft? '': 'width:100%'">复制代码

这样一个不算很完美的tab就完成了。希望制作思想可以帮到大家


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

HTML Dog

HTML Dog

Patrick Griffiths / New Riders Press / 2006-11-22 / USD 49.99

For readers who want to design Web pages that load quickly, are easy to update, accessible to all, work on all browsers and can be quickly adapted to different media, this comprehensive guide represen......一起来看看 《HTML Dog》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具