HaaS UI小程序解决方案基础教学之七:创建第一个自定义组件

简介: 前面已经介绍过通过HaaS UI内置的组件库来搭建页面,而组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素(在HaaS UI里就是扩展基础组件库),封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用。

名词解释

AliOS Things: 阿里云智能IoT团队自研的物联网操作系统

HaaS:全称是Hardware as a Service,阿里云智能IoT团队基于AliOS Things系统推出的硬件即服务

HaaS UI:全称是Hardware as a Service User Interface,是源自AliOS Things操作系统上的一套应用&图形解决方案,支持C/C++和 JS两种开发语言

1、前言

前面已经介绍过通过HaaS UI内置的组件库来搭建页面,而组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素(在HaaS UI里就是扩展基础组件库),封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用。

几乎任意类型的应用的界面都可以抽象为一个组件树:

image.png

2、自定义组件

Vue.js注册自定义组件支持全局组件和局部组件,全局组件是指在页面入口统一注册,所有组件都能使用,局部组件是在需要使用的地方进行注册。目前HaaS UI支持局部组件注册。

注册一个自定义组件的方法:

// 导入一个自定义vue组件
import Switch from "./switch.vue";
export default {
  // 注册自定义组件,只在当前实例中使用
  components: { Switch },
}
</script>

3、组件Prop

prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":

export default {
  name: 'Child',
  props: {
    message: {                          // 属性名
      type: String,             // 属性类型
      default: '',              // 默认值
      validator(val) {      // 属性值合法验证
        return true;
      }
    },
    }
}
</script>

3.1、Prop类型

属性类型type可以是下面原生构造器:

String Number Boolean Array Object Date Function Symbol

也可以是一个自定义构造器,使用 instanceof 检测。

3.2、动态Prop

组件prop也可以使用动态绑定方式传递,类似于用 v-bind 绑定到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:

  <div @click="click">
    <!-- 动态prop -->
    <Child v-bind:message="message" />
  </div>
</template>
<script>
import Child from "./child.vue";
export default {
  // 注册自定义Child组件
  components: {
    Child,
  },
  data() {
    return {
      message: 'Hello world',
    };
  },
  methods: {
    click(r) {
      // 修改message,child自动响应式更新
      this.message = 'message changed';
    },
  },
};
</script>

3.3、第一个自定义组件

根据上面介绍的相关内容,搭建一个自定义组件child.vue:

    <text>{{message}}</text>
</template>
<script>
export default {
  name: 'Child',
  props: {
    message: {                          // 属性名
      type: String,             // 属性类型
      default: '',              // 默认值
      validator(val) {      // 属性值合法验证
        return true;
      }
    },
    }
}
</script>

父组件容器:

  <div @click="click">
    <!-- 动态prop -->
    <Child v-bind:message="message" />
    <!-- 静态prop -->
    <Child message="message static" />
  </div>
</template>
<script>
import Child from "./child.vue";
export default {
  // 注册自定义Child组件,当前实例内可复用
  components: {
    Child,
  },
  data() {
    return {
      message: 'Hello world',
    };
  },
  methods: {
    click(r) {
      // 修改message,child自动响应式更新
      this.message = 'message changed';
    },
  },
};
</script>

运行效果如下:

e06789acd6aa94916039e9af7a308b4a.gif

4、扩展一个Switch组件

了解了如何扩展一个自定义组件,我们开始尝试扩展一个更加实用的switch组件,这个组件一般用于做开关控制,是一个非常常用的组件。效果如下:

66933ab787245e4010a4941ab255cc7f.gif

4.1、Switch组件

直接上代码:

  <!-- box为组件外框 -->
  <div class='box' :style="{'width': width + 'px', 'height': height + 'px', 'background-color': internalChecked ? colorChecked : colorNormal}" @click="toggle">
    <!-- button为内部圆球 -->
    <div class='button' :style="{'width': (height-4) + 'px', 'height': (height-4) + 'px', 'transform': `translateX(${internalChecked ? (width - height) + 'px' : (0 + 'px')})`, 'background-color' : colorButton}"></div>
  </div>
