美文网首页Vue.js 资料Web前端之路让前端飞
vue当中设计Tabbar插件时的思考

vue当中设计Tabbar插件时的思考

作者: 一横Coder | 来源:发表于2017-11-03 16:22 被阅读116次

    之前做移动端的项目一般会选用Mint-ui或者是Vux框架,不得不说这两款都是非常棒非常好用的UI框架,能给开发工作节省很多时间。

    在Mint-ui里关于tabbar的使用,有如下的Demo:

    <mt-tabbar v-model="selected">
      <mt-tab-item id="订单">
        <img slot="icon" src="http://placehold.it/100x100">
        <span slot="label">订单</span>
      </mt-tab-item>
    </mt-tabbar>
    

    使用了以后就想...为什么一定要对每个mt-tab-item指定一个id呢?对于tabbar来说,我并不需要关心我按下的对象id是多少,而需要关心的是按下哪个tabbar-item即可。
    引申出来这么个问题:

    1. 那么在父组件中如何区分按下的是哪个子组件呢?

    通过判断children的_uid可以区分出究竟是哪个子组件

    1. 子组件如何将自身的_uid抛给父组件呢?

    调用$parent.$emit('input', _uid),直接这样调用,会修改v-model绑定value值。

    v-model="selected" 可以看成是 v-bind:value="selected" v-on:input="selected = $event.target.value" 的语法糖

    有了这几步分析,然后自己写了一份简单的tabbar组件

    tabbar.vue

    <template>
      <div class="l-tabbar">
        <slot></slot>
      </div>
    </template>
    
    <script>
    export default {
      name: 'LTabbar',
      component: 'LTabbar',
      props: {
        value: {}
      },
      methods: {
        index (id) {
          for (let i = 0; i < this.$children.length; ++i) {
            if (this.$children[i]._uid === id) {
              return i
            }
          }
          return -1
        }
      }
    }
    </script>
    
    <style lang="scss">
    .l-tabbar {
      position: absolute;
      width: 100%;
      height: auto;
      bottom: 0;
      left: 0;
      right: 0;
      background: white;
      display: flex;
      justify-content: space-around;
    }
    </style>
    

    tabbarItem.vue

    <template>
      <div class="tabbar-item"
        @click="$parent.$emit('input', id)"
        :class="{ 'is-selected': $parent.value === id }">
        <div class="item-icon">
          <slot name="icon"></slot>
        </div>
        <div class="item-text">
          <slot></slot>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      name: 'LTabbarItem',
      component: 'LTabbarItem',
      data () {
        return {
          id: this.$parent.index(this._uid)
        }
      }
    }
    </script>
    
    <style lang="scss">
    @import '../../common/style/var.scss';
    
    .tabbar-item {
      text-align: center;
      margin: 5px auto;
      width: 100%;
      &.is-selected {
        color: $default-color;
      }
      .item-text {
        font-size: 12px;
      }
    }
    </style>
    

    这样写完以后,使用的时候会比mint-ui的组件更简化,可以取消对id的绑定依赖:

    <l-tabbar v-model="selected">
      <l-tabbar-item v-for="(item, index) in tabItems" :key="index">
        <svg slot="icon" :class="icon" aria-hidden="true">
          <use :xlink:href="`#${item.icon}`"></use>
        </svg>
        <span>{{ item.title }}</span>
      </l-tabbar-item>
    </l-tabbar>
    

    虽然到这一步改造是完成了,但是却总觉得有些问题。
    那么在子组件里面调用父组件的methods是否合适?
    但是后来想想tabbar-item仅仅是为tabbar服务的,所以不需要关心太过于耦合,考虑复用性等问题。
    如思考的不到位请各位大神能给予一些指导意见。

    Github: github.com/lyh2668
    AuthBy: lyh2668

    相关文章

      网友评论

        本文标题:vue当中设计Tabbar插件时的思考

        本文链接:https://www.haomeiwen.com/subject/mbitmxtx.html