小程序:自定义组件

ylbtech-小程序:自定义组件

 

1. 自定义组件返回顶部

自定义组件

从小程序基础库版本 1.6.3 开始,小程序支持简洁的组件化编程。html

开发者能够将页面内的功能模块抽象成自定义组件以便在不一样的页面中重复使用也能够将复杂的页面拆分红多个低耦合的模块有助于代码维护。自定义组件在使用时与基础组件很是类似。node

建立自定义组件

相似于页面,一个自定义组件由 json wxml wxss js 4个文件组成。要编写一个自定义组件,首先须要在 json 文件中进行自定义组件声明(将 component 字段设为 true 可这一组文件设为自定义组件):编程

{
  "component": true
}

同时,还要在 wxml 文件中编写组件模版在 wxss 文件中加入组件样式,它们的写法与页面的写法相似。具体细节和注意事项参见 组件模版和样式 。json

代码示例:小程序

<!-- 这是自定义组件的内部WXML结构 -->
<view class="inner">
  {{innerText}}
</view>
<slot></slot>
/* 这里的样式只应用于这个自定义组件 */
.inner {
  color: red;
}

注意:在组件wxss中不该使用ID选择器、属性选择器和标签名选择器api

在自定义组件的 js 文件中,须要使用 Component() 来注册组件,并提供组件的属性定义、内部数据和自定义方法数组

组件的属性值和内部数据将被用于组件 wxml 的渲染,其中,属性值是可由组件外部传入的。更多细节参见 Component构造器 。app

代码示例:xss

Component({
  properties: {
    // 这里定义了innerText属性,属性值能够在组件使用时指定
    innerText: {
      type: String,
      value: 'default value',
    }
  },
  data: {
    // 这里是一些组件内部数据
    someData: {}
  },
  methods: {
    // 这里是一个自定义方法
    customMethod: function(){}
  }
})

使用自定义组件

使用已注册的自定义组件前,首先要在页面的 json 文件中进行引用声明。此时须要提供每一个自定义组件的标签名和对应的自定义组件文件路径编程语言

{
  "usingComponents": {
    "component-tag-name": "path/to/the/custom/component"
  }
}

这样,在页面的 wxml 中就能够像使用基础组件同样使用自定义组件。节点名即自定义组件的标签名,节点属性即传递给组件的属性值。

代码示例:

<view>
  <!-- 如下是对一个自定义组件的引用 -->
  <component-tag-name inner-text="Some text"></component-tag-name>
</view>

自定义组件的 wxml 节点结构在与数据结合以后将被插入到引用位置内

Tips:

  • 对于基础库的1.5.x版本, 1.5.7 也一样支持自定义组件。
  • 由于WXML节点标签名只能是小写字母和下划线的组合,因此自定义组件的标签名也只能包含小写字母和下划线。
  • 自定义组件也是能够引用自定义组件的,引用方法相似于页面引用自定义组件的方式(使用 usingComponents 字段)。
  • 自定义组件和使用自定义组件的页面所在项目根目录名不能以“wx-”为前缀,不然会报错
  • 旧版本的基础库不支持自定义组件,此时,引用自定义组件的节点会变为默认的空节点
2. 组件模版和样式返回顶部

组件模版和样式

相似于页面,自定义组件拥有本身的 wxml 模版和 wxss 样式。

组件模版

组件模版的写法与页面模板相同。组件模版与组件数据结合后生成的节点树将被插入到组件的引用位置上

在组件模板中能够提供一个 <slot> 节点,用于承载组件引用时提供的子节点

代码示例:

<!-- 组件模板 -->
<view class="wrapper">
  <view>这里是组件的内部节点</view>
  <slot></slot>
</view>
<!-- 引用组件的页面模版 -->
<view>
  <component-tag-name>
    <!-- 这部份内容将被放置在组件 <slot> 的位置上 -->
    <view>这里是插入到组件slot中的内容</view>
  </component-tag-name>
</view>

组件wxml的slot

在组件的wxml中能够包含 slot 节点,用于承载组件使用者提供的wxml结构

默认状况下,一个组件的wxml中只能有一个slot。须要使用多slot时,能够在组件js中声明启用

Component({
  options: {
    multipleSlots: true // 在组件定义时的选项中启用多slot支持
  },
  properties: { /* ... */ },
  methods: { /* ... */ }
})

此时,能够在这个组件的wxml中使用多个slot,以不一样的 name 来区分。

