微信小程序官方文档:微信开放文档
目录
方法一:右键文件夹点击“新建Page”,快速生成单个页面的基本文件
方法二:在app.json的pages字段中直接添加页面路径,保存后,开发工具会根据路径自动生成相关文件
在小程序中使用flex布局实现一个小demo(引入微信小程序)
步骤二:在页面的wxss中使用flex布局给wxml添加样式
案例:movable-view(可移动的视图容器,在页面中可以拖拽滑动)
一、开发环境配置
申请开发Appid
- 进入小程序注册网址小程序
- 根据提示信息完成注册
- 查询注册后的appid
登录https://mp.weixin.qq.com查看自己的appid
后面会跟着自己的appid,这里看不见是进行了处理
安装开发工具
第一次打开开发工具需要微信登录
登录后进入项目管理页面
创建项目
项目开发界面以及项目结构说明
二、微信小程序开发相关配置及说明
允许上传的文件
wxs、png、jpg、jpeg、gif、svg、json、cer、mp3、aac、m4a、mp4、wav、ogg、silk、wasm、br、cert
- 注意:除以上文件能上传外,其他文件能在开发工具访问到,但是无法上传
全局配置
- 小程序根目录下的
app.json
文件用来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等(详细请查阅官方文档)
代码示例
{
"pages": [
"pages/index/index",
"pages/logs/index"
],
"window": {
"navigationBarTitleText": "Demo"
},
"tabBar": {
"list": [{
"pagePath": "pages/index/index",
"text": "首页"
}, {
"pagePath": "pages/logs/index",
"text": "日志"
}]
},
"networkTimeout": {
"request": 10000,
"downloadFile": 10000
},
"debug": true
}
配置相关名称说明
页面配置
- 每一个小程序页面也可以使用同名
.json
文件来对本页面的窗口表现进行配置,页面中配置项会覆盖app.json
的window
中相同的配置项。
代码示例
{
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationBarTitleText": "微信接口功能演示",
"backgroundColor": "#eeeeee",
"backgroundTextStyle": "light"
}
sitemap 配置
-
小程序根目录下的
sitemap.json
文件用来配置小程序及其页面是否允许被微信索引。完整配置项说明请参考小程序 sitemap 配置
三、小程序基本开发
小程序页面的创建及单个页面入口
在项目中的pages/index/index.js是单个页面的js脚本文件,在这个js文件中的Page字段为这个页面的入口程序
Page({
data:{
name:'123'
}
})
参数 | 说明 |
---|---|
data | 页面的初始数据 |
options | 页面的组件选项 |
behaviors | 类似于mixins和traits的组件间代码复用机制 |
onLoad | 生命周期回调—监听页面加载 |
onShow | 生命周期回调—监听页面显示 |
onReady | 生命周期回调—监听页面初次渲染完成 |
onHide | 生命周期回调—监听页面隐藏 |
onUnload | 生命周期回调—监听页面卸载 |
onRouteDone | 生命周期回调—监听路由动画完成 |
onPullDownRefresh | 监听用户下拉动作 |
onReachBottom | 页面上拉触底事件的处理函数 |
onShareAppMessage | 用户点击右上角转发 |
onShareTimeline | 用户点击右上角转发到朋友圈 |
onAddToFavorites | 用户点击右上角收藏 |
onPageScroll | 页面滚动触发事件的处理函数 |
onResize | 页面尺寸改变时触发 |
onTabItemTap | 当前是 tab 页时,点击 tab 时触发 |
onSaveExitState | 页面销毁前保留状态回调 |
小程序页面的创建
方法一:右键文件夹点击“新建Page”,快速生成单个页面的基本文件
优点:便捷快速,小程序会自动在app.json中的Pages字段中添加这个页面的路径,但是不默认是这个新建的页面为默认展示页面
缺点:该方法只生成单页面的基本文件,为方便文件架构,我们一般在Pages中手动创建一个文件夹,然后在这个文件夹里生成新的页面文件
补充:要展示的这个页面,要把页面的路径移动到第一个这个操作是在app.json中
方法二:在app.json的pages字段中直接添加页面路径,保存后,开发工具会根据路径自动生成相关文件
小程序页面的生命周期
生命周期名称 | 说明 |
---|---|
onLoad | 页面加载时触发。一个页面只会调用一次,可以在 onLoad 的参数中获取打开当前页面路径中的参数 |
onReady | 页面初次渲染完成时触发。一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互 |
onShow | 页面显示/切入前台时触发 |
onHide | 页面隐藏/切入后台时触发 |
onUnload | 页面卸载时触发 |
onRouteDone | 路由动画完成时触发 |
onPullDownRefresh | 监听用户下拉动作 |
事件名称 | 说明 |
---|---|
onPullDownRefresh | 监听用户下拉刷新事件 |
onReachBottom | 监听用户上拉触底事件 |
onPageScroll | 监听用户滑动页面事件 |
onAddToFavorites | 监听用户点击右上角菜单“收藏”按钮的行为,并自定义收藏内容 |
onShareAppMessage | 监听用户点击页面内转发按钮(button 组件open-type="")或右上角菜单“转发”按钮的行为,并自定义转发内容 |
onShareTimeline | 监听右上角菜单“分享到朋友圈”按钮的行为,并自定义分享内容 |
onResize | 页面尺寸改变时触发。详见响应显示区域变化 |
onTabItemTap | 点击 tab 时触发 |
onSaveExitState | 每当小程序可能被销毁之前,页面回调函数会被调用,可以进行退出状态的保存 |
在小程序中使用flex布局实现一个小demo(引入微信小程序)
目标效果
步骤一:在页面的wxml中使用列表渲染展示数据
<view class="box">
<view class="box_farg">
<view class="box_icon">icon</view>
<text>前端</text>
</view>
<view class="box_farg">
<view class="box_icon">icon</view>
<text>后端</text>
</view>
<view class="box_farg">
<view class="box_icon">icon</view>
<text>产品</text>
</view>
<view class="box_farg">
<view class="box_icon">icon</view>
<text>运维</text>
</view>
</view>
步骤二:在页面的wxss中使用flex布局给wxml添加样式
page {
height: 100vh;
display: flex;
flex-direction: column;
}
.box{
margin-top: 20rpx;
display: flex;
justify-self: baseline;
justify-content: space-around;
}
.box_farg{
display: flex;
flex-direction: column;
text-align: center;
}
.box_icon{
width: 100rpx;
height: 100rpx;
text-align: center;
line-height: 100rpx;
border-radius: 50%;
background-color: lightskyblue;
}
四、WSXL语法
WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。
数据绑定
- 数据绑定使用 Mustache 语法(双大括号)将变量包起来
- 支持组件属性(需要在双引号之内):<view id="item-{{id}}"> </view>
- 支持控制属性(需要在双引号之内):<view wx:if="{{condition}}"> </view>
- 支持关键字:<checkbox checked="{{false}}"></checkbox>
- 支持运算、三元运算、算数运算、逻辑判断、字符串运算、数据路径运算
- 支持组合,在双大括号内直接进行组合,构成新的对象或者数组:
<view wx:for="[zero,1,2,3,4]}">{item}</view> - setData方法修改数据触发页面更新
注意:如有存在变量名相同的情况,后边的会覆盖前面
基本用法示例
<!--wxml-->
<view> {{message}} </view>
<view id="item-{{id}}"> </view>
//控制属性
<view wx:if="{{condition}}"> </view>
//关键字
<checkbox checked="{{false}}"> </checkbox>
//三元运算
<view hidden="{{flag ? true : false}}"> Hidden </view>
//算数运算
<view> {{a + b}} + {{c}} + d </view>
//逻辑判断
<view wx:if="{{length > 5}}"> </view>
//字符串运算
<view>{{"hello" + name}}</view>
//数据路径运算
<view>{{object.key}} {{array[0]}}</view>
//组合---数组
<view wx:for="{{[zero, 1, 2, 3, 4]}}"> {{item}} </view>
//组合---对象
<template is="objectCombine" data="{{for: a, bar: b}}"></template>
// page.js
Page({
data: {
message: 'Hello MINA!',
id: 0,
condition: true,
a: 1,
b: 2,
c: 3,
name: 'MINA',
object: {
key: 'Hello '
},
array: ['MINA'],
zero: 0,
},
onLoad:function(){
// 数据改变 但不触发页面更新
this.data.name='lisi'
// setData 数据改变 触发页面更新
this.setData({
name:"lisi",
age:18
})
}
})
列表渲染
- 在组件上使用wx:for控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件
-
可以将wx:for用在<block>标签上,以渲染一个包含多节点的结构块
-
如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如input中的输入内容,switch的选中状态),需要使用wx:key来指定列表中项目的唯一的标识符
-
当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率
注意:如不提供wx:key,会报一个warning, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略
注意:
- 当wx:for的值为字符串时,会将字符串解析成字符串数组
- 花括号和引号之间如果有空格,将最终被解析成为字符串
基本示例
<!--wxml-->
<view wx:for="{{array}}"> {{item}} </view>
// page.js
Page({
data: {
array: [1, 2, 3, 4, 5]
}
})
小Demo引入列表渲染 (看不懂可跳过)
目标结果
步骤一:在wxs中定义数据
//wxs(js文件)
Page({
data:{},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
// 模拟网络数据
var courseList=[
{
img:'../../images/123.png',
name:"测试"
},
{
img:'../../images/123.png',
name:"测试"
},
{
img:'../../images/123.png',
name:"测试"
},
{
img:'../../images/123.png',
name:"测试"
},
]
// 将数据获取到data字段中中
this.setData({
list:courseList
})
},
})
步骤二:使用wx:for将数据列表渲染
//wxml
<view class="box">
<block wx:for="{{list}}" wx:for-item="course" wx:for-index="idx" >
<view class="box_item_img">
<image src="{{course.img}}" />
<text>{{course.name}}</text>
<text> {{idx}}</text>
</view>
</block>
</view>
步骤三:在wxss中使用flex布局修改样式
//wxss
.box{
width: 100%;
height: 400rpx;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
justify-items: normal;
}
.box_item_img{
display: flex;
flex-direction: column;
}
.box_item_img image{
width: 300rpx;
height: 300rpx;
}
条件渲染(wx:if、wx:else、wx:elif)
- 在框架中,使用wx:if=" "来判断是否需要渲染该代码块
- 也可以用wx:elif和wx:else来添加一个 else 块
- 如果要一次性判断多个组件标签,可以使用一个<block>标签将多个组件包装起来,并在block上使用wx:if控制属性
<!--wxml-->
<view wx:if="{{view == 'WEBVIEW'}}"> WEBVIEW </view>
<view wx:elif="{{view == 'APP'}}"> APP </view>
<view wx:else="{{view == 'MINA'}}"> MINA </view>
// page.js
Page({
data: {
view: 'MINA'
}
})
模版
WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用
定义模板
<template name="msgItem">
<view>
<text>{{index}}:{{msg}}
</text>
<text>
Time:{{time}}</text>
</view>
</template>
使用模板
//wxml中,is:模版匹配; data: 模版传递数据
<template is="msgItem" data="{{...item}}"/>
//js文件的Page字段中
data: {
item:{
index:0,
msg:'this is msg',
time:'2024-3-11'
}
},
渲染结果展示
注意:模版拥有自己的作用域,只能使用data传入的数据以及模版定义文件中定义的<wxs>模块
模版使用案例一:
目标结果展示:
方法一(在内部使用wxs):
<!-- 在wxml中定义wxs -->
<wxs module="info">
var msg = "hello world";
var num = function (num1, num2) {
return num1 + num2;
}
module.exports = {
message: msg,
add: num
}
</wxs>
<!-- 在wxml中使用wxs -->
<view>{{info.message}}</view>
<view>{{info.add(20,10)}}</view>
方法二(在wxml外部定义wxs):
// 在common.wxs中定义
var msg = "hello world";
var num = function (numl, num2) {
return numl +num2;
}
//commonjs模块化导出
module.exports = {
message: msg,
add: num
}
//引入,在其他文件调用,src是定义的wxs的文件路径
<!-- 导入外部的wxs文件并使用 -->
<wxs src="./common.wxs" module="info2"></wxs>
<view>{{info2.message}}</view>
<view>{{info2.add(20,10)}}</view>
模版使用案例二:
目标渲染结果(通过使用外部定义wxs实现一些方法的调用):
步骤一:创建wxs文件,并定义相关方法
var message = "hello 你好"
var add = function(num1,num2){
return num1+num2
}
// 格式化价格数字
var toFixed = function (value, count) {
return value.toFixed(count);
}
// 时间戳格式化
var formatNumber = function (n) {
n = n.toString()
return n[1] ? n : '0' + n
}
var regYear = getRegExp("(y+)", "i");
var dateFormat = function (timestamp, format) {
if (!format) {
format = "yyyy-MM--dd hh:mm:ss";
}
timestamp = parseInt(timestamp);
var realDate = getDate(timestamp);
function timeFormat(num) {
return num < 10 ? '0' + num : num;
}
var date = [
["M+", timeFormat(realDate.getMonth() + 1)],
["d+", timeFormat(realDate.getDate())],
["h+", timeFormat(realDate.getHours())],
["m+", timeFormat(realDate.getMinutes())],
["s+", timeFormat(realDate.getSeconds())],
["q+", Math.floor((realDate.getMonth() + 3) / 3)],
["S+", realDate.getMilliseconds()],
];
var reg1 = regYear.exec(format);
if (reg1) {
format = format.replace(reg1[1], (realDate.getFullYear() +
'').substring(4 - reg1[1].length));
}
for (var i = 0; i < date.length; i++) {
var k = date[i][0];
var k = date[i][1];
var reg2 = getRegExp("(" + k + ")").exec(format);
if (reg2) {
format = format.replace(reg2[1], reg2[1].length = 1 ? v :
("00" + v).substring(("" + v).length));
}
}
return format;
}
module.exports = {
message:message,
add:add,
formatNumber:formatNumber,
toFixed:toFixed,
dateFormat:dateFormat
}
步骤二:导入wxs并使用
<!-- 导入wxs -->
<wxs src="./demo3.wxs" module="info" />
<view>{{info.message}}</view>
<view>加法运算</view>
<view>{{info.add(20,10)}}</view>
<view>格式化小数</view>
<view>{{info.toFixed(20.133,3)}}</view>
<view>格式化时间戳</view>
<view>{{info.formatNumber(1566285608000)}} </view>
引用
WXML 提供两种文件引用方式import和include
- import可以在该文件中使用目标文件定义的template
- include可以将目标文件除了<template><wxs>外的整个代码引入,相当于拷贝到include位置
定义模版
使import导入模版并使用
<import src="../../template/item"/>
<template is="item" data="{{text:'hello'}}"></template>
渲染结果展示
注意:import的作用域:只会import目标文件中定义的template,而不会import目标文件import的template,如C import B,B import A,在C中不能使用A定义的template
使用include导入模板并使用
结果显示
五、WXSS语法
- WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。
- 为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。
wxss与css相比扩展的特性
尺寸单位
- rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
@import "common.wxss";
样式导入
-
使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的相对路径,用“;”表示语句结束
@import "common.wxss";
选择器
全局样式与局部样式
定义在 app.wxss 中的样式为全局样式,作用于每一个页面。在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器。
六、WXS语法
WXS(WeiXin Script)是小程序的一套脚本语言,结合WXML,可以构建出页面的结构。
模块
- 每一个.wxs文件和<wxs>标签都是一个单独的模块。
- 每个模块都有自己独立的作用域。即在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见。
- 一个模块要想对外暴露其内部的私有变量与函数,只能通过module实现
示例
var foo = "'hello world' from comm.wxs";
var bar = function(d) {
return d;
}
//不能简写
module.exports = {
foo: foo,
bar: bar
};
注意:该.wxs文件可以被其他的.wxs文件 或 WXML 中的<wxs>标签引用
module 对象
每个wxs模块均有一个内置的module对象,通过module.exports可以对外共享本模块的私有变量与函数。
module.exports.msg = "some msg";
require函数
在.wxs模块中引用其他wxs文件模块,可以使用require数。
var tools = require("./tools.wxs");
注意:
- 只能引用.wxs文件模块,且必须使用相对路径。
- wxs模块均为单例,wxs模块在第一次被引用时,会自动初始化为单例对象。多个页面,多个地方,多次引用,使用的都是同一个wxs模块对象。
- 如果一个xs模块在定义之后,一直没有被引用,则该模块不会被解析与运行。
<wxs>标签
示例
//类似与script标签
<wxs module="foo">
var some_msg = "hello world";
module.exports = {
msg : some_msg,
}
//外部导入
<wxs src="../../wxs/common.wxs" module="info"></wxs>
</wxs>
//支持响应式数据
<view> {{foo.msg}} </view>
注意:
- <wxs>模块只能在定义模块的WXML文件中被访问到。使用<include>或<import>时,<wxs>模块不会被引入到对应的WXML文件中。
- <template>:标签中,只能使用定义该<template>的WXML文件中定义的<wxs>模块。
变量
- WXS中的变量均为值的引用。
- 没有声明的变量直接赋值使用,会被定义为全局变量。
- 如果只声明变量而不赋值,则默以值为undefined。
- var表现与javascript-一致,会有变量提升。
var foo = 1;
var bar = "hello world";
var i; // i === undefined
运算符
基本运算符
var a = 10, b = 20;
// 加法运算
console.log(30 === a + b);
// 减法运算
console.log(-10 === a - b);
// 乘法运算
console.log(200 === a * b);
// 除法运算
console.log(0.5 === a / b);
// 取余运算
console.log(10 === a % b);
//加法运算(+)也可以用作字符串的拼接
var a = '.w' , b = 'xs';
// 字符串拼接
console.log('.wxs' === a + b);
一元运算符
var a = 10, b = 20;
// 自增运算
console.log(10 === a++);
console.log(12 === ++a);
// 自减运算
console.log(12 === a--);
console.log(10 === --a);
// 正值运算
console.log(10 === +a);
// 负值运算
console.log(0-10 === -a);
// 否运算
console.log(-11 === ~a);
// 取反运算
console.log(false === !a);
// delete 运算
console.log(true === delete a.fake);
// void 运算
console.log(undefined === void a);
// typeof 运算
console.log("number" === typeof a);
位运算符
var a = 10, b = 20;
// 左移运算
console.log(80 === (a << 3));
// 带符号右移运算
console.log(2 === (a >> 2));
// 无符号右移运算
console.log(2 === (a >>> 2));
// 与运算
console.log(2 === (a & 3));
// 异或运算
console.log(9 === (a ^ 3));
// 或运算
console.log(11 === (a | 3));
比较运算符
var a = 10, b = 20;
// 小于
console.log(true === (a < b));
// 大于
console.log(false === (a > b));
// 小于等于
console.log(true === (a <= b));
// 大于等于
console.log(false === (a >= b));
等值运算符
var a = 10, b = 20;
// 等号
console.log(false === (a == b));
// 非等号
console.log(true === (a != b));
// 全等号
console.log(false === (a === b));
// 非全等号
console.log(true === (a !== b));
赋值运算符
var a = 10;
a = 10; a *= 10;
console.log(100 === a);
a = 10; a /= 5;
console.log(2 === a);
a = 10; a %= 7;
console.log(3 === a);
a = 10; a += 5;
console.log(15 === a);
a = 10; a -= 11;
console.log(-1 === a);
a = 10; a <<= 10;
console.log(10240 === a);
a = 10; a >>= 2;
console.log(2 === a);
a = 10; a >>>= 2;
console.log(2 === a);
a = 10; a &= 3;
console.log(2 === a);
a = 10; a ^= 3;
console.log(9 === a);
a = 10; a |= 3;
console.log(11 === a);
二元逻辑运算符
var a = 10, b = 20;
// 逻辑与
console.log(20 === (a && b));
// 逻辑或
console.log(10 === (a || b));
其他运算符
var a = 10, b = 20;
//条件运算符
console.log(20 === (a >= 10 ? a + 10 : b + 10));
//逗号运算符
console.log(20 === (a, b));
语句
if 语句
// if ...
if (表达式) 语句;
if (表达式)
语句;
if (表达式) {
代码块;
}
// if ... else
if (表达式) 语句;
else 语句;
if (表达式)
语句;
else
语句;
if (表达式) {
代码块;
} else {
代码块;
}
// if ... else if ... else ...
if (表达式) {
代码块;
} else if (表达式) {
代码块;
} else if (表达式) {
代码块;
} else {
代码块;
}
switch 语句
switch (表达式) {
case 变量:
语句;
case 数字:
语句;
break;
case 字符串:
语句;
default:
语句;
}
注意:
- default 分支可以省略不写
- case关键词后面只能使用变量,数字,字符串
for 语句
- 支持break和continue
for (语句; 语句; 语句)
语句;
for (语句; 语句; 语句) {
代码块;
}
while 语句
- 当代码块为true时,循环执行语句或代码块
- 支持使用break和continue
while (表达式)
语句;
while (表达式){
代码块;
}
do {
代码块;
} while (表达式)
数据类型
- number:数值
- string:字符串
- boolean:布尔值
- object:对象
- function:函数
- array: 数组
- date:日期
- regexp:正则
number
var a = 10;
var PI = 3.141592653589793;
属性: constructor:返回字符串“Number”
方法名 |
---|
toString |
toLocaleString |
valueOf |
toFixed |
toExponential/ |
string
var a = 10;
var PI = 3.141592653589793;
属性: constructor:返回字符串“String”
方法名 |
---|
toString |
valueof |
charAt |
charCodeAt |
concat |
indexOf |
lastIndexOf |
localeCompare |
match |
replace |
search |
slice |
split |
substring |
toLowerCase |
toLocaleLowerCase |
toUpperCase |
toLocaleUpperCase |
trim |
boolean
- 布尔值只有两个特定的值:true和false
属性:constructor:返回字符串“Boolean”
方法名 | 说明 |
---|---|
toString | 转化为字符串 |
valueOf | 判断值的类型 |
object
- object 是一种无序的键值对
var o = {} //生成一个新的空对象
//生成一个新的非空对象
o = {
'string' : 1, //object 的 key 可以是字符串
const_var : 2, //object 的 key 也可以是符合变量定义规则的标识符
func : {}, //object 的 value 可以是任何类型
};
//对象属性的读操作
console.log(1 === o['string']);
console.log(2 === o.const_var);
//对象属性的写操作
o['string']++;
o['string'] += 10;
o.const_var++;
o.const_var += 10;
//对象属性的读操作
console.log(12 === o['string']);
console.log(13 === o.const_var);
属性:constructor:返回字符串“object”
方法 : 返回字符串“[object object]”
function
//方法 1
function a (x) {
return x;
}
//方法 2
var b = function (x) {
return x;
}
//或
var a = function (x) {
return function () { return x;}
}
var b = a(100);
console.log( 100 === b() );
//function 里面可以使用 arguments 关键词。该关键词目前只支持以下的属性:
//length: 传递给函数的参数个数。
//[index]: 通过 index 下标可以遍历传递给函数的每个参数。
var a = function(){
console.log(3 === arguments.length);
console.log(100 === arguments[0]);
console.log(200 === arguments[1]);
console.log(300 === arguments[2]);
};
a(100,200,300);
属性:
- constructor:返回字符串“Function”
- length:返回函数形参的个数
方法:
- toString:返回字符串“[function Function]”
array
var a = []; //生成一个新的空数组
a = [1,"2",{},function(){}]; //生成一个新的非空数组,数组元素可以是任何类型
属性:
- constructor:返回字符串“Array”
- length:返回数组元素个数
方法名 |
---|
toString |
concat |
join |
pop |
push |
reverse |
shift |
slice |
sort |
splice |
unshift |
indexOf |
lastIndexOf |
every |
some |
forEach |
map |
filter |
reduce |
reduceRight |
date
- 生成date对象需要使用getDate函数
//参数
//milliseconds: 从1970年1月1日00:00:00 UTC开始计算的毫秒数
//datestring: 日期字符串,其格式为:"month day, year hours:minutes:seconds"
getDate()
getDate(milliseconds)
getDate(datestring)
getDate(year, month[, date[, hours[, minutes[, seconds[, milliseconds]]]]])
//示例代码:
var date = getDate(); //返回当前时间对象
date = getDate(1500000000000);
// Fri Jul 14 2017 10:40:00 GMT+0800 (中国标准时间)
date = getDate('2017-7-14');
// Fri Jul 14 2017 00:00:00 GMT+0800 (中国标准时间)
date = getDate(2017, 6, 14, 10, 40, 0, 0);
// Fri Jul 14 2017 10:40:00 GMT+0800 (中国标准时间)
属性:constructor:返回字符串“Date”
方法名 |
---|
toString |
toDateString |
toTimeString |
toLocaleString |
toLocaleTimeString |
valueOf |
getTime |
getFullYear |
getUTCFullYear |
getMonth |
getDate |
getUTCDate |
getDay |
getUTCDay |
getHours |
getUTCHours |
getMinutes |
getUTCMinutes |
getSeconds |
getUTCSeconds |
getMilliseconds |
getUTCMilliseconds |
getTimezoneOffset |
setTime |
setMilliseconds |
setUTCMilliseconds |
setSeconds |
setUTCSeconds |
setMinutes |
setUTCMinutes |
setHours |
setUTCHours |
setDate |
setUTCDate |
setMonth |
setUTCMonth |
setFullYear |
setUTCFullYear |
toUTCString |
toISOString |
toJSON |
regexp
- 生成regexp对象需要使用getRegExp函数
- 参数:
pattern:正则表达式的内容
flags:修饰符、该字段只能包含一些字符(g:global、i:ignoreCase、m:multiline)
getRegExp(pattern[, flags])
基本示例
var a = getRegExp("x", "img");
console.log("x" === a.source);
console.log(true === a.global);
console.log(true === a.ignoreCase);
console.log(true === a.multiline);
属性名 |
---|
constructor |
source |
global |
ignoreCase |
multiline |
lastIndex |
方法名 |
---|
exec |
test |
toString |
数据类型判断
-
constructor:判断数据类型
var number = 10;
console.log( "Number" === number.constructor );
var string = "str";
console.log( "String" === string.constructor );
var boolean = true;
console.log( "Boolean" === boolean.constructor );
var object = {};
console.log( "Object" === object.constructor );
var func = function(){};
console.log( "Function" === func.constructor );
var array = [];
console.log( "Array" === array.constructor );
var date = getDate();
console.log( "Date" === date.constructor );
var regexp = getRegExp();
console.log( "RegExp" === regexp.constructor );
-
typeof:可以区分部分数据类型
var number = 10;
var boolean = true;
var object = {};
var func = function(){};
var array = [];
var date = getDate();
var regexp = getRegExp();
console.log( 'number' === typeof number );
console.log( 'boolean' === typeof boolean );
console.log( 'object' === typeof object );
console.log( 'function' === typeof func );
console.log( 'object' === typeof array );
console.log( 'object' === typeof date );
console.log( 'object' === typeof regexp );
console.log( 'undefined' === typeof undefined );
console.log( 'object' === typeof null );
WXS响应事件 (以官方提供例子为例)
- WXS 运行在视图层(Webview),里面的逻辑毕竟能做的事件比较少,需要有一个机制和逻辑层(App Service)开发者的代码通信,上面的callMethod是 WXS 里面调用逻辑层(App Service)开发者的代码的方法,而WxsPropObserver是逻辑层(App Service)开发者的代码调用 WXS 逻辑的机制
需求:有频繁用户交互的效果在小程序上表现是比较卡顿的,例如页面有 2 个元素 A 和 B,用户在 A 上做 touchmove 手势,要求 B 也跟随移动。
案例:movable-view(可移动的视图容器,在页面中可以拖拽滑动)
touchmove 事件的响应过程为:
- touchmove 事件从视图层(Webview)抛到逻辑层(App Service)
- 逻辑层(App Service)处理 touchmove 事件,再通过 setData 来改变 B 的位置
一次 touchmove 的响应需要经过 2 次的逻辑层和渲染层的通信以及一次渲染,通信的耗时比较大。此外 setData 渲染也会阻塞其它脚本执行,导致了整个用户交互的动画过程会有延迟
使用WXS函数用来响应小程序事件
- 目前只能响应内置组件的事件,不支持自定义组件事件。WXS 函数的除了纯逻辑的运算,还可以通过封装好的ComponentDescriptor实例来访问以及设置组件的 class 和样式
//在wxs中定义一个事件
var wxsFunction = function(event, ownerInstance) {
var instance = ownerInstance.selectComponent('.classSelector') // 返回组件的实例
//设置样式
instance.setStyle({
"font-size": "14px" // 支持rpx
})
instance.getDataset()
instance.setClass(className)
// ...
return false // 不往上冒泡,相当于调用了同时调用了stopPropagation和preventDefault
}
注意:
event是小程序事件对象基础上多了event.instance来表示触发事件的组件的ComponentDescriptor实例。ownerInstance表示的是触发事件的组件所在的组件的ComponentDescriptor实例,如果触发事件的组件是在页面内的,ownerInstance表示的是页面实例
方法名称 | 参数 | 说明 |
---|---|---|
selectComponent | selector对象 | 返回组件的ComponentDescriptor实例 |
selectAllComponents | selector对象数组 | 返回组件的ComponentDescriptor实例数组 |
setStyle | Object/string | 设置组件样式,支持rpx。设置的样式优先级比组件wxml里面定义的样式高。不能设置最顶层页面的样式 |
addClass/removeClass/hasClass | string | 设置组件的 class。设置的 class 优先级比组件 wxml 里面定义的 class 高。不能设置最顶层页面的 class |
getDataset | 无 | 返回当前组件/页面的dataset对象 |
callMethod | (funcName:string, args:object) | 调用当前组件/页面在逻辑层(App Service)定义的函数。funcName表示函数名称,args表示函数的参数 |
requestAnimationFrame | Function | 和原生requestAnimationFrame一样。用于设置动画 |
getState | 无 | 返回一个object对象,当有局部变量需要存储起来后续使用的时候用这个方法 |
triggerEvent | (eventName, detail) | 和组件的triggerEvent一致 |
getComputedStyle | Array.<string> | 参数与SelectQuery的computedStyle一致 |
setTimeout | (Function, Number) | 与原生setTime一致。用于创建定时器 |
clearTimeout | Number | 与原生clearTimeout一致。用于清除定时器 |
getBoundingClientRect | 无 | 返回值与与SelectorQuery的boundingClientRect一致 |
在WXML中定义事件
<wxs module="test" src="./test.wxs"></wxs>
//change:prop(属性前面带change:前缀)是在 prop 属性被设置的时候触发 WXS 函数,值必须用{{}}括起来。类似 Component 定义的 properties 里面的 observer 属性,在setData({propValue: newValue})调用之后会触发
<view change:prop="{{test.propObserver}}" prop="{{propValue}}" bindtouchmove="{{test.touchmove}}" class="movable"></view>
注意:WXS函数必须用{{ }}括起来。当 prop 的值被设置 WXS 函数就会触发,而不只是值发生改变,所以在页面初始化的时候会调用一次WxsPropObserver的函数
定义并导出WXS中的时间处理函数和属性改变触发的函数
module.exports = {
touchmove: function(event, instance) {
console.log('log event', JSON.stringify(event))
},
propObserver: function(newValue, oldValue, ownerInstance, instance) {
console.log('prop observer', newValue, oldValue)
}
}
Tips:
- 目前还不支持原生组件的事件、input和textarea组件的 bindinput 事件
- 目前在WXS函数里面仅支持console.log方式打日志定位问题,注意连续的重复日志会被过滤掉
七、事件
- 事件是视图层到逻辑层的通讯方式
- 事件可以将用户的行为反馈到逻辑层进行处理。
- 事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
- 事件对象可以携带额外信息,如 id, dataset, touches。
绑定事件与事件交互
绑定事件
- 法一:bind+事件名
- 法二:bind:事件名
//wxml
//绑定了changeDate、tmove、lpress事件,
<button bind:touchstart="changeDate" bindtouchend="tmove" bind:longpress="lpress">改变数据</button>
事件交互
//wxml
<button bind:touchstart="changeDate" bind:touchend="tmove" bind:longpress="lpress">改变数据</button>
//wxs
Page({
data:{},
//点击事件
changeDate:function(){
this.setData({textStr:"Hello 你好"})
},
//触摸移动
tmove:function(){
console.log("touchend");
//弹窗用于调试
wx.showToast({
title: '成功',
icon: 'success',
duration: 2000
})
},
//长按触发
lpress:function(){
console.log("longpress");
}
})
事件冒泡和捕获
事件分类
事件分为冒泡事件和非冒泡事件:
- 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
- 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递
事件名称 | 说明 |
---|---|
touchstart | 手指触摸动作开始 |
touchmove | 手指触摸后移动 |
touchcancel | 手指触摸动作被打断,如来电提醒,弹窗 |
touchend | 手指触摸动作结束 |
tap | 手指触摸后马上离开 |
longpress | 手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发 |
longtap | 手指触摸后,超过350ms再离开(推荐使用longpress事件代替) |
transitionend | 会在 WXSS transition 或 wx.createAnimation 动画结束后触发 |
animationstart | 会在一个 WXSS animation 动画开始时触发 |
animationiteration | 会在一个 WXSS animation 一次迭代结束时触发 |
animationend | 会在一个 WXSS animation 动画完成时触发 |
touchforcechange | 在支持 3D Touch 的 iPhone 设备,重按时会触发 |
注意: 除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如from的submit事件,input的input事件,scroll-view的scroll事件这些都是非冒泡事件
绑定并阻止事件冒泡
- 除bind外,也可以用catch来绑定事件。
- 与bind不同,catch会阻止事件向上冒泡。
<view id="outer" bindtap="handleTap1">
outer view
<view id="middle" catchtap="handleTap2">
middle view
<view id="inner" bindtap="handleTap3">
inner view
</view>
</view>
</view>
说明:点击 inner view 会先后调用handleTap3和handleTap2(因为tap事件会冒泡到 middle view,而 middle view 阻止了 tap 事件冒泡,不再向父节点传递),点击 middle view 会触发handleTap2,点击 outer view 会触发handleTap1。
互斥事件绑定
- 除bind和catch外,还可以使用mut-bind来绑定事件
- 一个mut-bind触发后,如果事件冒泡到其他节点上,其他节点上的mut-bind绑定函数不会被触发,但bind绑定函数和catch绑定函数依旧会被触发。即所有mut-bind是“互斥”的,只会有其中一个绑定函数被触发。同时,它完全不影响bind和catch的绑定效果
<view id="outer" mut-bind:tap="handleTap1">
outer view
<view id="middle" bindtap="handleTap2">
middle view
<view id="inner" mut-bind:tap="handleTap3">
inner view
</view>
</view>
</view>
说明:点击 inner view 会先后调用handleTap3和handleTap2,点击 middle view 会调用handleTap2和 handleTap1。
事件的捕获阶段
- 触摸类事件支持捕获阶段。捕获阶段位于冒泡阶段之前,且在捕获阶段中,事件到达节点的顺序与冒泡阶段恰好相反。需要在捕获阶段监听事件时,可以采用
capture-bind
、capture-catch
关键字,后者将中断捕获阶段和取消冒泡阶段。
示例:
正常捕获冒泡:
<view id="outer" bind:touchstart="handleTap1" capture-bind:touchstart="handleTap2">
outer view
<view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
inner view
</view>
</view>
说明:在下面的代码中,点击 inner view 会先后调用handleTap2、handleTap4、handleTap3、handleTap1。
中断捕获阶段和取消冒泡阶段:
<view id="outer" bind:touchstart="handleTap1" capture-catch:touchstart="handleTap2">
outer view
<view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
inner view
</view>
</view>
说明: 将正常捕获冒泡代码中的第一个capture-bind改为capture-catch,将只触发handleTap2。
事件对象
八、微信小程序组件
组件这块,只写一些基本组件,一些其他的组件可以直接查阅微信小程序组件文档(太多了参数属性了,手写个人感觉不全面,所以请大家自行查阅官方文档)
基本组件
icon(图标组件)
属性说明
属性 | 说明 |
---|---|
type | icon的类型,有效值:success, success_no_circle, info, warn, waiting, cancel, download, search, clea |
size | icon的大小,默认大小为23,单位默认为px |
color | icon的颜色,同css的color |
<icon type="warn" size="100rpx" color="red"/>
progress (进度条组件)
- 进度条。组件属性的长度单位默认为px
<progress percent="30" show-info="true" border-radius="10" stroke-width="50rpx" activeColor="red" backgroundColor="#000" active="true"></progress>
属性说明:
属性 | 类型 | 说明 |
---|---|---|
percent | number | 百分比0~100 |
show-info | boolean | 在进度条右侧显示百分比,默认false |
border-radius | number/string | 圆角大小,默认0 |
font-size | number/string | 右侧百分比字体大小,默认16 |
stroke-width | number/string | 进度条线的宽度,默认6 |
color | string | 进度条颜色(请使用activeColor),默认#09BB07 |
activeColor | string | 已选择的进度条的颜色,默认#09BB07,默认#EBEBEB |
backgroundColor | string | 未选择的进度条的颜色,默认false |
active | boolean | 进度条从左往右的动画,默认backwards |
active-mode | string | backwards: 动画从头播;forwards:动画从上次结束点接着播 |
duration | number | 进度增加1%所需毫秒数,默认30 |
bindactiveend | eventhandle | 动画完成事件 |
渲染展示 :
rich-text(渲染html内容组件)
- 作用:富文本解析展示
属性 | 说明 |
---|---|
nodes | 节点列表/HTML String |
space | 显示连续空格 |
user-select | 文本是否可选,该属性会使节点显示为block |
nodes属性说明
- nodes支持两种节点,通过type区分
属性 | 说明 |
---|---|
name | 标签名 |
attrs | 属性 |
children | 子节点列表 |
属性 | 说明 |
---|---|
text | 文本 |
text(文本组件)
- 该属性会使文本节点显示为 inline-block
属性 | 说明 |
---|---|
user-select | 文本是否可选,该属性会使文本节点显示为inline-block |
表单常用组件
组件说明
组件名称 | 说明 |
---|---|
button | 按钮 |
checkbox-group | 多项选择器,内部由多个checkbox组成 |
checkbox | 多选项目,放在checkbox-group内部 |
editor | 富文本编辑器 |
form | 表单 |
input | 输入框 |
label | 改进表单组件的可用性 |
radio | 单选框(由radio-group包裹) |
radio-group | 单选框组(里面嵌套多个radio) |
textarea | 多行文本输入框 |
keyboard-accessory | 设置 input / textarea 聚焦时键盘上方 cover-view / cover-image 工具栏视图 |
picker | 从底部弹起的滚动选择器 |
picker-view | 嵌入页面的滚动选择器。其中只可放置picker-view-column组件,其它节点不会显示 |
picker-view-column | 滚动选择器子项。仅可放置于picker-view中,其孩子节点的高度会自动设置成与picker-view的选中框的高度一致 |
slider | 滑动选择器 |
switch | 开关选择器 |
表单组件提交获取信息案例
- 结果展示(当点击提交时可在控制台输出表单收集到的数据)
- 实现代码
//wxml
<!-- 表单 -->
<!-- bindreset:重置触发的事件 -->
<form bindsubmit="handleSubmit" bindreset="handelReset">
<view>
<text>name:</text>
<input type="text" name="" id="" placeholder="请输入姓名" bind:blur="handleBlur" />
</view>
<view>
<text>age:</text>
<input type="text" name="" id="" placeholder="请输入年龄" bind:blur="handleBlurAge" />
</view>
<!-- bindchange:用于收集radio-group数据 -->
<radio-group bindchange="handlechange">
<label for="boy">
<radio value="boy" />男
</label>
<label for="girl">
<radio value="girl" />女
</label>
<label for="unKown">
<radio value="unKown" checked />保密
</label>
</radio-group>
<checkbox-group bindchange="handlechangeMajor">
<label for="">
<checkbox value="vue" checked />Vue
<checkbox value="react" checked />React
<checkbox value="app" />App
</label>
<!-- 文本输入 -->
<text>description:</text>
<textarea value="" placeholder="请输入您的信息" bind:blur="handleBlurDesc" />
</checkbox-group>
<view style="margin: 20rpx;">
<button form-type="submit">提交</button>
<button form-type="reset">重置</button>
</view>
</form>
//js,wxss
Page({
/**
* 页面的初始数据
*/
data: {
name:"",
gerder:"",
Major:[],
desc:" "
},
// e为事件对象
handleBlur:function(e){
this.setData({
name:e.detail.value
})
},
handleBlurAge:function(e){
this.setData({
age:e.detail.value
})
},
handleSubmit(){
console.log(this.data);
},
handelReset(e){
console.log(e);
},
handlechange(e){
this.setData({gerder:e.detail.value})
},
handlechangeMajor(e){
this.setData({Major:e.detail.value})
},
handleBlurDesc(e){
console.log(e.detail.value);
this.setData({
desc:e.detail.value
})
},
})
视图容器
组件说明
组件名称 | 说明 |
---|---|
swiper | 滑块视图容器。其中只可放置swiper-item组件,否则会导致未定义的行为。 |
swiper-item | 仅可放置在swiper组件中,宽高自动设置为100% |
scroll-view | 可滚动视图区域 |
cover-image | 覆盖在原生组件之上的图片视图 |
cover-view | 覆盖在原生组件之上的文本视图 |
match-media | media query 匹配检测节点。可以指定一组 media query 规则,满足时,这个节点才会被展示 |
movable-area | movable-view的可移动区域 |
movable-view | 可移动的视图容器,在页面中可以拖拽滑动。movable-view必须在movable-area组件中,并且必须是直接子节点,否则不能移动 |
page-container | 页面容器 |
root-portal | 使整个子树从页面中脱离出来,类似于在 CSS 中使用 fixed position 的效果。主要用于制作弹窗、弹出层等 |
view | 视图容器 |
轮播图案例(通过案例学习swiper相关属性)
- 目标结果(图片实现自动轮播,且可以通过属性切换横向和纵向)
- 代码实现及说明
//wxml
<!-- autoplay:是否自动播放,interval:滑动的间隔时间, duration:每次滑动的时间,indicator-dots:显示图片圆点预览,indicator-active-color:圆点的颜色,vertical:纵向滑动,circular:单向循环滑动,vertical circular display-multiple-items:一个界面显示图片的数量 -->
<swiper autoplay interval="500" duration="1000" indicator-dots indicator-active-color="#007aff" vertical circular display-multiple-items="2">
<swiper-item wx:for="{{images}}" wx:for-index="dbs">
<image src="{{item}}" mode=""/>
</swiper-item>
</swiper>
//js,wxss
Page({
data: {
images:[ '../../images/123.png','../../images/21212121.png','../../images/123.png']
},
})
注意:这里data里的images中是图片的地址,需要换成自己的图片地址
可滚动视图案例
- 目标结果(在指定区域内可滚动图片,且点击按钮回到指定页面)
- 代码实现
//wxml
<!-- scroll-view:可滚动视图 -->
<!-- 横向滑动 -->
<!-- <scroll-view scroll-x="{{true}}"
style="display: flex;white-space: nowrap;">
<block wx:for="{{imgs}}">
<image src="{{item}}" alt=""/>
</block>
</scroll-view> -->
//案例为模式二,横向滑动可作为学习参考
<!-- 模式二:在某个范围内滑动 -->
<!-- bindscrolltoupper:滑动到顶部触发的事件 -->
<!-- indscrolltolower:滑动到底部触发的事件 -->
<!-- scroll-into-view: 值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素 -->
<scroll-view scroll-y="{{true}}"
scroll-top="200" style="height: 800rpx;"
bindscrolltoupper="upper"
bindscrolltolower="lower"
scroll-into-view="{{toView}}">
<block wx:for="{{imgs}}">
<image src="{{item}}" id="{{'img'+index}}"/>
</block>
</scroll-view>
<button bind:tap="gotoview">回到顶部</button>
//js,wxss
Page({
/**
* 页面的初始数据
*/
data: {
imgs: [
'/images/123.png',
'/images/QQ图片20230223182711.jpg',
'/images/QQ图片20230223182711.jpg',
'/images/QQ图片20230223182711.jpg',
'/images/QQ图片20230223182711.jpg',
],
toView:'img1'
},
upper(){
console.log("upper");
},
lower(){
console.log("lower");
},
gotoview(){
this.setData({
toView:"img1"
})
},
})
注意:这里data里的imgs为图片地址,需要自行修改成自己图片的地址
横向滚动视图案例
- 目标结果(可实现标题栏的横向滑动,且自动将选中的标题居中显示)
- 代码实现
//wxml
<!-- data-c:data-后面跟数据属性名,可通过事件对象获取 -->
<scroll-view scroll-x="{{true}}" class="nav" scroll-left="{{navScrollLeft}}">
<block wx:for="{{navData}}" wx:key="index">
<view class="nav_item {{currentNav==index?'active':''}}" bind:tap="switchNav" data-c="{{index}}">{{item.text}}</view>
</block>
</scroll-view>
//wxss
Page({
data: {
navData:[
{
text:"首页"
},
{
text:"商品"
},
{
text:"地址"
},
{
text:"配送"
},
{
text:"GO"
},
{
text:"我的"
},
],
currentNav:0,
navScrollLeft:0
},
switchNav(e){
let singleWitdh = this.data.windowWidth /5
this.setData({
currentNav:e.currentTarget.dataset.c,
navScrollLeft:(e.currentTarget.dataset.c-2)*singleWitdh
})
},
onLoad(options) {
// 获取系统信息
wx.getSystemInfo({
success:(res)=>{
// 获取设备宽度
// console.log(res.windowWidth);
this.setData({
windowWidth:res.windowWidth
})
}
})
},
})
媒体组件
组件说明
组件名称 | 说明 |
---|---|
audio | 音频 |
camera | 系统相机 |
channel-live | 小程序内嵌视频号直播组件,展示视频号直播状态和封面,并无弹窗跳转至视频号 |
channel-video | 小程序内嵌视频号视频组件,支持在小程序中播放视频号视频,并无弹窗跳转至视频号 |
image | 图片。支持 JPG、PNG、SVG、WEBP、GIF 等格式 |
live-player | 实时音视频播放 |
live-pusher | 实时音视频录制 |
video | 视频 |
voip-room | 多人音视频对话 |
媒体组件案例---音频组件
- 目标结果(显示音频名称,作者,可以点击播放)
- 实现代码
//wxml
<!-- controls:播放器的控制台,name:歌曲名称,author:歌曲作者,poster:音乐封面图片 -->
<audio src="{{audio.audiosrc}}" poster="{{audio.Imageposter}}" controls="{{true}}"
name="{{audio.name}}" author="{{audio.author}}" ></audio>
//js,wxss
Page({
/**
* 页面的初始数据
*/
data: {
audio: {
name: "飞-致我们的星辰大海",
Imageposter: 'https://y.qq.com/music/photo_new/T002R300x300M000004fwlJg0Yug9n_2.jpg?max_age=2592000',
author: "璨乐团",
audiosrc: "/audio/璨乐团 - 飞-致我们的星辰大海.mp3"
},
}
})
媒体组件案例---视频组件
画图组件
组件说明
组件名称 | 说明 |
---|---|
canvas | 画布 |
画图组件案例
- 目标结果(在画布中显示两个方块)
- 代码实现
//wxml
<view class="container">
<!-- 注意画布的长宽比尽量是1:1才能正常使用 -->
<!-- type的值可以是2d,也可以是3d,id用于给js文件获取画布 -->
<canvas type="2d" id="mycanvas" class="canvas_container" />
</view>
//js,wxss
Page({
data: {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
//创建画布
wx.createSelectorQuery()
// 获取画布的id
.select('#mycanvas')
// 设置节点,大小
.fields({
node:true,
size:true
})
// 设置画布
.exec((res)=>{
console.log(res[0]);
console.log(res[0].node);
// 获取画布的节点
const canvas = res[0].node
const ctx = canvas.getContext('2d')
const width = res[0].width
const height = res[0].height
// 清空画布
ctx.clearRect(0,0,width,height)
// 画个图
ctx.fillStyle = 'rgb(200,0,0)'
ctx.fillRect(10,10,50,50)
ctx.fillStyle = 'rgb(0,0,200,0.5)'
ctx.fillRect(30,30,50,50)
})
},
})
其他组件
标签名称 | 说明 |
---|---|
functional-page-navigator | 仅在插件中有效,用于跳转到插件功能页 |
navigator | 页面链接 |
标签名称 | 说明 |
---|---|
map | map组件提供了地图展示、交互、叠加点线面及文字等功能,同时支持个性化地图样式,可结合地图服务 API 实现更丰富功能 |
九、自定义组件间及其配置
自定义组件
- 在全局下创键compontents文件夹,在里面新建component作为组件,并在wxml里输入组件内容
- 在要使用组件的页面的json中配置组件
- 在page的wxml中按照注册的组件名导入组件
- 效果
- 如果是全局组件就可以在app.json中定义组件
父组件向子组件传递数据
插槽
- 默认插槽
//默认插槽
<mycom>
<!-- 插槽:默认插槽直接在组件标签内部写内容 -->
1234344
</mycom>
//使用插槽
//mycom组件的wxml文件里使用
<view>
<!-- 插槽:默认 -->
<!-- <slot></slot> -->
</view>
- 多个插槽
//使用多个插槽,
<mycom>
<!-- 插槽 -->
1234344
<!-- 使用多个插槽 -->
<view slot="slot1">slot1 123</view>
<view slot="slot1">slot2 456</view>
</mycom>
//多个插槽需要在自定义组件中的js文件进行配置
Component({
/**
* 组件的属性列表
*/
options:{
multipleSlots:true
}
})
//在mycom组件的wxml中使用多个插槽
<view>
<!-- 插槽:默认 -->
<!-- <slot></slot> -->
<!-- 多个插槽 -->
<slot name="slot1"></slot>
<slot name="slot2"></slot>
</view>
注意:多个插槽是根据name标签来区分内容的
组件样式隔离、共享
//组件的js文件
Component({
/**
* 组件的属性列表
*/
options:{
multipleSlots:true,
// styleIsolation:"isolated" //页面 和 组件的样式隔离
// styleIsolation:"shared" //页面 和 组件的样式共享
// styleIsolation:"apply-shared" //页面的样式传给组件,且组件可以保留自己的样式
}
})
组件间传递值和样式
- 传递值
//在父组件中向子组件传递title值
<mycom dataA="{{title}}"></mycom>
//父组件js文件
data: {
title:"页面的传递的title"
},
//子组件接收父组件传过来的值并设置默认值
properties: {
dataA:{
type:String,
//当父组件没有传递值的时候子组件wxml获取到的就是这个默认值
value:"默认标题"
}
},
//在子组件的wxml中使用title值
<text>{{dataA}}</text>
- 传递样式
//在父组件中传递样式
<mycom my-class="red"></mycom>
//父组件wxss
.red{
color:red;
}
//在子组件js文件获取从父组件传递过来的样式
externalClasses:['my-class'],
//在子组件wxml中使用传递过来的样式
<view class="my-class"></view>
组件事件的传递
//父组件wxml使用子组件
<view><com_demo2 bind:search="search"></com_demo2></view>
//父组件js文件定义事件
search(){
console.log("search");
},
//子组件wxml的事件
<input type="text" placeholder="search" bind:confirm="getSearchText"/>
//子组件js文件
methods: {
getSearchText(e){
console.log(e.detail.value);
//在子组件中调用了父组件的方法
this.triggerEvent("search")
},
}
父组件获取子组件数据及方法
通过id获取子组件中的数据和方法(selectComponent)
//父组件的wxml
<view class="container">
<button bind:tap="count">计数</button>
<compontents12 id="mycount"></compontents12>
</view>
//子组件的wxml
<view>
<text>{{count}}</text>
</view>
//子组件的js文件
data: {
count:1
},
methods: {
innercount:function(){
this.setData({
count:this.data.count+1
})
},
},
//父组件获取子组件的data数据和methods方法
count:function(e){
console.log(this.selectComponent("#mycount").data); //获取子组件中的data数据
this.selectComponent("#mycount").innercount() //调用子组件中的方法
},
组件的生命周期
定义组件生命周期
//组件的js文件
Component({
lifetimes: {
attached: function() {
// 在组件实例进入页面节点树时执行
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
},
// 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
attached: function() {
// 在组件实例进入页面节点树时执行
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
})
生命周期 | 说明 |
---|---|
created | 在组件实例刚刚被创建时执行 |
attached | 在组件实例进入页面节点树时执行 |
ready | 在组件在视图层布局完成后执行 |
moved | 在组件实例被移动到节点树另一个位置时执行 |
detached | 在组件实例被从页面节点树移除时执行 |
error | 每当组件方法抛出错误时执行 |
定义组件所在页面的生命周期
Component({
pageLifetimes: {
show: function() {
// 页面被展示
},
hide: function() {
// 页面被隐藏
},
resize: function(size) {
// 页面尺寸变化
}
}
})
生命周期 | 说明 |
---|---|
show | 组件所在的页面被展示时执行 |
hide | 组件所在的页面被隐藏时执行 |
resize | 组件所在的页面尺寸变化时执行 |
routeDone | 组件所在页面路由动画完成时执行 |
组件属性监听
单个监听(observer)
- 在子组件接收父组件传递的数据的时候进行监听,可以监听到数据新值和旧值还有传数据的名称
properties: {
count1: {
type: Number,
value: 0,
observer: function (newvalue, oldvalue, change) {
console.log(newvalue, oldvalue, change);
}
},
},
多个监听(observers)
//子组件js文件
observers:{
// 同时监听两个数据
"count1,count2":function(n1,n2){
// 监听数据的新值
console.log(n1,n2);
this.setData({
sum:n1+n2
})
}
},
组件案例
目标结果:page tag为父组件,抽离tab栏为子组件,使得点击tab栏标题传递到父组件使得page tag显示点击的那个标题
步骤一:创建page页面及子组件
文件结构:
compontents
|——demo1-com(子组件)
|
pages
|
|——demo1(父页面)
//demo1.json
{
"usingComponents": {
//引入子组件
"compontents":"/compontents/demo1-com/demo1-com"
}
}
步骤二:完成基本架构
//demo1.wxml
<view>
//定义标题
<view>page tag:{{tag}}</view>
//使用子组件,并将父组件中的tabs传入子组件中遍历
<compontents tabs="{{tabs}}"></compontents>
</view>
//demo1.js
//定义数据
data: {
tag:"",
tabs:["推荐","体育","新闻","媒体"],
},
//demo1-com.wxml
<view class="tab-box">
<block wx:for="{{tabs}}" wx:key="index">
<view class="tab-item"><text>{{item}}</text></view>
</block>
</view>
//demo1-com.js
//定义选中标题的索引
data: {
currindex:0,
},
步骤三:在父页面完成相关css样式,并传入子组件
//demo1.wxss
//在父页面定义css样式
//盒子样式
.tab-box{
display: flex;
height: 100rpx;
line-height: 100rpx;
background-color: lightgray;
}
//盒子样式
.tab-item{
flex: 1;
text-align: center;
}
//点击时的样式
.active{
color: red;
}
//在demo1.wxml中向子组件传入样式
<view>
<view>page tag:{{tag}}</view>
<compontents tabs="{{tabs}}" tab-box="tab-box" tab-item="tab-item" active="active"></compontents>
</view>
//在子组件中接收样式
//demo1-com.js
externalClasses:["tab-box","tab-item","active"],
步骤四:定义点击事件,实现点击标题css样式切换
//demo1-com.wxml
<view class="tab-box">
<block wx:for="{{tabs}}" wx:key="index">
//使用"data-"定义index数据,并定义一个名称叫clickchange的点击事件
//在class中使用三元判断是否触发选中的Css样式
<view class="tab-item {{currindex==index?'active':''}}" data-index="{{index}}" bind:tap="clickchange"><text>{{item}}</text></view>
</block>
</view>
//dem1-com.js
//
methods: {
clickchange:function(e){
this.setData({
//通过event事件参数获取定义的index值并赋给data中的currindex
currindex:e.currentTarget.dataset.index
})
}
}
步骤五:将触发点击事件的标题的索引传递给父页面获取显示,这是第一种方法
//demo1.js
//在父页面定义事件
tagClick:function(e){
},
//demo1.wxml
<view>
<view>page tag:{{tag}}</view>
//将定义的事件传递给子组件
<compontents bind:tagClick="tagClick" tab-box=" tab-box" tab-item="tab-item" active="active" tabs="{{tabs}}"></compontents>
</view>
//demo1-com.js
methods: {
clickchange:function(e){
this.setData({
currindex:e.currentTarget.dataset.index
})
//调用父页面传到子组件的事件,并将点击标题的索引以index为键传递给父页面
this.triggerEvent('tagClick',{
index:this.data.currindex
})
}
}
//demo1.js
//使用在父页面中定义的事件获取子组件返回来的index下标并在tabs中选取值赋给tag从而显示到页面
tagClick:function(e){
console.log(e);
this.setData({
tag:this.data.tabs[e.detail.index]
})
第二种方法类似,只是在子组件中就通过索引获取到点击的标题再传给父页面显示
十、微信小程序API
页面跳转
-
法一:使用navigator
页面跳转
<navigator url="要跳转到的页面地址">页面跳转</navigator>
//返回上一个页面
<navigator open-type="navigateBack">返回上一个页面</navigator>
获取参数
//页面跳转时发送一个get请求的地址
<navigator url="../demo10/demo10?id=1&name=jack">页面跳转</navigator>
//获取get请求的参数(在跳转后的页面的js文件的监听页面加载的生命周期函数中获取参数)
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
//获取参数
console.log(options);
},
-
法二: 使用wx内置API(wx.navigateTo)
页面跳转
//在wxml中定义一个点击事件
<text bind:tap="gosort">sort page</text>
gosort:function(){
wx.navigateTo({
//定义跳转的页面地址
url: '/pages/demo1/demo1',
//成功后执行的函数
success:function(){
console.log("sucess");
}
})
},
页面返回
//wxml 定义一个点击事件
<view class="box_bottom"><button bind:tap="goback">返回</button></view>
//定义一个返回的参数
goback(){
// 增量2(一次返回2层)
wx.navigateBack({
delta:2
})
}
页面重定向
- 跳转后销毁当前页面
//在wxml定义点击事件
<text bind:tap="redirect">页面重定向</text>
//js
redirect:function(){
//重定向
wx.redirectTo({
url: '../demo10/demo10',
})
},
底部标签
- 底部标签显示及跳转
//在app.json中配置
"tabBar": {
"list": [
{
"pagePath":"pages/index/index",
"text":"首页"},
{
"pagePath":"pages/demo3/demo3",
"text":"分类"},
{
"pagePath":"pages/demo9/demo9",
"text":"个人"}
]
},
- 返回指定Tab页面
wx.switchTab({
url: '../demo2/demo2',
})