如何在快应用中实现标签组件

 什么是标签组件

用于展示1个或多个文字标签,可点击切换选中、不选中的状态。

cke_202.png

cke_203.png

图1 uniapp组件效果

图2 原生快应用实现效果

以上标签组件具有如下特点:

  • 可以配置标签内容
  • 可以配置大小尺寸
  • 可以配置颜色类型
  • 是否为禁用状态
  • 是否无需背景颜色
  • 是否为圆角样式
  • 是否为标记样式
  • 自定义标签样式

基本实现

标签组件化设计

Tag标签组件是由一个text组件构成的,通过计算属性来设置css样式来实现的。

代码结构如下:

<import name="tag" src="./Tag/tag.ux"></import>
<template>
<div class="container">
<text class="title">实心标签</text>
    <div style="flex-wrap: wrap;">
      <div class="tag-view">
        <tag text="标签"></tag>
      </div>
 <div class="tag-view">
        <tag text="标签" type="warning"></tag>
      </div>
</div>
</template>

子组件标签组件设计

支持的属性

cke_64395.png

标签子组件布局及样式

  • type控制Tag组件标签类型,可设置default、primary、success、warning、error、royal。通过计算属性获取设置的type值及css样式。

cke_204.pngcke_205.pngcke_206.png

  • size控制标签大小,可设置normal, small。通过计算属性获取设置的size值并判断是否使用small样式及对应css样式。

cke_207.pngcke_208.png

  • text控制标签内容。

<text>{{ text }}</text>

  • Disabled控制是否是不可点击状态,默认是false。通过计算属性获取设置的size值,并判断是否可点击及对应css样式。

cke_209.png

cke_210.png

cke_211.png

  • Inverted控制标签是否是实心显示,通过计算属性获取设置的Inverted值并判断是否实心,然后显示其对应的css样式。

cke_212.png

cke_213.png

  • circle控制是否为圆角样式,通过计算属性获取设置的circle值并判断是否圆角,然后显示其对应的css样式。

cke_214.png

cke_215.png

  • Mark控制是否为标记样式,通过计算属性获取设置的Inverted值并判断是否标记样式,然后显示其对应的css样式。

cke_216.png

cke_217.png

  • Customstyle控制自定义样式。

cke_218.png

cke_219.png

自定义子组件-change事件

子组件通过this.$emit注册

cke_220.png

父组件通过onchange去监听

cke_221.png

cke_222.png

父组件引用标签子组件

cke_223.png

总结

  • 熟悉快应用子组件的设计和属性定义;
  • 熟悉text组件以及通用样式的使用;
  • 熟悉通过计算属性来设置样式;
  • 熟悉$emit事件的使用;

代码附录

标签子组件Tag.ux代码

<template>
  <text class="tag {{markStyle}} {{basicStyle}} {{invertedColor}} {{tagSize}} {{opacityStyle}}{{radiuSize}}" style="{{customstyle}}" @click="onClick">{{ text }}</text>
</template>
<style>
  .tag {
    padding: 5px 15px;
    color: #333;
    border-radius: 5px;
    background-color: #eeecec;
    border-width: 1px;
    border-color: #eeecec;
    font-size: 28px;
  }

  .default-inverted {
    color: #333;
    background-color: #ffffff;
    border-width: 1px;
    border-color: #eeecec;
    font-size: 28px;
  }
  .opacityStyle {
    opacity: 0.5;
  }
  .radiuSize {
    border-radius: 50px;
  }

  .markStyle {
    border-top-right-radius: 50px;
    border-bottom-right-radius: 50px;
  }

  .success {
    color: #fff;
    background-color: #4cd964;
    border-width: 1px;
    border-color: #4cd964;
    font-size: 28px;
  }
  .success-inverted {
    color: #4cd964;
    background-color: #ffffff;
    border-width: 1px;
    border-color: #4cd964;
    font-size: 28px;
  }

  .warning {
    color: #fff;
    background-color: #f0ad4e;
    border-width: 1px;
    border-color: #f0ad4e;
    font-size: 28px;
  }
  .warning-inverted {
    color: #f0ad4e;
    background-color: #ffffff;
    border-width: 1px;
    border-color: #f0ad4e;
    font-size: 28px;
  }

  .error {
    color: #fff;
    background-color: #dd524d;
    border-width: 1px;
    border-color: #dd524d;
    font-size: 28px;
  }
  .error-inverted {
    color: #dd524d;
    background-color: #ffffff;
    border-width: 1px;
    border-color: #dd524d;
    font-size: 28px;
  }

  .royal {
    color: #fff;
    background-color: #4335d6;
    border-width: 1px;
    border-color: #4335d6;
  }
  .royal-inverted {
    color: #4335d6;
    background-color: #ffffff;
    border-width: 1px;
    border-color: #4335d6;
    font-size: 28px;
  }

  .primary {
    color: #fff;
    background-color: #007aff;
    border-width: 1px;
    border-color: #007aff;
    font-size: 28px;
  }
  .primary-inverted {
    color: #007aff;
    background-color: #ffffff;
    border-width: 1px;
    border-color: #007aff;
  }

  .tag-small {
    padding: 0px 8px;
    font-size: 25px;
  }
