小程序自定义组件(父子组件通信)+npm包的使用

自定义组件

创建自定义组件

在根目录下创建 components 文件夹 下创建自定义的组件

引用自定义组件

// 在页面的 .json 文件中,引入组件
{
    "usingComponents": {
        "my-test1": "/components/test1/test1"
    }
}
​
// 在页面的 .wxml 文件中,使用组件
<my-test1></mytest1>

组件和页面的区别

  • 组件中的 .json 文件中需要声明 “component”:true 属性

  • 组件的 .js 文件中调用的是 Component() 函数

  • 组件的事件处理函数需要定义到 methods 节点中

组件样式隔离

组件的样式不会影响组件之外的样式

注意:

  • app.wxss 定义的样式对组件样式无效

  • 只有 class 选择器会有样式隔离效果,id 选择器、属性选择器、标签选择器不受样式隔离的影响

建议:在组件和引用组件的页面中建议使用 class 选择器,不要使用 id、属性、标签选择器!

修改组件的样式隔离选项

通过 styleIsolation 修改组件的样式隔离选项

// 在组件的 .js 文件中新增如下配置
Component({
    options:{
        styleIsolation: 'isolated'
    }
})
// 或在组件的 .json 文件中新增配置如下
{
    "styleIsolation": "isolated"
}

自定义组件的方法

自定义方法建议以 _ 开头

properties 属性

是组件的对外属性,用来接收外界传递到组件中的数据。

Component({
    // 属性定义
    properties: {
       max: {				// 完整定义属性的方式【当需要指定属性默认值时,建议使用此方式】
           type: Number,	// 属性值的数据类型
           value: 10		// 属性默认值
       },
       max: Number			// 简化定义属性的方式【不需要指定属性默认值时,可以使用简化方式】
    }
})

<my-test1 max="10"></my-test1>

data 和 properties 的区别

都是可读可写的。

  • data 更倾向于存储组件的私有数据

  • properties 更倾向于存储外界传递到组件中的数据

使用 setData 修改 properties 的值

Component({
    properties: { max: Number },	// 定义属性
    methods: {
        addCount(){
			this.setData({ max: this.properties.max + 1 }) // 使用 setData 修改属性的值
        }
    }
})

数据监听器

类似于 vue 中的数据监听器

Component({
    observers: {
        '字段A, 字段B': function(字段A的新值, 字段B的新值){
            // do something
        }
    }
})

Component({
    observers: {
        'rgb.**': function(obj){
            this.setData({
                fullColor: `${obj.r}, ${obj.g}, ${obj.b}`
            })
        }
    }
})

纯数据字段

指定 pureDataPattern 为一个正则表达式,字段名符合这个正则表达式的字段将成为纯数据字段。

