第五单元 小程序组件
一、昨日知识点回顾
1.小程序导航 2.上拉加载和下拉刷新的配置 3.小程序网络请求 4.异步api的promise化
二、本单元知识点概述
(Ⅰ)指定教材
无
(Ⅱ)知识点概述
(Ⅲ)教学时长
共4课时,180分钟
三、本单元教学目标
(Ⅰ)重点知识目标
1.组件的创建 2.组件通信
(Ⅱ)能力目标
1.掌握组件的创建 2.掌握组件通信
四、本单元知识详讲
5.1. 小程序组件
5.1.1 组件创建
-
在项目的根目录中,鼠标右键,创建 components -> test 文件夹
-
在新建的 components -> test 文件夹上,鼠标右键,点击“新建 Component”
-
为新建的组件命名之后,会自动生成组件对应的 4 个文件,后缀名分别为 .js,.json, .wxml 和 .wxss
-
在.json文件中设置
component: true
注意:尽量将不同的组件,存放到单独的文件夹中,从而保证清晰的目录结构
5.1.2 组件的引用与样式
-
引用组件
-
在需要引用组件的页面中,找到页面的 .json 配置文件,新增usingComponents节点
-
在 usingComponents 中,通过键值对的形式,注册组件;键为注册的组件名称,值为组件的引用路径
usingComponents: { "组件名": "组件所在路径" }
usingComponents: { "my-test": "/component/test/test" }
-
在页面的 .wxml 文件中,把注册的组件名称,以标签形式在页面上使用,即可把组件展示到页面上
<组件名></组件名>
<my-test></my-test>
注意:注册组件名称时,建议把名称注册为短横线连接的形式,例如 vant-button 或 custom-button
-
-
样式
-
组件对应 wxss 文件的样式,只对组件 wxml 内的节点生效
-
注意点:
-
组件和引用组件的页面不能使用id选择器(#a)、属性选择器([a])和标签名选择器,请改用class选择器。
-
组件和引用组件的页面中使用后代选择器(.a .b)在一些极端情况下会有非预期的表现,如遇,请避免使用。
-
子元素选择器(.a>.b)只能用于 view 组件与其子节点之间,用于其他组件可能导致非预期的情况
-
继承样式,如 font 、 color ,会从组件外继承到组件内。
-
除继承样式外, app.wxss 中的样式、组件所在页面的样式对自定义组件无效。
-
-
5.2. 组件的数据与方法
5.2.1 使用data定义组件的私有数据
-
小程序组件中的 data,和小程序页面中的data 用法一致,只不过组件中的data是定义在
Component()
函数中 -
在组件的.js文件中,要访问data中的数据,直接this.data.数据名称即可
-
在组件的.js文件中,要修改data中的数据,直接调用
this.setData()
即可 -
示例代码:
<!--component/test/test.wxml--> <button bindtap="add">点击</button> <text>{{ num }}</text>
// component/test/test.js Component({ // 组件的初始数据 data: { num: 0 }, // 组件的方法列表 methods: { add() { this.setData({ num: this.data.num + 1 }) } } })
5.2.2 使用methods定义组件的事件处理函数
-
和页面不同,组件的事件处理函数,必须定义在 methods 节点中
-
示例代码:
// component/test/test.js // 组件的方法列表 methods: { add() { this.setData({ num: this.data.num + 1 }) } }
5.3. properties
5.3.1 properties简介
-
类似于 vue 组件中的 props,小程序组件中的 properties,是组件的对外属性,用来接收外界传递到组件中的数据
-
在小程序中,组件的 properties 和 data 的用法类似,它们都是可读可写的
-
和data的区别
-
data 更倾向于存储组件的私有数据
-
properties 更倾向于存储外界传递到组件中的数据
-
5.3.2 properties语法结构
-
声明properties的两种方式
Component({ properties: { // 完整的定义方式 propA: { // 属性名 type: String, // 属性类型 value: '' // 属性默认值 }, propB: String // 简化的定义方式 } })
-
示例代码:
// component/test/test.js // 接收对外传递过来的数据 properties: { msg: { // 接收的数据 type: String, // 数据类型 value: 'hello world' // 数据的默认值 } }
-
注意:type 的可选值为 Number,String、Boolean、Object、Array、null(表示不限制类型)
5.3.3 向组件传递properties的值
-
可以使用数据绑定的形式,向子组件的属性传递动态数据
-
示例代码:
<!--pages/home/home.wxml--> <view> <my-test msg="hello world2"></my-test> <my-test msg="{{ info }}"></my-test> </view>
// pages/home/home.js data: { info: "我是定义在data中的数据" }
-
注意:在定义 properties 时,属性名采用驼峰写法(propertyName);在 wxml 中,指定属性值时,则对应使用连字符写法(property-name=“attr value”),应用于数据绑定时,采用驼峰写法(attr="{{propertyName}}")
5.3.4 组件内修改properties
-
小程序中,properties 的值是可读可写的,它的用法与 data 几乎一致,因此可以通过 setData 修改 properties 中任 何属性的值
-
示例代码:
<!--component/test/test.wxml--> <button bindtap="updateProperties">修改propeoties属性</button>
// component/test/test.js updateProperties() { // 获取 properties中的值:this.properties.msg console.log(this.properties.msg) // 修改 properties中的值 this.setData({ msg: 'info' }) }
5.4. 数据监听器
-
数据监听器可以用于监听和响应任何属性和数据字段的变化,从而执行特定的操作。从小程序基础库版本 2.6.1 开始支持,作用类似于 vue 中的 watch
5.4.1 基本使用方法
语法格式:
Component({ observers: { '字段A, 字段B': function(字段A的新值,字段B的新值) { // do something } } })
示例代码:
Component({ // 接收对外传递过来的数据 properties: { msg: { // 接收的数据 type: String, // 数据类型 value: 'hello world' // 数据的默认值 } }, // 组件的初始数据 data: { num: 0 }, // 数据监听器 observers: { // 同时监听num和msg的变化,只要num或msg的值有一个发生变化了,就会触发监听器函数 'num, msg'(newNum, newMsg) { // newNum: 监听的num变化以后的值 // newMsg: 监听的msg变化以后的值 console.log(newNum, newMsg) } } })
5.4.2 监听子数据字段语法
-
监听子数据字段的变化
-
数据监听器支持监听属性或内部数据的变化,可以同时监听多个。一次 setData 最多触发每个监听器一次
observers: { // 如果obj这个对象改变了,数据监听器会响应;如果obj中a的值发生改变了,数据监听器也会响应 'obj.a'(newValue) { // do something // newValue: 变化以后的新值 }, 'arr[1]'(newValue) { // do something // newValue: 变化以后的新值 } }
示例代码:
Component({ data: { arr: [1, 2, 3, 4] }, // 数据监听器 observers: { //如果arr这个数组改变了,数据监听器会响应;如果arr中某一个值发生改变了,数据监听器也会响应 'arr[2]'(newValue) { console.log('改变了') console.log(newValue) } } })
-
-
使用通配符**监听所有子数据字段的变化
-
如果需要监听所有子数据字段的变化,可以使用通配符
**
observers: { 'some.field.**': function(field) { // 使用 setData 设置 this.data.some.field 本身或其下任何子数据字段时触发 // (除此以外,使用 setData 设置 this.data.some 也会触发) field === this.data.some.field } }
示例代码:
observers: { 'arr.**'(newValue) { console.log(newValue) // 变化以后的整个数组的值 } }
-
5.5. 插槽
-
在组件的 wxml 中可以包含
slot
节点,用于承载组件使用者提供的 wxml 结构 -
默认情况下,一个组件的 wxml 中只能有一
个slot
。需要使用多slot
时,可以在组件 js 中声明启用 -
注意:小程序中目前只有默认插槽和多个插槽,暂不支持作用域插槽
5.5.1 默认插槽
<!--component/test/test.wxml--> <view>header</view> <view> <!-- 插槽的占位符 --> <slot /> </view> <view>footer</view>
<!--pages/home/home.wxml--> <view> <my-test> <view>body</view> </my-test> </view>
5.5.2 多个插槽
-
在组件中,需要使用多 slot 时,可以在组件 js 中声明
options: { multipleSlots: true }
启用// // component/test/test.js Component({ // 配置多个插槽的使用 options: { multipleSlots: true // 在组件定义时的选项中启用多slot支持 } })
-
可以在组件的 wxml 中使用多个 slot 标签,以不同的 name 来区分不同的插槽
<!--component/test/test.wxml--> <view> <!-- 插槽的占位符 --> <slot /> <view>············</view> <slot name="body2" /> <view>············</view> <slot name="body3" /> </view>
-
使用时,用 slot 属性来将节点插入到不同的 slot 中
<!--pages/home/home.wxml--> <my-test> <view>body1</view> <view slot="body2">body2</view> <view slot="body3">body3</view> </my-test>
5.6. 组件间的通信
5.6.1 组件之间的三种基本通信方式
-
WXML 数据绑定:用于父组件向子组件的指定属性传递数据,仅能设置 JSON 兼容数据
-
在父组件的子组件当中绑定子组件要接收的属性,值为要传递的值
<!--component/test/test.wxml--> <my-test msg="{{ info }}"></my-test>
Page({ // 页面的初始数据 data: { info: "我是定义在data中的数据" } })
-
在子组件中通过
properties
属性中定义要接收的属性// component/test/test.js Component({ // 接收对外传递过来的数据 properties: { msg: { // 接收的数据 type: String, // 数据类型 value: 'hello world' // 数据的默认值 } } })
-
渲染数据
<!--component/test/test.wxml--> <view>{{ msg }}</view>
-
-
事件:用于子组件向父组件传递数据,可以传递任意数据
-
通过 this.selectComponent 方法获取子组件实例对象来直接访问组件的任意数据和方法
5.6.2 this.selectComponent使用
-
在小程序的组件中,调用
this.selectComponent(string)
,可以返回指定组件的实例对象 -
父组件的 .js 文件中,可以调用
selectComponent 函数
并指定 id 或 class 选择器,获取子组件对象 -
示例代码:
-
通过class或id给组件取个名字
<my-test class="my-test" id="mtTest" msg="{{ info }}"></my-test>
-
在onLoad生命周期函数中,通过selectComponent获取组件实例
Page({ // 生命周期函数--监听页面加载 onLoad: function (options) { // 获取组件 const component = this.selectComponent('.my-test'); console.log(component.data.arr) } })
-
5.6.3 通过事件监听实现向父组件传值
-
事件系统是组件间通信的主要方式之一。自定义组件可以触发任意的事件,引用组件的页面可以监听这些事件
-
步骤:
-
在子组件中,通过
triggerEvent('自定义事件的名称', 要传递的值)
方法派发一个自定义事件<!--component/test/test.wxml--> <button bindtap="addNum">数字+1</button>
methods: { addNum() { // 1.在子组件中通过triggerEvent,派发一个自定义事件 this.triggerEvent('addNum', { num: 10 }) } }
-
在父组件中,绑定子组件派发过来的自定义事件
<!--pages/home/home.wxml--> <view> <my-test bind:addNum="addNum"></my-test> <view>{{ num }}</view> </view>
-
定义事件处理函数,通过
ev.detail
来接收子组件传递过来的值Page({ addNum(ev) { // 通过ev.detail来接收子组件传递过来的值 //console.log(ev.detail) this.setData({ num: this.data.num + ev.detail.num }) } })
-
五、本单元知识总结
1.明白下单的流程