1. 什么是小程序?
小程序是一种"不需要下载安装"即可使用的应用,它实现了"触手可及"的梦想。使用起来方便快捷、用完即走
1.1 目前常见的小程序
- 微信小程序
- 支付宝小程序
- 淘宝小程序
- 抖音小程序
- 头条小程序
- QQ小程序
- 美团小程序
- 等等
1.1.2 为什么各个平台都需要支持小程序?
你有,我也得有
大厂竞争格局中一个重要的一环。
小程序作为介于页面和App之间的一项技术,它有自身很大的优势
体验比传统H5页面要好很多,相当于传统的App,使用起来更加方便,不需要在应用商店中下载安装,甚至注册登录等麻烦操作。
小程序可以间接的动态为App添加新动态
传统的App更新需要打包,上架到应用商店后需要通过审核用户才能进行下载(App Store),但是小程序可以在App不更新的情况下,动态为自己的应用添加新的功能要求。
1.2 小程序由谁开发?
-
小程序的定位
介于原生App和手机H5页面之间的一个产品定位 -
由此有一个疑问?小程序是由谁来开发呢?
小程序开发工程师?
由小程序的技术特点所决定的,比如微信小程序WXML、WXSS、JavaScript
它更接近于前端的开发技术栈,所以小程序是由前端开发工程师
来开发的
1.3 小程序的技术选型
1.3.1 原生小程序开发
- 微信小程序
WXML、WXSS、JavaScript - 支付宝小程序
AXML、ACSS、JavaScript
1.3.2 选择框架开发小程序
1.3.2.1 较少使用
- mpvue
mpvue是一个支持vue开发小程序的前端框架,支持微信小程序、百度小程序、头条小程序、支付宝小程序,框架在2018年之后就不再维护和更新了,目前已经被放弃
- wepy
wepy是由腾讯开源的,一款让小程序支持组件化开发的框架,通过预编译的手段让开发者可以选择自己喜欢的开发风格去开发小程序,该框架目前维护的也较少,不推荐使用
1.3.2.2 较常使用
- uni-app
由DCloud团队开发和维护,uni-app是一个使用vue开发所有前端应用的框架,开发者编写一套代码,可以发布到Ios、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台,uni-app目前是很多公司的技术选型,特别是希望适配移动端App的公司
- taro
由京东团队开发和维护,taro是一个
开放式 跨端 跨框架
解决方案,支持使用React/Vue/Nerv等框架来开发 (微信/京东/百度/支付宝/字节跳动/QQ/飞书)小程序 /H5/RN 等应用,taro因为本身支持React、Vue的选择,给了我们更加灵活的选择空间,特别是Taro3.x之后,支持Vue3、React Hook 等写法 - uni- app和taro开发原生App
- 无论是适配原生小程序还是原生App,都有较多的适配问题,所以还是需要多了解原生的一些开发知识
- 产品使用体验整体相较于原生App差很多
- 也有其他的技术选项来开发原生App
- ReactNative
- Flutter
1.3.3 需要掌握的预备知识
1.3.3.1 核心技术
页面布局
: WXML,类似于HTML
页面样式
: WXSS,几乎就是CSS(某些样式属性不支持,某些进行了增强,但是基本是一致的)
页面脚本
: JavaScript+WXS(WeixinScript)
如果之前已经掌握了Vue或者React等框架开发,那么学习小程序是更简单的
因为里面的核心思想都是一致的 组件化开发、数据响应式、mustache语法、事件绑定、等
2. 小程序架构和配置
2.1 小程序的架构模型
2.1.1 MVVM架构
2.1.1.1 Vue的MVVM和小程序MVVM对比
2.1.1.2 MVVM为什么好用呢?
- DOM Listeners
ViewModel层可以将DOM的监听绑定到Model层 - Data Bindings
ViewModel层可以将数据的变量,响应式的反应到View层
MVVM框架将我们从'命令式编程'转移到'声明式编程'
2.1.2 谁是小程序的宿主环境呢?
微信客户端
宿主环境为了执行小程序的各种文件WXML、WXSS、JS
小程序基于WebView
环境下时,WebView的 JS逻辑、DOM树构建、CSS解析、样式计算、Layout、Paint(Composite) 都发生在同一线程,在 WebView 上执行过多的Js逻辑可能会阻塞渲染,导致页面卡顿,以此为前提下,小程序同时考虑了性能与安全,来用了目前称为双线程模型
的架构。
2.1.3 双线程模型
- WXML模块和WXSS样式运行于渲染层,渲染层使用WebView线程渲染(一个程序有多个页面,会使用多个WebView的线程)
- JS脚本(app.js/home.js等) 运行于逻辑层,逻辑层使用JsCore运行JS脚本
- 这两个线程都会经由微信客户端(Native)进行中转交互
2.2 小程序的配置文件
小程序很多开发需求被规定在了配置文件中
为什么这样做?
更利于开发效率
保证开发出来的小程序某些开发风格是一致的
比如导航栏-顶部TabBar 页面路由等
2.2.1 常见的配置文件
project.config.json 项目配置文件,如项目名称、appid等
sitemap.json 小程序搜索相关的
app.json 全局配置
常用
- pages 页面路径列表
用于指定小程序由哪些页面组成,每一项都对应一个页面的路径(含文件名)信息
小程序中所有的页面都必须在pages中进行注册- window 全局的默认窗口展示
用户指定窗口如何展示,其中还包含了很多其他的属性- tabBar 顶部tab栏的展示
page.json 页面配置
每个小程序页面也可以使用
.json
文件来对本页面的窗口表现进行配置
页面中配置项在当前页面会覆盖app.json
(全局配置)的window中相同的配置项
2.3 注册小程序(App函数)
每个小程序都需要在app.js中调用 App函数 注册
在注册时可以绑定对应的生命周期函数,在生命周期函数中执行对应的代码
2.3.1 注册App时,一般会做些什么?
- 判断小程序的进入场景
- 常见的打开场景
- 群聊会话中打开
- 小程序列表打开
- 微信扫一扫打开
- 另一个小程序打开等
- 如何确定场景?
- 在onLaunch和onShow生命周期回调函数中,会有options参数,其中有scene值 链接
- 常见的打开场景
- 监听生命周期函数,在生命周期中执行对应的业务逻辑,比如在某个生命周期函数中进行登录操作或者请求网络数据
- 因为App()实例只有一个,并且是全局共享的(单例对象),所以可以将一些共享的数据放在这里
- 在App中定义全局的数据
globalData: { userInfo: {name:"蓝"} }
- 在其他页面中访问
onLoad(options) { const app = getApp() console.log(app.globalData) }
2.3 注册页面(Page函数)
小程序中的每个页面都有一个对应的js文件,其中调用Page函数注册页面示例
在注册时,可以绑定初始化数据,生命周期回调,事件处理函数等
2.3.1 注册一个page页面时,一般需要做些什么?
- 在生命周期函数中发送网络请求,从服务器获取数据
- 初始化一些数据,以方便被wxml引用展示
- 监听wxml中的事件,绑定对应的事件函数
- 其他的一些监听
- 页面滚动
- 上拉刷新
- 配置当前监听页面的json文件
"enablePullDownRefresh": true (开启上拉刷新)
- 在代码中进行监听
onPullDownRefresh() {}
- 配置当前监听页面的json文件
- 下拉加载
- 配置当前监听页面的json文件
"onReachBottomDistance": 0 (距离底部栏多少距离时开启下拉加载)
- 在代码中进行监听
onReachBottom() {}
- 配置当前监听页面的json文件
- 等
2.4 page页面的生命周期函数
3. WXSS-WXML-WXS语法
3.1 WXSS
是一套样式语言,用于描述wxml的组件样式,wxss用来决定wxml的组件应该怎么显示
3.1.1 小程序样式的写法
- 行内样式
- 页面样式
- 全局样式
三种样式都可以作用于页面的组件,如果有相同的样式,优先级的顺序是:行内样式>页面样式>全局样式
目前支持的选择器
wxss优先级与css类似
3.1.2 WXSS的扩展
wxss具有css大部分特性,同时为了更适合开发微信小程序,wxss对css进行了扩充及修改
3.1.2.1 尺寸单位
rpx(responsive pixel)
可以根据屏幕宽度进行自适应,规定屏幕宽度为750px
如在iPhone6上,屏幕宽度为375px,共有375个物理像素,则750rpx = 375px = 750物理像素, 1rpx = 0.5px = 1物理像素。
- 建议
开发微信小程序时设计师可以使用iPhone6作为视觉稿的标准 -
注意
在较小的屏幕上不可避免的会有一些毛刺
3.1.2.2 样式导入
使用@import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径,用;
表示语句结束
/** common.wxss **/
.small-p {
padding:5px;
}
/** app.wxss **/
@import "common.wxss";
.middle-p {
padding:15px;
}
3.2 WXML
3.2.1 WXML基本格式
类似于HTML代码
比如可以写成单标签,也可以写成双标签
必须有严格的闭合
没有闭合会导致编译错误
大小写敏感
class和Class时不同的属性
3.2.2 Mustache语法
开发中,界面上展示的数据并不是写死的,而是会根据服务器返回的数据,或者用户的操作来进行改变,如果使用原生JS或者Jquery的话,我们需要通过操作DOM来进行页面的更新,小程序和Vue一样,提供了插值语法,Mustache语法(双大括号)
3.2.3 block标签
某些情况下,我们需要使用 wx:if 或 wx:for 时,可能需要包裹一组或者多组组件标签,我们希望对这一组或者多组标签进行整体操作,这时就可以使用block标签。
- 注意
<block/>并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性 - 好处
将需要进行遍历或者判断的内容进行包裹,将遍历和判断的属性放在block标签中,不影响普通属性的阅读,提高代码的可读性
3.2.4 逻辑判断 wx:if - wx:elif - wx:else
有些时候,我们需要根据条件来决定一些内容是否渲染,当条件为true时,view组件会渲染出来,当条件为false时,view组件不会渲染出来
<view>
<block wx:if="{{score>=90}}">
<view>优秀</view>
</block>
<block wx:elif="{{score>80}}">
<view>良好</view>
</block>
<block wx:elif="{{score>=60}}">
<view>及格</view>
</block>
<block wx:else>
<view>不及格</view>
</block>
</view>
3.2.5 hidden属性
hidden是所有组件都默认拥有的属性
,当hidden属性为true时,组件会被隐藏,当hidden属性为false时,组件会显示出来
<view hidden="{{false}}">hi hi</view>
3.2.6 hidden和wx:if的区别
- hidden 控制组件的隐藏和显示,无论条件组件始终都会被渲染
- wx:if 控制组件是否渲染,wx:if 是惰性的,如果在初始渲染条件为false是,该组件不会进行任何处理
- 一般来说 wx:if 有更高的切换消耗 而 hidden 有更高的初始渲染消耗,
如果需要频繁切换,使用hidden。如果在运行时条件不大可能改变则使用wx:if
3.2.7 列表渲染
3.2.7.1 wx:for
为什么使用wx:for?
在实际开发中,服务器经常返回各种列表数据,我们不可能一一从列表中取出数据进行展示,需要通过for循环的方式来遍历所有的数据,一次性的进行展示
在组件中,我们可以使用wx:for来遍历数组(字符串、数字),默认情况下遍历后wxml中可以使用一个变量index
,保存的是当前遍历数据的下标值,数据中对应的某项的数据,使用变量名item获取
<block>
<!-- 遍历一个数组 -->
<view wx:for="{{['abc','aaa','ccc']}}">{{item}}</view>
<!-- 遍历一个字符串 -->
<view wx:for="{{'hello 你好'}}">{{item}}</view>
<!-- 遍历一个数字 -->
<view wx:for="{{5}}">{{item}}</view>
</block>
3.2.7.2 item/index名称
默认情况下,item/index的名字是固定的
但是某些情况下我们可能想使用其他名称,或者当出现多层变量时,名字会重复
使用wx:for-item
和wx:for-index
修改数组当前元素和下标的变量名
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
{{idx}}: {{itemName.message}}
</view>
3.2.7.3 wx:key的值以两种形式提供
-
字符串
,代表在for循环的array中item的某个property,该property的值需要是列表中唯一的字符串或者数字,且不能动态改变 - 保留关键字
*this
,代表在for循环中的item本身,这种表示需要item本身是一个唯一的字符串或者数字
3.2 WXS
3.2.1 什么是WXS?
3.2.1.1 WXS(WeiXin Script) 是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。
官方:WXS 与 JavaScript 是不同的语言,有自己的语言,并不和 JavaScript 一致。(不过基本一致)
WXS中目前只能使用ES5,ES6的使用会报错
3.2.2 为什么要设计WXS语言?
3.2.2.1 在WXML中是不能直接调用Page
/Component
中定义函数的; (双线程模式)
<!-- 在vue中可以直接调用函数 但是在小程序中这样调用是没用的(以前这样调用会报错,现在不会报错但是没有任何结果显示) -->
<view>结果:{{formatCount(value)}}</view>
但是某些情况下,我们希望使用函数来处理WXML中WXML中的数据(类似于Vue中的过滤器),这个时候就可以使用WXS了
3.2.3 WXS使用的限制和特点:
- WXS 不依赖于运行时的基础库版本,可以在所有版本的小程序中运行;
- WXS 的运行环境和其他 JavaScript 代码是隔离的,WXS中不能调用其他JavaScript文件中定义的函数,也不能调用小程序提供的API;
- 由于运行环境的差异,在IOS设备上小程序内的WXS会比JavaScript代码快 2~20 倍,在android设备上二者运行效率无差异;
3.2.4 WXS的写法
3.2.4.1 WXS有两种写法:
- 写在<wxs>标签中
- 写在以.wxs结尾的文件中
3.2.4.2 <wxs>标签的属性:
属性名 | 类型 | 说明 |
---|---|---|
module | String | 当前<wxs> 标签的模块名。必填字段。 |
src | String | 引用.wxs 文件的相对路径。仅当本标签为单闭合标签或标签内容为空时有效。 |
3.2.5 每一个.wxs文件和 <wxs> 标签都是一个单独的模块。(一个wxml文件中可以引入多个wxs"module不能重复")
- 每个模块都有自己独立的作用域。即在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见;
- 一个模块想要对外暴露起内部的私有变量,只能通过
module.exports
实现;
3.2.6 WXS简单案例
传入一个数字(整数或小数),格式化后进行展示(例如36456,展示结果3.6万)
-
传入一个时间(秒),格式化后进行展示(例如100秒,展示结果为01:40)
wxml
<wxs module="format" src="/utils/format.wxs"></wxs>
<block>
<view>传入一个数字(整数或小数),格式化后进行展示(例如36456,展示结果3.6万)</view>
<view>结果:{{format.formatCount(value)}}</view>
<input type="number" model:value="{{value}}" class="my-input" />
</block>
<block>
<view>传入一个时间(秒),格式化后进行展示(例如100秒,展示结果为01:40)</view>
<view>结果:{{format.formatDuration(value1)}}</view>
<input type="number" model:value="{{value1}}" class="my-input" />
</block>
- wxs
function formatCount(count) {
var patrn = getRegExp('(^[0-9]*\.([0-9]{1}\d*)$)|(^[0-9]*$)')
if (!patrn.test(count)) return count ? "格式错误" : "";
var count = +count;
if (count > 100000000) {
return (count / 100000000).toFixed(1) + "亿"
} else if (count > 10000) {
return (count / 10000).toFixed(1) + "万"
}
return count
}
function disposeTime(time) {
return time < 10 ? "0" + time : time
}
function formatDuration(duration) {
var patrn = getRegExp('(^[0-9]*$)');
if (!patrn.test(duration)) return "格式错误";
var isHours = duration >= 3600;
if (isHours) {
var hours = disposeTime(Math.floor(duration / 3600));
duration = duration - hours * 3600;
}
var minutes = disposeTime(Math.floor(duration / 60));
var seconds = disposeTime(duration % 60);
return (isHours ? (hours + ":") : "") + minutes + ":" + seconds;
}
module.exports = {
formatCount: formatCount,
formatDuration: formatDuration
}
3.2.7 WXS中使用正则表达式
直接使用会报错 var patrn = /'(^[0-9]*$)'/;
要使用getRegExp函数
var patrn = getRegExp('(^[0-9]*$)');
- 注意 使用getRegExp时里面不要带
/
!!!! - 错误
getRegExp('/(^[0-9]*$)/');
- 正确
getRegExp('(^[0-9]*$)');
4. 事件处理
4.1 什么时候会产生事件?
小程序需要经常和用户进行某种交互,比如点击界面上的某个按钮或者区域,比如滑动了某个区域 等
4.2 什么是事件?
事件是视图层到逻辑层的通讯方式
事件可以将用户的行为反馈到逻辑层进行处理
事件可以绑定在组件上,当触发事件时,就会执行逻辑层中对应的事件处理函数
事件对象可以携带额外信息,如id、dataset、touches等
4.3 事件是如何处理的?
- 事件通过
bind
/catch
这个属性绑定在组建上的(和普通的属性写法很相似,以key="value"形式) - key以bind或catch开头,从
1.5.0
版本开始,可以在bind和catch后加一个冒号 - 同时在当前页面的Page构造器中定义对应的事件处理函数,如果没有对应的函数,触发事件时会报错
- 比如当用户点击该button区域时,达到触发条件生成事件tap,该事件处理函数会被执行,同时还会收到一个事件对象
event
- 比如当用户点击该button区域时,达到触发条件生成事件tap,该事件处理函数会被执行,同时还会收到一个事件对象
4.4 事件对象event
当某个事件触发时,会产生一个事件对象,并且这个对象被传入到回调函数中
4.4.1 BaseEvent基础事件对象属性列表
4.5 current Target和target的区别
-
currentTarget
事件处理程序注册的元素 -
target
事件触发实际目标元素
4.6 touches和changedTouches的区别
- 在touched中不同
- 多手指触摸时不同
4.7 事件参数传递
4.7.1 dataset
当视图层发生事件时,某些情况需要事件携带一些参数到执行的函数中,这个时候就可以通过data-属性来完成
- 格式
data-属性的名称
- 获取
e.currentTarget.dataset.属性的名称
4.7.2 mark
版本2.7.1以上才可以使用
使用mark来识别具体触发事件的target节点,还可以用于承载一些自定义数据
当事件触发时,事件冒泡路径上所有的mark会被合并,并返回给事件回调函数
即使事件不是冒泡事件,也会mark
如何存在同名的mark,父节点的mark会被子节点的覆盖
在自定义组件中接收事件时,mark不包含自定义组件外的节点的mark
<view mark:myMark="last" bindtap="bindViewTap">
<button mark:anotherMark="leaf" bindtap="bindButtonTap">按钮</button>
</view>
Page({
bindViewTap: function(e) {
e.mark.myMark === "last" // true
e.mark.anotherMark === "leaf" // true
}
})
4.7.3 dataset和mark的区别
- mark会包含从触发事件的节点到根节点上的所有的mark属性值
- dataset仅包含一个节点的data-属性值
- dataset的值会做大小写的转换,mark不会做大小写的转换
4.8 事件冒泡和事件捕获
当界面产生了一个事件时,事件分为了捕获阶段和冒泡阶段
5. 组件化开发
1.6.3版本后小程序才开始支持自定义组件的开发
5.1 组件化思想的应用
- 尽可能的将页面拆分成一个个小的、可复用的组件
- 让代码更加方便组织和管理,并且扩展性也更强
5.2 创建一个组件
类似于页面,自定义组件由
json wxml wxss js
四个文件组成
首先先在根目录下创建一个文件夹components
,在里面存放后续新建的自定义组件
-
自定义组件的步骤
- 首先需要先在创建的自定义组件的json文件中进行自定义组件的声明(将component字段设置为true)
- 在wxml中编写组件自己的模版
- 在wxss中编写组件自己的相关样式
- 在js文件中可以定义数据或组件内部的相关逻辑
5.3 使用自定义组件和细节注意事项
自定义组件也是可以引用自定义组件的,引用方法类似于页面引用自定义组件的方法(使用usingComponents字段)
自定义组件和页面所在项目根目录名不能以"wx-"为前缀,否则会报错
如果在app.json和usingComponents声明某个组件,那么所有页面和组件都可以直接使用该组件
5.4 组件的样式细节
5.4.1 组件内的样式 对 外部样式 的影响
- 组件内的class样式,只对组件wxml内的节点生效,对引用组件的Page页面不生效
- 组件内不能使用id选择器、属性选择器、标签选择器
5.4.2 外部样式 对 组件内的样式 的影响
- 外部使用class的样式,只对外部wxml的class生效,对组件内是不生效的
- 外部使用了id选择器、属性选择器不会对组件内产生影响
- 外部使用了标签选择器,会对组件内产生影响
5.4.3 如何让class可以相互影响
- 在Component中,可以传入一个options属性,其中options属性中有一个styleIsolation(隔离)属性
- styleIsolation常用的三个值
-
isolated
表示启动样式隔离,在自定义组件内外,使用class指定的样式将不会互相影响 -
apply-shared
表示页面wxss样式将影响到自定义组件,但自定义组件wxss中指定的样式不会影响页面 -
shared
表示页面wxss样式将影响到自定义组件,自定义组件wxss中指定的样式也会影响页面和其他设置
-
5.5 组件的通讯
很多情况下,组件内展示的内容(数据、样式、标签)并不是在组件内写死的,而是可以由使用者来决定的
5.5.1 向组件传递数据 - properties
给组件传递数据
大部分情况下,组件只负责布局和样式,内容是由使用组件的对象决定的,所以经常需要从外部传递数据给我们的组件,让我们的组件来进行展示
5.5.1.1 如何传递?
使用properties属性
- 支持的类型
String、Number、Boolean、Object、Array、null(不限制类型)
- 默认值
可以通过value设置默认值
5.5.2 向组件传递样式 - externalClasses
有时候我们不希望将样式在组件内固定不变,而是外部可以决定样式
使用externalClasses属性
- 在Component对象中定义externalClasses属性
- 在组件那的wxml中使用externalClasses属性中的class
- 在页面中传入对应的class,并且给这个class设置样式
5.5.3 组件向外传递事件 - 自定义事件
有时候自定义组件内部发生了事件,需要告知使用者,这个时候就可以使用自定义事件
5.5.4 页面直接调用组件方法
在父组件里调用 this.selectComponent,获取子组件的实例对象
调用时需要传入一个匹配选择器selector 如:this.selectComponent(".tabs")
5.6 插槽slot
5.6.1 现实生活中什么是插槽?
- 在生活中很多地方都有插槽,电脑的USB插槽,插板当中的电源插槽
- 插槽的目的是让我们原来的设备具备更多的扩展性
- 比如电脑的USB我们可以插入U盘、硬盘、手机、音箱、键盘、鼠标等
5.6.2 组件的插槽
组件的插槽是为了让我们封装的组件更加具有扩展性,让使用者可以决定组件内部的一些内容到底展示什么
例子
移动开发中,几乎每个页面都有导航栏
导航栏必然会封装成一个插槽,比如nav-bar组件
一旦有了这个组件,我们就可以在多个页面中进行复用了
但是我们并不能确保每个页面中的导航栏是一模一样的,整体样式架构是一样的可能里面的内容不一样,这个时候就可以使用插槽
5.6.3 单个插槽的使用
除了内容和样式可能由外界决定之外,也可能外界想决定显示的方式,比如我们有一个组件定义了头部和尾部,但是中间的内容可能是一段文字、图片或者进度条,在不确定外界想插入什么其他组件的前提下,我们可以在组件内预留插槽
5.6.4 多个插槽的使用
有时候为了让组件更加灵活,我们需要定义多个插槽
5.6.5 slot插槽使用默认值方案
前提:
在很多场景下我们希望自定义组件有较好的扩展性
,在不传入slot的情况下默认展示默认的结构与样式,但小程序中的slot没有像vue中的slot一样提供默认值,这时候我们可以通过伪类选择器
:empty 和相邻选择器
+控制元素的display
来实现
- 使用自定义组件
<view>
<slot-item>
<button>我是一个按钮</button>
</slot-item>
<slot-item></slot-item>
<slot-item>
<text style="color: red;">我是一个文本</text>
</slot-item>
</view>
- 实现自定义组件
wxml
<view class="container">
<view>我是header</view>
<view class="content">
<slot></slot>
</view>
<!-- 插槽默认值 -->
<view class="default">我是slot默认值</view>
<view>我是footer</view>
</view>
wxss
.default {
width: 200rpx;
height: 200rpx;
background-color: #f99;
text-align: center;
line-height: 200rpx;
margin: 0 auto;
/* 默认值默认不显示 */
display: none;
}
/* 当插槽内为空时 通过相邻选择器将默认值显示 */
.content:empty+.default {
display: block;
}
5.7 behaviors
behaviors用于组件间代码共享的特性,类似于一些编辑语言中的"mixins"
- 每个behaviors可以包含一组属性、数据、生命周期和方法
- 组件应用它时,它的属性、数据和方法会被合并到组件中,生命周期也会在对应时机被调用
- 每个组件引用多个behavior,behavior也可以引用其它behavior
5.8 组件的生命周期
指的是组件自身的一些函数,这些函数在特殊的时间点或遇到一些特殊的框架事件时被触发,最重要的生命周期是 created、attached、detached,包含了一个组件实例生命流程的最主要的时间点
2.2.3起,组件的生命周期也可以在lifetimes字段内进行声明,推荐使用这个方式声明,其优先级最高
Component({
lifetimes: {
attached: function() {
// 在组件实例进入页面节点树时执行
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
},
// 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
attached: function() {
// 在组件实例进入页面节点树时执行
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
// ...
})
5.9 组件所在页面的生命周期
还有一些特殊的生命周期,它们并非与组件有很强的关联,但有时组件需要获知,以便组件内部处理,这样的生命周期称为"组件所在页面的生命周期",在pageLifetimes定义段中定义
Component({
pageLifetimes: {
show: function() {
// 页面被展示
},
hide: function() {
// 页面被隐藏
},
resize: function(size) {
// 页面尺寸变化
}
}
})
5.10 Component构造器
-
properties
定义传入的属性
-
data
定义内部属性
-
methods
定义方法
-
options
额外配置选项
-
externalClasses
引用外部样式
-
observers
属性和数据监听
-
pageLifetimes
页面生命周期
-
lifetimes
组件生命周期
6. 系统API调用
持续更新...