<!-- 组件模板 -->
<view class="wrapper">
  <slot name="before"></slot>
  <view>这里是组件的内部细节</view>
  <slot name="after"></slot>
</view>

使用时,用 slot 属性来将节点插入到不一样的slot上

<!-- 引用组件的页面模版 -->
<view>
  <component-tag-name>
    <!-- 这部份内容将被放置在组件 <slot name="before"> 的位置上 -->
    <view slot="before">这里是插入到组件slot name="before"中的内容</view>
    <!-- 这部份内容将被放置在组件 <slot name="after"> 的位置上 -->
    <view slot="after">这里是插入到组件slot name="after"中的内容</view>
  </component-tag-name>
</view>

组件样式

组件对应 wxss 文件的样式只对组件wxml内的节点生效。编写组件样式时,须要注意如下几点:

  • 组件和引用组件的页面不能使用id选择器(#a)、属性选择器([a])和标签名选择器请改用class选择器
  • 组件和引用组件的页面中使用后代选择器(.a .b在一些极端状况下会有非预期的表现,如遇,请避免使用。
  • 子元素选择器(.a>.b只能用于 view 组件与其子节点之间,用于其余组件可能致使非预期的状况。
  • 继承样式,如 font 、 color ,会从组件外继承到组件内。
  • 除继承样式外, app.wxss 中的样式、组件所在页面的的样式对自定义组件无效
#a { } /* 在组件中不能使用 */
[a] { } /* 在组件中不能使用 */
button { } /* 在组件中不能使用 */
.a > .b { } /* 除非 .a 是 view 组件节点,不然不必定会生效 */

除此之外,组件能够指定它所在节点的默认样式,使用 :host 选择器(须要 1.7.2 或更高版本的开发者工具支持)。

代码示例:

/* 组件 custom-component.wxss */
:host {
  color: yellow;
}
:host(.dark) {
  color: black;
}
<!-- 页面的 WXML -->
<custom-component>这段文本是黄色的</custom-component>
<custom-component class="dark">这段文本是黑色的</custom-component>

 

3. Component构造器返回顶部

Component构造器

Component构造器可用于定义组件,调用Component构造器时能够指定组件的属性、数据、方法等

定义段 类型 是否必填 描述
properties Object Map 组件的对外属性,是属性名到属性设置的映射表,属性设置中可包含三个字段, type表示属性类型、 value 表示属性初始值、 observer 表示属性值被更改时的响应函数
data Object 组件的内部数据,和 properties 一同用于组件的模版渲染
methods Object 组件的方法,包括事件响应函数和任意的自定义方法,关于事件响应函数的使用,参见 组件事件
behaviors String Array 相似于mixins和traits组件间代码复用机制,参见 behaviors
created Function 组件生命周期函数,在组件实例进入页面节点树时执行,注意此时不能调用 setData
attached Function 组件生命周期函数,在组件实例进入页面节点树时执行
ready Function 组件生命周期函数,在组件布局完成后执行,此时能够获取节点信息(使用 SelectorQuery )
moved Function 组件生命周期函数,在组件实例被移动到节点树另外一个位置时执行
detached Function 组件生命周期函数,在组件实例被从页面节点树移除时执行
relations Object 组件间关系定义,参见 组件间关系
options Object Map 一些组件选项,请参见文档其余部分的说明

生成的组件实例能够在组件的方法、生命周期函数和属性 observer 中经过 this 访问。组件包含一些通用属性和方法。

属性名 类型 描述
is String 组件的文件路径
id String 节点id
dataset String 节点dataset
data Object 组件数据,包括内部数据和属性值

 

方法名 参数 描述
setData Object newData 设置data并执行视图层渲染
hasBehavior Object behavior 检查组件是否具备 behavior (检查时会递归检查被直接或间接引入的全部behavior
triggerEvent String name, Object detail, Object options 触发事件,参见 组件事件
createSelectorQuery   建立一个 SelectorQuery 对象,选择器选取范围为这个组件实例内
selectComponent String selector 使用选择器选择组件实例节点,返回匹配到的第一个组件实例对象
selectAllComponents String selector 使用选择器选择组件实例节点,返回匹配到的所有组件实例对象组成的数组
getRelationNodes String relationKey 获取全部这个关系对应的全部关联节点,参见 组件间关系

代码示例:

Component({

  behaviors: [],

  properties: {
    myProperty: { // 属性名
      type: String, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
      value: '' // 属性初始值(可选),若是未指定则会根据类型选择一个
      observer: function(newVal, oldVal){} // 属性被改变时执行的函数(可选),也能够写成在methods段中定义的方法名字符串
    },
    myProperty2: String // 简化的定义方式
  },
  data: {}, // 私有数据,可用于模版渲染

  // 生命周期函数,能够为函数,或一个在methods段中定义的方法名
  attached: function(){},
  moved: function(){},
  detached: function(){},

  methods: {
    onMyButtonTap: function(){
      this.setData({
        // 更新属性和数据的方法与更新页面数据的方法相似
      })
    },
    _myPrivateMethod: function(){
      // 内部方法建议如下划线开头
      this.replaceDataOnPath(['A', 0, 'B'], 'myPrivateData') // 这里将 data.A[0].B 设为 'myPrivateData'
      this.applyDataUpdates()
    }
  }

})

注意:在 properties 定义段中,属性名采用驼峰写法(propertyName;在 wxml 中指定属性值时则对应使用连字符写法(component-tag-name property-name="attr value"应用于数据绑定时采用驼峰写法(attr="{{propertyName}}"

Tips:

  • Component 构造器构造的组件也能够做为页面使用
  • 使用 this.data 能够获取内部数据和属性值,但不要直接修改它们,应使用 setData 修改。
  • 生命周期函数没法在组件方法中经过 this 访问到。
  • 属性名不要命名成 dataXyz 这样的形式,由于在 WXML 中, data-xyz="" 会被做为节点 dataset 来处理,而不是组件属性。
  • 在一个组件的定义和使用时,组件的属性名和data字段相互间都不能冲突尽管它们位于不一样的定义段中)。
4. 组件事件返回顶部

组件事件

事件系统组件间交互主要形式。自定义组件能够触发任意的事件,引用组件的页面能够监听这些事件。关于事件的基本概念和用法,参见 事件 。

监听自定义组件事件的方法与监听基础组件事件的方法彻底一致:

代码示例:

<!-- 当自定义组件触发“myevent”事件时,调用“onMyEvent”方法 -->
<component-tag-name bindmyevent="onMyEvent" />
<!-- 或者能够写成 -->
<component-tag-name bind:myevent="onMyEvent" />
Page({
  onMyEvent: function(e){
    e.detail // 自定义组件触发事件时提供的detail对象
  }
})

自定义组件触发事件时,须要使用 triggerEvent 方法,指定事件名、detail对象和事件选项

代码示例:

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

触发事件的选项包括:

选项名 类型 是否必填 默认值 描述
bubbles Boolean false 事件是否冒泡
composed Boolean false 事件是否能够穿越组件边界,为false时,事件将只能在引用组件的节点树上触发,不进入其余任何组件内部
capturePhase Boolean false 事件是否拥有捕获阶段

关于冒泡和捕获阶段的概念,请阅读 事件 章节中的相关说明。

代码示例:

// 页面 page.wxml
<another-component bindcustomevent="pageEventListener1">
  <my-component bindcustomevent="pageEventListener2"></my-component>
</another-component>
// 组件 another-component.wxml
<view bindcustomevent="anotherEventListener">
  <slot />
</view>
// 组件 my-component.wxml
<view bindcustomevent="myEventListener">
  <slot />
</view>
// 组件 my-component.js
Component({
  methods: {
    onTap: function(){
      this.triggerEvent('customevent', {}) // 只会触发 pageEventListener2
      this.triggerEvent('customevent', {}, { bubbles: true }) // 会依次触发 pageEventListener2 、 pageEventListener1
      this.triggerEvent('customevent', {}, { bubbles: true, composed: true }) // 会依次触发 pageEventListener2 、 anotherEventListener 、 pageEventListener1
    }
  }
})

 

5. behaviors返回顶部

behaviors

定义和使用 behaviors

behaviors 是用于组件间代码共享的特性,相似于一些编程语言中的“mixins”或“traits”。

每一个 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 组件定义中加入了 my-behavior ,而 my-behavior 中包含有 myBehaviorProperty 属性、 myBehaviorData数据字段、 myBehaviorMethod 方法和一个 attached 生命周期函数。这将使得 my-component 中最终包含 myBehaviorProperty 、 myProperty 两个属性, myBehaviorData 、 myData 两个数据字段,和 myBehaviorMethod 、 myMethod 两个方法。当组件触发 attached 生命周期时,会依次触发 my-behavior 中的 attached 生命周期函数和 my-component 中的 attached 生命周期函数。

字段的覆盖和组合规则

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

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

内置 behaviors

自定义组件能够经过引用内置的 behavior 来得到内置组件的一些行为。

代码示例:

Component({
  behaviors: ['wx://form-field']
})

在上例中, wx://form-field 表明一个内置 behavior ,它使得这个自定义组件有相似于表单控件的行为。

内置 behavior 每每会为组件添加一些属性。在没有特殊说明时,组件能够覆盖这些属性来改变它的 type 或添加 observer 。

wx://form-field

使自定义组件有相似于表单控件的行为。 form 组件能够识别这些自定义组件,并在 submit 事件返回组件的字段名及其对应字段值。这将为它添加如下两个属性。

属性名 类型 描述 最低版本
name String 在表单中的字段名 1.6.7
value 任意 在表单中的字段值 1.6.7
 
6. 组件间关系返回顶部

组件间关系

定义和使用组件间关系

有时须要实现这样的组件:

<custom-ul>
  <custom-li> item 1 </custom-li>
  <custom-li> item 2 </custom-li>
</custom-ul>

这个例子中, custom-ul 和 custom-li 都是自定义组件,它们有相互间的关系,相互间的通讯每每比较复杂。此时在组件定义时加入 relations 定义段,能够解决这样的问题。示例:

// path/to/custom-ul.js
Component({
  relations: {
    './custom-li': {
      type: 'child', // 关联的目标节点应为子节点
      linked: function(target) {
        // 每次有custom-li被插入时执行,target是该节点实例对象,触发在该节点attached生命周期以后
      },
      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('path/to/custom-li')
    }
  },
  ready: function(){
    this._getAllLi()
  }
})
// path/to/custom-li.js
Component({
  relations: {
    './custom-ul': {
      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生命周期以后
      }
    }
  }
})

注意:必须在两个组件定义中都加入relations定义,不然不会生效。

关联一类组件

有时,须要关联的是一类组件,如:

<custom-form>
  <view>
    input
    <custom-input></custom-input>
  </view>
  <custom-submit> submit </custom-submit>
</custom-form>

custom-form 组件想要关联 custom-input 和 custom-submit 两个组件。此时,若是这两个组件都有同一个behavior

// path/to/custom-form-controls.js
module.exports = Behavior({
  // ...
})
// path/to/custom-input.js
var customFormControls = require('./custom-form-controls')
Component({
  behaviors: [customFormControls],
  relations: {
    './custom-form': {
      type: 'ancestor', // 关联的目标节点应为祖先节点
    }
  }
})
// path/to/custom-submit.js
var customFormControls = require('./custom-form-controls')
Component({
  behaviors: [customFormControls],
  relations: {
    './custom-form': {
      type: 'ancestor', // 关联的目标节点应为祖先节点
    }
  }
})

则在 relations 关系定义中,可以使用这个behavior来代替组件路径做为关联的目标节点:

// path/to/custom-form.js
var customFormControls = require('./custom-form-controls')
Component({
  relations: {
    'customFormControls': {
      type: 'descendant', // 关联的目标节点应为子孙节点
      target: customFormControls
    }
  }
})

relations 定义段

relations 定义段包含目标组件路径及其对应选项,可包含的选项见下表。

选项 类型 是否必填 描述
type String 目标组件的相对关系,可选的值为 parent 、 child 、 ancestor 、 descendant
linked Function 关系生命周期函数,当关系被创建在页面节点树中时触发,触发时机在组件attached生命周期以后
linkChanged Function 关系生命周期函数,当关系在页面节点树中发生改变时触发,触发时机在组件moved生命周期以后
unlinked Function 关系生命周期函数,当关系脱离页面节点树时触发,触发时机在组件detached生命周期以后
target String 若是这一项被设置,则它表示关联的目标节点所应具备的behavior,全部拥有这一behavior的组件节点都会被关联

 

7.返回顶部
 
8.返回顶部
 
9.返回顶部
 
10.返回顶部
一、
二、
 
11.返回顶部
 
warn 做者:ylbtech
出处:http://ylbtech.cnblogs.com/
本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文链接,不然保留追究法律责任的权利。
相关文章
相关标签/搜索