2019.12.16号开始接触小程序,也是第一次接触。随笔写些流程也好,想法也罢,方便之后参考。
一、小程序简介
1.小程序是一种全新的连接用户与服务的方式。
2.小程序并非凭空冒出来的一个概念,当微信中的WebView逐渐成为移动Web的一个重要入口时,微信就有相关的JS API了。
3.小程序的主要语言是JavaScript。小程序的逻辑层和渲染层是分开的,逻辑层运行在JSCore中,并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API。这一区别导致了前端开发非常熟悉的一些库,例如jQuery等,在小程序中是无法运行的。同时JSCore的环境同NodeJS环境也不尽相同,所以一些NPM的包在小程序中也是无法运行的(只是一部分不可使用,小程序还是支持npm的)
4.小程序的开发需要经过:申请小程序账号、安装小程序开发者工具、配置项目等等过程方可完成。下面是小程序申请账号的官方文档,一步步的按步骤进行即可。
https://developers.weixin.qq.com/miniprogram/dev/framework/quickstart/getstart.html
二、小程序的代码构成
1.文件类型:
<1> .json后缀的JSON配置文件
<2> .wxml后缀的WXML配置文件
<3> .wxss后缀的WXSS配置文件
<4> .js后缀的JS配置文件
JSON配置:JSON是一种数据格式,并非编程语言
2.创建页面:
先在项目中创建一个文件夹,然后在开发者工具中右键文件夹,点击“新建Page”,起好名字后,会自动创建“xx.js”、“xx.json”、“xx.wxml”、“xx.wxss”四个文件。创建之后,会在项目app.json中的“pages”项中自动生成路径。
3.app.json配置介绍
<1>pages:各个页面的路径,可以理解在这里配置路由。
<2>permission:在小程序开发中,需要获取用户所在地理位置,需要在app.json中增加premission属性配置。
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
}
<3>window:
用于设置小程序的状态栏、导航条、标题、窗口背景色。
每一个小程序页面都可以使用.json文件对本页面的窗口表现进行配置(可以理解成小程序页面的顶部靠.json中的window来设置,不过也是可以自定义的,用window方便一些)。
页面中配置项在当前页面会覆盖app.json的window中相同的配置项(可以理解每个页面中的json配置项的优先级大于app.json配置项)。
<4>usingComponents:
引入组件
这真是我最想吐槽的一个点。。真xxx的是xxx的难用!!
感受一下:我用小程序的组件,不能全局引用,用到哪个引入哪个,最恐怖的是路径还要自己去文件夹中找。
目前我是这样用的,如果有更好的用法,希望有大佬指点一下!
"usingComponents": {
"l-loading": "/miniprogram_npm/lin-ui/loading/index",
"l-tabs": "/miniprogram_npm/lin-ui/tabs/index",
"l-tabpanel": "/miniprogram_npm/lin-ui/tabpanel/index",
"l-input": "/miniprogram_npm/lin-ui/input/index",
"l-textarea": "/miniprogram_npm/lin-ui/textarea/index",
"l-search-bar": "/miniprogram_npm/lin-ui/search-bar/index"
},
<5>tabBar:
如果小程序是一个多tab应用(客户端窗口的底部或顶部有tab栏可以切换页面),可以通过tabBar配置项指定tab栏的表现,以及tab切换时显示的对应页面。
小程序的这一点我觉得还是很好用的,用vue来说就是一个底部标签页的组件,我用vue要用状态管理要自己封装引入,然后在小程序自己定义一个tabBar就可以搞定了。
"tabBar": {
"color": "#8c8c8c",
"selectedColor": "#2A5AAA",
"backgroundColor": "#fff",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"selectedIconPath": "./images/assets/我的订单(选中状态)@3x.png",
"iconPath": "./images/assets/我的订单(未选中)@3x.png"
},
{
"pagePath": "pages/logs/logs",
"text": "设置",
"selectedIconPath": "./images/assets/设置(选中)@3x.png",
"iconPath": "./images/assets/设置(未选中)@3x.png"
}
],
"position": "bottom"
},
4.项目思路
1.app.js:用户每次登录都会调用wx.login接口获取code,并将code存入缓存。判断用户是否之前已经授权信息,如果已授权则直接进入index首页,仍未授权进入login登录页。
2.login.js:登陆页面。用户点击登录按钮,弹出授权框,点击授权进入手机绑定页面,拒绝授权则停留在当前页面。
3.information:手机绑定页面。用户第一次授权成功后进入手机绑定页面。绑定成功后进入首页。
4.index:首页。在首页点击任意一条信息进入信息详情页。并且将本条信息的单号和tabNum传给信息详情页。
5.orderDetails:信息详情页。接受上一页的单号和tabNum传给回单上传页面。
6.replyUpload:回单上传页。点击添加图片调用wx.chooseImage选择图片后调用后台接口,将已选择图片信息上传给服务器,并且获取返回值id。点击确定上传对接上传接口,将id作为参数上传。上传成功后返回index首页。
eg:用户再次进入该项目的时候,继续执行第一步,不过已经授权过,则会直接进入index首页,以上是此项目的一个大概的思路流程。
三、小程序应用点
1.小程序本地存储
//存数据
wx.setStorageSync("code",res.code);
//取数据
wx.getStorageSync("code")
2.存数据到当前页面data中
//控制显隐时立刻生效
that.setData({
list: res.data.list
});
//单纯的赋值
that.data.list = res.data.list
其实这里面原本是this.setData,而至于为什么要用that,是因为:
如果使用this在函数中的话会出现——使用回调函数异常
报错信息:TypeError: Cannot read property 'setData' of undefined
问题:作用域问题,回调函数中的作用域已经脱离了调用函数,因此需要在回调函数外边把this赋给一个新的变量
才可以
解决方法:var that = this;
建议:****在每一个方法中都先定义一下that,每次都使用that****
3.小程序传参/接参
路由传参
很重要的一点:url里面都是字符串
传参如果是对象类型或者数组,隐式转换为[Object,Object]
JSON.stringify():JavaScript => JSON (直接转)
JSON.parse():JSON => JavaScript(先转为 JSON 再转为 JS)
wx.navigateTo({
url:
"/pages/****/****?orderMovementGid=" +
orderMovementGid +
"&tabNum=" +
that.data.tabNum
});
onLoad: function(options) {
var that = this;
that.setData({
orderMovementGid: options.orderMovementGid,
tabNum: options.tabNum
});
}
小程序传参
wx.navigateTo({
url: "/pages/costFallIn/costFallIn",
success: function (res) {
// 通过eventChannel向被打开页面传送数据
res.eventChannel.emit("acceptDataFromOpenerPage", {
status: "chaKan",
id,(前后一样可以写一个就ok了)
tlFiles: item.tlFiles,
});
},
});
const eventChannel = this.getOpenerEventChannel()
// 监听acceptDataFromOpenerPage事件,获取上一页面通过eventChannel传送到当前页面的数据
eventChannel.on('acceptDataFromOpenerPage', function(data) {
console.log(data)
})
4.页面跳转
页面跳转的话还是参考一下官方文档,有好几种跳转
我最常用的几种:wx.switchTab(需要跳转至tab页),wx.redirectTo(需要跳转至非tab页),wx.navigateTo(跳转至下一页,自带返回按钮)
https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.switchTab.html
5.onLoad和onShow
不需要刷新的函数写在onLoad里面,
需要刷新的函数写在onShow里面。
(这里onShow可以理解为监控路由,路由发生变化的时候,重新调用onShow)
6.开发者工具
<1>预览:使用开发者工具预览小程序,点击“预览”按钮,开发者工具会自动打包当前项目,并上传小程序代码至微信的服务器。
<2>上传:点击上传的话,相当于打包当前小程序,发送“体验版”,可以在微信后台管理中进行查看。
<3>开发者工具不能识别1rpx,最低2rpx(1px)
手机可以识别1rpx
7.小程序解决文字超出不换行问题
display:block;
word-break: break-all;
word-wrap: break-word;
//弹性布局换行
flex-wrap: wrap;
8.点击事件(bindtap="xxx")
.wxml
<view class="bottomButton" bindtap="okBinding">确认绑定</view>
.js
okBinding: function() {}
点击事件传参,不能有()会报警告
需要给元素绑定 data-id='{{item.id}}'。
从事件对象中:e.currentTarget.dataset.id获取。
(多个参数就绑定多个data-xxx='{{item.xxx}}')
9.获取input输入框内容(bindInput="xxx")
.wxml
<input label="手机号" placeholder="请输入手机号" type="number" bindinput="phoneInput"/>
.js
//每次输入都会触发这个事件
phoneInput: function(e) {
this.data.phoneNum = e.detail.value;
},
10.控制显隐(wx:if)
<view wx:if="{{tabNum=='PICKUP'}}" >确认提货</view>
11.循环遍历(wx:for)
<view class="midContent" wx:for="{{list}}" wx:key="{{index}}"></view>
wx:for-item="item1" wx:for-index="index1"
12.设置顶部标题
"navigationBarTitleText": "首页"
动态更改小程序顶部标题
wx.setNavigationBarTitle({
title: "我是修改后的标题"
});
自定义顶部导航栏
"navigationStyle": "custom",
13.回调函数——我觉得很不友好的一点
比如我们一个回调函数,正确的话进入success,错误的话进入fail。
但是小程序的回调函数不同,这是官方解释
只要成功接收到服务器返回,无论statusCode是多少,都会进入success回调。请开发者根据业务逻辑对返回值进行判断。
也就是说我们即使调通接口失败了,只要后台返回给我们信息了,也要通过statusCode来判断。
四、封装组件(自定义提示框)
<1>新建文件夹
在根目录下新建components文件夹,然后在文件夹中新建自定义目录,再右键“新建Page”,(记得把prompt-box.js中表头的Page改成Component)。
<2>组件:json配置
{
"component":true //官方文档说的是:将component字段设为true可将这一组文件设为自定义组件
}
<3>组件:wxml编写
<!-- 提示框组件 -->
<view class="promptBox">
提示框
</view>
<4>app.json全局引入组件
"usingComponents": {
"prompt-box": "./components/prompt-box/prompt-box"
}
<5>父组件:使用组件
<prompt-box></prompt-box>
五、父子传值
1.子文件→父文件。(通过 triggerEvent 事件)(需要手动触发获取)
.wxml
<!-- 提示框组件 -->
<view class="promptBox">
<view class="buttonBox" bindtap="toUpperLevel">朕知道了</view>
</view>
.js
// 点击“朕知道了”,传递给父组件信息
toUpperLevel: function(e) {
this.triggerEvent("clickzdl", "zzdl");
},
//通过bind:clickzdl="clickzdlClick"把子组件的clickzdl事件绑定在父组件的clickzdlClick事件上
.wxml
<prompt-box bind:clickzdl="clickzdlClick"></prompt-box>
.js
// 点击“朕知道了”,接受子组件信息
clickzdlClick: function(e) {
var that = this;
console.log("子组件给父组件传值");
console.log(e);
if (e.detail == "zzdl") {
that.setData({
promptBoxShow: false
});
}
},
2.父组件→子组件。
.wxml (要传给子组件的数据)
<prompt-box propA="{{dataFieldA}}"></prompt-box>
.js
Page({
data: {
dataFieldA: "登陆异常,请联系管理员"
},
.js
Component({
data: {
errMsg: "程序出现错误,请联系管理员"
},
properties: {
propA: {
type: String
}
},
lifetimes: {
attached: function() {
var that = this;
// console.log(that.properties);
that.setData({
errMsg: that.properties.propA
});
}
}
});
六、验证码倒计时(定时器)
.wxml
<button class="QRcode">
<text bindtap="gainCode" wx:if="{{codeShow}}">获取验证码</text>
<text wx:if="{{!codeShow}}">{{timeDown}}s</text>
</button>
.js
var that = this;
let time = setInterval(function() {
that.setData({
codeShow: false,
timeDown: that.data.timeDown - 1
});
if (that.timeDown == 0) {
that.setData({
codeShow: true,
timeDown:60
});
clearInterval(time);
console.log("清除");
}
}, 1000);
七、下拉刷新,上拉加载
官方文档:https://developers.weixin.qq.com/miniprogram/dev/reference/api/Page.html#onPullDownRefresh
app.json
{
"usingComponents": {},
"navigationBarTitleText": "我的订单",
"enablePullDownRefresh": true, //设置为true则默认开启下拉刷新功能
"onReachBottomDistance": 10 //上拉加载的触发距离
}
1.下拉刷新
onPullDownRefresh监听用户下拉刷新事件
onPullDownRefresh: function() {
wx.showNavigationBarLoading(); //在标题栏中显示加载(小菊花)
//模拟加载 模拟网络加载所消耗的时间
setTimeout(function() {
wx.hideNavigationBarLoading(); //在标题栏中隐藏加载(小菊花)
wx.stopPullDownRefresh(); //停止下拉刷新
}, 1500);
},
2.上拉加载更多数据
onReachBottom监听用户上拉触底事件
在json文件中设置触发onReachBottom的触发距离onReachBottomDistance
在触发距离内滑动期间,本事件只会被触发一次
onReachBottom: function() {
console.log("加载更多");
let listConcat = [...that.data.list, ...res.data.data.content];
that.setData({
list: listConcat
});
},
八、很重要的一点
在微信小程序中,盒子模型box-sizing属性默认是content-box
可以在每个标签后加上
box-sizing: border-box;
或者app.wxss加上 小程序所有组件初始化样式 box-sizing: border-box
view,scroll-view,swiper,swiper-item,movable-area,movable-view,cover-view,cover-image,icon,text,rich-text,progress,button,checkbox-group,checkbox,form,input,label,picker,picker-view,radio-group,radio,slider,switch,textarea,navigator,functional-page-navigator,image,video,camera,live-player,live-pusher,map,canvas,open-data,web-view,ad{
box-sizing: border-box;
}
九、小程序的栈!
首先,先明确两点
1.小程序的onLoad方法在页面的生命周期中,只执行一次。
2.先执行onLoad,后执行onShow。
前提:用户——>首页(A页面)——>上传页面(B页面)。栈的示意图
第一种情况:进入上传页面(B页面)之后,使用redirectTo返回首页(C页面)。redirectTo会将栈顶出栈,新页面入栈,即B页面出栈,C页面进栈。(redirectTo会进行顶部栈的替换)
第二种情况:进入上传页面(B页面)之后,使用navigateTo返回首页(C页面)。navigateTo会将C页面添加到栈顶。
第三种情况:即不使用redirectTo,也不使用navigateTo,使用navigateBack返回至首页。在A页面onShow中打印栈的信息,只有miniHome(A页面)。
实例参考:https://www.cnblogs.com/caicaizi/p/6652103.html
var pagelist = getCurrentPages();
var currPage = pagelist[pagelist.length - 1]; //当前页面
var prevPage = pagelist[pagelist.length - 2]; //上一个页面
prevPage.setData({
statusOk: "直接给上一个页面中的字段赋值",
});
wx.navigateBack({
delta: 1,
});
上一个页面在onShow中进行操作,因为页面改变,可以触发onShow
跳转页面传参的话在onLoad
十、微信小程序图片显示问题(IOS访问正常,安卓访问不显示)
有以下几种可能:
1.非本地图片:确定图片资源存在,copy图片url在浏览器打开,确定图片资源存在且能正常访问。
2.本地图片:确定相对路径或者绝对路径正确。
3.微信小程序图片路径,不可存在中文,使用英文做路径和文件名。
4.文件后缀文小写且保持正确。
5.网络图片,必须确保域名已经备案。
注:排除以上5种通病之后,仍出现IOS访问正常,安卓访问不到图片的问题,大概率原因是图片做了CDN转发,多数CDN会默认开启防盗链,需要关闭CDN防盗链,因为防盗链会导致浏览器能显示,而客户端无法显示。
本内容转自:https://www.cnblogs.com/sheep-sheep/p/9645797.html
十一、Loading
wx.showLoading({
icon: "loading",
title: "Loading",
mask: true,
});
wx.hideLoading();
wx.showToast({
title: "刷新成功",
icon: "success",
duration: 1000,
});
下拉刷新时
wx.showNavigationBarLoading(); //在标题栏中显示加载(小菊花)
wx.hideNavigationBarLoading(); //在标题栏中隐藏加载(小菊花)
wx.stopPullDownRefresh(); //停止下拉刷新
十二、forEach
1.逻辑尽量写在JS文件中
2.多个三步运算符,要加()
3.forEach循环中,element相当于item,可以直接点点使用,
一个参数可以直接写,多个参数要加()
that.data.list.forEach((element, index) => {
if (element.stopStatus == "ARRIVED") {
that.setData({
statusList: [index],
changeIndex: index,
});
}
});
十三、接口
小程序可以调用本地接口
1.拉下来后台代码,在前端的电脑上跑起来,然后localhost调接口。
2.后台自己跑起来服务,用后台的ip地址调用接口。
十四、报文
请求报文:前端给后台传参。
响应报文:后台给前端的返回值。
十五、关于canvas
1.滑动问题
前提:设置canvas宽度大于当前可视屏幕宽度,但是却无法左右滑动。
问题:设置class mask遮罩物,z-index 99 在开发者工具上可以正常滑动,但是在真机上无法滑动。
原因:(1)canvas是原生组件,原生组件层级最高,其他组件无法通过z-index来覆盖原生组件。
(2)原生组件脱离WebView渲染流程。但是在开发者工具上,原生组件是用web组件模拟的,不能完全还原真机效果。
解决方法:使用cover-view
和cover-image
可以覆盖部分原生组件上面。(这两个是小程序提供的原生组件,专门用来解决原生组件层级问题的)
原生组件的使用限制:https://developers.weixin.qq.com/miniprogram/dev/component/native-component.html