小程序随笔

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)。


新建components.png

<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页面)。栈的示意图
前提.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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342