</template>
<script>
export default {
  name: 'FlSwitch',
  model:{           // v-model双向数据绑定
    prop: 'checked',
    event: 'change'
  },
  props: {
    colorChecked: { // 选中时的背景色
      type: String,
      default: '#108ee9'
    },
    colorNormal: {  // 默认未选中时的背景色
      type: String,
      default: '#fff'
    },
    colorButton: {  // 按钮颜色
      type: String,
      default: '#fff'
    },
    width: {        // 宽度(px),需大于高度,设置整体组件宽度
      type: Number,
      default: 50
    },
    height: {       // 高度(px),需小于宽度,设置组件高度
      type: Number,
      default: 25
    },
    checked: {      // 是否选中
      type: Boolean,
      default: false,
    }
  },
  data() {
    return {
      internalChecked : this.checked
    };
  },
  methods: {
    toggle() {
      this.internalChecked = !this.internalChecked;
    }
  },
  watch: {
    checked() {
      this.internalChecked = this.checked;
    },
    internalChecked() {
      this.$emit('change', this.internalChecked);
    }
  }
}
</script>
<style scoped>
.box {  /* switch背景样式 */
  border-style: solid;
  border-width: 1px;
  border-color: #888;
  border-radius: 1000px;
  box-sizing: border-box;
  transition-property: background-color;
  transition-duration: 100ms;
  padding: 1px;
}
.button { /* switch圆球样式 */
  border-radius: 1000px;
  box-shadow: 0px 0px 5px #888;
  transition-property: transform;
  transition-duration: 100ms;
}
</style>

以上,为switch组件定义了6个属性

  • colorChecked:组件选中态的背景颜色
  • colorNormal:组件未选中时的默认背景色
  • colorButton:switch中间圆球的颜色
  • width:组件整体宽度
  • height:组件整体高度
  • checked:默认的选中态true/false

以及通过v-model支持checked属性的双向数据绑定,可用于与父组件的变量绑定。

并通过transition样式为组件提供切换动效。

4.2、使用Switch组件

以上实现了一个Switch组件,接下来就可以在任意页面或者组件中引进来使用了。使用方法就是上面介绍的先import进来,然后注册到vue里面就行。

通过以下方法,就可以实现上面动图的效果:

  <div class="page">
    <div class="list-item">
      <FlSwitch v-model="switch1" /><text class="list-item-text">{{switch1Value}}</text>
    </div>
  </div>
</template>
<script>
import FlSwitch from "../packages/switch/index.vue";
export default {
  components: {
    FlSwitch,
  },
  data() {
    return {
      switch1: true,
    };
  },
  computed: {
    switch1Value() {
      return this.switch1 ? 'checked' : 'unchecked';
    },
  }
};
</script>
<style scoped>
.page {
  padding: 30px;
}
.list-item {
  flex-direction: row;
  align-items: center;
}
.list-item-text {
  font-size: 20px;
  margin-left: 30px;
}
</style>

4.3、更多用法

switch组件中定义了一些可定制的属性,在使用时就可以按照组件属性的方式来定制switch显示的样式和事件了:

  <div class="page">
    <div class="list-item">
      <text class="list-item-title">普通样式:</text>
      <FlSwitch v-model="switch1" /><text class="list-item-text">{{switch1Value}}</text>
    </div>
    <div class="list-item">
      <text class="list-item-title">双向绑定:</text>
      <FlSwitch v-model="switch1" /><text class="list-item-text">{{switch1Value}}</text>
    </div>
    <div class="list-item">
      <text class="list-item-title">修改样式:</text>
      <FlSwitch v-model="switch2" colorChecked="red" colorButton="green" colorNormal="#ccc"/><text class="list-item-text">{{switch2Value}}</text>
    </div>
    <div class="list-item">
      <text class="list-item-title">修改大小:</text>
      <FlSwitch v-model="switch3" :width="200" :height="100"/><text class="list-item-text">{{switch3Value}}</text>
    </div>
    <div class="list-item">
      <text class="list-item-title">事件监听:</text>
      <FlSwitch v-model="switch4" @change="switchChange"/><text class="list-item-text">{{switch4Value}}</text>
    </div>
  </div>
</template>
<script>
import FlSwitch from "../packages/switch/index.vue";
export default {
  components: {
    FlSwitch,
  },
  data() {
    return {
      switch1: true,
      switch2: false,
      switch3: false,
      switch4: false,
    };
  },
  computed: {
    switch1Value() {
      return this.switch1 ? 'checked' : 'unchecked';
    },
    switch2Value() {
      return this.switch2 ? 'checked' : 'unchecked';
    },
    switch3Value() {
      return this.switch3 ? 'checked' : 'unchecked';
    },
    switch4Value() {
      return this.switch4 ? 'checked' : 'unchecked';
    },
  },
  methods: {
    switchChange(c) {
      let modal = $falcon.jsapi.modal;
      modal.toast({
        content: 'switchChange ' + c,
        duration: 1000
      });
    }
  }
};
</script>
<style scoped>
.page {
  padding: 30px;
}
.list-item {
  flex-direction: row;
  margin-bottom: 30px;
  align-items: center;
}
.list-item-title {
  font-size: 20px;
  margin-right: 30px;
  width: 100px;
}
.list-item-text {
  font-size: 20px;
  color: red;
  margin-left: 30px;
}
</style>

