1. 组件化开发的介绍
- 组件化思想的应用:
-
尽可能的将页面拆分成一个个小的、可复用的组件
-
这样让代码更加方便组织和管理,并且扩展性也更强
-
2. 创建自定义组件
-
自定义组件的步骤:
- 首先需要在 json 文件中进行自定义组件声明(将component 字段设为 true 可将这一组文件设为自定义组件)
- 在wxml中编写属于组件的模板
- 在wxss中编写属于组件自己的相关样式
- 在js文件中, 可以定义数据或组件内部的相关逻辑
-
注意的细节:
-
自定义组件也是可以引用自定义组件的,引用方法类似于页面引用自定义组件的方式(使用usingComponents 字段)
-
自定义组件和页面所在项目根目录名 不能以“wx-”为前缀,否则会报错
-
在app.json的usingComponents声明某个组件,那么所有页面和组件可以直接使用该组件
-
3. 组件的样式细节
3.1 组件内的样式 对 外部样式 的影响
-
组件内的class样式,只对组件wxml内的节点生效, 对于引用组件的Page页面不生效。
-
组件内不能使用id选择器、属性选择器、标签选择器
3.2 外部样式 对 组件内样式 的影响
-
外部使用class的样式,只对外部 wxml 的 class 生效,对组件内是不生效的
-
外部使用了id选择器、属性选择器不会对组件内产生影响
-
外部使用了标签选择器,会对组件内产生影响
3.3 如何让class可以相互影响
-
在Component对象中,可以传入一个options属性,其中options属性中有一个styleIsolation(隔离)属性。
-
styleIsolation有三个取值:
-
isolated 表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响(默认取值)
-
apply-shared 表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面
-
shared 表示页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响页面和其他设置
Component({ options: { styleIsolation: "shared" } })
-
4. 组件的数据传递
4.1 properties
-
支持的类型:
- String、Number、Boolean、Object、Array、null(不限制类型)
4.2 externalClasses
-
在Component对象中,定义externalClasses属性
externalClasses: ["info"],
-
在组件内的wxml中使用externalClasses属性中的class
<section-info info="cba" title="黄金时代" content="在我一生中最好的黄金时代, 我想吃, 我想爱"/>
-
在页面中传入对应的class,并且给这个class设置样式
.cba { background-color: #00f; }
4.3 自定义事件
-
子组件
Component({ properties: { title: { type: String, value: "默认标题" }, content: { type: String, value: "默认内容" } }, externalClasses: ["info"], methods: { onTitleTap() { console.log("title被点击了~"); // 发射自定义事件 this.triggerEvent("titleclick", "aaa") } } })
-
父组件
<section-info info="abc" title="我与地坛" content="要是有些事情我没说, 别以为是我忘记了" bind:titleclick="onSectionTitleClick" />
onSectionTitleClick(event) { console.log("区域title发生了点击", event.detail); },
5. 调用子组件的方法
-
在父组件里调用
this.selectComponent
,获取子组件的实例对象。- 调用时需要传入一个匹配选择器 selector,如:
this.selectComponent(".my-component")
- 调用时需要传入一个匹配选择器 selector,如:
6. 自定义组件tab-control案例
-
wxml
<view class="tab-control"> <block wx:for="{{ titles }}" wx:key="*this"> <view class="item {{index === currentIndex ? 'active': ''}}" bindtap="onItemTap" data-index="{{index}}" > <text class="title">{{ item }}</text> </view> </block> </view>
-
wxss
.tab-control { display: flex; height: 40px; line-height: 40px; text-align: center; } .tab-control .item { flex: 1; } .tab-control .item.active { color: #ff8189; } .tab-control .item.active .title { border-bottom: 3px solid #ff8189; padding: 5px; }
-
js
Component({ properties: { titles: { type: Array, value: [] } }, data: { currentIndex: 0 }, methods: { onItemTap(event) { const currentIndex = event.currentTarget.dataset.index this.setData({ currentIndex }) // 自定义事件 this.triggerEvent("indexchange", currentIndex) }, test(index) { console.log("tab control test function exec"); this.setData({ currentIndex: index }) } } })
-
父组件js
onTabIndexChange(event) { const index = event.detail console.log("点击了", this.data.digitalTitles[index]); }, onExecTCMethod() { // 1.获取对应的组件实例对象 const tabControl = this.selectComponent(".tab-control") // 2.调用组件实例的方法 tabControl.test(2) }
7. 插槽的使用
-
单个插槽
<view class="my-slot"> <view class="header">Header</view> <view class="content"> <!-- 小程序中插槽是不支持默认值的 --> <slot></slot> </view> <view class="default">默认值</view> <view class="footer">Footer</view> </view>
- 默认值(设置wxss)
.default { display: none; } .content:empty + .default { display: block; }
-
多个插槽
- 子组件
<view class="mul-slot"> <view class="left"> <slot name="left"></slot> </view> <view class="center"> <slot name="center"></slot> </view> <view class="right"> <slot name="right"></slot> </view> </view>
Component({ options: { // 必须在此处设置 multipleSlots: true } })
- 父组件
<mul-slot> <button slot="left" size="mini">left</button> <view slot="center">哈哈哈</view> <button slot="right" size="mini">right</button> </mul-slot>
8. Behaviors混入
behaviors 是用于组件间代码共享的特性,类似于一些编程语言中的 “mixins”
-
每个 behavior 可以包含一组属性、数据、生命周期函数和方法
export const counterBehavior = Behavior({ data: { counter: 100 }, methods: { increment() { this.setData({ counter: this.data.counter + 1 }) }, decrement() { this.setData({ counter: this.data.counter - 1 }) } } })
-
组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用
import { counterBehavior } from "../../behaviors/counter" Component({ behaviors: [counterBehavior] })
-
每个组件可以引用多个 behavior ,behavior 也可以引用其它 behavior
9. 生命周期函数
-
组件的生命周期函数
- 最重要的生命周期是 created attached detached ,包含一个组件实例生命流程的最主要时间点
- 组件的的生命周期推荐在 lifetimes 字段内进行声明
-
页面的生命周期函数
- 在 pageLifetimes 定义段中定义
Component({ lifetimes: { created() { console.log("组件被创建created"); }, attached() { console.log("组件被添加到组件树中attached"); }, detached() { console.log("组件从组件树中被移除detached"); } }, pageLifetimes: { show() { console.log("page show"); }, hide() { console.log("page hide"); } } })
- 在 pageLifetimes 定义段中定义
10. Component选项