上周学习了微信小程序的开发,这里总结一下微信小程序和原生web开发的不同,和一些微信小程序的基本开发。
1.文件后缀的不同
- html文件的后缀改为.wxml
- css文件的后缀改为.wxss
2.html结构的不同
- 把html,header和body标签删掉,默认外面包上page标签
- 微信小程序不识别原生大多数的标签
- 大部分块级标签(例:div,p,ul,li,)需要改为
<view></view> - 大部分行内标签(例:span,i)需要改为
<text></text> - img标签需要改为image,且需要通过mode属性来更改图片展示的模式
<a href="xxxx"></a>=><navigator url="xxxx"> </navigator>- 小程序中的标签像一个组件,加上属性就可以添加对应的功能
- 小程序中还有很多组件标签,例:swiper(轮播图)scroll-view(可滚动视图区域)等等
3.创建页面的不同
微信小程序创建页面需要在app.js文件的pages下添加路径到数组中。还有添加底部tab栏,不同于原生web,微信小程序只需要在app.js文件tabBar下配置,可以设置其页面路径,标题,未选择和选中后的颜色和图标
4.小程序使用vant-ui
在小程序中使用vant-ui需要一些配置
-
初始化项目
npm init -y -
安装ui库
npm i @vant/weapp -S --production -
构建npm
开发工具 => 工具 => 构建 npm
-
修改 app.json
把
"style": "v2"去除 -
导入组件
// 修改app.json,添加以下代码 "usingComponents": { "van-button": "@vant/weapp/button/index", ... // 添加其它组件 }
5.小程序弹窗api
小程序还提供了一些弹窗提示用户的api,在加载数据中和加载完毕后可以给用户一些弹窗信息,增强交互性
- showToast
wx.showToast({ title: '成功', icon: 'success', duration: 2000 }) - showModal
wx.showModal({ title: '提示', content: '这是一个模态弹窗', success (res) { if (res.confirm) { console.log('用户点击确定') } else if (res.cancel) { console.log('用户点击取消') } } }) - showLoading
wx.showLoading({ title: '加载中', }) setTimeout(function () { wx.hideLoading() //隐藏加载 }, 2000)
6.生命周期
小程序有以下生命周期
- onLoad 生命周期函数--监听页面加载`
- onReady 生命周期函数--监听页面初次渲染完成
- onShow 生命周期函数--监听页面显示
- onHide 生命周期函数--监听页面隐藏
- onUnload 生命周期函数--监听页面卸载
- onPullDownRefresh 页面相关事件处理函数--监听用户下拉动作
- onReachBottom 页面上拉触底事件的处理函数
- onShareAppMessage 用户点击右上角分享
注意:
- onLoad 只会在小程序中执行一次,比如当前页面是 a 页面,我们在 onLoad 发送请求去获取数据,然后我们切到 b 页面,再切回 a 页面的时候,onLoad 不会再触发,也就是不会再重新发请求获取数据
- onShow 跟 onLoad 不同,每次切回 a 页面的时候都会触发这个生命周期函数
- 所以到底是在 onLoad 发请求还是在 onShow 发请求,要根据实际的业务去做
7.实战开发-发请求
在项目中我们一般在app.js中使用 promise 封装请求,在app.js下的属性和方法,其他页面都可以通过getApp()得到一个对象,这个对象里包含了app.js下的属性和方法
8.渲染页面
小程序, vue, react框架都是数据驱动视图的框架, 两层含义
- 不需要操作dom节点
- 如果要展示不同的内容, 只需要修改数据即可
1. data 和 setData
-
data 定义数据
-
setData 修改数据
-
查看数据: 打开控制台 => 调试器 => appData
// demo.js Page({ // 定义数据 data: { msg: 'hello小程序', count: 100 }, });// demo.wxml <view>{{msg}}</view> <view>{{count}}</view>
2. 条件渲染 wx:if
{{}} --- 这里面可以写data里面的数据,也可以写一下简单js表达式
<!-- demo.wxml -->
//if else 必须一起用
<view wx:if="{{show}}">
一些内容........
</view>
<view wx:else>
另一些内容......
</view>
<view wx:if="{{num === 10}}">
222222222222
</view>
// demo.js
Page({
data: {
show: true,
num: 10
},
});
3. 列表渲染 wx:for
-
列表渲染用
wx:for= -
item 列表的成员
-
index 成员的下标
-
wx:key 需要一个唯一的值
- 基本数据类型
wx:key="*this" - 引用数据类型
wx:key="id"
- 基本数据类型
9.绑定事件
(1) 绑定事件
// demo.wxml 文件
<button type="primary" bindtap="clickFn"> Click me! </button>
Page({
clickFn: function(event) {
// alert('哈哈哈'); // 没有alert方法
console.log(event);
},
});
(2) 事件传参
// demo.wxml 文件
<button type="primary" bindtap="clickFn" data-name="张三">张三</button>
<button type="primary" bindtap="clickFn" data-name="李四">李四</button>
<button type="primary" bindtap="clickFn" data-name="王五">王五</button>
// demo.js文件
Page({
data: {},
clickFn(ev) {
// ev.target 被点击的元素 dataset 存放在元素的数据
console.log(ev.target.dataset.name);
}
})
注意: wxml和html一样, 不区分大小写, 页面上的大写, 最后变成了小写
(3)常见事件类型 | 类型 | 触发条件 | 最低版本
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 设备,重按时会触发
10.页面跳转
小程序常用两种方式,普通页面跳转和 tab 栏切换(跳转)
注意: 路径前面加 '/' (/ 表示根路径)
// demo.wxml
<!-- 跳转到普通页面 -->
<navigator open-type="navigate" url="/pages/film/detail">电影详情</navigator>
<button size="mini" bindtap="toDetail">电影详情</button>
<!-- 跳转到tab栏页面 -->
<navigator open-type="switchTab" url="/pages/cinema/cinema">影院列表</navigator>
<button size="mini" bindtap="toCinema">影院列表</button>
// demo.js
Page({
data: {
},
// 普通页面跳转
toDetail() {
wx.navigateTo({
url: '/pages/film/detail',
})
},
// js跳转到tab栏页面
toCinema() {
wx.switchTab({
url: '/pages/cinema/cinema',
})
}
});
11.路由传参
(1) 页面传参: 参数是基本数据类型
// 列表页面
<navigator url="/pages/film/detail?id={{item.id}}">详情</navigator>
// 详情页面
onLoad: function (options) {
// 获取列表页面传过来的id
console.log(options.id);
},
注意: wx.swichTab跳转url后不能带参数
(2) 页面传参: 参数是对象(引用数据类型)
- 小程序路由传参只能传字符串, 不能传对象
- 如果想要传对象, 需要先将对象转成字符串
- 在接收的页面, 再将字符串转成对象
详细代码
// 列表页面
// 列表的wxml文件 index是数组成员的下标
<view bindtap="toDetail" data-index="{{index}}" class="play-but abs"></view>
// 列表的js文件
toDetail(event) {
// 获取点击元素的下标
let index = event.target.dataset.index;
// 根据下标获取数组对应的成员
let obj = this.data.videoList[index];
// 将obj对象转为json字符串
let objStr = JSON.stringify(obj);
wx.navigateTo({
url: '/pages/video/detail?objStr='+objStr,
})
},
// 详情页面
Page({
data: {
detail: {}
},
onLoad: function (options) {
// 将字符串转成对象
let obj = JSON.parse(options.objStr);
this.setData({
detail: obj
})
},
})
12.数据缓存
- 异步方法
//储存数据
wx.setStorage({
key: "key",
data: "value",
});
//取数据
wx.getStorage({
key: "key",
success(res) {
console.log(res.data);
},
});
- 同步方法
wx.setStorageSync("key", "value");
// 例子
let token = 'asdfasdfasjdflasdjf;asdf;asdfjsak;ldf';
wx.setStorageSync('token',token);
let token = wx.getStorageSync('token');
13.小程序获取位置
(1) 获取位置信息
-
文档资料
- 小程序文档->api->位置
- [腾讯地图API](平时的开发也可以使用百度地图,高度地图):
-
添加密钥
使用位置服务需要先添加密钥,添加到app.json中
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
}
- 获取经纬度
wx.getLocation({
type: 'wgs84',
success: (res) => {
const latitude = res.latitude;
const longitude = res.longitude;
},
fail: (err) => {
this.setData({
city: '定位失败,请手动选择'
})
}
})
(2) 实际应用:
-
获取城市名称(需要上一点提供的经纬度)
wx.request({ url: `https://apis.map.qq.com/ws/geocoder/v1/?location=${latitude},${longitude}&key=XBZBZ-OBG63-LOD3N-3QR5Q-X6Z2Q-BFBIR`, success: (res) => { let cityName = res.data.result.address_component.city; console.log(cityName) } }) -
计算两个坐标之间的距离
//通过经纬度计算两个地方的距离
// 第一个参数是城市的,第二个参数是影院的,返回的距离单位是KM
function getDistance({lat1, lng1},{ lat2, lng2}) {
var radLat1 = lat1 * Math.PI / 180.0;
var radLat2 = lat2 * Math.PI / 180.0;
var a = radLat1 - radLat2;
var b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;
var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
s = s * 6378.137; // EARTH_RADIUS;
s = Math.round(s * 10000) / 10000;
return s;
},
注: 上面计算的函数是网上copy来的仅供记录笔记学习
14.小程序登录
- 前端首先调用 wx.login 获取 code,
- 紧接着需要调用 wx.getUserInfo 来获得用户信息 (需要用户授权) ,获得 iv 和 encryptedData
- 调用后台登录接口,比如 /user/login,把以上三个参数
- openId: 小程序用户在小程序中的唯一编号
{
code, iv,userInfo, encryptedData;
}
- 传给后台, 后台调用微信平台的相关接口, 对encryptedData进行解密, 得到用户的详细信息, 然后返回给前端
代码开发步骤:
- 绑定登录事件, 获取用户授权, 拿到用户相关信息
- 调用wx.login获取code
- 发送登录请求, 传入用户相关信息和code
- 登录成功, 修改文案
- 登录成功时, 把用户昵称存入缓存
- 在onload里获取缓存的昵称, 若有, 就修改文案
- 点击登录按钮先判断是否已登录