美文网首页微信小程序让前端飞微信小程序开发
微信小程序填坑之---自定义组件

微信小程序填坑之---自定义组件

作者: 程序员王大可 | 来源:发表于2017-12-19 11:28 被阅读3682次

    自定义组件从小程序基础库版本 1.6.3 开始,小程序支持简洁的组件化编程。开发者可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用;也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护。自定义组件在使用时与基础组件非常相似。

    前言

    从去年开始接触了vue以后,就一发不可收拾,尤其是vue的一切皆组件的思想,通过数据的分离,将各功能模块组件化,也将代码再次解耦,写代码的效率提高了,思路也更清晰了,到了2017年,开始负责公司的小程序开发,在踩了无数的坑以后,也接连发布了两个项目,小程序也引用了vue的思路,数据绑定,页面模块分离,但是又不像vue那样能够自由的分离拆解各个组件,终于,就在半个月前,小程序开始了自定义组件的公测,我也在开发的新项目中第一时间引入了自定义组件,和以前一样,看着超级减配摸索版的官方文档,开始了小程序的又一个填坑之旅。

    开始组件化

    众所周知,小程序的页面都是采用了模块化的管理方式,每个页面都对应着四个文件,分别负责结构,逻辑,样式和基础配置,同样,自定义组件也保持着这样的结构,一个自定义组件由wxml,wxss,js,json,4个文件组成,如果想要在页面中引入相应的组件,首先,需要在该页面的json文件里写入一下配置:

    {
      "component": true,
      "usingComponents":  {
        "component-Name":  "Path",
        ......
      }
    }
    

    同样,如果组件也是由更加细分的组件组成的话,配置是一样的,对应的,在上层的wxml里直接以标签的形式载入组件:

    <component-Name></component-Name>
    

    这样,一个自定义的组件就完成了,这个标签对应的内容就是该组件,以下面的这个页面为例:

    image.png

    产品展示的区域都是由组件构成的,分为三个组件,展示区域 > 标题 > 列表,列表还可以继续再分为两个组件,列表 > 列表内容,对于这种高复用性的内容,组件化可以极大的减少代码量和优化代码结构,例如,点开更多后的页面,就可以复用 列表 + 列表内容的组件,如果产品下方的区域还有动态展示,成交记录等等,都可以复用以上组件,但是,组件之间的数据传递时怎么进行的呢?

    组件数据的传递

    组件之间的数据传递分为很多种,例如,在上级组件传递数据、事件给下级页面,上级页面监听下级页面的事件回调,跨级的数据传递,例如,在首页将获取的产品列表数据传递给产品列表组件:

    上级组件:

    <component-list list-data="{{ListData}}"></component-list>
    

    下级组件:

    wxml:
      <view wx:for="{{ListData}}">
        <view class="item">{{item.data}}</view>
        ......
      </view>
    
    js:
      Component({
        properties: {
        ListData: {
          type: Array,
          value: [],
          observer: function(newData, oldData){
            ......
          }
        }
      },
      data: {
        someData: {}
      },
      methods: {
        customMethod: function(){}
      }
    })
    

    可以看到,组件的写法和页面基本一样,只是Page变成了Component,这里要注意,只要是由上层组件传递过来的数据,都应该在properties里声明,数据类型是必须值,而observer则是监听数据变化后产生的事件,例如,上级页面的传递的值产生变化了,就可以在observer里捕获到两个值newData, oldData,在observer里可以调用该组件的methods,去做不同的操作。同样,组件也有生命周期,这点和page略有区别,文档里对这一点写的还是很详细的。可是,如果遇到跨组件的数据该怎么传递呢?

    根据官方的说法,组件的事件是逐层传递的,并没有广播机制,这样的话就有些麻烦了,以上图为例,如果主页想要把数据传递给产品展示组件的列表组件的详情组件(有些绕),就要在每一层组件中都声明,然后把时间和数据进行逐层传递。

    根据多组件数据传递的特性,可以将数据的标识,或者api向下传递,在组件中请求、渲染,这样对于复用率较高的组件来说比较便于管理,以此为例,home-show为下层组件,home-show里又包含了组件home-show-titlehome-list,只用传入相应的标识,即可将不同的数据在不同的组件里请求和渲染:

    <home-show showTitle="产品展示" more="product" detailApi="{{ProductDetailApi}}" showList="{{info.EntProductModelList}}"></home-show>
    
    <list loadApi="{{api}}" root="{{root}}" detailApi="{{detailApi}}" isRefresh="{{isRefresh}}"></list>
    
    <view class="show_container">
      <home-show-title title="{{showTitle}}" more="{{more}}"></home-show-title>
      <home-list list="{{showList}}" detailApi="{{detailApi}}" isNews="{{isNews}}"></home-list>
    </view>
    

    组件事件

    根据官方文档,引用组件的页面可以监听到组件中触发的任意事件,如下写法:

    <!-- 当自定义组件触发“myevent”事件时,调用“onMyEvent”方法 -->
    <component-tag-name bindmyevent="onMyEvent" />
    

    可是在实际使用中发现,第一种方法貌似兼容性并不好,可以用如下的方式代替:

    <component-tag-name bind:myevent="onMyEvent" />
    

    在组件中触发事件时,可以使用triggerEvent方法,这个在文档里写的还算是清楚,就直接照搬了:

    <!-- 在自定义组件中 -->
    <button bindtap="onTap">点击这个按钮将触发“myevent”事件</button>
    
    Component({
      properties: {}
      methods: {
        onTap: function(){
          var myEventDetail = {} // detail对象,提供给事件监听函数
          var myEventOption = {} // 触发事件的选项
          this.triggerEvent('myevent', myEventDetail, myEventOption)
        }
      }
    })
    

    behaviors

    behaviors 是用于组件间代码共享的特性,类似于一些编程语言中的“mixins”或“traits”。
    每个 behavior 可以包含一组属性、数据、生命周期函数和方法,组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用。每个组件可以引用多个 behavior 。 behavior 也可以引用其他 behavior 。

    关于behaviors,刚刚接触的时候还是云里雾里,通过在实际的使用中发现,它其实就是把不同的组件中需要单独定义的内容提取出来,可以在组件的js文件开头引用,就像引用任何一个库或者文件一样,import *** from ***,如果组件中有同名的属性或方法,会进行覆盖,后面的覆盖前面的,而数据则会进行合并,这点具体可参考文档字段的覆盖和组合规则,有了behaviors,自定义的组件的可能性又被延伸,可以根据业务需要进行不同的搭配

    end

    总的来说,微信开放了自定义组件,也再次开放了小程度,开发者可以更高效率和自由的进行开发,但是现在还在公测阶段,开发中要注意的问题还是挺多的,例如,通过组件里的wxss文件,可以定义组件的样式,但是自定义组件的样式还有一些规则,这点可以参考文档的组件模版和样式;在引用组件页面的json文件里,如果添加了usingComponents还会导致页面不正常,而且引用组件的路径也偶尔会不一致发生错误。。。

    填坑持续进行中。。。

    相关文章

      网友评论

      • VenpleD:组件自己内部怎么知道自己的宽高呢?你这个有知道吗?
      • 叮咚_8a48:properties: {
        ListData: {
        type: Array,
        value: [],
        observer: function(newData, oldData){
        ......
        }
        }
        上述讲的是通过这样的方式传值,为啥我打印这两个值newData,oldData这个值根本就没有输出?这个ListData的值有发生变化

      本文标题:微信小程序填坑之---自定义组件

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