从微信小程序到鸿蒙js开发【14】——自定义组件 原创 精华

Chris.
发布于 2021-2-21 16:03
浏览
3收藏

在项目开发中,有些业务需求是需要通过多个组件共同实现的。为了便于模块化管理,减少代码的冗余,我们可以使用自定义组件,将多个组件融合成为一个组件。这部分官方文档中个人感觉讲述的不够详细和连贯,在此做一个总结。

1、新建组件

在项目工程目录上右键, New, JS Component即可新建一个组件,目录自动生成在js文件夹中,与default平级。

从微信小程序到鸿蒙js开发【14】——自定义组件-鸿蒙开发者社区

从微信小程序到鸿蒙js开发【14】——自定义组件-鸿蒙开发者社区

2、前端设计

自定义组件的目录结构和页面一致,这里做一个购物车中可以增加和减少商品个数的组件。

hml视图层:

<div class="container">
    <text class="icon"> - </text>
    <text class="cnt"> 1 </text>
    <text class="icon"> + </text>
</div>

css渲染层:

.container {
    height: 60px;
    width: 240px;
    border: 1px solid #bbbbbb;
    border-radius: 30px;
}
.container>text {
    height: 100%;
    line-height: 60px;
    text-align: center;
    color: #333333;
}
.icon {
    width: 70px;
    font-size: 40px;
}
.cnt {
    width: 100px;
    background-color: #eeeeee;
    font-size: 36px;
}

组件无法像页面一样在远程设备中直接查看,但可通过IDE的Previewer查看效果。

从微信小程序到鸿蒙js开发【14】——自定义组件-鸿蒙开发者社区

3、页面使用

在需要使用该组件的页面中通过element标签引入。该标签可与最外层div平级,个人习惯将它们写在最上面。

<element name="counter" src="../../../cart_counter/pages/index/index.hml"></element>

name属性指定组件标签名,src指向该组件的hml文件。

使用组件,和已有组件一样,用自定义的标签引入即可。若element中没有指定name属性,则和hml文件名一致。

 <counter></counter>

看一眼效果:

从微信小程序到鸿蒙js开发【14】——自定义组件-鸿蒙开发者社区

4、属性传入

商品的索引、购买件数等属性需要在页面中通过属性传入。在自定义组件的js文件的data中,定义一个键为"props"的字符串数组,其中存放所有该组件支持的属性。

export default {
    data: {
        props: ['goodsCnt', 'itemIdx']
    },
}

视图层即可直接通过动态绑定取得属性值。

<div class="container">
    <text class="icon"> - </text>
    <text class="cnt">
        {{ goodsCnt }}
    </text>
    <text class="icon"> + </text>
</div>

在使用该组件的页面中,通过 属性key="属性value" 即可将属性传入组件。这里需注意自定义组件的属性定义和使用采用驼峰命名法,使用该组件属性时采用短横线分隔命名法,对应的属性值才可以正常传递。

<counter goods-cnt="{{ $item.number }}" item-idx="{{ $idx }}"></counter>

这样就可以让组件绑定索引值,并显示商品选择的个数了。

从微信小程序到鸿蒙js开发【14】——自定义组件-鸿蒙开发者社区

5、自定义事件

点击“+”或“-”,对应商品的选择个数可以随之变化,这个组件的功能就完成了。这就要用到自定义事件。

自定义组件视图层,绑定点击事件:

<div class="container">
    <text class="icon" onclick="minus({{ itemIdx }})">
        -
    </text>
    <text class="cnt">
        {{ goodsCnt }}
    </text>
    <text class="icon" onclick="add({{ itemIdx }})">
        +
    </text>
</div>

自定义组件逻辑层,定义对应方法。

export default {
    data: {
        props: ['goodsCnt', 'itemIdx']
    },
    minus(idx) {
        this.$emit("minus", {idx});
    },
    add(idx) {
        this.$emit("add", {idx});
    }
}

在自定义组件方法中可进行一些处理,也可通过this.$emit()直接将事件抛给组件使用者进行处理。方法有两个参数,第一个参数指定使用组件时的事件名,第二个对象参数将数据传给使用组件时触发的事件。

