一,注册微信小程序
1.打开 微信公众平台
2.注册开发者账号
可以选择注册服务号/小程序号,如果有公司资质可选择注册服务号,在服务号里快速复用公司资质直接注册小程序号,一个服务号可以关联注册10个同主体或关联主体的小程序,3个非同主体小程序。
服务号:企业资质,在服务号里可直接快速注册多个小程序号
小程序:企业资质、个人资质···
注册需要用到的资料
个人注册:身份证姓名、身份证号码、管理员手机、短信验证、管理员身份验证等等
企业注册:企业类型、营业执照注册号、管理员身份证姓名、管理员身份证号码、管理员手机号码、短信验证等
小程序注册
3.微信公众平台
注册完成后,既可登录微信公众平台,填写小程序信息、小程序类目,填写完整既可在设置中找到小程序AppId以及配置小程序秘钥。
在里面版本管理、成员管理、添加开发域名、管理插件、查看核心数据等,
二,微信开发者工具
下载微信web开发者工具,根据自己的操作系统下载对应的安装包进行安装即可。
2.1.创建工程
- 登录微信公众平台,填写好小程序信息后,去设置里面找到账号信息,找到小程序AppID
- 打开微信开发者工具,点击加号创建工程
- 填写好AppID等信息,选择工程模板,确定
-
进入工程
2.2.界面介绍
-
微信开发工具界面
-
项目工程目录
2.3 全局配置
小程序配置项 微信开发文档
小程序根目录下的 app.json 文件用来对微信小程序进行全局配置。文件内容为一个 JSON 对象
配置项
属性 | 类型 | 必填 | 描述 | 最低版本 |
---|---|---|---|---|
entryPagePath | string | 否 | 小程序默认启动首页 | |
pages | string[] | 是 | 页面路径列表 | |
window | Object | 否 | 全局的默认窗口表现 | |
tabBar | Object | 否 | 底部 tab 栏的表现 |
|
networkTimeout | Object | 否 | 网络超时时间 | |
debug | boolean | 否 | 是否开启 debug 模式,默认关闭 | |
functionalPages | boolean | 否 | 是否启用插件功能页,默认关闭 | 2.1.0 |
subpackages | Object[] | 否 | 分包结构配置 | 1.7.3 |
workers | string | 否 |
Worker 代码放置的目录 |
1.9.90 |
requiredBackgroundModes | string[] | 否 | 需要在后台使用的能力,如「音乐播放」 | |
plugins | Object | 否 | 使用到的插件 | 1.9.6 |
preloadRule | Object | 否 | 分包预下载规则 | 2.3.0 |
resizable | boolean | 否 | PC 小程序是否支持用户任意改变窗口大小(包括最大化窗口);iPad 小程序是否支持屏幕旋转。默认关闭 | 2.3.0 |
usingComponents | Object | 否 | 全局自定义组件配置 | 开发者工具 1.02.1810190 |
permission | Object | 否 | 小程序接口权限相关设置 | 微信客户端 7.0.0 |
sitemapLocation | string | 是 | 指明 sitemap.json 的位置 | |
style | string | 否 | 指定使用升级后的weui样式 | 2.8.0 |
useExtendedLib | Object | 否 | 指定需要引用的扩展库 | 2.2.1 |
entranceDeclare | Object | 否 | 微信消息用小程序打开 | 微信客户端7.0.9 |
darkmode | boolean | 否 | 小程序支持 DarkMode | 2.11.0 |
themeLocation | string | 否 | 指明 theme.json 的位置,darkmode为true为必填 | 开发者工具 1.03.2004271 |
lazyCodeLoading | string | 否 | 配置自定义组件代码按需注入 | 2.11.1 |
singlePage | Object | 否 | 单页模式相关配置 | 2.12.0 |
- pages配置
用于指定小程序由哪些页面组成,每一项都对应一个页面的 路径(含文件名) 信息。文件名不需要写文件后缀,框架会自动去寻找对应位置的 .json, .js, .wxml, .wxss 四个文件进行处理。
"pages": [
"pages/index/index",
"pages/next-bus/next-bus",
"pages/park-map/park-map",
"pages/park/park",
"pages/route-info/route-info",
"pages/glory-futian/glory-futian",
"pages/glory-futian/details/vehicle-road/vehicle-road",
"pages/glory-futian/details/station/station",
"pages/glory-futian/details/smart-road/smart-road",
"pages/glory-futian/details/slow/slow",
"pages/bind-car/bind-car",
"pages/offiaccount-login/offiaccount-login",
"pages/construction/construction"
],
- window配置
用于设置小程序的状态栏、导航条、标题、窗口背景色等。
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
navigationBarBackgroundColor | HexColor | #000000 | 导航栏背景颜色,如 #000000
|
navigationBarTextStyle | string | white | 导航栏标题颜色,仅支持 black / white
|
navigationBarTitleText | string | 导航栏标题文字内容 | |
navigationStyle | string | default | 导航栏样式,仅支持以下值:default 默认样式custom 自定义导航栏,只保留右上角胶囊按钮。参见注 2。 |
homeButton | boolean | default | 在非首页、非页面栈最底层页面或非 tabbar 内页面中的导航栏展示 home 键 |
backgroundColor | HexColor | #ffffff | 窗口的背景色 |
backgroundTextStyle | string | dark | 下拉 loading 的样式,仅支持 dark / light
|
backgroundColorTop | string | #ffffff | 顶部窗口的背景色,仅 iOS 支持 |
backgroundColorBottom | string | #ffffff | 底部窗口的背景色,仅 iOS 支持 |
enablePullDownRefresh | boolean | false | 是否开启全局的下拉刷新。 |
onReachBottomDistance | number | 50 | 页面上拉触底事件触发时距页面底部距离,单位为 px。 |
pageOrientation | string | portrait | 屏幕旋转设置,支持 auto / portrait / landscape
|
restartStrategy | string | homePage | 重新启动策略配置 |
initialRenderingCache | string | 页面初始渲染缓存配置,支持 static / dynamic
|
|
visualEffectInBackground | string | none | 切入系统后台时,隐藏页面内容,保护用户隐私。支持 hidden / none
|
handleWebviewPreload | string | static | 控制预加载下个页面的时机 支持 static / manual / auto
|
- tabBar配置
客户端窗口的底部或顶部有 tab 栏可以切换页面,可以通过 tabBar 配置项指定 tab 栏的表现,以及 tab 切换时显示的对应页面。
属性 | 类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
color | HexColor | 是 | tab 上的文字默认颜色,仅支持十六进制颜色 | |
selectedColor | HexColor | 是 | tab 上的文字选中时的颜色,仅支持十六进制颜色 | |
backgroundColor | HexColor | 是 | tab 的背景色,仅支持十六进制颜色 | |
borderStyle | string | 否 | black | tabbar 上边框的颜色, 仅支持 black / white
|
list | Array | 是 | tab 的列表,详见 list 属性说明,最少 2 个、最多 5 个 tab |
|
position | string | 否 | bottom | tabBar 的位置,仅支持 bottom / top
|
custom | boolean | 否 | false | 自定义 tabBar |
其中 list 接受一个数组,只能配置最少 2 个、最多 5 个 tab。tab 按数组的顺序排序,每个项都是一个对象,其属性值如下:
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
pagePath | string | 是 | 页面路径,必须在 pages 中先定义 |
text | string | 是 | tab 上按钮文字 |
iconPath | string | 否 | 图片路径,icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片。当 position 为 top 时,不显示 icon。 |
selectedIconPath | string | 否 | 选中时的图片路径,icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片。当 position 为 top 时,不显示 icon。 |
- networkTimeout 网络请求超时配置
各类网络请求的超时时间,单位均为毫秒。
- 分包加载加载
某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。
在构建小程序分包项目时,构建会输出一个或多个分包。每个使用分包小程序必定含有一个主包。所谓的主包,即放置默认启动页面/TabBar 页面,以及一些所有分包都需用到公共资源/JS 脚本;而分包则是根据开发者的配置进行划分。
在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示。
目前小程序分包大小有以下限制:
整个小程序所有分包大小不超过 20M
单个分包/主包大小不能超过 2M
2.4 小程序页面配置
页面配置地址
小程序中,可以在页面对应的 .json 文件来对本页面的表现进行配置。如:导航栏样式、自定义组件注入等。
注意:app.json 中的部分配置,可以再页面对应的.json进行重新配置,页面中配置项在当前页面会覆盖 app.json 中相同的配置项。
配置项
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
navigationBarBackgroundColor | HexColor | #000000 | 导航栏背景颜色,如 #000000
|
navigationBarTextStyle | string | white | 导航栏标题颜色,仅支持 black / white
|
navigationBarTitleText | string | 导航栏标题文字内容 | |
navigationStyle | string | default | 导航栏样式,仅支持以下值:default 默认样式custom 自定义导航栏,只保留右上角胶囊按钮。 |
homeButton | boolean | false | 在非首页、非页面栈最底层页面或非 tabbar 内页面中的导航栏展示 home 键 |
backgroundColor | HexColor | #ffffff | 窗口的背景色 |
backgroundTextStyle | string | dark | 下拉 loading 的样式,仅支持 dark / light
|
backgroundColorTop | string | #ffffff | 顶部窗口的背景色,仅 iOS 支持 |
backgroundColorBottom | string | #ffffff | 底部窗口的背景色,仅 iOS 支持 |
enablePullDownRefresh | boolean | false | 是否开启当前页面下拉刷新 |
onReachBottomDistance | number | 50 | 页面上拉触底事件触发时距页面底部距离,单位为px |
pageOrientation | string | portrait | 屏幕旋转设置,支持 auto / portrait / landscape
|
disableScroll | boolean | false | 设置为 true 则页面整体不能上下滚动。只在页面配置中有效,无法在 app.json 中设置 |
usingComponents | Object | 否 | 页面自定义组件配置 |
initialRenderingCache | string | 页面初始渲染缓存配置,支持 static / dynamic
|
|
style | string | default | 启用新版的组件样式 |
singlePage | Object | 否 | 单页模式相关配置 |
restartStrategy | string | homePage | 重新启动策略配置 |
handleWebviewPreload | string | static | 控制预加载下个页面的时机。支持 static / manual / auto
|
visualEffectInBackground | string | 否 | 切入系统后台时,隐藏页面内容,保护用户隐私。支持 hidden / none ,若对页面单独设置则会覆盖全局的配置 |
enablePassiveEvent | Object或boolean | 否 | 事件监听是否为 passive,若对页面单独设置则会覆盖全局的配置 |
renderer | string | 否 | 渲染后端 |
三、小程序语法
网页编程采用的是 HTML + CSS + JS 这样的组合,小程序也是如此 WXML + WXSS+ JS 。
3.1.wxml
和html没什么区别,只是标签名称不同。 多了一些表达式
<!-- 渲染 -->
<text>{{parkType}}</text>
<image data-text="{{index}}" bindtap="clickParkMap" class="item-poi" src="{{img_server_url}}/pos_icon.png"></image>
<view style="height:50rpx;">{{msg.length}}</view>
<!-- 条件渲染 -->
<block wx:if="{{selRegionIndex==1}}">
<view class="select_result0">数据加载中···请稍后!</view>
</block>
<block wx:elif="{{selRegionIndex==2}}">
<view class="select_result0">数据加载中···请稍后!</view>
</block>
<block wx:else>
<view class="select_result0">数据加载中···请稍后!</view>
</block>
<!-- 列表渲染 -->
<view class="item" wx:for="{{selSort}}" wx:key="index" wx:for-index="index" wx:for-item="item" data-text="{{index}}" bindtap='selSort'>
<text class="{{selSortIndex==index?'sel_text':''}}">{{item.name}}</text>
<image wx:if="{{selSortIndex==index}}" src="{{img_server_url}}/radio_icon_sel.png"></image>
</view>
<!-- 引入过滤器 -->
<wxs module="filters" src="../../utils/filter.wxs"></wxs>
<!-- 使用过滤器 -->
<checkbox class="radio" color="#fff" wx:key="*this" wx:for="{{fieldsInfo.live_reason}}" wx:for-item="item" value="{{item}}" checked="{{ filters.setChecked(allData.live_reason,item) }}" >
<text>{{item}}</text>
</checkbox>
<!-- 使用自定义组件 -->
<nav-bar header='{{nvabarData}}'></nav-bar>
<view>{{"hello" + name}}</view>
<template is="objectCombine" data="{{...obj1, ...obj2, a, c: 6}}"></template>
<template is="objectCombine" data="{{...obj1, ...obj2, e: 5}}"></template>
- wxml模板使用
定义item.wxml
<template name="item">
<text>{{text}}</text>
</template>
使用模板
<!-- 引入 -->
<import src="item.wxml"/>
<!-- 使用 -->
<template is="item" data="{{text: 'forbar'}}"/>
- include
可以将目标文件除了 <template/> <wxs/> 外的整个代码引入,相当于是拷贝到 include 位置,
<!-- header.wxml -->
<view> header </view>
<!-- footer.wxml -->
<view> footer </view>
<!-- index.wxml -->
<include src="header.wxml"/>
<view> body </view>
<include src="footer.wxml"/>
=
<view> header </view>
<view> body </view>
<view> footer </view>
- 注意事项
当 wx:for 的值为字符串时,会将字符串解析成字符串数组
<view wx:for="array">
{{item}}
</view>
=
<view wx:for="{{['a','r','r','a','y']}}">
{{item}}
</view>
当花括号和引号之间如果有空格,将最终被解析成为字符串
<view wx:for="{{[1,2,3]}} ">
{{item}}
</view>
=
<view wx:for="{{[1,2,3] + ' '}}" >
{{item}}
</view>
3.2.wxss
WXSS 具有 CSS 大部分的特性,小程序在 WXSS 也做了一些扩充和修改。
新增了单位尺寸:rpx
.body{
width:100%;
height:100%;
background:rgba(243,247,249,1);
overflow: hidden;
display: flex;
flex-direction: column;
}
.top-panel{
height:160rpx;
padding:20rpx;
border-radius:4px;
position: relative;
}
/* 选项面板 */
.top-panel .sel-panel{
height:calc( 100% - 40rpx );
position: relative;
padding:20rpx;
background:rgba(255,255,255,1);
}
/* 输入 */
.top-panel .sel-panel .input-c{
height:65rpx;
display: flex;
flex-direction: row;
align-items: center;
}
3.3.wxs
小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。包含 wxs模块、变量、注释、运算符、语句、数据类型、基础类库
- wxs文件定义
// /pages/tools.wxs 定义
var foo = "'hello world' from tools.wxs";
var bar = function (d) {
return d;
}
module.exports = {
FOO: foo,
bar: bar,
};
module.exports.msg = "some msg";
-
wxs标签使用
// 使用
<wxs src="./../tools.wxs" module="tools" />
<view> {{tools.msg}} </view>
<view> {{tools.bar(tools.FOO)}} </view>
- 示例:
var filters = {
// 设置复选框选中
setChecked: function (selArr,fields) {
if (selArr == null || selArr == undefined || selArr == '') {
return false;
}
if (selArr.indexOf(fields) != -1) {
return true;
}
return false;
},
strToArr: function (strArr, index) {
return strArr.split(',')[index];
}
}
module.exports = {
setChecked: filters.setChecked,
strToArr: filters.strToArr
}
<!-- 引入过滤器 -->
<wxs module="filters" src="../../utils/filter.wxs"></wxs>
<view class="field-item">
<checkbox-group class="radio-group-col" bindchange="radioChange" data-field="live_reason">
<checkbox wx:key="*this" wx:for="{{fieldsInfo.live_reason}}" wx:for-item="item" value="{{item}}" checked="{{ filters.setChecked(allData.live_reason,item) }}" >
<text>{{item}}</text>
</checkbox>
</checkbox-group>
</view>
3.4. js
-
3.4.1 App.js
使用App()注册小程序。接受一个 Object 参数,其指定小程序的生命周期回调、定义全局变量等。
全局变量如何使用后面会说。
//app.js
App({
// 小程序初始化完成时触发,全局只触发一次
onLaunch: function () {
//获取手机导航栏高度
wx.getSystemInfo({
success: res => {
var isIos = res.system.indexOf('iOS') > -1;
this.globalData.statusHeight = res.statusBarHeight;
this.globalData.navHeight = isIos ? 44 : 48;
this.globalData.fontSize = res.fontSizeSetting;
//设置低版本不显示自定义导航栏
if (res.SDKVersion && res.SDKVersion.split('.')[0] * 1 <= 2 && res.SDKVersion.split('.')[1] * 1 < 5){
this.globalData.navHeightHidden=true;
}
},
fail(err) {
console.log(err);
}
})
// 位置授权
wx.getSetting({
success(res) {
if (!res.authSetting['scope.userLocation']) {
wx.authorize({
scope: 'scope.userLocation',
success() {}
})
}
}
})
},
// 监听小程序启动或切前台
onShow (options) {
// Do something when show.
},
// 监听小程序切后台
onHide () {
// Do something when hide.
},
// 错误监听函数。
onError (msg) {
console.log(msg)
},
// 页面不存在监听函数
onPageNotFound(){
// 小程序要打开的页面不存在时触发
},
// 未处理的 Promise 拒绝事件监听函数。
onUnhandledRejection(){
// 小程序有未处理的 Promise 拒绝时触发。
},
// 监听系统主题变化
onThemeChange(){
// 系统切换主题时触发。也可以使用 wx.onThemeChange 绑定监听
},
globalData: {
//标题
header:'交通行为与意愿调查系统',
//自定义导航组件高度
navHeightHidden:false,
statusHeight:null,
navHeight:null,
fontSize:null,
/**发布版-请求数据地址 */
request_server_url: 'https://l***',
/**开发版-请求数据地址本地 */
// request_server_url: 'http:/***',
/**发布版-图片地址 */
img_server_url: 'https://***',
/**开发版-图片地址 */
// img_server_url: '../../images',
//地图相关
selMap:null,
mapKey: 'YPNBZ-PMSCX-G664V-7XBWG-SYFB6-KRBUO',
referer: '深研居民调查',
category: '生活服务,娱乐休闲',
//用户信息
openid:null,
userInfo:null,
surveyJob:false,
//版本号
version: 'v1.4.7',
}
})
-
3.4.2 页面page.js
使用Page() 注册小程序中的一个页面。接受一个 Object 类型参数,其指定页面的初始数据、生命周期回调、事件处理函数等。
// pages/ceshi/ceshi.js
// 引入公用函数
const Common = require("../../utils/common.js");
//获取应用实例
const app = getApp();
Page({
/**
* 页面的初始数据
*/
data: {
// 图片链接
img_server_url: app.globalData.img_server_url,
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
-
3.4.3 数据绑定使用
<!-- index.wxml-->
<text wx:if="{{text}}">{{text}}</text>
<input model:value="{{text}}" />
<view wx:for="{{persons}}" wx:key="*this" wx:for-index="index" wx:for-item="item">
<view class="item-person" data-value="{{item.value}}" bindtap="setCheck">
<text>{{item.name}}</text>
<text>{{item.value}}</text>
</view>
</view>
// index.js
// 获取应用实例
const app = getApp()
Page({
data: {
text:null,
active:1,
list:[
{ name:'',value:'' },
{ name:'',value:'' },
{ name:'',value:'' },
]
},
onShow: function () {
this.setData({
text:11
})
},
// 事件处理函数
setCheck(e) {
var value = e.currentTarget.dataset.value;
this.setData({
active:value,
text:'1111'
})
}
})
-
3.4.4 事件介绍
事件列表
- 点击事件(单击):tap
- 长按事件:longpress、longtap
- 键盘输入事件:input
- 回车事件:confirm
- 输入框聚焦:focus
- 输入框失焦:blur
- value改变事件:change
- 触摸动作开始:touchstart
- 触摸动作结束:touchend
- 触摸过程移动:touchmove
- 触摸动作被打断:touchcancel
- 提交表单事件:submit
- 重置表单事件:reset
事件对象属性列表
BaseEvent基础事件对象属性列表
属性 | 类型 | 说明 |
---|---|---|
type | String | 事件类型 |
timeStamp |
Integer | 事件生成时的时间戳 |
target |
Object | 触发事件的源组件的一些属性值集合 |
currentTarget |
Object | 当前组件的一些属性值集合 |
- CustomEvent 自定义事件对象属性列表(继承 BaseEvent)
属性 | 类型 | 说明 |
---|---|---|
detail |
Object | 额外的信息 |
- TouchEvent 触摸事件对象属性列表(继承 BaseEvent)
属性 | 类型 | 说明 |
---|---|---|
touches |
Array | 触摸事件,当前停留在屏幕中的触摸点信息的数组 |
changedTouches |
Array | 触摸事件,当前变化的触摸点信息的数组 |
事件对象属性说明
type
通用事件类型timeStamp
该页面打开到触发事件所经过的毫秒数。target
触发事件的源组件
属性 | 类型 | 说明 |
---|---|---|
id |
String | 事件源组件的id |
tagName |
String | 当前组件的类型 |
dataset |
Object | 事件源组件上由data- 开头的自定义属性组成的集合 |
- currentTarget
事件绑定的当前组件
属性 | 类型 | 说明 |
---|---|---|
id |
String | 当前组件的id |
tagName |
String | 当前组件的类型 |
dataset |
Object | 当前组件上由data- 开头的自定义属性组成的集合 |
- dataset
在组件中可以定义数据,这些数据将会通过事件传递给 SERVICE。书写方式:以data-开头,多个单词由连字符-链接,不能有大写(大写会自动转成小写)
如data-element-type
,最终在 event.target.dataset 中会将连字符转成驼峰elementType
。
如data-elementType
,最终在 e.currentTarget.dataset.elementtype 大写会自动转成小写elementtype
。
- 事件绑定
事件绑定的写法同组件的属性,以key、value的形式
- key以
bind
或catch
开头,然后跟上事件的类型,如bindtap
,catchtouchstart
- value是一个字符串,需要在对应的Page中定义同名的函数。不然当触发事件的时候会报错
<view bindtap="bindViewTap" data-field="name" data-text="aa"></view>
<view bind:tap="bindViewTap" data-field="name" data-text="aa"></view>
<view catch:tap="bindViewTap" data-field="name" data-text="aa"></view>
<view catchtap="bindViewTap" data-field="name" data-text="aa"></view>
bind与catch的区别
- bind事件绑定不会阻止冒泡事件往上冒泡,简单来说,bind所绑定的事件对应会向上传递,让自己的父组件响应对应的事件。
- catch事件会把对应的事件阻拦在自己这里,只有自己能够响应对应事件。
- 事件的使用
<!--index.wxml-->
<view bindtap="bindViewTap" data-field="name" data-text="aa"></view>
// index.js
Page({
// 事件处理函数
bindViewTap(e) {
var field= e.currentTarget.dataset.field;
var aa= e.currentTarget.dataset.text;
},
})
- 事件参数
- 使用:dataset
- 注意:事件携带参数 dataset使用的时候 ,数据名尽量用小写,不要使用驼峰
<!--index.wxml-->
<view bindtap="bindViewTap" data-element-type="name" data-elementType="aa"></view>
// index.js
Page({
// 事件处理函数
bindViewTap(e) {
// 获取时候 data-element-type = e.currentTarget.dataset.elementType
// 获取时候 data-elementType= e.currentTarget.dataset.elementtype
},
})
- 使用wxs响应事件
支持使用 WXS 函数绑定事件,WXS函数接受2个参数:
- event,在原有的 event 的基础上加了event.instance对象,
- ownerInstance,和event.instance一样是一个ComponentDescriptor对象
在组件中绑定和注册事件处理的 WXS 函数
<!-- text.wxml -->
<wxs module="test" src="./test.wxs"></wxs>
<!-- 绑定wxs中函数 -->
<view id="tapTest" data-hi="Weixin" bindtap="{{test.tapName}}"> Click me! </view>
<!-- prop 属性改变的时候调用 propObserver -->
<view change:prop="{{test.propObserver}}" prop="{{propValue}}" class="movable"></view>
test.wxs文件实现 tapName 函数
// test.wxs
module.exports = {
tapName: function(event, ownerInstance) {
var hi= e.currentTarget.dataset.hi;
},
// 监听prop属性变化
propObserver: function(newValue, oldValue, ownerInstance, instance) {
console.log('prop observer', newValue, oldValue)
}
}
-
3.4.5 App.js中全局变量使用
可在App.js中定义全局变量
- 定义
// app.js
App({
onLaunch() { },
globalData: {
userInfo: null,
dataList:[]
}
})
- 使用
//获取应用实例
const app = getApp();
Page({
/**
* 页面的初始数据
*/
data: {
// 图片链接
img_server_url: app.globalData.img_server_url,
},
/* 修改全局变量 */
updateRecord(data){
//保存全局数据
app.globalData.dataList= data;
// 注意,修改后,此页面如果又用到了,重新获取app,不然值不会变。
var app = getApp();
},
-
3.4.6 模块化
可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过module.exports
或者 exports
才能对外暴露接口。
- 定义公用变量 base.js
const accountInfo = wx.getAccountInfoSync();
let webViewSrc = 'http://cBus';
let pathWebViewSrc = 'https://***/index';
let userSubscribeUrl = 'https://i***e/app/user';
let SogoEnvVersion = 'trial'; //跳转到体验版
// let SogoEnvVersion = "release"; //跳转到生产版本
if (accountInfo.miniProgram.envVersion === 'trial') {
webViewSrc = 'https://****tcBus';
pathWebViewSrc = 'https://****ndex';
userSubscribeUrl = 'https://****/user';
} else if (accountInfo.miniProgram.envVersion === 'release') {
webViewSrc = 'https://***/ftcBus';
pathWebViewSrc = 'https:/***/#/index';
maasBaseUrl = 'https://***/entry';
userSubscribeUrl = 'https://***/app/user';
}
module.exports = {
webViewSrc,
pathWebViewSrc,
maasBaseUrl,
SogoEnvVersion,
userSubscribeUrl,
};
使用
import { maasBaseUrl, SogoEnvVersion } from "/utils/base.js"
Page({
onLoad() {
let ceshi = maasBaseUrl
...
}
})
- 定义公用函数 methods.js
/***
* 转换距离 转换成相应的展示单位
* */
function computedDistance(distance) {
if (distance > 1000) {
return (distance / 1000) + 'km'
} else {
return distance + '米'
}
};
/**
* 判断用户滑动
* 上滑还是下滑
*/
function getTouchData(endX, endY, startX, startY) {
let turn = "";
if (endY - startY > 50 && Math.abs(endX - startX) < 50) { //下滑
turn = "bottom";
} else if (endY - startY < -50 && Math.abs(endX - startX) < 50) { //上滑
turn = "top";
}
return turn;
};
module.exports = {
computedDistance,
getTouchData
}
使用
import { computedDistance, getTouchData } from "/utils/methods.js"
Page({
onLoad() {
let ceshi = computedDistance('')
}
})
-
3.4.7 封装 wx-request.js
function tansParams(obj){
var str = "";
for(var k in obj){
str+=k+"="+obj[k]+"&";
}
//移除最后一个&
return str.slice(0,-1);
}
function wxRequest(option){
var url = option.url;
// 选项里面有params(get传入的参数)
if(option.params){
// 如果有参数,把参数转换为url编码形式加入
url+="?"+tansParams(option.params);
}
// 02 可以添加请求头
var header = { };
var contentType = option.contentType || 'form';
header ['Content-Type'] = {
form: 'application/x-www-form-urlencoded',
json: 'application/json',
}[contentType];
header = {
header,
...option.header
}
header.Authorization ="Bearer "+wx.getStorageSync('token');
// 添加加载提示
if(option.loading){
wx.showToast({
title: option.loading.title,
icon:option.loading.icon,
})
}
// 返回一个Promise
return new Promise((resolve,reject)=>{
wx.request({
// 请求的地址如果一http开头直接用url不是http开头添加我们 baseUrL
url: url,
method:option.method||"GET",//请求的方法 默认get
data:option.data, //post出入的参数
header,
success(res){
// 请求成功
resolve(res.data);
},
fail(err){
// 04 对错误进行处理
wx.showToast({title:"加载失败",icon:"none"})
// 请求失败
reject(err);
},
complete(){
// 关闭加载提示
wx.hideToast();
}
})
})
}
// 定义get简易方法
wxRequest.get= (url,config)=>{
return request({url,method:"get",...config})
}
// 定义post简易方法
wxRequest.post= (url,data,config)=>{
return request({url,method:"post",data,...config})
}
// 导入request
module.exports={
wxRequest
}
使用
import { wxRequest } from "/utils/wx-request.js"
Page({
onLoad() {
wxRequest({
method: "POST",
url: `${maasBaseUrl}/trp/api/v1/openResource/getRouteInfo`,
data: routeNo
}).then((res) => {
if (res) {
}
})
}
})
-
3.4.8 组件封装与使用 自定义组件
将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用;在自定义组件的 js 文件中,需要使用 Component() 来注册组件,并提供组件的属性定义、内部数据和自定义方法。
组件的文件夹结构应和页面一样:.wxml .wxss .js .json
- 定义组件
.json****************** 中配置这是一个组件
{
"component": true
}
.wxml******************
<view class="inner">
{{innerText}}
</view>
<slot></slot>
.wxss******************
.inner {
color: red;
}
.js******************
Component({
properties: {
// 这里定义了 innerText 属性,属性值可以在组件使用时指定
innerText: {
type: String,
value: 'default value',
}
},
data: {
// 这里是一些组件内部数据
someData: {}
},
methods: {
// 这里是一个自定义方法
customMethod: function(){}
}
})
- 使用组件
// index.json 中引入组件
{
"usingComponents": {
"component-tag-name": "path/to/the/custom/component"
}
}
// index.wxml 中使用组件
<view>
<!-- 以下是对一个自定义组件的引用 -->
<component-tag-name inner-text="Some text">
<view>11111</view>
</component-tag-name>
</view>
- 开启多插槽模式(自定义组件默认是单插槽)
.js*********
Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用多 slot 支持
},
properties: { /* ... */ },
methods: { /* ... */ }
})
.wxml**********
<!-- 组件模板 -->
<view class="wrapper">
<slot name="before"></slot>
<view>这里是组件的内部细节</view>
<slot name="after"></slot>
</view>
index.wxml 使用*********
<view>
<component-tag-name>
<!-- 这部分内容将被放置在组件 <slot name="before"> 的位置上 -->
<view slot="before">这里是插入到组件slot name="before"中的内容</view>
<!-- 这部分内容将被放置在组件 <slot name="after"> 的位置上 -->
<view slot="after">这里是插入到组件slot name="after"中的内容</view>
</component-tag-name>
</view>
-
组件样式
默认情况下,自定义组件的样式只受到自定义组件 wxss 的影响,但是,可以配置页面和组件之间样式是否互相影响。
Component({}) 对象配置 options中有个属性styleIsolation:
- isolated 表示启用样式隔离,互不影响。
- apply-shared 表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面;
- shared 表示页面wxss样式和组件wxss样式 相互影响。
.js*********
Component({
options: {
styleIsolation: 'isolated'
}
})
-
数据传输
可以再组件properties 定义接收参数
Component({
properties: {
name: {
type: 'String'
},
type: {
type: 'String'
},
index:{
type:'Number'
}
}
)}
<component-nav index="{{index}}" type="person" name="点击编辑【个人特征】{{index+1}}"/>
- 事件沟通
自定义组件触发事件时,需要使用 triggerEvent 方法,接收参数参数:指定事件名、detail对象、事件选项;
触发事件的选项包括:
选项名 | 类型 | 是否必填 | 默认值 | 描述 |
---|---|---|---|---|
bubbles | Boolean | 否 | false | 事件是否冒泡 |
composed | Boolean | 否 | false | 事件是否可以穿越组件边界,为false时,事件将只能在引用组件的节点树上触发,不进入其他任何组件内部 |
capturePhase | Boolean | 否 | false | 事件是否拥有捕获阶段 |
代码示例:
组件**********************
<view>
<!-- 定义事件 -->
<button bindtap="onTap">点击这个按钮将触发“myevent”事件</button>
<slot></slot>
</view>
Component({
methods: {
onTap: function(){
// detail对象,提供给事件监听函数 传输数据
var myEventDetail = {}
// 触发事件的选项
var myEventOption = {
}
// 组件通信
this.triggerEvent('myevent', myEventDetail, myEventOption)
}
}
})
使用**********************
<component-nav bindmyevent="onMyEvent"></component-nav>
Page({
onMyEvent: function(e){
e.detail // 自定义组件触发事件时提供的 detail 对象
}
}
- 获取组件实例
可在父组件里调用 this.selectComponent ,获取子组件的实例对象,调用时需要传入一个匹配选择器 selector。
如:this.selectComponent(".my-component"),父组件将会获取 class 为 my-component 的子组件实例对象,即子组件的 this 。
// .wxml***********
<component-nav class="component-nav"/>
// .js***********
Page({
data: {},
getChildComponent: function () {
const child = this.selectComponent('.my-component');
console.log(child)
}
})
- 示例创建自定义组件Nav
nav.json
{
"component": true
}
nav.wxml
<view class="nav-item" bindtap="routeToFamily">
<image src='{{img_server_url}}/ic_status_{{imgName}}.png' mode="aspectFit"></image>
<view class="name">{{name}}</view>
<!-- 定义事件 -->
<button bindtap="onTap">点击这个按钮将触发“myevent”事件</button>
<slot name="before"></slot>
<slot name="after"></slot>
</view>
nav.wxss
.nav-item{
width:100%;
height:70rpx;
display: flex;
flex-direction: row;
align-items: center;
}
...
nav.js
//获取应用实例
const app = getApp();
Component({
options: {
// 在组件定义时的选项中启用多 slot 支持
multipleSlots: true,
// isolated 表示启用样式隔离
// apply-shared 表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面;
// shared 表示页面 wxss 和 组件wxss 相互影响
styleIsolation: 'isolated'
},
// 接收参数
properties: {
name: {
type: 'String'
},
type: {
type: 'String'
},
index:{
type:'Number'
}
},
data: {
img_server_url: app.globalData.img_server_url,
imgName:0,
setIcon:false
},
pageLifetimes: {
// 页面被展示
show: function () {
this.setData({
setIcon:true
});
this.setIcon();
}
},
ready(){
},
methods: {
onTap: function(){
var myEventDetail = {} // detail对象,提供给事件监听函数
var myEventOption = {} // 触发事件的选项
// 组件通信
this.triggerEvent('myevent', myEventDetail, myEventOption)
// 出发事件时,可传入配置
// { bubbles:事件是否冒泡,composed: 事件是否可以穿越组件边界,为 false 时,事件将只能在引用组件的节点树上触发,不进入其他任何组件内部,capturePhase:事件是否拥有捕获阶段}
this.triggerEvent('myevent', {}, { bubbles: true, composed: true })
},
setIcon:function(){
}
...
}
})
- 在index页面中使用自定义组件Nav
// index.json
{
"navigationBarTitleText": "样本",
"navigationStyle": "custom",
"usingComponents": {
"component-nav": "../../component/nav/nav",
"nav-bar": "../../component/navbar/index"
}
}
// index.wxml
<component-nav class="component-nav" bindmyevent="onMyEvent" type="family" name="点击编辑【户特征】">
<!-- 这部分内容将被放置在组件 <slot name="before"> 的位置上 -->
<view slot="before">这里是插入到组件slot name="before"中的内容</view>
<!-- 这部分内容将被放置在组件 <slot name="after"> 的位置上 -->
<view slot="after">这里是插入到组件slot name="after"中的内容</view>
</component-nav>
// index.js
Page({
// 这样可以获取到子组件
getChildComponent: function () {
// 调用组件时候,给起一个 id、class 都可以
const child = this.selectComponent('.component-nav'); // #
console.log(child)
}
onMyEvent: function(e){
// 自定义组件触发事件时提供的 detail 对象 数据
e.detail
}
})
-
3.4.9 页面跳转
- 使用API跳转
路由方式 | 功能描述 | 路由前页面 | 路由后页面 |
---|---|---|---|
navigateTo |
打开新页面 | onHide | onLoad, onShow |
redirectTo |
页面重定向 | onUnload | onLoad, onShow |
navigateBack |
页面返回 | onUnload | onShow |
switchTab |
Tab 切换 | onHide onUnload.. | onLoad B.onShow.. |
reLaunch |
重启动 | onUnload | onLoad, onShow |
共有 switchTab
reLaunch
redirectTo
navigateTo
navigateBack
五个方法,可以通过 this.pageRouter
、 this.router
、wx对象 wxNavAction
, 获得当前页面或自定义组件的路由器对象,进行跳转,功能相同;但有区别。
注意:
- navigateTo,redirectTo只能打开非 tabBar 页面。
- switchTab 只能打开 tabBar 页面。
- reLaunch 可以打开任意页面。
- 页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
- 调用页面路由带的参数可以在目标页面的onLoad中获取。
- 非tabba页面跳转 navigateTo、redirectTo、navigateBack等
// 保留当前页面,跳转到应用内的某个页面。
wx.navigateTo({
url: '/pages/calculator/calculator',
})
this.pageRouter.navigateTo({
url: '/pages/calculator/calculator',
})
this.router.navigateTo({
url: '/pages/calculator/calculator',
})
// 关闭当前页面,跳转到应用内的某个页面。
wx.redirectTo({
url: '/pages/calculator/calculatort?id=1'
})
this.pageRouter.redirectTo({
url: '/pages/calculator/calculatort?id=1'
})
// 关闭当前页面,返回上一页面或多级页面 参数是后退数
wx.navigateBack({
delta: 1 // 2 3
})
...
- tabbar页面跳转 wx.switchTab
wx.switchTab({
url: '/pages/calculator/calculator',
})
this.pageRouter.switchTab({
url: '/pages/calculator/calculator',
})
唯一的区别是,页面路由器中的方法调用时,相对路径永远相对于 this
指代的页面或自定义组件,比wx.navigateTo等方法稳定。
在使用相对路径跳转的时候
- 页面 index/index 的 js 代码如下所示。如果此时已经跳转到了一个新页面 pack/index ,然后才调用到上面的 wxNavAction 方法,跳转的新页面路径将是 pack/new-page ;而如果调用的是 routerNavAction 方法,跳转的新页面路径仍然是 index/new-page。
// com/index.js
Page({
wxNavAction: function () {
wx.navigateTo({
url: './new-page'
})
},
routerNavAction: function () {
// this.pageRouter
this.pageRouter.navigateTo({
url: './new-page'
})
}
})
- this.pageRouter 和 this.router区别
this.pageRouter 和 this.router 在页面中将获得同样的页面路由器对象。
但如果在自定义组件中调用, this.pageRouter 将相对于自定义组件所在的页面来进行路由跳转,而 this.router 相对于自定义组件自身的路径。
// components/ceshi/index.js
Component({
/**
* 组件的方法列表
*/
methods: {
goto(){
//路径:index/logs/logs
// wx.navigateTo({
// url: './logs/logs'
// })
//路径:index/logs/logs
// this.pageRouter.navigateTo({
// url: './logs/logs'
// })
//路径:ceshi/logs/logs
this.router.navigateTo({
url: './logs/logs'
})
}
}
})
// 使用组件
<!--index.wxml-->
<view class="container">
<ceshi/>
<button bindtap="bindViewTap">2222</button>
<!-- 引入 -->
</view>
-
使用组件标签navigator 跳转
navigator 页面链接
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
target | String | self | 在哪个目标上发生跳转,默认当前小程序,可选值self/miniProgram |
url | String | 应用内的跳转链接 | |
open-type | String | navigate | 跳转方式 |
delta | Number | 当 open-type 为 'navigateBack' 时有效,表示回退的层数 | |
app-id | String | 当target="miniProgram"时有效,要打开的小程序 appId | |
path | String | 当target="miniProgram"时有效,打开的页面路径,如果为空则打开首页 | |
extra-data | Object | 当target="miniProgram"时有效,需要传递给目标小程序的数据,目标小程序可在 App.onLaunch() ,App.onShow() 中获取到这份数据。 |
|
version | version | release | 当target="miniProgram"时有效,要打开的小程序版本,有效值 develop(开发版),trial(体验版),release(正式版),仅在当前小程序为开发版或体验版时此参数有效;如果当前小程序是正式版,则打开的小程序必定是正式版。 |
hover-class | String | navigator-hover | 指定点击时的样式类,当hover-class="none" 时,没有点击态效果 |
hover-stop-propagation | Boolean | false | 指定是否阻止本节点的祖先节点出现点击态 |
hover-start-time | Number | 50 | 按住后多久出现点击态,单位毫秒 |
hover-stay-time | Number | 600 | 手指松开后点击态保留时间,单位毫秒 |
bindsuccess | String | 当target="miniProgram"时有效,跳转小程序成功 | |
bindfail | String | 当target="miniProgram"时有效,跳转小程序失败 | |
bindcomplete | String | 当target="miniProgram"时有效,跳转小程序完成 |
open-type 有效值:
值 | 说明 | 最低版本 |
---|---|---|
navigate | 对应wx.navigateTo 的功能 |
|
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-hover
默认为{background-color: rgba(0, 0, 0, 0.1); opacity: 0.7;}
, <navigator/>
的子节点背景色应为透明色
<view class="btn-area">
<navigator url="/page/navigate/navigate?title=navigate" hover-class="navigator-hover">跳转到新页面</navigator>
<navigator url="../../redirect/redirect/redirect?title=redirect" open-type="redirect" hover-class="other-navigator-hover">在当前页打开</navigator>
<navigator url="/page/index/index" open-type="switchTab" hover-class="other-navigator-hover">切换 Tab</navigator>
<navigator target="miniProgram" open-type="navigate" app-id="" path="" extra-data="" version="release">打开绑定的小程序</navigator>
</view>
-
页面跳转传参
传输
直接放到页面路径后既可。示例:
// 查看地图分布
clickAllParkMap(){
var parkId=this.data.parkData[0].parkId;
wx.navigateTo({
url: "../park-map/park-map?inputValue="+this.data.inputValue+'&parkId='+parkId
});
},
// 点击单个
clickParkMap(e){
var index = e.currentTarget.dataset.text;
var parkId=this.data.parkData[index].parkId;
var parkName = this.data.parkData[index].parkName;
wx.navigateTo({
url: "../park-map/park-map?inputValue="+parkName+'&parkId='+parkId
});
},
获取
在页面的onLoad函数,接收参数 options 中获取,
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
var parkId=options.parkId || null;
var parkName=options.parkId || null;
},
-
3.4.10 提示、加载
- wx.showToast 显示消息提示框
- wx.hideToast 隐藏消息提示框
- wx.showModal 显示模态对话框
- wx.showLoading 显示 loading 提示框
- wx.hideLoading 关闭 loading 提示框
- wx.showActionSheet 显示操作菜单
- wx.showToast(option) 显示消息提示框
参数 | 类型 | 必填 | 说明 | |
---|---|---|---|---|
title |
String | 是 | 提示的内容 | |
icon |
String | 否 | 图标,有效值"success"、"error" 、"loading" 、"none" | |
image |
String | 否 | 自定义图标的本地路径,image 的优先级高于 icon | |
duration |
Number | 否 | 提示的延迟时间,单位毫秒,默认:1500 | |
mask |
Boolean | 否 | 是否显示透明蒙层,防止触摸穿透,默认:false | |
success |
Function | 否 | 接口调用成功的回调函数 | |
fail |
Function | 否 | 接口调用失败的回调函数 | |
complete |
Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
wx.showToast({
title: '成功',
icon: 'success',
duration: 2000
})
wx.hideToast()
- wx.showModal(option) 显示模态对话框
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
title |
String | 是 | 提示的标题 |
content |
String | 是 | 提示的内容 |
showCancel |
Boolean | 否 | 是否显示取消按钮,默认为 true |
cancelText |
String | 否 | 取消按钮的文字,默认为"取消",最多 4 个字符 |
cancelColor |
HexColor | 否 | 取消按钮的文字颜色,默认为"#000000" |
confirmText |
String | 否 | 确定按钮的文字,默认为"确定",最多 4 个字符 |
confirmColor |
HexColor | 否 | 确定按钮的文字颜色,默认为"#3CC51F" |
success |
Function | 否 | 接口调用成功的回调函数 |
fail |
Function | 否 | 接口调用失败的回调函数 |
complete |
Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
succes返回参数说明:
参数 | 类型 | 说明 |
---|---|---|
confirm | Boolean | 为 true 时,表示用户点击了确定按钮 |
cancel | Boolean | 为 true 时,表示用户点击了取消(用于 Android 系统区分点击蒙层关闭还是点击取消按钮关闭) |
wx.showModal({
title: '提示',
content: '这是一个模态弹窗',
success (res) {
if (res.confirm) {
console.log('用户点击确定')
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
- wx.showActionSheet(option) 显示操作菜单
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
itemList | String Array | 是 | 按钮的文字数组,数组长度最大为6个 |
itemColor | HexColor 否 | 按钮的文字颜色,默认为"#000000" | |
success | Function | 否 | 接口调用成功的回调函数,详见返回参数说明 |
fail | Function | 否 | 接口调用失败的回调函数 |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
success返回参数说明:
参数 | 类型 | 说明 |
---|---|---|
tapIndex | Number | 用户点击的按钮,从上到下的顺序,从0开始 |
wx.showActionSheet({
itemList: ['A', 'B', 'C'],
success (res) {
console.log(res.tapIndex)
},
fail (res) {
console.log(res.errMsg)
}
})
注意
-
wx.showLoading
和wx.showToast
同时只能显示一个 -
wx.showToast
应与wx.hideToast
配对使用
-
3.4.11 自定义导航栏
使用page.json中配置:navigationStyle 。 详情可以看我另外一片文章 自定义页面导航栏
属性 | 类型 默认值 | 描述 |
---|---|---|
navigationStyle |
string default | 导航栏样式,配置值:default 默认、custom 自定义,只保留右上角胶囊按钮 |
usingComponents |
Object 无 | 页面自定义组件配置 |
- 在对应页面的json中开启自定义顶部状态栏,且引入自定义的状态栏组件。
"navigationStyle": "custom",
"usingComponents": {
"nav-bar": "../../component/navbar/index"
}
- 自定义组件navbar
- 在 app.js中获取 手机的状态栏高度以及字体大小。wx.getSystemInfo()
onLaunch: function () {
//获取手机导航栏高度
wx.getSystemInfo({
success: res => {
var isIos = res.system.indexOf('iOS') > -1;
this.globalData.statusHeight = res.statusBarHeight;
this.globalData.navHeight = isIos ? 44 : 48;
this.globalData.fontSize = res.fontSizeSetting;
//设置低版本不显示自定义导航栏
if (res.SDKVersion && res.SDKVersion.split('.')[0] * 1 <= 2 && res.SDKVersion.split('.')[1] * 1 < 5){
this.globalData.navHeightHidden=true;
}
},
fail(err) {
console.log(err);
}
})
}
globalData: {
//自定义导航组件高度
navHeightHidden:false,
statusHeight:null,
navHeight:null,
fontSize:null,
}
- navbar.wxml
<!-- 如果版本低于2.5后,不显示自定义状态栏 -->
<block wx:if="{{navHeightHidden}}">
<view></view>
</block>
<block wx:else>
<view style="height:{{statusHeight+navHeight}}px" hidden='{{header.hiddenBlock}}'></view>
<view class='topbar' style="background:{{header.headerbg}}">
<view class='status' style="height:{{statusHeight}}px"></view>
<view class='navbar' style="height:{{navHeight}}px">
<block wx:if="{{header.slot}}">
<slot></slot>
</block>
<block wx:else>
<view class='navbar_home' wx:if="{{header.homeCapsule}}" style="background:{{header.capsulebg}};border:{{header.capsuleborder}}">
<image src='../../images/black_back.png' bindtap='backClick' style="border-right:{{header.capsulesep}}"></image>
<image src='../../images/home_black.png' bindtap='homeClick'></image>
</view>
<view class='navbar_back' bindtap='backClick' wx:else>
<image src='../../images/black_back.png'></image>
</view>
<view class='navbar_title' style="height:{{navHeight}}px">
<view style="color:{{header.fontColor}};font-size:{{fontSize}}px">{{header.title}}</view>
</view>
</block>
</view>
</view>
</block>
- navbar.wxss
.topbar {
position: fixed;
left: 0;
top: 0;
width: 100%;
z-index: 9999;
}
.status {
width: 100%;
}
...
- navbar.js
编写业务员逻辑,我的是点击左上角返回按钮的事件,弹窗提示要不要返回
var app = getApp();
Component({
properties: {
header: {
type: Object,
value: {
homeCapsule: false,
headerbg: "#fff",
title: "",
fontColor: "#000",
fontSize: '16',
hiddenBlock: false,
capsulebg: 'rgba(0,0,0,0.2)',
capsuleborder: '1px solid rgba(0, 0, 0, 0.1)',
capsulesep: '1px solid rgba(255,255,255,0.2)',
slot: false
}
},
customBackReturn: {
type: Boolean,
value: false
}
},
data:{
statusHeight: app.globalData.statusHeight,
navHeight: app.globalData.navHeight,
fontSize: app.globalData.fontSize,
navHeightHidden: app.globalData.navHeightHidden
},
methods: {
// 定义点击左上角返回按钮的函数
backClick() {
var me=this;
wx.showModal({
title: '提示',
content: '如有改动,请确认是否已点击【保存】',
success(res) {
if (res.confirm) {
if (me.data.customBackReturn) {
me.triggerEvent("customBackReturn")
} else {
if (getCurrentPages().length == 1) {
wx.switchTab({
url: '/pages/index/index',
})
} else {
wx.navigateBack({
delta: 1
})
}
}
} else if (res.cancel) {
}
}
})
},
homeClick() {
wx.switchTab({
url: '/pages/index/index',
})
}
}
})
- 组件的json index.json
{
"component": true
}
- 使用组件
- 在对应页面的json中开启自定义顶部状态栏,且引入自定义的状态栏组件。
"navigationStyle": "custom",
"usingComponents": {
"nav-bar": "../../component/navbar/index"
}
- 在对应页面的js中写好定义的组件状态和标题名
//自定义顶部 参数直接能看懂
nvabarData: {
homeCapsule: false,
title: '户特征',
fontColor: "white",
fontSize: '26rpx',
headerbg: '#04aceb',
hiddenBlock: false,
slot: false
},
// 整个导航栏高度
navHeight: app.globalData.navHeight + app.globalData.statusHeight,
// 是否显示自定义导航栏(为低版本)
navHeightHidden: app.globalData.navHeightHidden,
- 在index 中使用自定义组件
<!-- 自定义顶部 -->
<nav-bar header='{{nvabarData}}'></nav-bar>
// 我的页面用的是100% 高度的布局, 所有要减去这个状态栏的高度
<view class="container" style="height: calc( 100% - {{navHeightHidden?0:navHeight}}px );"></view>
四、常用功能
4.1 常用小程序api
-
4.1.1 数据缓存 官方API地址
wx.setStorage(option)
将数据存储在本地缓存中指定的key中,会覆盖掉原来该key对应的内容,这是一个异步接口。
设置setStorage、获取getStorage、删除removeStorage
OBJECT参数说明
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
key | String | 是 | 本地缓存中的指定的 key |
data | Object/String | 是 | 需要存储的内容 |
success | Function | 否 | 接口调用成功的回调函数 |
fail | Function | 否 | 接口调用失败的回调函数 |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
Page({
data: {
logs: []
},
onLoad() {
// 设置
wx.setStorage({
key:"key11",
data:"value"
})
// 获取
wx.getStorage({
key: 'key11',
success (res) {
// 直接就是对象
console.log(res.data)
}
})
// 批量读取 数组
wx.batchGetStorage({
keyList: ['key11'],
success (res) {
console.log(res)
}
})
// 删除
wx.removeStorage({
key: 'key',
success (res) {
console.log(res)
}
})
}
})
-
wx.setStorageSync(option)
将data存储在本地缓存中指定的key中,会覆盖掉原来该key对应的内容,这是一个同步接口。
设置setStorageSync、获取getStorageSync、删除removeStorageSync
OBJECT参数说明
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
key | String | 是 | 本地缓存中的指定的key |
data | Object/String | 是 | 需要存储的内容 |
Page({
data: {
regionData:null
},
onLoad() {
// 设置
wx.setStorageSync('regionData', {a:1,b:2});
// 获取 直接就是对象
var regionData = wx.getStorageSync('regionData') || '';
// 删除
wx.removeStorageSync('regionData');
}
})
-
wx.batchSetStorageSync(option) 批量存储
Array.<Object> kvList,将数据批量存储在本地缓存中指定的 key 中,单个 key 允许存储的最大数据长度为 1MB,所有数据存储上限为 10MB。这是一个同步接口。
等同于多个setStorageSync ,但是对于多个 key 的读取, 批量读取在性能上优于多次 getStorageSync 读取
OBJECT参数说明 Array.<Object> kvList
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
key | String | 是 | 本地缓存中的指定的key |
data | Object/String | 是 | 需要存储的内容 |
Page({
data: {
regionData:null
},
onLoad() {
// 设置
wx.batchSetStorageSync([
{key: 'key1', value: '1'},
{key: 'key2', value: {a:1,b:2} }
])
// 获取
var valueList = wx.batchGetStorageSync(['key1','key2'])
// ["1", "2"]
// 删除
// 使用removeStorageSync 单个删除;
}
})
以上三类存储API,注意事项:
1:存储同样的key,会覆盖掉原来该 key 对应的内容。
2:除非用户主动删除或因存储空间原因被系统清理,否则数据都一直可用。
-
4.1.2 微信小程序画布 canvas
微信小程序标签组件:canvas
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
---|---|---|---|---|---|
type | string | 否 | 指定 canvas 类型,支持 2d (2.9.0) 和 webgl (2.7.0) | 2.7.0 | |
canvas-id | string | 否 | canvas 组件的唯一标识符,若指定了 type 则无需再指定该属性 | 1.0.0 | |
disable-scroll | boolean | false | 否 | 当在 canvas 中移动时且有绑定手势事件时,禁止屏幕滚动以及下拉刷新 | 1.0.0 |
bindtouchstart | eventhandle | 否 | 手指触摸动作开始 | 1.0.0 | |
bindtouchmove | eventhandle | 否 | 手指触摸后移动 | 1.0.0 | |
bindtouchend | eventhandle | 否 | 手指触摸动作结束 | 1.0.0 | |
bindtouchcancel | eventhandle | 否 | 手指触摸动作被打断,如来电提醒,弹窗 | 1.0.0 | |
bindlongtap | eventhandle | 否 | 手指长按 500ms 之后触发,触发了长按事件后进行移动不会触发屏幕的滚动 | 1.0.0 | |
binderror | eventhandle | 否 | 当发生错误时触发 error 事件,detail = {errMsg} | 1.0.0 |
注意事项:
- canvas 标签默认宽度300px、高度150px
- 同一页面中的 canvas-id 不可重复,如果使用一个已经出现过的 canvas-id,该 canvas 标签对应的画布将被隐藏并不再正常工作
- 请注意原生组件使用限制
- 开发者工具中默认关闭了 GPU 硬件加速,可在开发者工具的设置中开启“硬件加速”提高 WebGL 的渲染性能
- WebGL 支持通过 getContext('webgl', { alpha: true }) 获取透明背景的画布
- Canvas 2D(新接口)需要显式设置画布宽高 (默认为 300x150)
- 避免设置过大的宽高,在安卓下会有crash的问题
- Canvas 2D 示例代码
<!-- canvas.wxml -->
<canvas type="2d" id="myCanvas"></canvas>
// canvas.js
Page({
onReady() {
const query = wx.createSelectorQuery()
query.select('#myCanvas')
.fields({ node: true, size: true })
.exec((res) => {
const canvas = res[0].node
const ctx = canvas.getContext('2d')
const dpr = wx.getSystemInfoSync().pixelRatio
canvas.width = res[0].width * dpr
canvas.height = res[0].height * dpr
ctx.scale(dpr, dpr)
ctx.fillRect(0, 0, 100, 100)
})
}
})
- WebGL 示例代码
<!-- canvas.wxml -->
<canvas type="webgl" id="myCanvas"></canvas>
// canvas.js
Page({
onReady() {
const query = wx.createSelectorQuery()
query.select('#myCanvas').node().exec((res) => {
const canvas = res[0].node
const gl = canvas.getContext('webgl')
gl.clearColor(1, 0, 1, 1)
gl.clear(gl.COLOR_BUFFER_BIT)
})
}
})
- 示例
Page({
data: {
},
// 画背景
drawProgressbg: function () {
// 使用 旧api绘制 + 新api 自动适配圆圈大小
const query = wx.createSelectorQuery();
query.select('#canvasProgressbg')
.fields({ node: true, size: true })
.exec((res) => {
// 获取 px -> rpx 比例
// const dpr = wx.getSystemInfoSync().pixelRatio;
var width = res[0].width;
var height = res[0].height;
var ctx = wx.createCanvasContext('canvasProgressbg', this)
ctx.setLineWidth(4);// 设置圆环的宽度
ctx.setStrokeStyle('#e2e0e0'); // 设置圆环的颜色
ctx.setLineCap('round') // 设置圆环端点的形状
ctx.beginPath();//开始一个新的路径
var radius = (height - 26) / 2;
//设置圆的路径到当前路径
ctx.arc(width / 2, height / 2, radius, 0, 2 * Math.PI, false);
ctx.stroke();//对当前路径进行描边
ctx.draw();
})
},
// 画公交线路倒计时 参数: step=( 到站秒数 / (900/2) ) 最大900s
drawCircle: function (step) {
// 使用 旧api绘制 + 新api 自动适配圆圈大小
const query = wx.createSelectorQuery();
query.select('#canvasProgress')
.fields({ node: true, size: true })
.exec((res) => {
// 获取 px -> rpx 比例
// const dpr = wx.getSystemInfoSync().pixelRatio;
var width = res[0].width;
var height = res[0].height;
var ctx = wx.createCanvasContext('canvasProgress', this);
// 设置渐变
var gradient = ctx.createLinearGradient(200, 100, 100, 200);
gradient.addColorStop("0", "#77d0dc");
gradient.addColorStop("0.5", "#1db1c6");
gradient.addColorStop("1.0", "#09b1c7");
ctx.setLineWidth(6);
ctx.setStrokeStyle(gradient);
ctx.setLineCap('round')
ctx.beginPath();
var radius = (height - 30) / 2;
// 参数step 为绘制的圆环周长,从0到2为一周 。 -Math.PI / 2 将起始角设在12点钟位置 ,结束角 通过改变 step 的值确定
ctx.arc(width / 2, height / 2, radius, -Math.PI / 2, step * Math.PI - Math.PI / 2, false);
ctx.stroke();
// 画跟随的圆圈 内圆
var e = step * Math.PI - Math.PI / 2;
ctx.beginPath()
let x, y, r1 = 8;
// 通过三角函数计算x y 坐标
x = radius * Math.cos(e) + width / 2;
y = radius * Math.sin(e) + width / 2;
ctx.arc(x, y, r1, 0, 2 * Math.PI)
ctx.fillStyle = 'rgba(29,177,198,1)';
ctx.fill()
ctx.closePath()
// 外圆
ctx.beginPath()
let r2 = 15
ctx.arc(x, y, r2, 0, 2 * Math.PI);
ctx.fillStyle = 'rgba(29,177,198,0.5)'
ctx.fill()
ctx.closePath();
ctx.draw();
})
},
})
-
4.1.3 相机 wx.chooseImage
使用接口:wx.chooseImage(Object object)从本地相册选择图片或使用相机拍照。具体可看我另外一篇文章 微信小程序调用相机
参数
属性 | 类型 | 说明 |
---|---|---|
width | number | 图像数据矩形的宽度 |
height | number | 图像数据矩形的高度 |
data | ArrayBuffer | 图像像素点数据,一维数组,每四项表示一个像素点的 rgba |
返回值参数
属性 | 类型 | 默认值 | 必填 |
---|---|---|---|
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
success 返回值 res
属性 | 类型 | 说明 |
---|---|---|
tempThumbPath | string | 封面图片文件的临时路径 (本地路径) |
tempVideoPath | string | 视频的文件的临时路径 (本地路径) |
Page({
data: {
carWin_img_hidden:true, //展示照片的view是否隐藏
carWin_img:'' //存放照片路径的
},
//页面加载设置初始值 可以不要
onReady(res){
this.setData({
carWin_img_hidden: true,
carWin_img: ''
});
},
//点击事件
clickCarWin(){
var that = this;
wx.chooseImage({
count: 1,
success: function (res) {
// 无论用户是从相册选择还是直接用相机拍摄,路径都是在这里面
var filePath = res.tempFilePaths[0];
//将刚才选的照片/拍的 放到下面view视图中
that.setData({
carWin_img: filePath, //把照片路径存到变量中,
carWin_img_hidden: false //让展示照片的view显示
});
// 这个是使用微信接口保存文件到数据库
// wx.uploadFile({
// url: "",
// filePath: filePath,
// name: 'file',
// success: function (res) {
// }
// })
},
fail: function (error) {
console.error("调用本地相册文件时出错")
console.warn(error)
},
complete: function () {
}
});
}
})
-
4.1.4 获取位置
获取用户位置信息,共需要使用以下三个api:
- wx.getSetting 获取用户授权信息列表
- wx.authorize 向用户发起授权请求
- wx.getLocation 获取用户位置信息
-
wx.getSetting(option)
获取用户的当前设置。*返回值中只会出现小程序已经向用户请求过的权限。
option 参数说明
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
withSubscriptions | Boolean | false | 是否同时获取用户订阅消息的订阅状态,默认不获取。 |
success | function | 接口调用成功的回调函数 | |
fail | function | 接口调用失败的回调函数 | |
complete | function | 接口调用结束的回调函数(调用成功、失败都会执行) |
success 回调函数
属性 | 类型 | 说明 | |
---|---|---|---|
authSetting | AuthSetting | 用户授权结果 | |
subscriptionsSetting | SubscriptionsSetting | 用户订阅消息设置,接口参数withSubscriptions 值为true 时才会返回。 |
|
miniprogramAuthSetting | AuthSetting | 在插件中调用时,当前宿主小程序的用户授权结果 |
wx.getSetting({
success (res) {
console.log(res.authSetting)
// res.authSetting = {
// "scope.userInfo": true,
// "scope.userLocation": true
// }
}
})
-
wx.authorize (option)
用户授权名称列表 可查看 授权scope 列表
option参数说明
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
scope | string | 是 | 需要获取权限的 scope |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
// 可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.record" 这个 scope
wx.getSetting({
success(res) {
// 查询用户是否授权位置信息
if (!res.authSetting['scope.userLocation']) {
// 调用位置授权
wx.authorize({
scope: 'scope.userLocation',
success() { }
})
}
}
})
-
wx.getLocation(option)
获取当前的地理位置、速度。当用户离开小程序后,此接口无法调用;当用户点击“显示在聊天顶部”时,此接口可继续调用。
option参数说明
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
type | String | 否 | 默认为"wgs84"返回gps坐标,"gcj02"返回可用于wx.openLocation的坐标 |
success | Function | 是 | 接口调用成功的回调函数,返回内容详见返回参数说明。 |
fail | Function | 否 | 接口调用失败的回调函数 |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
success返回参数说明
参数 | 说明 |
---|---|
latitude | 纬度,浮点数,范围为-90~90,负数表示南纬 |
longitude | 经度,浮点数,范围为-180~180,负数表示西经 |
speed | 速度,浮点数,单位m/s |
accuracy | 位置的精确度 |
altitude | 高度,单位 m |
verticalAccuracy | 垂直精度,单位 m(Android 无法获取,返回 0) |
horizontalAccuracy | 水平精度,单位 m |
wx.getLocation({
type: 'wgs84',
success (res) {
const latitude = res.latitude
const longitude = res.longitude
const speed = res.speed
const accuracy = res.accuracy
}
})
- 获取用户位置信息示例
- 第一步:在app.json中申明
{
"pages": [
"pages/index/index"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle": "black"
},
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序首页获取附近公交站点"
}
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
- 第二步:提前让用户授权,示例在app.js中调用wx.getSetting、wx.authorize 弹窗让用户授权
// app.js
App({
onLaunch() {
// 位置授权
wx.getSetting({
success(res) {
if (!res.authSetting['scope.userLocation']) {
wx.authorize({
scope: 'scope.userLocation',
success() { }
})
}
}
})
},
globalData: {
userInfo: null
}
})
- 第三步:在需要获取位置的地方,调用获取
<!--index.wxml-->
<view class="container">
<map id="myMap" show-location />
<button type="primary" bindtap="getCenterLocation">获取位置</button>
<button type="primary" bindtap="moveToLocation">移动位置</button>
<button type="primary" bindtap="translateMarker">移动标注</button>
<button type="primary" bindtap="includePoints">缩放视野展示所有经纬度</button>
</view>
// map.js
Page({
onReady: function (e) {
// 使用 wx.createMapContext 获取 map 上下文
this.mapCtx = wx.createMapContext('myMap')
},
getCenterLocation: function () {
this.mapCtx.getCenterLocation({
success: function(res){
console.log(res.longitude)
console.log(res.latitude)
}
})
},
moveToLocation: function () {
this.mapCtx.moveToLocation()
},
translateMarker: function() {
this.mapCtx.translateMarker({
markerId: 0,
autoRotate: true,
duration: 1000,
destination: {
latitude:23.10229,
longitude:113.3345211,
},
animationEnd() {
console.log('animation end')
}
})
},
includePoints: function() {
this.mapCtx.includePoints({
padding: [10],
points: [{
latitude:23.10229,
longitude:113.3345211,
}, {
latitude:23.00229,
longitude:113.3345211,
}]
})
}
})
-
4.1.5 屏幕操作
-
设置屏幕亮度:wx.setScreenBrightness()
参数值:value 0-1,越大越亮
if (wx.setScreenBrightness) {
//设置屏幕亮度 参数值:0-1,越大越亮
wx.setScreenBrightness({
value: 0.6
});
} else {
// 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示
wx.showModal({
title: '提示',
content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
})
}
- 获取屏幕亮度 wx.getScreenBrightness()
if (wx.getScreenBrightness) {
//获取屏幕亮度 值:0-1,越大越亮
success: function (res) {
// res.value
},
fail: function () {
//请求失败
}
} else {
// 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示
wx.showModal({
title: '提示',
content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
})
}
以上两个方法可以配合使用,设置前记得先获取一下屏幕亮度,存起来,设置好亮度等不需要这么亮或用户退出程序时候,在给设置回去,这样用户体验好一些。
注:记得别忘记用户退出程序或者是某个界面时,恢复一下了亮度。
-
设置屏幕常亮 wx.setKeepScreenOn
参数值: true / false
if (wx.setScreenBrightness) {
// 保持屏幕常亮 true / false
wx.setKeepScreenOn({
keepScreenOn: false
});
} else {
// 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示
wx.showModal({
title: '提示',
content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
})
}
注:记得别忘记用户退出程序或者是某个界面时,重新设置一下不常亮。
-
4.1.6 扫码 wx.scanCode
调起客户端扫码界面进行扫码
option参数说明
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
onlyFromCamera | boolean | false | 是否只能从相机扫码,不允许从相册选择图片 |
scanType | Array.<string> | ['barCode', 'qrCode'] | 扫码类型 |
success | function | 接口调用成功的回调函数 | |
fail | function | 接口调用失败的回调函数 | |
complete | function | 接口调用结束的回调函数(调用成功、失败都会执行) |
object.scanType 的合法值
值 | 说明 |
---|---|
barCode | 一维码 |
qrCode | 二维码 |
datamatrix | Data Matrix 码 |
pdf417 | PDF417 条码 |
success res
属性 | 类型 | 说明 |
---|---|---|
result | string | 所扫码的内容 |
scanType | string | 所扫码的类型 |
charSet | string | 所扫码的字符集 |
path | string | 当所扫的码为当前小程序二维码时,会返回此字段,内容为二维码携带的 path |
rawData | string | 原始数据,base64编码 |
// 允许从相机和相册扫码
wx.scanCode({
success (res) {
console.log(res)
}
})
// 只允许从相机扫码
wx.scanCode({
onlyFromCamera: true,
success (res) {
console.log(res)
}
})
4.2 第三方插件使用
微信官方及第三方等提供了很多优秀的小程序页面插件,如:腾讯位置服务地图选点、腾讯位置导航等,使用方式相同,均是无缝跳转到插件小程序页面
-
在微信公众平台中配置插件
“微信小程序官方后台-设置-第三方服务-插件管理” 里点击 “添加插件”,如:搜索 “腾讯位置服务地图选点” 申请,审核通过后,小程序开发者可在小程序内使用该插件。
-
引入插件包
点击插件详情,既可看到插件APPid
- 在app.json中配置使用插件
{
"pages": [
"pages/index/index",
"pages/logs/logs",
"components/ceshi"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle": "black"
},
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序首页获取附近公交站点"
}
},
"plugins": {
"routePlan": {
"version": "1.0.5",
"provider": "wx76a9a06e5b4e693e"
}
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
-
设置定位授权
地图选点插件需要小程序提供定位授权才能够正常使用定位功能:
// app.json
{
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序定位"
}
}
}
-
使用插件
插件页面调用示例:
const key = ''; //使用在腾讯位置服务申请的key
const referer = ''; //调用插件的app的名称
// 初始位置的经纬度,如果不传 默认当前位置
const location = JSON.stringify({
latitude: 39.89631551,
longitude: 116.323459711
});
const category = '生活服务,娱乐休闲';
wx.navigateTo({
url: 'plugin://chooseLocation/index?key=' + key + '&referer=' + referer + '&location=' + location + '&category' + category
});
- 插件返回数据
//地图返回 在页面的 onShow中 获取数据返回。
const location = chooseLocation.getLocation();
// 返回的数据放在这个对象里面
if (location) {
allData.address_name = location.name;
allData.address = location.address;
allData.address_poi = location.latitude + ',' + location.longitude;
}
效果如下
4.3 微信扫码快捷打开小程序页面
微信公众平台开放扫描普通链接二维码跳转小程序能力。
普通链接二维码,是指开发者使用工具对网页链接进行编码后生成的二维码。
线下商户可不需更换线下二维码,在小程序后台完成配置后,即可在用户扫描普通链接二维码时打开小程序,使用小程序的功能。
对于普通链接二维码,目前支持使用微信“扫一扫”或微信内长按识别二维码跳转小程序。
-
登录小程序后台
进入“设置-开发设置-扫普通链接二维码打开小程序”,开启功能后即可配置二维码规则。
- 配置规则
- 二维码规则
二维码规则的域名须通过ICP备案的验证。
支持http、https、ftp开头的链接,一个小程序帐号可配置不多于10个二维码前缀规则。
- 前缀占用规则
可选择是否占用符合二维码匹配规则的所有子规则。如选择占用,则其他帐号不可申请使用满足该前缀匹配规则的其他子规则。
如:若开发者A配置二维码规则:http://aaa/mp?id=123,并选择“占用所有子规则“,其他开发者将不可以配置满足前缀匹配的子规则
下载随机校验文件,并将文件上传至服务器指定位置的目录下(你填写的这个链接,加上这个校验文件名称,必须能访问到,如:http://aaa/mp/rOO4daUTUI.txt),方可通过所属权校验。
根据要求填写好下列选项
如:
-
制作二维码
使用二维码工具制作二维码:如 草料二维码
将域名放入,可传参,小程序对应页面可接收参数,方法同路由跳转接收参数一样。生成二维码, 然后就可以使用微信扫描这个二维码进入小程序对应页面。
如:its.***.com/ft-xcx?a=1&b=2
4.4 地图
map组件提供了地图展示、交互、叠加点线面及文字等功能,同时支持个性化地图样式,可结合地图服务 API 实现更丰富功能,这里简单说一下, 不过多讲解,内容很多,详情去文档看既可。。 微信文档-map
个性化地图
个性化地图能力可在小程序后台“开发-开发者工具-腾讯位置服务”申请开通。 小程序内地图组件应使用同一 subkey,可通过 layer-style(地图官网设置的样式 style 编号)属性选择不同的底图风格。 组件属性的长度单位默认为px,2.4.0起支持传入单位(rpx/px)。。
示例
<!-- line-map -->
<view class='station_map'>
<map
class='map'
subkey="3A4BZ-TMKEP-OPEDL-VCRQ7-HUJZ5-TJBYJ"
id="station_map"
longitude="{{longitude}}"
latitude="{{latitude}}"
scale="14"
markers="{{markers}}"
polyline="{{polyline}}"
show-location
></map>
</view>
// pages/line/line.js
const Common = require("../../../utils/common.js");
//获取应用实例
const app = getApp();
Component({
properties:{
stations: {
type: 'Object',
value: {}
},
lineId: {
type: 'String',
value:''
}
},
data: {
// 图片链接
img_server_url: app.globalData.img_server_url,
latitude: 22.533773,
longitude: 114.057678,
markers: [],
polyline: [],
controls: []
},
ready(){
var markers = [];
for (var i = 0; i < this.data.stations.length; i++) {
var station = this.data.stations[i];
var poi = Common.wgs84togcj02(station.lng, station.lat);
markers.push({
id: i,
iconPath:"./images/station_icon1.png",
latitude: poi[1],
longitude: poi[0],
width: 20,
height: 20,
callout: {
content: '站名:' + station.station_name,
color: '#000',
fontSize: '24rpx',
padding: '10rpx',
bgColor: '',
borderRadius: '10rpx'
}
})
}
var poi = Common.wgs84togcj02(this.data.stations[0].lng, this.data.stations[0].lat);
this.setData({
markers: markers,
latitude: poi[1],
longitude: poi[0],
});
wx.showLoading({
title: '加载中···',
mask: true
});
var me = this;
let param = {
lineId: this.data.lineId
};
var url = app.globalData.request_server_url + "/wechat/getLineGeom";
Common.fetchGet(url, param, function (records) {
wx.hideLoading();
let lineGeo = records.message.replace(/\w+/, '');
lineGeo = lineGeo.replace(/\(|\)/g, '');
lineGeo=lineGeo.split(',');
var points = lineGeo.map( (item)=>{
item = item.replace(/^\s+/,'');
item=item.split(' ');
var poi = Common.wgs84togcj02(item[0], item[1]);
return {
longitude: poi[0],
latitude: poi[1]
}
});
var polyline=[{
points: points,
color: '#09b1c7',
borderColor:'#2f7f39',
borderWidth:2,
width: 5
}];
me.setData({
polyline: polyline
})
});
},
method:{
}
})
4.5 echarts使用
- 下载echarts
下载echarts微信版 地址:https://github.com/ecomfe/echarts-for-weixin
下载后打开,如图所示:
将下载好的文件中 ec-canvas目录 放在小程序项目目录中即可。如下图所示:
然后在需要的地方引入即可。
效果
示例
在页面开启使用echarts
如:在 page目录的ceshi页面中使用echarts的话,需要在ceshi.json中添加以下配置。
"usingComponents": {
"ec-canvas": "../../ec-canvas/ec-canvas"
}
- 引入
在 ceshi.js 中引入echarts.js
import * as echarts from '../../ec-canvas/echarts';
- wxml元素
在ceshi.wxml中建立一个元素,外层用view包一下是方便设置echarts元素的宽高。
<view class="echart_panel">
<ec-canvas></ec-canvas>
</view>
- 开始编写图表 折线图
我是在ceshi.js中直接写了一个函数,传一些参数,返回一个option,至于echarts的option写法,可以参考echats官网api文档。
function getOption(xData, data_cur, data_his) {
var option = {
backgroundColor: "#f5f4f3",
color: ["#37A2DA", "#f2960d", "#67E0E3", "#9FE6B8"],
title: {
text: '实时运行速度',
textStyle: {
fontWeight: '500',
fontSize: 15,
color: '#000'
},
x:'center',
y:'0'
},
legend: {
data: ['今日', '昨日'],
right: 10
},
grid: {
top: '15%',
left: '1%',
right: '3%',
bottom: '60rpx',
containLabel: true
},
tooltip: {
show: true,
trigger: 'axis'
},
xAxis: {
type: 'category',
boundaryGap: false,
data: xData||[],
axisLabel: {
interval: 11,
formatter: function (value, index) {
return value.substring(0, 2) * 1;
},
textStyle: {
fontsize: '10px'
}
}
},
yAxis: {
x: 'center',
name: 'km/h',
type: 'value',
min: 0,
max: 120
},
series: [{
name: '今日',
zIndex:2,
type: 'line',
smooth: true,
symbolSize: 0,
data: data_cur||[]
},{
name: '昨日',
zIndex: 1,
type: 'line',
smooth: true,
symbolSize: 0,
data: data_his||[]
}]
};
return option;
}
然后就可以在 页面page中的data中配置初始化,如何初始化?
首先 建立一个全局变量(注意,放在page外面,要全局变量,不然你在页面加载之后,在动态修改图表数据的话,没法修改,这样方便点),
然后在data中初始化echats对象 ecLine,名字随便起,按照官方写法即可,onInit函数中参数有三个,canvas, width, height,这些都不需要管,直接初始化echats元素。复制粘贴即可。
let chartLine;
Page({
data: {
ecLine: {
onInit: function (canvas, width, height){
//初始化echarts元素,绑定到全局变量,方便更改数据
chartLine = echarts.init(canvas, null, {
width: width,
height: height
});
canvas.setChart(chartLine);
//可以先不setOption,等数据加载好后赋值,
//不过那样没setOption前,echats元素是一片空白,体验不好,所有我先set。
var xData = [1,2,3,4,5......]; // x轴数据 自己写
var option = getOption(xData);
chartLine.setOption(option);
}
}
}
})
然后将建立的echats对象绑定到echarts元素中,如下:
<view class="echart_panel">
<ec-canvas ec="{{ ecLine }}"></ec-canvas>
</view>
然后就可以在数据加载后,给图表赋值option了,或者是重新setOption的数据。
//ajax请求好数据后,调用获取option函数,传一些数据,
//然后用全局变量echarts元素chartLine 来 setOption即可。
// 三个参数: x轴数据,第一条线数据,第二条数据。 随意,echarts就跟正常用随便写就行
// 随便写几个假数据
var xData=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23];
var data_cur=[55,67,66,78,55,67,66,78,55,67,66,78,55,67,66,78,55,67,66,78,65,66,65,54];
var data_his=[67,66,78,65,66,65,54,67,66,78,65,66,65,54,67,66,78,65,66,65,54,67,66,78];
// 方法一:
var option = getOption(xData, data_cur, data_his);
chartLine.setOption(option);
// 方法二:
//如果上面初始化时候,已经chartLine已经setOption了,
//那么建议不要重新setOption,官方推荐写法,重新赋数据即可。
chartLine.setOption({
xAxis: {
data: xData
},
series: [{
data: data_cur
}, {
data: data_his
}]
});
效果如下:
示例写的折线图,其他类型图表,可以参考echarts官网文档即可。
因为从github下载的echarts.js包含类型比较多,如果上传代码进行发布时,提示echarts文件过大,可以忽略。
或者是自己重新下载echarts定制需要的组件,如我就需要折线图,我就定制带折线图的即可。然后直接替换文件夹中的echarts.js即可。
下载定制echarts官网链接:http://echarts.baidu.com/builder.html
五、上传、发布
小程序打包发布等都很简单,流程:
- 从微信开发工具上面上传代码到微信公众平台
- 使用小程序账号登录,进入管理-版本管理,选择发布 正式版、体验版 既可。
-
配置域名
登录微信公众平台-点击开发管理-开发设置,往下拉进去配置合法域名
上传
-
发布
进入管理-版本管理,选择刚才提交的版本,点击提交审核发布既可,或者点击小三角,选择选为体验版。
六、小程序开发技术选型(不限于微信小程序)
-
原生开发
使用小程序原生开发,很方便,官方提供了非常详细的组件、API等,文档也很丰富,开发者社区等。
优点
- 官方文档清晰明了,更接近手机服务的底层逻辑,开发者可以更有针对性的对小程序进行深度开发
- 小程序原生平台社区更加活跃
- 使用原生开发可以紧随官方的版本,更新响应速度快,让项目达到最优状态
- 完美适配,不会出现适配问题
- 原生开发的功能更加完善,可以优秀的调用小程序API使用手机各种功能
缺点
- 仅适用于单个平台的小程序
- 开发成本高,开发不同平台下的小程序,需要不同的开发工具及语法
- 维护成本高,同样的项目需要写多套代码,后期维护起来工作量大成本高,
- 原生组件样式不太美观,需要专门写css美化
-
uni-app
uniapp是跨端的快速开发工具,当前支持微信小程序、百度小程序、头条小程序、qq小程序等14个平台,一套代码适应多个平台。 支持原生代码混写和原生sdk集成,通过条件编译+平台特有API调用,可以优雅的为某平台写个性化代码,调用专有能力而不影响其他平台。
优点
- 多端开发,一套代码可打包超多个不同平台,生成各种小程序H5及APP应用,不需来回切换各种开发工具
- 学习成本低,uni-app基于通用的前端技术栈,采用vue语法+微信小程序api,无额外学习成本
- 插件市场, uni-app拥有上千款的插件,支持NPM、支持平台小程序组件和SDK
- 组件丰富,样式漂亮
- 微信小程序依赖于微信的一键登录非常方便,uniapp不但能使用微信登录,而且还有一套自己的用户管理系统
缺点
- 完善性差,uni-app问世的时间还比较短,坑多,不过官方版本更新活跃,相信这些问题逐渐都会得到解决
- 兼容问题,uni-app打包出来的小程序可能会存在平台兼容问题,同样的代码会在不同平台下存在差异,如微信小程序、支付宝小程序。
- 如更新不及时,就不能紧随平台小程序,使用不了小程序平台发布的新功能
- 文档比较松散,社区质量不如小程序平台
其他类似uni-app的框架
taro、yonbuilder总结
项目只做单平台的小程序,原生是最优的选择
项目同时开发多平台小程序,使用uni-app最优选择