微信小程序自定义组件

组件的定义

  • 配置文件
    • 要编写一个自定义组件,首先需要在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

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

微信小程序-自定义组件

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271