赞
踩
小程序是一个全新的、轻量级的移动端应用。
在小程序出现之前的移动端开发的解决方案有:
移动端开发发展了一段时间之后也暴漏出来一些问题,传统 App (Android / iOS)的开发和运营成本很高:
为了解决传统 App 的这些问题,小程序应运而生。
最早推出小程序的是微信团队。
小程序上线之后取得了巨大的成功,这导致一些其它平台也跟风上线了小程序的内容,如支付宝、京东、今日头条、百度。
微信小程序推出的最早且目前最有影响力(后文默认介绍微信小程序)。
小程序的运行环境与网页开发不同:
所以小程序与网页开发有一些区别:
小程序的运行环境主要有两个:
不同的操作系统,内部的支持也不一样:
运行环境 | 逻辑层 | 渲染层 |
---|---|---|
iOS | JSCore | WKWebView |
Android | V8 引擎 | Chromium 定制内核 |
虽然不同操作系统的渲染机制和逻辑不一样,但外部的表现是一样的。
下面通过案例学习微信小程序的基础使用,主要包括:
在小程序官网注册:https://mp.weixin.qq.com/wxopen/waregister?action=step1
注意:注册过微信公众号的邮箱,不能再注册微信小程序账号
也可以申请测试号,免注册快速体验小程序开发(不能发布)。
注册成功后,可以在后台获取小程序的 AppID,它是小程序的唯一标识。
去小程序官网,下载安装微信开发者工具:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
详细界面介绍参考官网文档:界面
打开微信开发者工具新建小程序项目:
“不使用模板” 与 “JavaScript - 基础模板” 基本没区别。
本文创建的项目:
下面依次解读小程序初始化项目:
官方文档:
全局文件存放在根目录,文件名是固定的,不能修改,其中包括:
页面文件存放在 pages 文件夹下,初始包括 index 和 logs 两个页面,每个页面由四个文件组成,以 index 为例:
需要注意的是:
.js
、.json
、.wxml
、.wxss
,四个文件的文件名必须一致app.json
的 pages
,保存文件后就会自动创建页面文件例如:
"pages": [
// 未指定 entryPagePath 时,数组的第一项代表小程序的初始页面(首页)
"pages/index/index",
"pages/logs/logs",
// pages 是页面存放目录
// test 是页面存放的子目录
// my-test 是页面文件名称
"pages/test/my-test"
],
小程序生命周期主要指两个循环状态:前台到后台、初始化到销毁。
关于前后台的定义参考官方文档:小程序运行机制
小程序中的生命周期有两类:
常用小程序生命周期函数及触发时机:
// app.js App({ onLaunch() { console.log('onLaunch - 小程序加载') // 默认初始代码... }, onShow() { console.log('onShow - 小程序显示') }, onHide() { console.log('onHide - 小程序隐藏') }, globalData: { userInfo: null } })
保存文件后,小程序会重新初始化,依次触发 onLaunch
和 onShow
。
可点击工具栏上的 切后台
切换到后台触发 onHide
。
PS:如果工具栏没有
切后台
按钮,可以通过工具 - 工具栏管理
设置显示的工具栏图标。
常用页面生命周期函数及触发时机:
修改 test 页面的生命周期函数
// pages/test/test.js Page({ /** * 页面的初始数据 */ data: { }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { console.log('onLoad - 页面加载') }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { console.log('onReady - 页面就绪') }, /** * 生命周期函数--监听页面显示 */ onShow: function () { console.log('onShow - 页面显示') }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { console.log('onHide - 页面隐藏') }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { console.log('onUnload - 页面卸载') }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { }, /** * 重载页面 */ goIndex: function() { // 调用原生 API 重新加载页面 wx.reLaunch({ url: "/pages/index/index" }) } })
添加重载功能:
<!--pages/test/test.wxml-->
<text bindtap="goIndex">跳转到 index</text>
配置小程序的底部导航栏 tabBar
,用于切换页面:
{ "pages": [ "pages/index/index", "pages/logs/logs", "pages/test/test" ], // 窗口配置 "window": { "backgroundTextStyle": "light", // 顶部导航栏背景 "navigationBarBackgroundColor": "#fff", // 顶部导航栏标题 "navigationBarTitleText": "Weixin", // 顶部导航栏文字颜色 "navigationBarTextStyle": "black" }, // 底部导航配置 "tabBar": { "list": [ { "pagePath": "pages/index/index", "text": "首页" }, { "pagePath": "pages/logs/logs", "text": "日志" }, { "pagePath": "pages/test/test", "text": "测试" } ] }, "style": "v2", "sitemapLocation": "sitemap.json", "lazyCodeLoading": "requiredComponents" }
上面的空白是图标预留,可以自行配置 iconPath
和 selectedIconPath
。
现在点击导航栏切换页面,查看控制台输出:
官方文档 - 生命周期 中有一张图分别介绍了 View(视图)和 AppService(App 服务)两个线程的生命周期顺序:
综合小程序和页面的生命周期就是微信小程序的启动流程:
小程序开发框架提供了丰富的微信原生 API,这些 API 存放在云端(服务器端),不需要自己开发和部署。
除了一些 web API,还提供了一些移动端的 API,只能在移动端调用,如:
原生 API 通过 wx.<api>
调用,详细参考 API 文档。
// app.js App({ onLaunch() { console.log('onLaunch - 小程序加载') // 展示本地存储能力 // 同步方式获取本地缓存数据 const logs = wx.getStorageSync('logs') || [] // 添加当前启动时间 logs.unshift(Date.now()) // 同步方式设置本地缓存数据 wx.setStorageSync('logs', logs) // 登录 wx.login({ success: res => { // 发送 res.code 到后台换取 openId, sessionKey, unionId } }) }, onShow() { console.log('onShow - 小程序显示') }, onHide() { console.log('onHide - 小程序隐藏') }, // 全局数据 globalData: { // 旧版初始化的项目将用户信息保存在这里 // 新版初始化的项目将用户信息保存在 index.js 中 userInfo: null } })
以前的版本会在
onLaunch
内部调用wx.getSettings
获取用户当前设置,根据返回的数据判断授权状态,如果用户已授权,则调用wx.getUserInfo
获取用户信息。现在更改为在
pages/index/index.js
中调用的wx.getUserProfile
,每次请求都会弹出授权窗口,用户同意后返回userInfo
。
初始化项目默认启动获取用户信息,可将 canIUseOpenData
设置 false
变更为手动获取:小程序启动后页面会显示 获取头像昵称
,点击请求 wx.getUserProfile
// index.js // 获取应用实例 // 获取的是 app.js 中生成的小程序的实例 const app = getApp() Page({ // 绑定数据,类似 vue 的 data data: { motto: 'Hello World', userInfo: {}, hasUserInfo: false, canIUse: wx.canIUse('button.open-type.getUserInfo'), canIUseGetUserProfile: false, canIUseOpenData: wx.canIUse('open-data.type.userAvatarUrl') && wx.canIUse('open-data.type.userNickName') // 如需尝试获取用户信息可改为false }, // 事件处理函数 bindViewTap() { wx.navigateTo({ url: '../logs/logs' }) }, onLoad() { if (wx.getUserProfile) { // 修改数据 this.setData({ canIUseGetUserProfile: true }) } }, getUserProfile(e) { // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗 wx.getUserProfile({ desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写 success: (res) => { console.log(res) this.setData({ userInfo: res.userInfo, hasUserInfo: true }) } }) }, getUserInfo(e) { // 不推荐使用getUserInfo获取用户信息,预计自2021年4月13日起,getUserInfo将不再弹出弹窗,并直接返回匿名的用户个人信息 console.log(e) this.setData({ userInfo: e.detail.userInfo, hasUserInfo: true }) } })
官方文档:
WXML(WeiXin Markup Language) 是框架设计的一套标签语言。
作用 | 小程序组件 | HTML 标签 |
---|---|---|
展示区块 | view | div |
展示图片 | image | img |
展示文本 | text | p |
链接导航 | navigator | a |
… | … | … |
WXML 的模板可以定义代码片段,在不同地方中调用。
使用 <template>
定义模板,使用 <import>
引用模板,使用 is
声明需要使用的模板名称,使用 data
传入模板所需的数据。
注意:如果
app.json
配置了"lazyCodeLoading": "requiredComponents"
,开发者工具中使用了<import>
引入模板的页面会显示白屏,因为项目开启了按需注入,但真机预览中会正常显示,开发时可以将该配置项删除。
<!--index.wxml--> <view class="container"> <view class="userinfo"> <!-- wx:if 是 WXML 的条件渲染语法 --> <!-- 使用数据或表达式的语法是 {{}} --> <block wx:if="{{canIUseOpenData}}"> <!-- bindtap 是事件属性,值是需要绑定的处理函数的名称 --> <!-- 事件触发时会在该页面对应的 Page 中找到相应的事件处理函数 --> <!-- 小程序绑定事件处理函数只接受字符串,及处理函数名 --> <!-- 无法自定义调用方式或传参,如 bindtap="{{(e, 'params') => bindViewTap}}" --> <!-- 可以将参数绑定在标签上(如 data-param="value"),通过 event 获取 --> <view class="userinfo-avatar" bindtap="bindViewTap"> <open-data type="userAvatarUrl"></open-data> </view> <open-data type="userNickName"></open-data> </block> <!-- 注意这里是 elif 而不是 elseif --> <block wx:elif="{{!hasUserInfo}}"> <button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 </button> <button wx:elif="{{canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 </button> <view wx:else> 请使用1.4.4及以上版本基础库 </view> </block> <block wx:else> <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image> <text class="userinfo-nickname">{{userInfo.nickName}}</text> </block> </view> <view class="usermotto"> <text class="user-motto">{{motto}}</text> </view> </view>
// logs.js // 小程序中的模块化开发遵循 CommonJS 规范(exports 导出,require 导入) const util = require('../../utils/util.js') Page({ data: { logs: [] }, onLoad() { // 获取日志并设置到 data 中 this.setData({ // 同步获取本地缓存 logs: (wx.getStorageSync('logs') || []).map(log => { return { // 格式化时间 date: util.formatTime(new Date(log)), timeStamp: log } }) }) } })
<!--logs.wxml-->
<view class="container log-list">
<!-- 列表渲染 -->
<block wx:for="{{logs}}" wx:key="timeStamp" wx:for-item="log">
<text class="log-item">{{index + 1}}. {{log.date}}</text>
</block>
</view>
{
// 优先级高于全局配置的导航标题
"navigationBarTitleText": "查看启动日志",
"usingComponents": {}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。