一、小程序逻辑层
1.概述
在 JavaScript
的基础上,我们增加了一些功能,以方便小程序的开发:
- 增加
App
和Page
方法,进行程序注册和页面注册。 - 增加
getApp
和getCurrentPages
方法,分别用来获取App
实例和当前页面栈。 - 提供丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力。
- 提供模块化能力,每个页面有独立的作用域。
注意:小程序框架的逻辑层并非运行在浏览器中,因此 JavaScript
在 web 中一些能力都无法使用,如 window
,document
等。
2.App注册小程序实例
在app.js中 调用app({}),接收一个对象,可以定义生命周期,自定义函数,自定义全局变量,监听函数等
2.1生命周期
/**
* 当小程序初始化完成时,会触发onLaunch(全局只触发一次)
*/
onLaunch: function () {
console.log('onLaunch');
},
/**
* 当小程序启动,或从后台进入前台显示,会触发 onShow
*/
onShow: function (options) {
console.log('onShow');
},
/**
* 当小程序从前台进入后台,会触发 onHide
*/
onHide: function () {
console.log('onHide');
},
2.2监听函数
/**
* 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
*/
onError: function (msg) {
console.log('onError',msg);
},
// 页面不存在 监听
onPageNotFound:function(){
console.log('onPageNotFound');
// 重定向 跳转404
wx.redirectTo({
url: './pages/page404/page404',
})
},
2.3any属性
用 this 去访问自定义全局变量 、全局方法
// 全局变量
globalData:{
name:"赵四"
},
// 全局方法
fun(){
return "在跑步"
},
/**
* 当小程序启动,或从后台进入前台显示,会触发 onShow
*/
onShow: function (options) {
console.log('onShow');
// 用this去访问自定义全局变量 全局方法
console.log(this);
console.log(this.globalData);
let txt = this.fun()
console.log(this.globalData.name + txt);
}
2.4在page页面获取应用实例
index.js
// 在页面 获取全局唯一app实例,利用getApp方法
let app = getApp()
console.log(app);
3.注册页面page
3.1注册page
在XX.js 调用 Page( { }) 接收一个对象,在这个里面可以指定页面的初始数据,生命周期,事件处理函数等
3.2data属性
//数据绑定
<view>{{msg}}</view>
/**
* 页面的初始数据,都是在这个里面去定义
*/
data: {
msg:"一寸光阴一寸金"
},
onShow: function () {
// 1)获取data数据
console.log(this.data.msg);
// 2)修改data里边的数据
// 第一种:修改js的值,不会同步页面
this.data.msg = "寸金难买寸光阴"+"123"
this.setData({
msg:this.data.msg
})
// 第二种:修改js的值,并且可以重新渲染到页面
// this.setData({
// msg:"寸金难买寸光阴"
// })
}
3.3生命周期
/**
* 生命周期函数--监听页面加载,只加载一次
*/
onLoad: function (options) {
console.log('onLoad');
// 重定向,关闭当前页面,跳转其他页面
wx.redirectTo({
url: '../list/list',
})
},
/**
* 生命周期函数--监听页面初次渲染完成,只加载一次
*/
onReady: function () {
console.log('onReady');
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
console.log('onShow');
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
console.log('onHide');
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
// 页面关闭
console.log('onUnload');
},
3.4其他函数
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
console.log('onPullDownRefresh下拉刷新');
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
console.log('onReachBottom 上拉触底');
// this.page++;
// 重新请求
// 新老数据拼接
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
// 逻辑
},
// 分享到朋友圈
onShareTimeline:function(){
},
// 页面滚动 监听
onPageScroll(){
console.log('滚动');
this.fun()
},
// 自定义函数
fun(){
console.log('在跑步');
}
二、视图层
框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示。
将逻辑层的数据反映成视图,同时将视图层的事件发送给逻辑层。
WXML(WeiXin Markup language) 用于描述页面的结构。
WXSS(WeiXin Style Sheet) 用于描述页面的样式。
组件(Component)是视图的基本组成单元。
1.wxml语法
1.1数据绑定
<!-- 数据 内容的绑定 -->
<view>{{msg}}</view>
<!-- 属性绑定 -->
<view id="id{{idname}}">属性绑定</view>
<!-- 关键字绑定 true false -->
<view hidden="{{false}}">关键字绑定</view>
<view hidden="{{true}}">关键字绑定2</view>
<!-- 三目运算 -->
<view>{{5>3 ? "真" : "假"}}</view>
<!-- 算术运算 -->
<view>{{ 1+1 }}</view>
<!-- 字符串运算 -->
<view>{{ 2+1+"1"+2 }}</view>
<!--路径运算 数组 对象-->
<view>{{arr[2]}}</view>
<!--路径运算 对象-->
<view>{{obj.name}}</view>
Page({
/**
* 页面的初始数据,数据都定义在这个里面
*/
data: {
msg:"今天天气很热",
idname:"box",
arr:[1,2,3],
obj:{
name:"张三"
}
},
1.2列表渲染
在vue中,数据的渲染:
v-for="(item,index) in arr"
微信小程序中数据的渲染:
wx:for="{{}}"
在这里,默认循环项 item , 默认下标 index
要是我们需要修改默认值:
wx:for-item=“val”
wx:for-index=“ind”
wx:key
<!-- 列表循环 wx:for="" -->
<view wx:for="{{arr}}">
{{index}}----{{item}}
</view>
<view wx:for="{{obj}}">
{{index}}----{{item}}
</view>
<!-- 修改默认值item index -->
<view wx:for="{{arr}}" wx:for-item="val" wx:for-index="ind">
{{item}}--{{val}}---{{ind}}
</view>
<!-- wx:key
使用场景:
循环的列表是静态的情况,或者是忽略顺序 可以忽略警告
循环的列表是动态的情况,必须添加
取值:
1)*this 代表的循环项 本身的值
循环项本身唯一,string number
2) item 中唯一的属性
-->
<view>
<switch wx:for="{{arr2}}" wx:key="*this"></switch>
<button bindtap="_add">添加一个开关</button>
</view>
<view wx:for="{{list}}" wx:key="id">
{{index}}--{{item.id}}--{{item.name}}
</view>
data: {
arr:[1,2,3],
obj:{
name:"李四",
age:"40"
},
item:"abc",
arr2:[1,2,3,4],
list:[
{
id:1,
name:"王昭君"
},
{
id:2,
name:"后羿"
}
]
},
_add(){
let len = this.data.arr2.length
len = len+1
// 往前边添加一个开关
this.data.arr2.unshift(len)
console.log(this.data.arr2);
this.setData({
arr2:this.data.arr2
})
}
1.3条件渲染
wx:if=“ ” 在切换时销毁或重新渲染
<!-- 条件渲染 -->
<!-- wx:if 真则渲染,假则不渲染-->
<view wx:if="{{age>18}}">成年</view>
<!-- wx:if wx:else -->
<view wx:if="{{age>18}}">成年</view>
<view wx:else>未成年</view>
<!-- wx:if wx:elif wx:else -->
<view wx:if="{{age>18}}">成年</view>
<view wx:elif="{{age<=18 && age>14}}">青少年</view>
<view wx:else>未成年</view>
<!-- v-show -->
<view hidden="{{true}}">锄禾日当午</view>
<view hidden="{{false}}">汗滴禾下土</view>
总结:wx:if vs hidden
wx:if===》为真 渲染模块 为假 销毁模块
hidden===》为真 css隐藏 为假 css显示
一般来说,wx:if有更高的切换消耗而hidden有更高的初始渲染消耗。
因此,如果需要频繁切换的情景下,用hidden更好,如果在运行时条件不大可能改变则 wx:if 较好。
block 包装元素,不会在页面中做任何渲染
<!-- 它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性 -->
<block wx:if="{{true}}">
<view> view1 </view>
<view> view2 </view>
</block>
<block wx:for="{{[1, 2, 3]}}">
<view> {{index}}: </view>
<view> {{item}} </view>
</block>
1.4模板/引用
1.4.1 模板:
1.定义模板 template name=" "
<template name="temp2">
<view>李四</view>
</template>
2.使用模板 template is=" "
<!-- 使用模板 -->
<template is="temp1"></template>
1.4.2 引用文件
import 引用
<!--引用文件--模板
import 只引用模板内容
-->
<import src="../../common/common.wxml"></import>
<!-- 使用模板 -->
<template is="temp1"></template>
include引用
<!-- 引用文件--除了模板外其他的内容
复制了引用的文件的内容
-->
<include src="../../common/common.wxml"></include>
总结:
import可以在该文件中使用目标文件定义的template
include 可以将目标文件除了 <template/>外的整个代码引入,相当于是拷贝到 include 位置
2.wxss样式
语法,使用的大部分都是css的语法
2.1新的特性
1.rpx
屏幕 宽度 始终750rpx
2.样式文件的导入
import语句可以导入外联样式表
@import "../../common/common.wxss";
3.选择器支持部分选择器
class id 元素 群组 等
4.新增全局样式 app.wxss
和页面样式冲突,页面样式覆盖全局样式
2.2 style与class
style
接收动态传入的样式绑定(未知)
class
接收静态样式的绑定
3.事件系统
事件就是视图层(wxml)到逻辑层(js)的通讯方式,同时能够携带参数!!!
3.1事件绑定
语法:
1.bind + 事件类型 = “事件处理函数”
bindtap == click
2.catch + 事件类型 = “事件处理函数”
区别:
bind绑定事件,允许事件冒泡
catch绑定事件,阻止事件冒泡
<button bindtap="fun">bind</button>
<!-- 注意1:事件处理函数中,不能加小括号 -->
<!-- <button bindtap="fun()">bind</button> -->
<button catchtap="fun2">catch</button>
data: {
msg:12
},
fun2(){
console.log('catch');
},
// 注意2:多种写法
// 对象
// fun:function(){
// console.log('bind');
// },
// 简写:建议书写
fun(){
console.log('bind2',this);
},
// 箭头函数,在事件处理函数中不建议使用,this指向问题
// fun:()=>{
// console.log('bind3',this);
// }
3.2事件传参/接参
-
传递参数
第一种形式:data-name data-good-name
第二种形式:id=""
<!-- 事件传参 -->
<button bindtap="fun3" data-name="苹果" data-goodsName="红富士" data-good-name="123" data-price="99" id="1001">传递参数</button>
-
接收参数
事件处理函数中通过事件对象接收
fun3(e){
// 接收一个参数---事件对象
console.log(e);
// 获取参数
console.log(e.currentTarget.dataset.name);//接收data-传递的参数
console.log(e.currentTarget.id);//接收id传递的参数
}
3.3事件分类
冒泡事件、非冒泡事件
- 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
- 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。
<!-- 事件分类 -->
<view class="father" bindtap="father" data-name="father">
father
<view class="son" bindtap="son" data-name="son">son</view>
<!-- <view class="son" catchtap="son" >son</view> -->
</view>
问题:
currentTargt和target接收参数有什么区别?
currentTarget
获取参数,事件绑定的当前组件身上的参数
target
获取参数,触发事件的源组件,点谁就获取谁的参数