美文网首页
微信小程序自定义组件

微信小程序自定义组件

作者: mipaifu328 | 来源:发表于2018-02-05 15:30 被阅读0次

    组件的定义

    • 配置文件
      • 要编写一个自定义组件,首先需要在json文件中进行自定义组件声明(将 component 字段设为true )。
      • 使用用已注册的自定义组件前,首先要在页面的json文件中进行引用声明。此时需要提供每个自定义组件的标签名和对应的自定义组件文件路径(标签名称只能是小写字母、中划线和下划线的组合,组件根目录名不能以“wx-”为前缀)。
    //自定义组件component.json
    {
      "component": true
    }
    
    //引用自定义组件的页面 page.json
    {
      "usingComponents": {
        "component-tag-name": "../component/component"
      }
    }
    
    • wxml文件
      在组件模板中可以提供一个 <slot> 节点,用于承载组件引用时提供的子节点。默认情况下,一个组件的wxml中只能有一个slot。需要使用多slot时,可以在组件js中声明启用options: {multipleSlots: true },以不同的 name 来区分。
    <!-- 这是自定义组件的内部WXML结构(component.wxml)-->
    <view class='wapper'>
      <text>this is component</text>
      <slot name="slot1"></slot>
      我在中间
      <slot name="slot2"></slot>
    </view>
    
    <!-- 以下是对一个自定义组件的引用 (page.wxml)-->
    <view>
      <text>This is Page</text>
      <component-tag-name inner-text="Some text" class="page-component">
        <view slot="slot1" class="slot">来自page页面,通过slot标签</view>
        <view slot="slot2"></view>
      </component-tag-name>
    </view>
    
    • wxss文件
    //component.wxss
    .wapper{
      background-color:#ccc;
      width: 100%;
      height:auto;
    }
    .slot{
      color:red;
    }
    
    //page.wxss
    .page-component{
      color:#fff;//有效,继承样式
      padding:10px;//无效
    }
    .slot{
      color:green;
    }
    
    • js文件
    //component.js
    Component({
      options: {
        multipleSlots: true // 在组件定义时的选项中启用多slot支持
      },
      properties: {
        // 这里定义了innerText属性,属性值可以在组件使用时指定
        innerText: {
          type: String,
          value: 'default value', //不存在此属性时
        }
      },
      data: {
        // 这里是一些组件内部数据
        someData: {}
      },
      methods: {
        // 这里是一个自定义方法
        customMethod: function(){}
      }
    })
    

    Component构造器API

    组件的定义
    通过上面的代码和显示结果可以看出:
    1. slot样式受page.wxss里的.slot影响显示绿色,不受component.wxss.slot影响显示红色。
    2. 继承样式,如 font 、 color ,会从组件外继承到组件内。除继承样式外, app.wxss 中的样式、组件所在页面的的样式对自定义组件无效。例子中.page-componentcolor:#fff能生效,而padding则不生效。

    Page与Component数据交互

    Tip:page代指引用组件页面,component代指自定义组件

    • page > component
    1. page在引用组件时能通过属性值设置,component.js在properties获取。
    2. page在引用组件时通data-xxx设置,component.js在this.dataset获取。
    <!-- page.wxml -->
    <component-tag-name fromPage="来自Page" data-other="from dataset"></component-tag-name>
    
    Component({
      properties: {
        formPage: String  //简写
        /*
        myProperty: { // 属性名
          type: String, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
          value: '', // 属性初始值(可选),如果未指定则会根据类型选择一个
          observer: function(newVal, oldVal){} // 属性被改变时执行的函数(可选),也可以写成在methods段中定义的方法名字符串, 如:'_propertyChange'
        }
        */
      },
      attached:function(){
        console.log(this.properties.fromPage);
        console.log(this.data.fromPage); //用data也能访问properties
        //设置properties值用setData()
        this.setData({
          fromPage: '改变了'
        });
        console.log(this.properties.fromPage);
        //通过dataset获取data-other的值
        console.log(this.dataset.other);
      }
    })
    

    控制台打印如下

    来自Page
    来自Page
    改变了
    from dataset
    
    • component > page
      组件中的变量要传递到page页面可以通过事件触发this.triggerEvent();来实行
    <!-- page.wxml -->
    <!-- 当自定义组件触发“myevent”事件时,调用“onMyEvent”方法 -->
    <component-tag-name bindmyevent="onMyEvent" />
    
    <!--component.wxml -->
    <!-- 在自定义组件中 -->
    <button bindtap="onTap">点击这个按钮将触发“myevent”事件</button>
    
    
    //page.js
    Page({
      onMyEvent: function(e){
        console.log(e.detail.msg);
      }
    })
    
    //component.js
    Component({
      methods: {
        onTap: function () {
          var myEventDetail = {msg:'来自component的信息'} // detail对象,提供给事件监听函数
          var myEventOption = {} // 触发事件的选项
          this.triggerEvent('myevent', myEventDetail, myEventOption)
        }
      }
    })
    

    点击component组件,控制台输出入下

    来自component的信息
    

    behaviors

    behaviors 是用于组件间代码共享的特性。每个 behavior 可以包含一组属性、数据、生命周期函数和方法,组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用。每个组件可以引用多个 behavior 。 behavior 也可以引用其他 behavior 。
    behavior 需要使用 Behavior() 构造器定义。

    // my-behavior.js
    module.exports = Behavior({
      behaviors: [],
      properties: {
        myBehaviorProperty: {
          type: String
        }
      },
      data: {
        myBehaviorData: {}
      },
      attached: function(){},
      methods: {
        myBehaviorMethod: function(){}
      }
    })
    

    组件引用时,在behaviors定义段中将它们逐个列出即可。

    // my-component.js
    var myBehavior = require('my-behavior')
    Component({
      behaviors: [myBehavior],
      properties: {
        myProperty: {
          type: String
        }
      },
      data: {
        myData: {}
      },
      attached: function(){},
      methods: {
        myMethod: function(){}
      }
    })
    

    在上例中,my-component中最终包含myBehaviorPropertymyProperty两个属性,myBehaviorDatamyData两个数据字段,和myBehaviorMethodmyMethod两个方法。当组件触发attached生命周期时,会依次触发my-behavior中的attached生命周期函数和my-component中的attached生命周期函数。

    组件和它引用的 behavior 中可以包含同名的字段,对这些字段的处理方法如下:

    • 如果有同名的属性或方法,组件本身的属性或方法会覆盖 behavior 中的属性或方法,如果引用了多个 behavior ,在定义段中靠后 behavior 中的属性或方法会覆盖靠前的属性或方法;
    • 如果有同名的数据字段,如果数据是对象类型,会进行对象合并,如果是非对象类型则会进行相互覆盖;
    • 生命周期函数不会相互覆盖,而是在对应触发时机被逐个调用。如果同一个 behavior 被一个组件多次引用,它定义的生命周期函数只会被执行一次。

    组件间关系

    两个自定义组件间的嵌套关系(parent父 / child 子/ ancestor祖先 / descendant子孙),通过relations 定义段来相互间的通信(必须在两个组件定义中都加入relations定义,否则不会生效)。

    <!-- page.wxml -->
    <custom-ul>
      <custom-li> item 1 </custom-li>
      <custom-li> item 2 </custom-li>
    </custom-ul>
    
    <!-- component.wxml -->
    <view class='wapper'>
      <text>custom-ul</text>
      <slot></slot>
    </view>
    
    
    <!-- children-component.wxml -->
    <view>
      <text>li-item</text>
      <slot></slot>
    </view>
    
    //page.json
    {
      "usingComponents": {
        "custom-ul": "../component/component",
        "custom-li": "../component/children-component"
      }
    }
    
    //component.json
    {
      "component": true
    }
    
    //children-component.json
    {
      "component": true
    }
    
    //component.js
    Component({
      relations:{
        'children-component': {  //子组件相对路径
          type: 'child', // 关联的目标节点应为子节点
          linked: function (target) {
            // 每次有custom-li被插入时执行,target是该节点实例对象,触发在该节点attached生命周期之后
            console.log('--linked--');
            console.log(target);
          },
          linkChanged: function (target) {
            // 每次有custom-li被移动后执行,target是该节点实例对象,触发在该节点moved生命周期之后
          },
          unlinked: function (target) {
            // 每次有custom-li被移除时执行,target是该节点实例对象,触发在该节点detached生命周期之后
          }
        }
      },
      methods: {
        _getAllLi: function () {
          // 使用getRelationNodes可以获得nodes数组,包含所有已关联的custom-li,且是有序的
          var nodes = this.getRelationNodes('children-component');
          console.log('--getAllLi--');
          console.log(nodes);
        }
      },
      ready: function () {
        this._getAllLi()
      }
    })
    
    
    //children-component.js
    Component({
      data:{
        name: 'name'
      },
      relations: {
        'component': {  //父组件相对路径
          type: 'parent', // 关联的目标节点应为父节点
          linked: function (target) {
            // 每次被插入到custom-ul时执行,target是custom-ul节点实例对象,触发在attached生命周期之后
          },
          linkChanged: function (target) {
            // 每次被移动后执行,target是custom-ul节点实例对象,触发在moved生命周期之后
          },
          unlinked: function (target) {
            // 每次被移除时执行,target是custom-ul节点实例对象,触发在detached生命周期之后
          }
        }
      }
    })
    
    
    页面显示
    console

    官网API

    说了这么多,官网基本都有

    微信小程序-自定义组件

    相关文章

      网友评论

          本文标题:微信小程序自定义组件

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