<counter goods-cnt="{{ $item.number }}" item-idx="{{ $idx }}" onminus="minusCarts" @add="addCarts"></counter>

使用自定义组件时,可用"on+方法名"或"@+方法名"绑定事件处理的方法。由自定义组件传过来的值可通过"event.detail.指定的key"取出。这里的命名规范和属性一致,在自定义组件中定义方法采用驼峰命名法,使用组件时绑定方法的属性使用短横线分割命名法。

// 减少一个商品
    minusCarts(e) {
        let idx = e.detail.idx;
        let item = this.carts[idx];
        if (item.number == 1) {
            prompt.showToast({
                message: "至少购买1件商品哦",
                duration: 3000
            });
        } else {
            this.carts[idx].number--;
            this.totalPrice -= this.carts[idx].price;
            if (this.carts[idx].checked == 1) {
                this.nowPrice -= this.carts[idx].price;
            }
            this.updateNumber(idx);
        }
    },
// 添加一个商品
    addCarts(e) {
        let idx = e.detail.idx;
        this.carts[idx].number++;
        this.totalPrice += this.carts[idx].price;
        if (this.carts[idx].checked == 1) {
            this.nowPrice += this.carts[idx].price;
        }
        this.updateNumber(idx);
    },

大功告成。

从微信小程序到鸿蒙js开发【14】——自定义组件-鸿蒙开发者社区微信小程序的自定义组件相对来说就比较复杂了,且在js中的写法和页面差距也较大。个人感觉,鸿蒙js的自定义组件开发方式更容易上手,配置和冗余功能少。下面贴出微信小程序一个自定义组件的小demo。

从微信小程序到鸿蒙js开发【14】——自定义组件-鸿蒙开发者社区

自定义组件wxml:

<view class="parent">
    <view class="text">{{text}}</view>
    <input type="{{type}}" placeholder="{{placeholder}}" name="{{name}}" onblur="blur" disabled="{{disabled}}"></input>
</view>

自定义组件js:

Component({
   
    properties: {
        text:{
            type: String,
            value: "输入:"
        },
        type:{
            type: String,
            value: "text"
        },
        placeholder:{
            type: String,
            value: "请输入内容"
        },
        name:{
            type: String,
            value: null
        },
        disabled:{
            type: Boolean,
            value: false
        }
    },

    data: {
       
    },

    methods: {
        blur(event){
            this.triggerEvent("blur", event.detail)
        }
    }
})

自定义组件json:

{
    "component": true,
    "usingComponents": {}
}

页面wxml:

<myInput text="用户名" placeholder="请输入用户名" type="text" onblur="blur"></myInput>

页面js:

Page({

  data: {
  },

  blur(e) {
    wx.showToast({
      title: e.detail.value,
      duration: 3000,
      icon: 'none'
    })
  },
}

页面json:

{
  "usingComponents": {
    "myInput": "/component/myInput/myInput"
  }
}

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2021-2-21 16:07:44修改
10
收藏 3
回复
举报
6条回复
按时间正序
/
按时间倒序
张荣超_九丘教育
张荣超_九丘教育

好文👍👍👍

回复
2021-2-21 16:09:08
Chris.
Chris. 回复了 张荣超_九丘教育
好文👍👍👍

哈哈 张老师这么快就来了

回复
2021-2-21 16:10:23
wx601cb5b0b658d
wx601cb5b0b658d 回复了 Chris.
哈哈 张老师这么快就来了

老哥,有群没,加我一个呗

回复
2021-2-21 16:55:09
入门大师小波哥
入门大师小波哥

可以的 好文。到现在才看到

回复
2021-8-27 08:56:55
爱吃土豆丝的打工人
爱吃土豆丝的打工人

学习学习

回复
2021-8-27 09:36:06
芹菜妹纸??
芹菜妹纸??

组件里面我怎么引用组件里面common的图片呀 路径怎么写呀 我引用的不知道为啥老是default里面的commo n

回复
2021-9-16 10:25:10
回复
    相关推荐