Component({
   options: {
       // 指定所有 _ 开头的数据字段为纯数据字段
       pureDataPattern: /^_/
   },
   data: {
       a: true, // 普通字段
       _b: true, // 纯数据字段
   }
}

组件的生命周期

createdattached 、ready 、moved 、detached 、 error

created :不能调用 setData;通常在这个生命周期函数中,只用于给组件的 this 添加一些自定义的属性字段。

attached:this.data 此时已初始化完毕;初始化的工作可以在这里进行(例如发请求获取初始数据)

detached:退出一个页面时,会触发页面内每个自定义组件的 detached 生命周期函数;此时适合做一些清理性质的工作

lifetimes节点

Component({
    lifetimes: {
        created(){
      		// do something
  		},
        attached(){
    		
		}
	}
}

组件所在页面的生命周期函数

show \ hide \ resize

pageLifetimes 节点

Component({
    pageLifetimes: {
        show: function(){}, // 页面被展示时
        hide: function(){}, // 页面被隐藏时
        resize: function(){} // 页面尺寸发生变化时
	}
}

 

自定义组件的插槽

<slot> 插槽,占位符

单个插槽

在小程序中,默认每个自定义组件中只允许使用一个 <slot> 插槽

// 组件的封装者
<view>
	<view>这里是组件的内部节点</view>    
	// 对于不确定的内容,可以使用 插槽 占位,具体内容由组件的使用者决定
	<slot></slot>
</view>

<component-tag-name>
    // 这部分内容将放置在组件 插槽 的位置上
    <view>这里是插入到组件slot中的内容</view>
</component-tag-name>

多个插槽

Component({
	options: {
        mulitipSlots: true // 在组件定义时的选项中启用多 slot 支持
    },
})
// 组件的封装者
<view>
	<view>这里是组件的内部节点</view>    
	// 对于不确定的内容,可以使用 插槽 占位,具体内容由组件的使用者决定
	<slot name="before"></slot>
	<slot name="after"></slot>
</view>

<component-tag-name>
    // 这部分内容将放置在组件 插槽 的位置上
    <view slot="before">这里是插入到组件slot中的内容</view>
    <view slot="after">这里是插入到组件slot中的内容</view>
</component-tag-name>

组件通信

父子组件通信

  1. 属性绑定

    • 用于父组件向子组件的指定属性设置数据,仅能设置 JSON 兼容

  2. 事件绑定

    • 用于子组件向父组件传递数据,可以传递任意数据

      • 在父组件的 js 中,定义一个函数,这个函数即将通过自定义事件的形式,传递给子组件

      • 在父组件的 wxml 中,通过自定义事件的形式,将👆步骤中定义的函数引用,传递给子组件

      • 在子组件的 js 中,通过调用 this.triggerEvent('自定义事件名称',{/参数对象/}),将数据发送到父组件

      • 在父组件的 js 中,通过 e.detail 获取到子组件传递过来的数据

  3. 获取组件实例

    • 父组件还可以通过 this.selectComponent() 获取子组件实例对象

    • 这样就可以直接访问子组件任意数据和方法

// 父传子 属性绑定
// 子组件在 properties 节点中声明对应的属性并使用
properties: {
    count: Number
}

// 子组件的 wxml 结构
<text>子组件中,count值为:{{count}}</text>

// 子传父 事件绑定
// 父组件中定义方法
syncCount(e){
    this.setData({
    	count: e.detail.value
    })
}
<view bind:sync="syncCount"></view>

// 子组件中 调用方法
methods: {
	addCount(){
        // 触发自定义事件,给父组件传值
		this.triggerEvent('sync', {value: this.properties.count})
    }
}

// 父组件获取子组件的实例对象
// wxml 结构
<my-test class="custiom" id="cA"></my-test>
<button bindtap="getChild">获取子组件实例</button>

getChild(){ // 按钮的 tap 事件处理函数
    // 切记下面参数不能传递标签选择器,'my-test',不然返回的是null
    const child = this.selectComponent('.customA') // 也可以传递 id 选择器 #cA
    child.setData({ count: child.proprties.count + 1 }) // 调用子组件的 setData 方法
    child.addCount() // 调用子子组件的 addCount 方法
}

 

behaviors

用于实现组件间代码共享的特性,类似于 Vue.js 中的 "mixins"。

behavior 可以包含一组属性、数据、声明周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中。

创建 behaviors

调用 Behavior(Object object) 方法即可创建一个共享的 behavior 实例对象,供所有的组件使用

// 调用 Behavior() 方法,创建实例对象
// 并使用 module.exports 将 behavior 实例对象共享出去
module.exports = Behavior({
    // 属性节点
    properties: {},
    // 私有数据节点
    data: { username: 'zs' },
    // 事件处理函数和自定义方法节点
    methods: {},
    // 其他节点。。。
})

导入并使用 behavior

在组件中,使用 require() 方法导入需要的 behavior,挂载后即可访问 behavior 中的数据或方法。

// 1.使用 require() 导入需要的自定义 behavior 模块
const myBehavior = require('../../behavior/my-behavior')

Component({
    // 2.将导入的 behavior 实例对象,挂载到 behavior 数组节点中,即可生效
    behaviors: [myBehavior],
    // 组件的其他节点。。。
})

同名字段的覆盖和组合规则

Behavior(Object object) | 微信开放文档 (qq.com)

组件和它引用的 behavior 中可以包含同名的字段,此时可以参考如下3种同名时的处理规则:

  1. 同名的数据字段(data)

  2. 同名的属性(properties)或方法(methods)

  3. 同名的生命周期函数

 

使用 npm 包

小程序对 npm 的限制

限制:

  1. 不支持依赖于 Node.js 内置库的包

  2. 不支持依赖于浏览器内置对象的包

  3. 不支持依赖于 C++ 插件的包

 

API Promise化

小程序官方提供的异步 API 都是基于回调函数实现的。容易造成回调地狱的问题,代码的可读性、维护性差。

API Promise化,指的是通过额外的配置,将官方提供的、基于回调函数的异步 API,升级改造为基于 Promise 的异步 API,从而提高代码的可读性、维护性,避免回调地狱的问题。

实现 API Promise 化主要依赖于 miniprogram-api-promise 这个第三方的 npm 包。安装步骤如下:

npm install --save miniprogram-api-promise@1.0.4

// 在小程序入口文件中(app.js),只需调用一次 promisifyAll() 方法
// 即可实现异步 API 的 Promise 化
import { promisifyAll } from 'miniprogram-api-promise'

const wxp = wx.p = {}
// promisify all wx's api
promisifyAll(wx,wxp)

调用 promise 化的 API

// 页面 .wxml 结构
<van-button bandtap="getInfo"></van-button>

// 在页面的 .js 文件中,定义对应的 tap 事件处理函数
async getInfo() {
    const {data: res} = await wx.p.request({
        method: 'GET',
        url: 'url',
        data: {data...}
    })
}
 
posted @ 2022-12-11 18:18  东八区  阅读(198)  评论(0编辑  收藏  举报