小程序随笔

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(a)
字符串->对象 JSON.parse(b)
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 确认绑定 .js okBinding: function() {}

点击事件传参,不能有()会报警告
需要给元素绑定 data-id='{{item.id}}'。
从事件对象中:e.currentTarget.dataset.id获取。
(多个参数就绑定多个data-xxx='{{item.xxx}}')
9.获取input输入框内容(bindInput="xxx")
.wxml .js //每次输入都会触发这个事件 phoneInput: function(e) { this.data.phoneNum = e.detail.value; },

10.控制显隐(wx:if)
确认提货

11.循环遍历(wx:for)
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)。

小程序随笔
文章图片
新建components.png
【小程序随笔】<2>组件:json配置
{ "component":true//官方文档说的是:将component字段设为true可将这一组文件设为自定义组件 }

<3>组件:wxml编写
提示框

<4>app.json全局引入组件
"usingComponents": { "prompt-box": "./components/prompt-box/prompt-box" }

<5>父组件:使用组件

五、父子传值
1.子文件→父文件。(通过 triggerEvent 事件)(需要手动触发获取)
.wxml 朕知道了 .js // 点击“朕知道了”,传递给父组件信息 toUpperLevel: function(e) { this.triggerEvent("clickzdl", "zzdl"); },

//通过bind:clickzdl="clickzdlClick"把子组件的clickzdl事件绑定在父组件的clickzdlClick事件上 .wxml.js // 点击“朕知道了”,接受子组件信息 clickzdlClick: function(e) { var that = this; console.log("子组件给父组件传值"); console.log(e); if (e.detail == "zzdl") { that.setData({ promptBoxShow: false }); } },

2.父组件→子组件。
.wxml(要传给子组件的数据).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

.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页面)。栈的示意图 小程序随笔
文章图片
前提.png 第一种情况:进入上传页面(B页面)之后,使用redirectTo返回首页(C页面)。redirectTo会将栈顶出栈,新页面入栈,即B页面出栈,C页面进栈。(redirectTo会进行顶部栈的替换) 小程序随笔
文章图片
redirectTo.png 第二种情况:进入上传页面(B页面)之后,使用navigateTo返回首页(C页面)。navigateTo会将C页面添加到栈顶。 小程序随笔
文章图片
navigateTo.png 第三种情况:即不使用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-viewcover-image可以覆盖部分原生组件上面。(这两个是小程序提供的原生组件,专门用来解决原生组件层级问题的)
原生组件的使用限制:https://developers.weixin.qq.com/miniprogram/dev/component/native-component.html

    推荐阅读