小程序和h5区别
常见app
原生app
安卓ios用的是纯原生组件
优点:运行流畅,且可以访问手机硬件
缺点:开发成本高,维护成本高,一旦上线后,内容结构无法改变
混合开发app (hybrid app)用的最多
原生app中有一个组件webview(相当一个小型浏览器,可以定义webview尺寸位置,
webview给以一个url,指定一个h5应用)(一个app壳子,里面套webview引入h5代码)
优点:运行比较流畅,可以调用手机硬件(需要原生封装,传给webview,h5代码调用传入的jsbrige传过来的方法)
webapp m站 在手机浏览器打开的网页
小程序宿主环境
渲染层(多个webview)
逻辑层(jscore)
程序与页面
一个小程序有多个页面
有全局的样式配置,全局可以作用到局部,如果两者都有相同的配置以局部为准
全局配置,
局部配置
sitemap配置(SEO搜索)
小程序中的适配
传统移动端适配方案
1.百分比布局
2.rem布局()
3.flex布局
推荐布局:flex布局+rem单位(rem不建议设置字体大小)
小程序中的适配
布局使用flex
容器 :flex-direction flex-wrap justify-content align-items align-content
项目:order flex-grow(放大比例) flex-shink(缩小比例)
flex-basis(项目在主轴占据的空间auto) flex:0 1 auto;align-self
wxss新增一个响应式单位 rpx
依据设计图 750px(自动根据屏幕等比缩放)
2rpx=1px
750rpx
总之是多少px就写多少rpx
注意:小程序字体推荐使用px
全局配置
pages:数组,页面的配置,如果数组位于第一个则默认打开该下标
window:状态栏顶部之类的设置,
tabbar:tabbar相关设置,
networktimeout:自定义网络超时时间
debug:调式模式,开发模式可以打开
小程序分包
其源码要求体积不能超过2m,
如果分包的话
整个小程序所有分包不能超过20m
单个分包/主包不能超过2m
requiredBackgroundModes
申明在后台运行的能力
permission
用户权限相关设置
style:改变ui界面设置
页面级别配置
大多数属性与全局相同,设置冲突时候,页面优先级更高
sitmap配置
sitmap.json
配置项
详见接口
全局程序
// app.js
App({
onLaunch(){
//小程序开始加载
},
onShow(){
//小程序开始显示,比如后台切前台
},
onHide(){
//小程序消失,比如切后台
},
globlData:{
//公共的数据,类似vuex,可以直接修改,不建议直接修改,可以在全局实例中定义一个修改数据的方法,再在页面中调用
}
})
getApp()全局函数可以获取小程序的实例,其返回App()创建的实例
getApp().globlData.xxx 获取和设置globlData的数据
页面程序
// pages/home/home.js
Page({
//页面初始数据可以通过{{}}直接渲染,类似vue
fn(){
wx.getLocation({
altitude: ‘altitude‘,
success:(res)=>{
console.log(res)
}
})
},
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载,类似vue的created切换到其他页面在回来是,其不会再次出发,因为每个页面都有一个单独的webview,可以调用请求函数
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成,类似vue的mounted,如果组件没有鞋子后重新加载,值触发一次
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示,类似vue中keepalive的actived,可以触发多次
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
事件
绑定事件
<button bindtap="fn">获取地理位置</button>
page({
fn(){}
//其修改data数据,要使用setData()
this.setData({
msg:"侬好"
},()=>{
console.log(123) //修改数据是同步的,视图刷新是异步的,当视图刷新是此回调触发
})
})
** etCurrentPages()**
PageObject[] getCurrentPages()
获取当已经打开(未销毁)的所有页面
获取当前页面栈。数组中第一个元素为首页,最后一个元素为当前页面。
注意:
不要尝试修改页面栈,会导致路由以及页面状态错误。
不要在 App.onLaunch 的时候调用 getCurrentPages(),此时 page 还没有生成。
小程序的组件
Commponent
// components/CommonHead.js
Component({
/**
* 组件的属性列表 ,类似vue中props
*/
properties: {
title:{
type:String,
observer:()=>{
console.log(789);
}
}
},
/**
* 组件的初始数据,类似vue中的data
*/
data: {
zi:"差不多得了"
},
/**
* 组件的方法列表,类似vue中的methods
*/
methods: {
bbb(){
this.triggerEvent("aa",this.data.zi) //子向父通信,触发自定义事件,第一项参数是事件名字,第二项是携带的参数
}
}
})
使用组件
//page页 page.json
{
"usingComponents": {
"common-head":"/components/common-head"
}
}
//wxml
<common-head title="{{msg}}" bindaa="fn2"></common-head>
fn2(e){
console.log(e); e.detail就是父向子通信传递的参数
}
小程序中的模块化
可以用es6,也可以用node
WXMl语法
WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。
数据绑定
WXML 中的动态数据均来自对应 Page 的 data。
简单绑定
数据绑定使用 Mustache 语法(双大括号)将变量包起来,可以作用于:
内容
<view> {{ message }} </view>
Page({
data: {
message: ‘Hello MINA!‘
}
})
组件属性(需要在双引号之内)
<view id="item-{{id}}"> </view>
Page({
data: {
id: 0
}
})
控制属性(需要在双引号之内)
<view wx:if="{{condition}}"> </view>
Page({
data: {
condition: true
}
})
关键字(需要在双引号之内)
true:boolean 类型的 true,代表真值。
false: boolean 类型的 false,代表假值。
<checkbox checked="{{false}}"> </checkbox>
特别注意:不要直接写 checked="false",其计算结果是一个字符串,转成 boolean 类型后代表真值。
运算
可以在 {{}} 内进行简单的运算,支持的有如下几种方式:
三元运算
<view hidden="{{flag ? true : false}}"> Hidden </view>
算数运算
<view> {{a + b}} + {{c}} + d </view>
Page({
data: {
a: 1,
b: 2,
c: 3
}
})
view中的内容为 3 + 3 + d。
逻辑判断
<view wx:if="{{length > 5}}"> </view>
字符串运算
<view>{{"hello" + name}}</view>
Page({
data:{
name: ‘MINA‘
}
})
数据路径运算
<view>{{object.key}} {{array[0]}}</view>
Page({
data: {
object: {
key: ‘Hello ‘
},
array: [‘MINA‘]
}
})
组合
也可以在 Mustache 内直接进行组合,构成新的对象或者数组。
数组
<view wx:for="{{[zero, 1, 2, 3, 4]}}"> {{item}} </view>
Page({
data: {
zero: 0
}
})
最终组合成数组[0, 1, 2, 3, 4]。
对象
<template is="objectCombine" data="{{for: a, bar: b}}"></template>
Page({
data: {
a: 1,
b: 2
}
})
最终组合成的对象是 {for: 1, bar: 2}
也可以用扩展运算符 ... 来将一个对象展开
<template is="objectCombine" data="{{...obj1, ...obj2, e: 5}}"></template>
Page({
data: {
obj1: {
a: 1,
b: 2
},
obj2: {
c: 3,
d: 4
}
}
})
最终组合成的对象是 {a: 1, b: 2, c: 3, d: 4, e: 5}。
如果对象的 key 和 value 相同,也可以间接地表达。
<template is="objectCombine" data="{{foo, bar}}"></template>
Page({
data: {
foo: ‘my-foo‘,
bar: ‘my-bar‘
}
})
最终组合成的对象是 {foo: ‘my-foo‘, bar:‘my-bar‘}。
注意:上述方式可以随意组合,但是如有存在变量名相同的情况,后边的会覆盖前面,如:
<template is="objectCombine" data="{{...obj1, ...obj2, a, c: 6}}"></template>
Page({
data: {
obj1: {
a: 1,
b: 2
},
obj2: {
b: 3,
c: 4
},
a: 5
}
})
最终组合成的对象是 {a: 5, b: 3, c: 6}。
注意: 花括号和引号之间如果有空格,将最终被解析成为字符串
<view wx:for="{{[1,2,3]}} ">
{{item}}
</view>
等同于
<view wx:for="{{[1,2,3] + ‘ ‘}}">
{{item}}
</view>
列表渲染 循环
<text>{{msg}}</text>
<button bindtap="fn">改数据</button>
<button wx:for="{{arr}}" wx:key="index">{{item}}</button>
//循环使用wx:for,默认循环变量是item,循环下标是index,要加wx:key属性,key直接写index,不需要加item
<!-- 自定义循环及下标 -->
<button wx:for="{{arr}}" wx:for-item="el" wx:for-index="id" wx:key="id">{{el}}</button>
//自定义循环变量下标(一般是多层嵌套循环)
//wx:for-item="el" wx:for-index="id"自定义变量及其下标
Block组件
用于做容器,渲染时候就不变成空,相当于react的空标签
条件渲染
类似于vue中的条件渲染
wx:if
<view class="box1" wx:if="{{gaibian%3===0}}"></view>
<view class="box2" wx:elif="{{gaibian%3===1}}"></view>
<view class="box3" wx:else></view>
模板
WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。
定义模板
使用 name 属性,作为模板的名字。然后在<template/>内定义代码片段,如:
<!--
index: int
msg: string
time: string
-->
<template name="msgItem">
<view>
<text> {{index}}: {{msg}} </text>
<text> Time: {{time}} </text>
</view>
</template>
使用模板
使用 is 属性,声明需要的使用的模板,然后将模板所需要的 data 传入,如:
<template is="msgItem" data="{{...item}}"/>
Page({
data: {
item: {
index: 0,
msg: ‘this is a template‘,
time: ‘2016-09-15‘
}
}
})
is 属性可以使用 Mustache 语法,来动态决定具体需要渲染哪个模板:
<template name="odd">
<view> odd </view>
</template>
<template name="even">
<view> even </view>
</template>
<block wx:for="{{[1, 2, 3, 4, 5]}}">
<template is="{{item % 2 == 0 ? ‘even‘ : ‘odd‘}}"/>
</block>
模板的作用域
模板拥有自己的作用域,只能使用 data 传入的数据以及模板定义文件中定义的 <wxs /> 模块
不好用,不如定义组件
小程序中的事件
类型 | 触发条件 | 最低版本 |
---|---|---|
touchstart | 手指触摸动作开始 | |
touchmove | 手指触摸后移动 | |
touchcancel | 手指触摸动作被打断,如来电提醒,弹窗 | |
touchend | 手指触摸动作结束 | |
tap | 手指触摸后马上离开 | |
longpress | 手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发 | 1.5.0 |
longtap | 手指触摸后,超过350ms再离开(推荐使用longpress事件代替) | |
transitionend | 会在 WXSS transition 或 wx.createAnimation 动画结束后触发 | |
animationstart | 会在一个 WXSS animation 动画开始时触发 | |
animationiteration | 会在一个 WXSS animation 一次迭代结束时触发 | |
animationend | 会在一个 WXSS animation 动画完成时触发 | |
touchforcechange | 在支持 3D Touch 的 iPhone 设备,重按时会触发 | 1.9.90 |
bind绑定与catch绑定
bind会冒泡,catch不会
八、事件
1、事件传参
【自定义数据】`data-xx="..."
xx.wxml
<button bindtap="fn" data-id="1">传参</button>
# xx.js
{
fn(e){ // e是事件对象
e.currentTarget // 事件源
e.currentTarget.dataset.id // button data-id 绑定自定义数据的值
}
}
常用组件
十、原生组件
1、视图容器
组件 | 说明 |
---|---|
cover-image | 覆盖在原生组件之上的图片视图。可覆盖的原生组件同cover-view,支持嵌套在cover-view 里 |
cover-view | 覆盖在原生组件之上的文本视图 |
view | 视图容器 |
- match-media
media query 匹配检测节点。可以指定一组 media query 规则,满足时,这个节点才会被展示
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
---|---|---|---|---|---|
min-width | number | 否 | 页面最小宽度( px 为单位) | 2.11.1 | |
max-width | number | 否 | 页面最大宽度( px 为单位) | 2.11.1 | |
width | number | 否 | 页面宽度( px 为单位) | 2.11.1 | |
min-height | number | 否 | 页面最小高度( px 为单位) | 2.11.1 | |
max-height | number | 否 | 页面最大高度( px 为单位) | 2.11.1 | |
height | number | 否 | 页面高度( px 为单位) | 2.11.1 | |
orientation | string | 否 | 屏幕方向( landscape 或 portrait ) | 2.11.1 |
# 例
<match-media min-width="300" max-width="600">
<view>当页面宽度在 300 ~ 500 px 之间时展示这里</view>
</match-media>
<match-media min-height="400" orientation="landscape">
<view>当页面高度不小于 400 px 且屏幕方向为纵向时展示这里</view>
</match-media>
- 可移动组件
组件 | 说明 |
---|---|
movable-area | movable-view 的可移动区域 |
movable-view | 可移动的视图容器,在页面中可以拖拽滑动。movable-view必须在 movable-area组件中,并且必须是直接子节点,否则不能移动 |
- 滚动组件
【scroll-view】
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
scroll-x | boolean | false | 否 | 允许横向滚动 |
scroll-y | boolean | false | 否 | 允许纵向滚动 |
upper-threshold | number/string | 50 | 否 | 距顶部/左边多远时,触发 scrolltoupper 事件 |
bindscrolltoupper | eventhandle | 否 | 滚动到顶部/左边时触发 | |
lower-threshold | number/string | 50 | 否 | 距底部/右边多远时,触发 scrolltolower 事件 |
bindscrolltolower | eventhandle | 否 | 滚动到底部/右边时触发 | |
scroll-top | number/string | 否 | 设置竖向滚动条位置 | |
scroll-left | number/string | 否 | 设置横向滚动条位置 | |
scroll-with-animation | boolean | false | 否 | 在设置滚动条位置时使用动画过渡(滑动更流畅) |
- 轮播组件**
组件 | 说明 |
---|---|
swiper | 滑块视图容器。其中只可放置 swiper-item 组件,否则会导致未定义的行为 |
swiper-item | 仅可放置在 swiper组件中,宽高自动设置为100% |
- 容器组件**
view 相当于div
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
---|---|---|---|---|---|
hover-class | string | none | 否 | 指定按下去的样式类。当 hover-class="none" 时,没有点击态效果 | 1.0.0 |
hover-stop-propagation | boolean | false | 否 | 指定是否阻止本节点的祖先节点出现点击态 | 1.5.0 |
hover-start-time | number | 50 | 否 | 按住后多久出现点击态,单位毫秒 | 1.0.0 |
hover-stay-time | number | 400 | 否 | 手指松开后点击态保留时间,单位毫秒 | 1.0.0 |
- 配置项
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
longitude | number | 是 | 中心经度 | |
latitude | number | 是 | 中心纬度 | |
scale | number | 16 | 否 | 缩放级别,取值范围为3-20 |
min-scale | number | 3 | 否 | 最小缩放级别 |
max-scale | number | 20 | 否 | 最大缩放级别 |
markers | Array | 否 | 标记点 | |
polyline | Array | 否 | 路线 | |
polygons | Array. |
否 | 多边形 | |
show-compass | boolean | false | 否 | 显示指南针 |
内容组件
组件 | 说明 |
---|---|
icon | 图标 |
progress | 进度条 |
rich-text | 富文本,通过nodes属性渲染 |
text | 文本,相当于span |
客服系统
1.在小程序后台中添加客服,
2.<button plain="{{true}}" loading="{{true}}" open-type="contact" bindcontact="contact">按钮</button>
3、表单组件
- 数据双向绑定
# xx.wxml
<input type="text" value="{{formData.username}}" bindinput="setInput"/>
# xx.js
{
data: {
formData: {
username: "aa"
}
},
setInput(e){
this.setData({
formData: {
username: e.datail.value
}
})
}
}
- 提交表单数据
# xx.wxml
<form bindsubmit="submit">
<button form-type="submit">提交</button>
</form>
# xx.js
submit(){
xxx
}
小程序路由操作
- 声明式导航 利用组件操作路由跳转
<navigator></navigator>
// 属性
target //跳转方式
self // 默认值 当前小程序范围 内跳转
miniProgram // 跳转到其他小程序
//怎么跳转到其他小程序
当target = "miniProgram"
app-id = "跳转小程序appid"
path="跳转的小程序某个页面的路径为空则打开的是首页"
extra-data="{{ {a:10,b:20} }}" // 目标小程序可在 App.onLaunch(),App.onShow() 中获取到这份数据
url // 跳转的页面路径 用于小程序内部跳转
open-type 跳转方式
值请见下方
navigate 普通跳转 跳转同时 新建webview(添加一个新的记录),不能跳转到tab页 open-type得默认值
redirect 跳转到普通 覆盖当前历史记录
switchTab 跳转到tab页
reLaunch 关闭页面上所有的已经打开的页面的webview,同时 打开目标页面
navigateBack 回退 navigator的delta控制回退 层级(1 回退一步)
exit 退出小程序,target="miniProgram"时生效
open-type的值
值 | 说明 | 最低版本 |
---|---|---|
navigate | 对应 wx.navigateTo 或 wx.navigateToMiniProgram 的功能 | |
redirect | 对应 wx.redirectTo 的功能 | |
switchTab | 对应 wx.switchTab 的功能 | |
reLaunch | 对应 wx.reLaunch 的功能 | 1.1.0 |
navigateBack | 对应 wx.navigateBack 的功能 | 1.1.0 |
exit | 退出小程序,target="miniProgram" 时生效 | 2.1.0 |
路由跳转传参
// 跳转传参
<navigator url="/pages/itemLists/itemLists?a=10&b=20">到列表页</navigator>
// 获取 在目标页面的 js onLoad钩子函数的参数中获取
Page({
onLoad(options){
// options.a options.b获取
}
})
- 编程式导航
wx.switchTab({ // 相当于 navigator open-type = ‘switchTab‘
url:"地址"
})
wx.reLaunch() // 相当于 navigator open-type = ‘reLaunch‘
wx.redirectTo() // 相当于 navigator open-type = ‘redirect‘
wx.navigateTo() // 相当于 navigator open-type = ‘navigator‘
编程导航传参
hah(e){
const id= e.currentTarget.dataset.shuju
console.log(id)
wx.navigateTo({
url: `/pages/shoplists/shoplists?id=${id}`,
})
},
常用的多媒体组件
audio,image
界面交互相关
详见api