vue elment-ui 对navTab导航组件封装

图示

nav-tab1
nav-tab2

组件

代码

<template>
  <div class="nav-tab-wrap">
    <div class="nav-list">
      <div
        v-for="(item, index) in navList"
        :key="item"
        class="nav-item"
        :class="{'active': currentTab === index}"
        @click="handleCurrentTab(index)"
      >{{ item }}</div>
      <!-- 下拉菜单类型导航 -->
      <el-dropdown
        v-for="(item, index) in navDropList"
        :key="item.title"
        class="nav-item"
        :class="{'active': isActive(index)}"
        @command="handleCurrentTab($event, index)"
      >
        <!-- 菜单标题 -->
        <span class="el-dropdown-link">
          {{ isActive(index) ? list[currentTab] : item.title }}
          <i class="el-icon-arrow-down el-icon--right" />
        </span>
        <!-- 菜单项 -->
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item
            v-for="(v, i) in item.list"
            :key="v"
            :command="i + navList.length"
          >{{ v }}</el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
    </div>
    //  其他代码......
  </div>
</template>

<script>
export default {
  props: {
    // 当前的tab
    currentTab: {
      type: Number,
      default: 0
    },
    // 导航标签
    navList: {
      type: Array,
      default: () => []
    },
    // 下拉菜单
    navDropList: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      list: this.navList
    }
  },
  created() {
    // 合并标题
    this.navDropList.forEach(v => {
      this.list = [...this.list, ...v.list]
    })
  },
  methods: {
    // 改变当前tab
    handleCurrentTab(index, step) {
      let value = index
      for (let i = 0; i < step; i++) {
        value += this.navDropList[i].list.length
      }
      this.$emit('handleCurrentTab', value)
    },
    // 是否选中菜单标题
    isActive(step) {
      let minLen = 0
      let maxLen = this.navList.length
      for (let i = 0; i < step + 1; i++) {
        minLen = maxLen
        maxLen += this.navDropList[i].list.length
      }
      return this.currentTab >= minLen && this.currentTab < maxLen
    }
  }
}
</script>

<style lang="less" scoped>
@import '~assets/less/variable.less';
.nav-tab-wrap{
  height: 62px;
  margin: 0 24px;
  padding: 0 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-radius: 0 0 4px 4px;
  background-color: #fff;
  .nav-list{
    flex: 1;
    display: flex;
    .nav-item{
      color: @fontColor2;
      font-size: 16px;
      cursor: pointer;
      & + .nav-item{
        margin-left: 40px;
      }
      &:hover,
      &.active{
        color: @themeColor;
      }
    }
  }
}
</style>

使用

父组件代码

<template>
  <div class="my-tab-wrap">
    <nav-tab
      :current-tab="currentTab"
      :nav-list="navList"
      :nav-drop-list="navDropList"
      @handleCurrentTab="handleCurrentTab"
    />
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex'
import navTab from '../components/navTab'
export default {
  components: {
    navTab
  },
  data() {
    return {
      navList: ['标题1', '标题2', '标题3', '标题4'],
      navDropList: [{
        title: '菜单1',
        list: ['菜单标题1', '菜单标题2', '菜单标题3']
      }, {
        title: '菜单2',
        list: ['菜单标题1', '菜单标题2']
      }]
    }
  },
  computed: {
    ...mapState({
      currentTab: state => state.myResource.currentTab
    })
  },
  methods: {
    ...mapMutations('myResource', ['handleCurrentTab'])
  }
}
</script>

<style lang="less" scoped>

</style>

vuex

myResource 模块下

const state = {
  // 当前tab下标
  currentTab: 2
}

const mutations = {
  // 改变当前tab下标
  handleCurrentTab(state, index) {
    state.currentTab = index
  }
}

const actions = {

}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

补充 另一种传参方式

// 通用组件-tab导航
<template>
  <div class="nav-tab-wrap">
    <!-- 普通导航 -->
    <ul class="nav-list">
      <li
        v-for="(item) in navList"
        :key="item.code"
        class="nav-item"
      >
        <!-- 普通类型标签 -->
        <span
          v-if="!item.children"
          class="nav-tab"
          :class="{'active': item.code === currentCode}"
          @click="handleCurrentTab(item)"
        >{{ item.name }}</span>

        <!-- 下拉类型标签 -->
        <el-dropdown
          v-else
          class="nav-tab"
          :class="{'active': item.code === parentCode}"
          @command="handleCurrentTab($event, item.code)"
        >
          <span>
            {{ item.code === parentCode ? currentName : item.name }}
            <i class="el-icon-arrow-down el-icon--right" />
          </span>
          <!-- 下拉菜单 -->
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item
              v-for="child in item.children"
              :key="child.code"
              :command="child"
            >{{ child.name }}</el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  props: {
    // 导航标签
    navList: {
      type: Array,
      default: () => [{
        code: '01',
        name: '课件'
      }, {
        code: '02',
        name: '导学案'
      }, {
        code: '03',
        name: '试卷',
        children: [{
          code: '04',
          name: '同步试卷'
        }, {
          code: '05',
          name: '专题试卷'
        }]
      }, {
        code: '06',
        name: '哈哈'
      }, {
        code: '07',
        name: '试卷aa',
        children: [{
          code: '08',
          name: '同步试卷'
        }]
      }]
    }
  },
  data() {
    return {
      currentCode: '01', // 当前选中的的导航code
      currentName: '', // 当前选中的的导航name(主要用于下拉菜单的名称显示)
      parentCode: '' // 下拉菜单导航的父级code(主要用于显示选中状态)
    }
  },
  methods: {
    // 切换导航时触发
    handleCurrentTab({ code, name }, parentCode) {
      this.currentCode = code
      this.parentCode = parentCode || ''
      this.currentName = name || ''
    }
  }
}
</script>

<style lang="less" scoped>
@import '~assets/less/variable.less';
.nav-tab-wrap{
  height: 62px;
  margin: 0 24px;
  padding: 0 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-radius: 0 0 4px 4px;
  background-color: #fff;
  .nav-list{
    flex: 1;
    display: flex;
    .nav-item{
      margin-right: 40px;
      .nav-tab{
        color: @fontColor2;
        font-size: 16px;
        cursor: pointer;
        &:hover,
        &.active{
          color: @themeColor;
        }
      }
    }
  }
}
</style>
posted @ 2020-08-14 20:14  lwlcode  阅读(752)  评论(0编辑  收藏  举报