以上代码就是使用了switch组件不同属性,运行效果如下:

0805c7d9f040327ce1221ec8cda983a5.gif

5、开发者技术支持

如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号

image.png

更多技术与解决方案介绍,请访问阿里云AIoT首页https://iot.aliyun.com/

相关文章
|
2月前
|
小程序 JavaScript 前端开发
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
775 1
|
9天前
「Mac畅玩鸿蒙与硬件46」UI互动应用篇23 - 自定义天气预报组件
本篇将带你实现一个自定义天气预报组件。用户可以通过选择不同城市来获取相应的天气信息,页面会显示当前城市的天气图标、温度及天气描述。这一功能适合用于动态展示天气信息的小型应用。
103 38
|
1月前
|
UED
「Mac畅玩鸿蒙与硬件31」UI互动应用篇8 - 自定义评分星级组件
本篇将带你实现一个自定义评分星级组件,用户可以通过点击星星进行评分,并实时显示评分结果。为了让界面更具吸引力,我们还将添加一只小猫图片作为评分的背景装饰。
74 6
|
1月前
|
前端开发 开发者
「Mac畅玩鸿蒙与硬件23」鸿蒙UI组件篇13 - 自定义组件的创建与使用
自定义组件可以帮助开发者实现复用性强、逻辑清晰的界面模块。通过自定义组件,鸿蒙应用能够提高代码的可维护性,并简化复杂布局的构建。本篇将介绍如何创建自定义组件,如何向组件传递数据,以及如何在不同页面间复用这些组件。
51 5
|
24天前
|
人工智能 小程序 API
【一步步开发AI运动小程序】十三、自定义一个运动分析器,实现计时计数02
本文介绍如何利用“云智AI运动识别小程序插件”开发AI运动小程序,详细解析了俯卧撑动作的检测规则构建与执行流程,涵盖卧撑和撑卧两个姿态的识别规则,以及如何通过继承`sports.SportBase`类实现运动分析器,适用于小程序开发者。
|
24天前
|
人工智能 小程序 API
【一步步开发AI运动小程序】十二、自定义一个运动分析器,实现计时计数01
随着AI技术的发展,AI运动APP如雨后春笋般涌现,如“乐动力”、“天天跳绳”等,推动了云上运动会、线上健身等热潮。本文将指导你从零开始开发一个AI运动小程序,利用“云智AI运动识别小程序插件”,介绍运动识别原理、计量方式及运动分析器基类的使用,帮助你在小程序中实现运动计时和计数功能。下篇将继续探讨运动姿态检测规则的编写。
|
7天前
|
小程序 前端开发 数据挖掘
圈子论坛社区交友系统开源版小程序源码,自定义小程序管理社区圈子软件开发,打造受欢迎社交圈
通过获取开源版小程序源码、进行自定义小程序管理社区圈子软件开发以及注重用户体验和功能模块的设计,可以打造一个受欢迎的社交圈。同时,需要不断优化和完善系统,以满足用户不断变化的需求和期望。
27 0
|
1月前
|
人工智能 小程序 搜索推荐
uni app下开发AI运动小程序解决方案
本文介绍了在小程序中实现AI运动识别的解决方案。该方案依托于UNI平台,通过高效便捷的插件形式,实现包括相机抽帧控制、人体识别、姿态识别等在内的多项功能,无需依赖后台服务器,大幅提高识别效率和用户体验。方案内置多种运动模式,支持自定义扩展,适用于AI健身、云上赛事、AI体测等多场景,适合新开发和存量改造项目。
|
1月前
|
小程序 机器人 开发者
QQ 小程序已发布,但无法被搜索的解决方案
我的 QQ 小程序在 2024 年 8 月就已经审核通过,上架后却一直无法被搜索到。打开后,再在 QQ 上下拉查看 “最近使用”,发现他出现一下又马上消失。
47 2
|
2月前
|
API UED 容器
深入探索 Element UI:自定义滚动条与弹出层管理的技巧
在这篇博客中,我们将深入探讨 Element UI 中的自定义滚动条及弹出层管理技巧。文章详细介绍了 el-scrollbar 组件的使用和参数设置,以及 PopupManager 如何有效管理弹出层的 z-index。我们还将探讨如何实现灵活的全屏组件,利用 vue-popper 创建自定义弹出层,最后介绍 ClickOutside 指令的用法。这些高级技巧将帮助你提升 Element UI 应用程序的用户体验与交互灵活性。
315 1
深入探索 Element UI:自定义滚动条与弹出层管理的技巧