</style>
<script>
  module.exports = {
    props: {
      type: {
        // 标签类型default、primary、success、warning、error、royal
        type: String,
        default: "default"
      },
      size: {
        // 标签大小 normal, small
        type: String,
        default: "normal"
      },
      // 标签内容
      text: {
        type: String,
        default: ""
      },
      disabled: {
        // 是否为禁用状态
        type: [Boolean, String],
        default: false
      },
      inverted: {
        // 是否为空心
        type: [Boolean, String],
        default: false
      },
      circle: {
        // 是否为圆角样式
        type: [Boolean, String],
        default: false
      },
      mark: {
        // 是否为标记样式
        type: [Boolean, String],
        default: false
      },
      customstyle: {
        type: String,
        default: ''
      }
    },
    data: {
      invertedColor: '',
      radiuSize: '',
      markStyle: '',
      tagSize: '',
    },
    computed: {
      invertedColor() {
        const {
          isTrue,
          type,
          inverted
        } = this
        return isTrue(inverted) ? type + '-inverted' : '';
      },
      radiuSize() {
        const {
          isTrue,
          circle
        } = this
        return isTrue(circle) ? 'radiuSize' : '';
      },
      opacityStyle() {
        const {
          isTrue,
          disabled
        } = this
        return isTrue(disabled) ? 'opacityStyle' : '';
      },
      markStyle() {
        const {
          isTrue,
          mark
        } = this
        return isTrue(mark) ? 'markStyle' : '';
      },
      basicStyle() {
        const {
          type
        } = this
        return type
      },
      tagSize() {
        const {
          size
        } = this
        return size === 'small' ? 'tag-small' : ''
      }
    },
    isTrue(value) {
      return value === true || value === 'true'
    },
    onClick() {
      if (this.isTrue(this.disabled)) {
        return
      }
      this.$emit("change");
    },

  }
</script>

页面hello.ux

<import name="tag" src="./Tag/tag.ux"></import>
<template>
  <!-- Only one root node is allowed in template. -->
  <div class="container">
    <text class="example-info">标签组件多用于商品分类、重点内容显示等场景。</text>
    <text class="title">实心标签</text>
    <div class="example">
      <div class="tag-view">
        <tag text="标签"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="primary"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="success"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="warning"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="error"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="royal"></tag>
      </div>
    </div>
    <text class="title">空心标签</text>
    <div class="example">
      <div class="tag-view">
        <tag inverted="true" text="标签"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="primary" inverted="true"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="success" inverted="true"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="warning" inverted="true"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="error" inverted="true"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="royal" inverted="true"></tag>
      </div>
    </div>
    <text class="title">标签尺寸(normal和small)</text>
    <div class="example">
      <div class="tag-view">
        <tag text="标签" type="primary"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="primary" size="small"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="warning" inverted="true"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="warning" inverted="true" size="small"></tag>
      </div>
    </div>
    <text class="title">圆角样式</text>
    <div class="example">
      <div class="tag-view">
        <tag text="标签" type="primary" circle="true"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="primary" size="small" circle="true"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="warning" circle="true" inverted="true"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="warning" size="small" circle="true" inverted="true"></tag>
      </div>
    </div>
    <text class="title">标记样式</text>
    <div class="example">
      <div class="tag-view">
        <tag text="标签" type="primary" mark="true"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="primary" size="small" mark="true"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="warning" mark="true" inverted="true"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="warning" size="small" mark="true" inverted="true"></tag>
      </div>
    </div>
    <text class="title">不可点击状态</text>
    <div class="example">
      <div class="tag-view">
        <tag text="标签" type="primary" disabled="true"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="primary" size="small" mark="true" disabled="true"></tag>
      </div>
    </div>
    <text class="title">点击事件(变更颜色或实心/空心切换)</text>
    <div class="example">
      <div class="tag-view">
        <tag text="标签" type="{{type}}" @change="setType"></tag>
      </div>
      <div class="tag-view">
        <tag text="标签" type="primary" inverted="{{inverted}}" circle="true" @change="setInverted"></tag>
      </div>
    </div>
    <text class="title">自定义标签(使用 customstyle 属性自定义样式)</text>
    <div class="example">
      <div class="tag-view">
        <tag text="自定义标签样式" customstyle="background-color: black; border-color: #4335d6; color: #fff;"></tag>
      </div>
    </div>
  </div>
</template>

<style>
  .container {
    flex-direction: column;
  }
  .tag-view {
    flex-direction: column;
    margin: 10px 15px;
    justify-content: center;
  }

  .example-info {
    padding: 15px;
    color: #3b4144;
    background-color: #ffffff;
    font-size: 40px;
  }
  .example {
    display: flex;
    flex-direction: row;
    align-items: flex-end;
    flex-wrap: wrap;
    padding: 20px 20px;
  }

  .title {
    font-size: 35px;
    padding: 10px;
    background-color: rgb(235, 233, 233);
  }
</style>

<script>
  module.exports = {
    data: {
      type: 'primary',
      inverted: false,
      customstyle: ''
    },
    setType() {
      let types = ['default', 'primary', 'success', 'warning', 'error'];
      let index = types.indexOf(this.type);
      types.splice(index, 1);
      let randomIndex = Math.floor(Math.random() * 4);
      this.type = types[randomIndex];
      console.log("message", this.type);
    },
    setInverted() {
      this.inverted = !this.inverted;
    },
    onInit() {
      this.$page.setTitleBar({
        text: 'Tag',
        textColor: '#ffffff',
        backgroundColor: '#007DFF',
        backgroundOpacity: 0.5,
        menu: true
      });
    },

  }
</script>

欲了解更多更全技术文章,欢迎访问https://developer.huawei.com/consumer/cn/forum/?ha_source=zzh

{{o.name}}
{{m.name}}

猜你喜欢

转载自my.oschina.net/u/4478396/blog/5551174