自定义组件

生命周期

  • created: 不能调用setData。这个生命周期只应该给组件this添加一些自定义属性字段
  • attached: data被初始化,大多数初始化在这里完成
  • detached: 组件离开

数据

数据是组件的私有数据,可以用于模板渲染,但是在data中不能使用外部数据,比如引入图片路径,data将读取不到

访问数据

this.data.dataName

属性

​ 属性是由外部传入

Component({
    properties:{
       userName:String,
       innerText:{
           type: String,
           value: "文字"
       }
    }
})

访问属性

this.properties.propName
//    OR
this.data.propName

属性类型校验和默认值

  • 使用type可以校验属性的类型,类型包括: String、Number、Boolean、Object、Array、null(任意类型) 。
  • 使用value可以设置属性的默认值。

使用属性还是数据

一般不直接使用属性里面的值,尤其是属性里面的值会变动时。这个时候我们监听属性,获取到属性的值并设置为data的值

//    绑定内部数据
<text>{{myNumber}}</text>
properties: {
    //    对外数据
    numOrigin:{
      type:Number,
      value:10,
      observer:function(newV,oldV,changedPath){
        let val = newV<10?`0${newV}`:newV;
        this.setData({
          // 修改对内数据
          myNumber:val
        })
      }
    }
  },
  data: {
    //    对内数据
    myNumber:10
  },
 //    调用组件
  <number-area numOrigin="{{8}}"/>

数据和属性监听

监听属性

properties:{
    userName:{
        type:String,
        value:"默认名字",
        observer:function(newV, oldV, changePath){

        }
    }
}

监听数据

//    参数中的name对应user.name
user.name:funcion(name){
    name = this.data.user.name;
}
//    监听所有子数据的变动
'user.**':function(user){
    user = this.data.user
}

参考:数据监听器 | 微信开放文档

父子组件通信

父组件传值给子组件

调用组件时在组件上使用prop-data-name即可给父组件传值,在子组件中声明properties即可接收。

//    在父页面中
<view>
    <test-component prop-a="{{dataA}}" prop-b="{{dataB}}"></test-component>
</view>

子组件传值给父组件

在子组件中使用triggerEvent(事件名,值)的方式即可将数据传递给父组件

 this.triggerEvent('emitPerson', { name: '李明',age:'123' });

父组件中使用bind:事件名或者bind事件名的方式绑定事件(后者更常用),使用e.detail获取到传出的值。

//    方式一
<carousel bind:emitPerson="getPerson" />
getPerson:function(e){
    console.log(e.detail);
}
//    方式二
<carousel bind:emitPerson="getPerson" />
getPerson:function(e){
    console.log(e.detail);
}

父组件调用子组件的事件

调用子组件时,在组件上声明一个id属性,通过selectComponent("#id").方法调用

<carousel content="{{mydata}}" bind:emitPerson="getPerson" myTitle="测试标题测试标题" id="banner"/>
this.selectComponent("#banner").clear();

插槽

单个插槽

如果编写的组件中只有一个插槽,我们可以直接在组件使用使用slot

//    test组件
<view>
组件的名字叫做<slot></slot>    
</view>

//    调用test组件
<test-com>测试组件</test-com>

多个插槽

如果编写的组件中有多个插槽, 则需要在组件js中声明multipleSlots: true

Component({
    options:{
        multipleSlots: true
    }
})

示例slot

//    在组件中test-component
<view>
    <slot name="header"></slot>
    <view>页面内容</view>
    <slot name="footer"></slot>
</view>
//    引用组件时
<test-component>
    <view slot="header">页头</view>
    <view slot="footer">页脚</view>
</test-component>

混用 behaviors

组件的复用,当多个组件有相同的properties、data和methods甚至相同的生命周期,我们可以使用behaviors.

behaviors是一个数组,小程序会自动合并相同的属性。如果有多个behaviors,且存在相同的属性,那么会按照前后顺序覆盖。

比如以下:

//    beh.js 混用
const testBeh = Behavior({
    data:{
        name:1
    }
})
export {testBeh}

//    调用
import {testBeh} from './testBeh';
Component({
    behaviors:[testBeh]
})

样式

注意事项

  • 组件中尽量使用class,不使用id选择器、属性选择器和标签名选择器
  • 不使用后代选择器和子元素选择器
  • 样式会从组件外继承到组件内
  • 要使组件外的样式不影响组件,在js文件的options属性声明stylesolation:'isolated'

传入外部样式

//    组件引入页
<test-component my-class="test-class"></test-component>
Component({
    externalClasses:['my-class']
})

//    wxss样式
.test-class{
    color: red;
}

组件关系 relations

relations: {
    //    该组件的父组件为cell-group
    '../cell-group/index': {
        type: 'parent' 
    }
},
relations: {
    //    该组件的子组件为cell
    '../cell/index': {
        type: 'child',
        linked () {
            this._updateIsLastCell();
        },
        linkChanged () {
            this._updateIsLastCell();
        },
        unlinked () {
            this._updateIsLastCell();
        }
    }
},

组件方法