小程序整理杂篇

微信的WebSocket接口和HTML5的WebSocket基本一样,是HTTP协议升级来的,做为一个新的Socket在B/S上使用,它实现了浏览器与服务器全双工通信。
WebSocket与Ajax 的选择
在WebSocket出来之前,实现即时通讯通常使用Ajax来实现,而Ajax是通过轮询的方式进行实时数据的获取,轮询就
是在指定的时间间隔内,进行HTTP 请求来获取数据,而这种方式会产生一些弊端,一方面产生过多的HTTP请求,占
用带宽,增大服务器的相应,浪费资源,另一方面,因为不是每一次请求都会有数据变化(就像聊天室),所以就
会造成请求的利用率低。
而WebSocket正好能够解决上面的弊端,WebSocket是客户端与服务器之前专门建立一条通道,请求也只请求一次,
而且可以从同道中实时的获取服务器的数据,所以当应用到实时的应用上时,WebSocket是一个很不错的选择
WebSocket协议名

WebSocket的链接不是以http或https开头的,而是以ws和wss开头的,这里需要注意一下。

SSL
SSL(Secure Socket Layer,安全套接层) 简单来说是一种加密技术, 通过它, 我们可以在通信的双方上建立一个安全的通信链路, 因此数据交互的双方可以安全地通信, 而不需要担心数据被窃取. 关于 SSL 的深入知识, 可以看这篇文章: SSL/TLS协议运行机制的概述


WSS
WSS 是 Web Socket Secure 的简称, 它是 WebSocket 的加密版本. 我们知道 WebSocket 中的数据是不加密的, 但是不加密的数据很容易被别有用心的人窃取, 因此为了保护数据安全, 人们将 WebSocket 与 SSL 结合, 实现了安全的 WebSocket 通信, 即 WebSocket Secure.
所以说 WSS 是使用 SSL 进行加密了的 WebSocket 通信技术.


HTTPS
其实 HTTPS 和 WSS 类似, HTTP 之于 HTTPS 就像 WebSocket 之于 WebSocket Secure.
HTTP 协议本身也是明文传输, 因此为了数据的安全性, 人们利用 SSL 作为加密通道, 在 SSL 之上传递 HTTP 数据, 因此 SSL 加密通道上运行的 HTTP 协议就被称为 HTTPS 了.


总结

SSL 是基础, 在 SSL 上运行 WebSocket 协议就是 WSS; 在 SSL 上运行 HTTP 协议就是 HTTPS.

需要注意:每个微信小程序需要事先设置一个通讯域名,小程序可以跟指定的域名与进行网络通信。包括普通 HTTPS 请求(request)、上传文件(uploadFile)、下载文件(downloadFile) 和 WebSocket 通信(connectSocket)
配置流程
服务器域名请在 小程序后台-设置-开发设置-服务器域名 中进行配置,配置时需要注意:
域名只支持 https (request、uploadFile、downloadFile) 和 wss (connectSocket) 协议;
域名不能使用 IP 地址或 localhost,且不能带端口号;
域名必须经过 ICP 备案;
出于安全考虑,api.weixin.qq.com 不能被配置为服务器域名,相关API也不能在小程序内调用。开发者应将 apps
ecret 保存到后台服务器中,通过服务器使用 appsecret 获取 accesstoken,并调用相关 API。

对于每个接口,分别可以配置最多 20 个域名

1.首先copy文件夹 wxParse 
  - wxParse/
  -wxParse.js(必须存在)
  -html2json.js(必须存在)
  -htmlparser.js(必须存在)
  -showdown.js(必须存在)
  -wxDiscode.js(必须存在)
  -wxParse.wxml(必须存在)
  -wxParse.wxss(必须存在)
  -emojis(可选)
2.引入必要文件
//在使用的View中引入WxParse模块
var WxParse = require('../../wxParse/wxParse.js');




//在使用的Wxss中引入WxParse.css,可以在app.wxss
@import "/wxParse/wxParse.wxss";


3.数据绑定
var article = '<div>我是HTML代码</div>';
/**
* WxParse.wxParse(bindName , type, data, target,imagePadding)
* 1.bindName绑定的数据名(必填)
* 2.type可以为html或者md(必填)
* 3.data为传入的具体数据(必填)
* 4.target为Page对象,一般为this(必填)
* 5.imagePadding为当图片自适应是左右的单一padding(默认为0,可选)
*/
var that = this;
WxParse.wxParse('article', 'html', article, that, 5);


4.模版引用
// 引入模板
<import src="你的路径/wxParse/wxParse.wxml"/>
//这里data中article为bindName
<template is="wxParse" data="{{wxParseData:article.nodes}}"/>


!注意:在上面的基本使用里面在.js文件和.wxml文件里面出现的article这个是两个文件里面是一样的。但是article是js文件里面的一个变量是可以变的,只要保证js文件和wxml文件里面变量名一致即可。


测试案例:


wxml文件:
<import src="../../wxParse/wxParse.wxml"/>
<view class="container">
  <!-- 这一块是富文本 显示的内容区 -->
  <template is="wxParse" data="{{wxParseData:article.nodes}}"/>
</view>


wxss文件:
@import "../../wxParse/wxParse.wxss";


js文件:
var WxParse = require('../../wxParse/wxParse.js');
data: {
  article: '<div style="text-align:center;">《静夜思》· 李白<br />床前明月光,<br />疑是地上霜。 <br />举头望明月, <br />低头思故乡。<br /><img src="http://www.xiexingcun.com/Poetry/6/images/53e.jpg" alt="" /><br /><img src="http://www.xiexingcun.com/Poetry/6/images/53.jpg" alt="" /><br /><br /><img src="http://www.xiexingcun.com/Poetry/6/images/53b.jpg" alt="" /><br /></div>',
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
 var that = this;
 var temp = WxParse.wxParse('article', 'html', that.data.article, that, 5);
 that.setData({
   article: temp
 })
},




通过以上方法引入以后可以使用,但是我遇到以下两个问题


1)上下图片和图片之间有间距。


2)当富文本中图片本身没有居中时,在设置padding那个参数图片显示有问题。


解决办法:


针对问题1)的解决办法,找到wxParse.wxml,找到里面的<template name="wxParseImg">,修改style内容,将里面的display:inline-block改成display:block。


针对问题2)的解决办法,首先将上面说的style中的width设置保存成width:100%,同时找到wxParse.js文件将that.wxParseImgTap = wxParseImgTap这句注释。




wxParse多数据循环使用方法


* WxParse.wxParseTemArray(temArrayName,bindNameReg,total,that)


* 1.temArrayName: 为你调用时的数组名称


* 2.bindNameReg为循环的共同体 如绑定为reply1,reply2...则bindNameReg = 'reply'


* 3.total为reply的个数
* 懒人建站http://www.51xuediannao.com/
        *  var that = this; WxParse.wxParseTemArray("replyTemArray",'reply', replyArr.length, that)
*/
使用方式:  循环绑定数据 例子
var replyHtml0 = `<div style="margin-top:10px;height:50px;">
        <p class="reply">
            wxParse回复0:不错,喜欢[03][04]
        </p>    
    </div>`;
    var replyHtml1 = `<div style="margin-top:10px;height:50px;">
        <p class="reply">
            wxParse回复1:不错,喜欢[03][04]
        </p>    
    </div>`;
    var replyHtml2 = `<div style="margin-top:10px;height:50px;">
        <p class="reply">
            wxParse回复2:不错,喜欢[05][07]
        </p>    
    </div>`;
     var replyArr = [];
    replyArr.push(replyHtml0);
    replyArr.push(replyHtml1);
    replyArr.push(replyHtml2);
    
    for (let i = 0; i < replyArr.length; i++) {
      WxParse.wxParse('reply' + i, 'html', replyArr[i], that);
      if (i === replyArr.length - 1) {
        WxParse.wxParseTemArray("replyTemArray",'reply', replyArr.length, that)
      }
    }
    
    模版使用: 
    <block wx:for="{{replyTemArray}}" wx:key="">
        回复{{index}}:<template is="wxParse" data="{{wxParseData:item}}"/>

    </block>


体验方面:独立性比较好,可以挂载到桌面,在最近任务栏也是独立窗口,独立线程,可以后台运行,微信暴露的 API 端口也算丰富,运行效率还不错,除了偶尔有闪屏现象
小程序入口:扫码 朋友圈分享 和 搜索  摇一摇附近的小程序
 接口全局返回码:
返回码 说明
-1 系统繁忙
0 请求成功
40001 获取access_token时AppSecret错误,或者access_token无效
40002 不合法的凭证类型
40003 不合法的OpenID
40004 不合法的媒体文件类型
40005 不合法的文件类型
40006 不合法的文件大小
40007 不合法的媒体文件id
40008 不合法的消息类型
40009 不合法的图片文件大小
40010 不合法的语音文件大小
40011 不合法的视频文件大小
40012 不合法的缩略图文件大小
40013 不合法的APPID
40014 不合法的access_token
40015 不合法的菜单类型
40016 不合法的按钮个数
40017 不合法的按钮个数
40018 不合法的按钮名字长度
40019 不合法的按钮KEY长度
40020 不合法的按钮URL长度
40021 不合法的菜单版本号
40022 不合法的子菜单级数
40023 不合法的子菜单按钮个数
40024 不合法的子菜单按钮类型
40025 不合法的子菜单按钮名字长度
40026 不合法的子菜单按钮KEY长度
40027 不合法的子菜单按钮URL长度
40028 不合法的自定义菜单使用用户
40029 不合法的oauth_code
40030 不合法的refresh_token
40031 不合法的openid列表
40032 不合法的openid列表长度
40033 不合法的请求字符,不能包含\uxxxx格式的字符
40035 不合法的参数
40038 不合法的请求格式
40039 不合法的URL长度
40050 不合法的分组id
40051 分组名字不合法
41001 缺少access_token参数
41002 缺少appid参数
41003 缺少refresh_token参数
41004 缺少secret参数
41005 缺少多媒体文件数据
41006 缺少media_id参数
41007 缺少子菜单数据
41008 缺少oauth code
41009 缺少openid
42001 access_token超时
42002 refresh_token超时
42003 oauth_code超时
43001 需要GET请求
43002 需要POST请求
43003 需要HTTPS请求
43004 需要接收者关注
43005 需要好友关系
44001 多媒体文件为空
44002 POST的数据包为空
44003 图文消息内容为空
44004 文本消息内容为空
45001 多媒体文件大小超过限制
45002 消息内容超过限制
45003 标题字段超过限制
45004 描述字段超过限制
45005 链接字段超过限制
45006 图片链接字段超过限制
45007 语音播放时间超过限制
45008 图文消息超过限制
45009 接口调用超过限制
45010 创建菜单个数超过限制
45015 回复时间超过限制
45016 系统分组,不允许修改
45017 分组名字过长
45018 分组数量超过上限
46001 不存在媒体数据
46002 不存在的菜单版本
46003 不存在的菜单数据
46004 不存在的用户
47001 解析JSON/XML内容错误
48001 api功能未授权
50001 用户未授权该api



小程序js中 函数中获取data中的值 var that = this; that.data.xxx
上一下跳转下一页 跳转链接+id  在下页options.id直接能够获取到
页面跳转3种方式:{
wx.navigateTo 保留当前页面跳转 可以使用wx.navigateBack返回
wx.redirectTo 关闭当前页面跳转\
wx.switchTab 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
}
循环遍历wx:for 为防止遍历中动态数据错乱 使用wx:key作为标识 可以是wx:key="*this" 也可以是item中的proprety参数
小程序底部导航 只有app.json的第一个才能显示出来 子页面中只能配置json中的window配置 会覆盖app.json中的window配置
小程序获取当前wxml中传入的参数比如id 在js中打印 console.log(e.currentTarget.id);




微信小程序设置id的方法标识来传值:
在要跳转的item处,设置一个id并给当前的id赋值上对应的key值,
如 id="{{item.index}}"
后我们在js的bindtap的响应事件中获取,并传递到下一个界面中;
获取到id传的值
通过e.currentTarget.id;获取设置的id值,并通过设置全局对象的方式来传递数值,
获取全局对象 var app=getApp(); //设置全局的请求访问传递的参数 app.requestDetailid=id;
在调试模式下:我们也可以在,wxml中查看到我们设置的每一个item的id值


通过使用data - xxxx 的方法标识来传值
通过使用data - xxxx 的方法标识来传值,xxxx可以自定义取名 比my.wxml中的data-index。
如何获取data-xxxx传递的值?
在js的bindtap的响应事件中:
通过数据解析一层层找到数据,var id=e.target.dataset.index(根据你的data-id的取名)
如js中的两个打印就是通过两种不同方式获得的id。


微信小程序如何跨页面获取值?
依据上面的方式设置要传递的值,页面跳转后,我们就需要在下一个页面拿到传递的数据(这个数据在传递前,就已经被设置成全局变量)相当于给全局变量添加了新的key,value
在跳转后的js页面,接收传递过来的数据detail.js
同样通过全局额方式取值出来,(即和app.js中取某个变量的值是一样的)
var id=getApp().requestId;
var index=getApp().requestIndex;
console.log(id);
console.log(index);


通过链接传参:
wx.navigateTo({  
  url: '/pages/account/feedback/feedback?test=feedback_test&name=jia',  
  success: function(res) {},  
  fail: function(res) {},  
  complete: function(res) {},  
}) 


点击页面跳转时通过?方式传参。在跳转后的页面JS中做如下接收:
onLoad: function (e) {  
    var movieid = getApp().requestId;  
    var movieIndex = getApp().requestIndex;  
    console.log("-----feedback--movieid--" + movieid +" " + movieIndex);  
    console.log("-----feedback--test--" + e.test);  
    console.log("-----feedback--name--" + e.name);  
  }, 
  
传参实例:
my.wxml
<view class="container">  
  
  <view bindtap="bindViewTap" class="userinfo">  
    <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>  
    <text class="userinfo-nickname">{{userInfo.nickName}}</text>  
  </view>  
  
  <view class="info_list">  
    <block wx:for="{{userListInfo}}" >  
      <view class="weui_cell" data-index="{{item.index}}" id="{{item.index}}"  
       bindtap="userinfo_item">  
      
        <view class="weui_cell_hd">  
          <image src="{{item.icon}}"></image>  
        </view>  
        <view class="weui_cell_bd">  
          <view class="weui_cell_bd_p"> {{item.text}} </view>  
        </view>  
        <view wx:if="{{item.isunread}}" class="badge">{{item.unreadNum}}</view>  
        <view class="with_arrow"></view>  
      </view>  
    </block>  
  </view>  
  
</view>  


my.js
var app = getApp()  
Page({  
  data: {  
    userInfo: {},  
    userListInfo: [{  
      icon: '../../images/iconfont-dingdan.png',  
      text: '我的订单',  
      isunread: true,  
      unreadNum: 2,  
      index:1  
    }, {  
      icon: '../../images/iconfont-kefu.png',  
      text: '联系客服',  
      index: 5  
    }, {  
      icon: '../../images/iconfont-help.png',  
      text: '常见问题',  
      index: 6  
    }]  
  
  },  
  
  onLoad: function () {  
    var that = this  
    //调用应用实例的方法获取全局数据  
    app.getUserInfo(function (userInfo) {  
      //更新数据  
      that.setData({  
        userInfo: userInfo  
      })  
    })  
  },  
  
  userinfo_item: function (e) {  
    var index = e.target.dataset.index;  
    console.log("----index----" + index)  
       
    console.log('-----id-----'  
      + e.currentTarget.id)  
    var app = getApp();  
    //设置全局的请求访问传递的参数   
    app.requestId = e.currentTarget.id;  
    app.requestIndex = index;  
  
  }  
  

})  


问题:开发工具视频组件运行正常 但是报403 手机端测试出现视频无法播放


一般遇到403的几种情况:
1:开发者工具设置代理问题:
2:VPN等科学上网代理
3:文件不存在;
4:服务器有反盗链  防盗链的话需要添加servicewechat.com域名到许可域名
5:文件不存在
6:异步调用的问题


Failed to load resource: the server responded with a status of 400 (Bad Request)
将ContentType改为 "application/x-www-form-urlencoded"




防盗链常见做法:
1.设置 referer 白名单,非白名单内的一律拒绝访问
2.在 URL 中添加 token 校验,使用私有 key 和 time 实时计算 token,服务器作校验
3.在第2条的基础上,使用 https POST token 参数,增加抓取难度
4.使用 HLS(m3u8) 自带的加密功能,加密传输数据,没有密码无法播放
5.使用数字版权保护(DRM)技术


还有一些不太常见的手段:
1.使用HTTPS客户端证书,服务器可以对客户端进行识别(目前常见的HTTPS是服务器端证书)
2.使用HLS(m3u8)自带的加密功能,并对密码做二次处理,客户端经过两次解密才能得到原数据

3.对视频编码进行二次处理,解码时需要知道算法,否则无数得到原数据,见于海康监控系统 

post请求的时候'Content-Type': 'application/x-www-form-urlencoded' 
小程序默认是'Content-Type': 'application/json
例子:有一个数组需要更改其中的值,循环传入i将无效的,只能是固定数字
for(var i=0; i<3; i++){
  this.setData({
      array[i]:‘hello’不对           
    }
  })
  this.setData({
    'array[1]':‘hello’ 只能写固定数字
  }
})
}
css中无法使用本地资源的图片作为background-image,可使用网络资源或base64,或使用image。tabBar的icon资源可使用本地资源
image默认width:300px,height:225px,lazy-load懒加载只对page与scroll-view下的image有效
var wxReg=new RegExp("^[a-zA-Z]([-_a-zA-Z0-9]{5,19})+$") //微信号正则验证


var qqReg=new RegExp("[1-9][0-9]{4,}")  //QQ号正则验证


var phReg=new /^1[345678]\d{9}$/  //手机号正则验证


var nameReg=new RegExp("^[\u4e00-\u9fa5]{2,4}$")  //2-4位中文姓名正则验证
如果待跳转页面从属于TabBar,wx.navigateTo将失效,如要切换,需使用wx.switchTab:使用该方法之后将不再有返回按钮
设置背景色
在app.wxss中使用


page{这里需要注意的是,page前面没有点。


background-color="#fff";


}


设置换行和空格
\t 空格 \xa0 空格 
\n 换行
必须在<text>标签中!


微信小程序引入外部wxss
@import "test.wxss" text标签属于行内标签


下拉加载的两种方式


1.全局设置


打开app.json,添加这样一句话
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "老焦家",
    "navigationBarTextStyle":"black",
    "enablePullDownRefresh": "true"  //添加这句话
  },


使用这种方法,是将微信小程序中所有的页面都添加下拉加载功能


2.单个页面设置


找到你需要添加下拉加载功能的wxml页面,找到其对应的.json文件
{


  "enablePullDownRefresh": "true" //添加这句话
}
1
使用这种方法,只给单独页面添加下拉加载功能


必须结束,否则会一直在加载状态


直接贴代码;(加载page({})里面)


onPullDownRefresh:function(){
    setTimeout(function(){
      wx.stopPullDownRefresh();
      console.log(1);
    },1000)
  },


轮播图(swiper)
微信小程序开发的循环用到了


<block wx:for="{{数组名}}" wx:for-index="index">
1
属性名 类型 默认值 说明
indicator-dots Boolean false 是否显示面板指示点
autoplay Boolean false 是否自动切换
Number 0 当前页面所在的index
Number 5000 自动切换时间间隔
duration Number 1000 滑动动画时长
<swiper class="swiper" indicator-dots="true" autoplay="true" interval="5000" duration="1000">    
        <swiper-item>    
          <image src="a.png"  mode="aspectFill"/>    
        </swiper-item>  
    </swiper>    


image中的mode属性
image组件默认宽度300px 高度225px
mode有13种模式,其中4中缩放模式,9种是裁剪模式
aspectFill 保持纵横比缩放图片,只保证图片短边完全显示出来
widthFix 宽度不变,高度自动化,保持原图宽高比不变、
scaleTo 不保持纵横比缩放图片,是图片填满image


mode="aspectFill"


在使用swiper的时候,需要用swiper-item包起来,否则会出现图片显示不出来,但是也不报错的情况
初次使用swiper的的时候可能遇到当图片自动轮播到最后的时候,跳转到第一页的效果不友好,此时需要添加circular=“true” 无缝衔接


扫描二维码
scancode(){
    wx.scanCode({
      success:function(){
        console.log("scancode")
      }
    })
  }
  
  e.target
在小程序中,可以通过e.target获取到点击的元素的一些属性
包括id offsetleft offsettop ,还可以通过data-*=“ ”,传一些值


在微信小程序中添加或修改样式
通过以下的方式实现类似选项卡的功能;
index.wxml
 <view class='navs'>
    <view class='{{flag?"navsSon1 navsSon":"navsSon"}}' bindtap='meau' id="meau" data-text="text">点单</view>
    <view class='{{flag1?"navsSon1 navsSon":"navsSon"}}' bindtap='talk'>评价</view>
    <view class='{{flag2?"navsSon1 navsSon":"navsSon"}}' bindtap='shop'>商家</view>
  </view>
  zaiindex.wxss中定义两个样式


.navsSon{
  width: 20%;
  height: 100%;
  line-height: 90rpx;
  text-align: center;
}
.navsSon1{
  border-bottom: 5rpx solid yellowgreen;
}
在index.js中操作如下
pages({
  data{
    flag:false,
    flag1: false,
    flag2: false,
  },
   meau(){
    var that=this;
    that.setData({
      flag: true,
      flag1: false,
      flag2: false,
    })
  },
  talk(){
    this.setData({
      flag: false,
      flag1: true,
      flag2: false,
    })
  },
  shop(){
    this.setData({
      flag: false,
      flag1: false,
      flag2: true,
    })
})
navigiteTo跳转不会保存最下面的tab


2 存储:
一个小程序功能比较多,涉及的页面也很多,准备在本地预览时发现,打包后的代码不允许超过2M(2048KB
).最后解决方案:1.UI提供的图片进行压缩.2.代码进行简化,尽量写的精简 3.背景图或者一些稍微大点的图片可以
挂到服务器上使用。


页面跳转:
当我使用navigateTo方法进行页面跳转时,发现跳转失效,检查代码并没有什么问题,后来发现这是小程序的一个限制
.TabBar中的list项的配置pagePath,不能其作为他页面的跳转链接。为了解决这个问题,我使用了wx.switchTab方

页面跳转:
很多时候点击某个模块区域需要触发事件跳转到其他页面,但是往往在该模块区域会有按钮点击等触发功能,因此在
绑定按钮事件时需要进行阻止冒泡行为,只需要将事件的bind改成catch,bind 是阻止不了冒泡的, 例如 bindtap 改
成 catchtap


页面跳转:
在开发列表上拉分页加载功能时用到了小程序提供的组件scroll-view(可滚动视图区域),通过bindscrolltolower(
滚动到底部/右边,会触发 scrolltolower 事件)绑定了一个方法,但是无论我怎么上拉,并没有触发该方法,发现自
己遗漏了一个属性,需要给scroll-view配上height样式属性,这样才能触发事件。
代码如下:
<scroll-view scroll-y style="height:1200rpx" lower-threshold="30rpx" bindscrolltolower="searchScrollLower" ></scroll-view>


wx.checkSession(OBJECT):
开发者需要调用wx.checkSession接口检测当前用户登录态是否有效。登录态过期后开发者可以再调用wx.login获取
新的用户登录态。 本人发现在pc端测试会一直检测状态成功,一切已真机测试结果为主,这是个小坑


 scroll-view高度
给scroll-view标签设的高度不好定死,因此做了以下处理
WXML:


<scroll-view scroll-y style="height:{{scrollHeight}}px;" bindscrolltolower="searchScrollLower">
js:
wx.getSystemInfo({
  success: function (res) {
    that.setData({
      scrollHeight: parseInt(res.windowHeight) + 200
    })
  }
});


page里面的onload函数里面只能使用this.setData进行数据绑定,之前的this.data将不可以在onload里面进行绑定。




js的回调
function b() {
    // do something when sucess
}


function a(aSucess) {
    wx.request({
        url:'...',
        sucess: function(res) {
            aSucess()
        }
    })
}


a(b);这样就很清晰的知道a函数里当请求成功的时候做了什么事情,因为直接在调用a的时候就已经传入其中了


微信小程序没有数据双向绑定,在Page对象中设置的data只能单向改变前台渲染,而前台改变无法同步更改此变量
。那么如果需要将前台的变化也同步到后台,只能监控前台控件的变化事件,如input的bindinput事件,在此事件
中对输入值进行判断,如下:
<input bindinput="bindMoney" value="{{money}}" />
其中value="{{money}}"用于后台到前台的绑定,而bindinput则用于前台到后台的绑定,如下:


bindMoney: function (e) {
    var value = parseInt(e.detail.value);
    this.setData({
      money: value
    })
}
并且小程序在绑定变化的时候前台会出现undefined的情况,如果是图像的话就会造成请求错误,倒是无伤大雅,时间很短,前台基本不会察觉。


客服按钮
这个客服按钮<contact-button>很坑爹,不能自定样式,并且有效的点击区域也只有它显示的图标那么大,而且图
标也很丑,想到这就异常的无语。不过,我们想到了一个投机的方式解决了。我们的需求是点击这一块进入客服会
话,客服按钮有个属性type,我们设置它为default-light,它就是白色,能和白色背景融合看不出来,然后再铺满
n个按钮,达到点击进入客服会话。红色框部分全是客服按钮!


request请求
微信小程序中为我们封装了ajax请求,api是wx.request(options)。在我项目中的需求,很多请求用的是post,但
是如果你把参数method设置为post后还需要添加header的"content-type"为"application/x-www-form-urlencoded
",如果你们每个request中都要重新写这个一样的header就很麻烦。在一个就是统一的错误回调,我们很多请求的
错误回调中干的事情基本一样,所以我们是否设置个默认的错误回调,这样代码就简洁多了。
新建一个ajax.js文件,我们可以根据自己需求来配置defaultConfig,然后通过Object.assign来是否覆盖配置
function ajax(config) {
    var defaultConfig = {
        method: "GET",
        fail: function() {
            console.log('fail')
            wx.hideToast()
            wx.stopPullDownRefresh()
            wx.showModal({
                title: "提示",
                content: "网络异常",
                showCancel: false,
                confirmText: "确定",
                confirmColor: "#3CC51F",
            })
        }
    }


    if (config.method == 'POST') {
        defaultConfig.header = {
            'content-type': 'application/x-www-form-urlencoded'
        }
    }


    let _config = Object.assign(defaultConfig, config)
    wx.request(_config)
}


module.exports = ajax


然后在app.js中引用var ajax = require('utils/ajax.js'),挂载到全局的方法中,这样在每个页面通过getApp(
).ajax(config)就能使用自己封装后的api请求了。


小程序引用公共js需要在公共js用 module.exports 来暴露模块接口
如果直接 调用则会出现这样的错误
thirdScriptError
util.Regular is not a function;at "pages/test/test" page lifeCycleMethod onLoad function
TypeError: util.Regular is not a function


一般情况报错:setData is not function 就是你的需要加 var xxx(一般用that) = this;  that.setData(); 


js中数组push对象,前面的值总是被最后一次的值覆盖的问题
var array = [];
 for (var i = 0; i < res.data.result.rows.length; i++) {
          var obj = {};//放在外面的话 每次的地址是一样的 最后一次赋值时由于是同一个obj会覆盖前面的数据,
          obj.index1 = res.data.result.rows[i].id;
          obj.bImg1 = "xxxxxxxxx;
          obj.noblText1 = res.data.result.rows[i].ntitle;
          obj.nogrText1 = res.data.result.rows[i].nabstract;
          obj.timeImg1 = "xxxxxxx";
          obj.timeText1 = util.toDate(res.data.result.rows[i].nsendate);
          array.push(obj);
          that.setData({
            notice:array,
          })
        }
        
        
        
        
 直接在返回值里var 一个变量 然后setData 应该是不行 报错setDataisnotfunction  只能在函数起始位置var "",而后赋值在设置
 
 
 一般前后端分离出现session不一致的问题:因为小程序客户端请求会被转接到微信服务器,sessionID会变化,因此我们要自行设置Cookie.
 
 俩种传值写法:
  var data={};
       var param = 'id';
       data[param] = Ve2*52*Eteu1E3*
      data.id ="Ve2*52*Eteu1E3*";
      console.log('testparam:' + JSON.stringify(data));
      console.log(data.id);
 
 
  json 串 转对象:console.log(JSON.parse(res.data.result));
  对象转json串 JSON.stringify
  
  请求 -->cookie jsessionId -->服务器 session sessionId 
  小程序 ---> 微信服务器sessionId --->   sessionId 服务器
  验证码sessionId  表单提交-->生成SessionId -->服务器 1 2 俩不同 1 session 表单null
  手动 header --> sessionId -->带  全局 你的所有接口 都需要 sessionId

  登陆 会用


小程序的HTTP请求全部使用wx.request({})方法,但是该方法每次都会产生一个新的会话,因此在特定使用场景(安全验证、session保存、CSRF保护)等方面会遇到一些麻烦。比如csrf保护的应用中,即使上次拿到csrf,再下一次请求中又会失效。


解决方法
step 1: 获取sessionId以及csrf并保存
已获取csrf为例,简单粗暴,在应用启动时候()可以在onLaunch时候)获取第一次请求的Cookie信息,保存在本地,以后每次在请求头强制加上cookie信息即可。 
代码入下:


//app.js
App({
    onLaunch:function(){
        this.initSession();
    },
    initSession:function(){
        var that = this;
        // step one:get cookie
        wx.request({
            url:'https://my.domain.com/open-api/cookie',
            header:{'Content-Type':'application/x-www-form-urlencoded'},
            method:'GET',
            success:function(res){
                for(let cookie of res.data){
                    //这里我仅保存了sessionid,根据需要,也可以保存cookie的其它信息。
                    if(cookie.name === 'JSESSIONID') {
                        that.globalData.sessionId=cookie.value;
                        wx.request({
                            url:'https://my.domain.com/open-api/csrf',
                            header:{'Content-Type':'application/x-www-form-urlencoded','Cookie':'JSESSIONID='+that.globalData.sessionId},
                            method:'GET',
                            success:function(res){
                                that.globalData.csrf=res.data;
                            }
                        })
                        break;
                    }
                }
            }
        })
    }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
step 2: 根据sessionId以及csrf请求别的接口
以后,每次请求别的api接口,就可以在请求头中添加csrf以及sessionId来维持同一个会话了。 
代码如下:


doSth:function(){
    var that = this;
    wx.request({
        url:'my.domain.com/api/some-thing',
        //这里的CSRF的key(CSRF-TOKEN)具体写什么,根据各位自己的程序设置来写
        header:{'Content-Type':'application/x-www-form-urlencoded','Cookie':'JSESSIONID='+that.globalData.sessionId,'CSRF-TOKEN':that.globalData.csrf},
        method:'POST',
        data:paramdata,
        success:function(res){
            doSomething(res.data);
        }
    })

}


js核心代码


Page({


  data: {
    // 前台显示list
    showlist: [],
    // 当前页
    pageNumber: 1,
    // 总页数
    totalPage: 1,


  },


  onLoad: function (options) {
    var self = this;
    // 请求后台 
    // 获取第一页的list及总页数
    wx.request({
      url: '',
      data: {


      },
      success: function (res) {
          self.setData({
            showlist: res.data.list,
            totalPage: res.data.totalPage,
          })
      },
      fail: function (res) {


      }
    })
  },
    /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
    var self = this;
    // 当前页+1
    var pageNumber = self.data.pageNumber + 1;


    self.setData({
       pageNumber: pageNumber,
    })


    if (pageNumber <= self.data.totalPage) {
      wx.showLoading({
        title: '加载中',
      })
      // 请求后台,获取下一页的数据。
      wx.request({
        url: '',
        data: {
          pageNumber: pageNumber,
        },
        success: function (res) {
          wx.hideLoading()
          // 将新获取的数据 res.data.list,concat到前台显示的showlist中即可。
          self.setData({
            showlist: self.data.showlist.concat(res.data.list)
          })
        },
        fail: function (res) {
          wx.hideLoading()
        }
      })
    }


  }

})


当用户点击咨询的时候会自动生成一个openid 
用户登陆的时候,首先小程序调用wx.login()获取临时凭证code,wx.request()发送code到开发者服务器,开发者服务器以appid+appsecret+code到微信接口服务换取
session_key(会话密钥)+openId(用户唯一标识),后开发者可以根据openId来生成自定义登陆态,用于后续业务逻辑前后端交互时识别身份








access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。


公众平台的API调用所需的access_token的使用及生成方式说明:


1、建议公众号开发者使用中控服务器统一获取和刷新Access_token,其他业务逻辑服务器所使用的access_token均来自于该中控服务器,不应该各自去刷新,否则容易造成冲突,导致access_token覆盖而影响业务;


2、目前Access_token的有效期通过返回的expire_in来传达,目前是7200秒之内的值。中控服务器需要根据这个有效时间提前去刷新新access_token。在刷新过程中,中控服务器可对外继续输出的老access_token,此时公众平台后台会保证在5分钟内,新老access_token都可用,这保证了第三方业务的平滑过渡;


3、Access_token的有效时间可能会在未来有调整,所以中控服务器不仅需要内部定时主动刷新,还需要提供被动刷新access_token的接口,这样便于业务服务器在API调用获知access_token已超时的情况下,可以触发access_token的刷新流程。


公众号可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在“微信公众平台-开发-基本配置”页中获得(需要已经成为开发者,且帐号没有异常状态)。调用接口时,请登录“微信公众平台-开发-基本配置”提前将服务器IP地址添加到IP白名单中,点击查看设置方法,否则将无法调用成功。


接口调用请求说明


https请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
参数说明


参数 是否必须 说明
grant_type 获取access_token填写client_credential
appid 第三方用户唯一凭证
secret 第三方用户唯一凭证密钥,即appsecret
返回说明


正常情况下,微信会返回下述JSON数据包给公众号:


{"access_token":"ACCESS_TOKEN","expires_in":7200}
参数说明


参数 说明
access_token 获取到的凭证
expires_in 凭证有效时间,单位:秒
错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):


{"errcode":40013,"errmsg":"invalid appid"}
返回码说明


返回码 说明
-1 系统繁忙,此时请开发者稍候再试
0 请求成功
40001 AppSecret错误或者AppSecret不属于这个公众号,请开发者确认AppSecret的正确性
40002 请确保grant_type字段值为client_credential
40164 调用接口的IP地址不在白名单中,请在接口IP白名单中进行设置


由于微信对access token每天获取的次数是有限制的,


而且每次获取到access token它的有效期是7200秒,


所以当获取到access token后,


一般建议把它保存到你的web服务器,


然后设置一个有效期。


保存access token的方法


1、 保存到文本中


2、 保存到数据库中


3、 保存到缓存中


@Value("${weixin.app_id}") // spring配置文件配置了appID
    private String appId;
    
    @Value("${weixin.app_secret}") // spring配置文件配置了secret
    private String secret;
    
    @RequestMapping("/openId")
    @ResponseBody
    public Map<String, Object> openId(String code){ // 小程序端获取的CODE
        Map<String, Object> result = new HashMap<>();
        result.put("code", 0);
        try {
            boolean check = (StringUtils.isEmpty(code)) ? true : false;
            if (check) {
                throw new Exception("参数异常");
            }
            StringBuilder urlPath = new StringBuilder("https://api.weixin.qq.com/sns/jscode2session"); // 微信提供的API,这里最好也放在配置文件
            urlPath.append(String.format("?appid=%s", appId));
            urlPath.append(String.format("&secret=%s", secret));
            urlPath.append(String.format("&js_code=%s", code));
            urlPath.append(String.format("&grant_type=%s", "authorization_code")); // 固定值
            String data = HttpUtils.sendHttpRequestPOST(urlPath.toString(), "utf-8", "POST"); // java的网络请求,这里是我自己封装的一个工具包,返回字符串
            System.out.println("请求结果:" + data);
            String openId = new JSONObject(data).getString("openid");
            System.out.println("获得openId: " + openId);
            result.put("openId", openId);
        } catch (Exception e) {
            result.put("code", 1);
            result.put("remark", e.getMessage());
            e.printStackTrace();
        }
        return result;
    }
    
    请求以上这个控制器将返回openId,注意data中还有session_key也可以从这里取出来使用,至于JSON的处理方式,根据自己项目中的jar包更改代码即可

比如我想知道用户微信帐号相关的信息。先用 wx.getSetting 检查一下用户当前对我们的小程序的授权状态,如果
发现用户还没有授权小程序查看他的用户信息,就去调用 wx.authorize 弹出对话窗提醒用户是否要授权小程序得
到他的用户信息。用户如果按了同意,接下来我们就可以使用 wx.getUserInfo 这个接口去得到用户相关的信息了
,比如他的头像,名字等等。
   wx.getSetting({
      success: (response) => {
        console.log(response)
        if (!response.authSetting['scope.userInfo']) {
          wx.authorize({
            scope: 'scope.userInfo',
            success: () => {
              console.log('yes')
            }
          })
        }
      }

    })

必须需要类似传统web那种前后端分离的方法获得 比如 客户端传code 到服务端 服务端请求微信服务端返回openid 后返还给小程序 
不能用小程序直接带着参数去微信服务端 比如密钥appSecret是非常重要的敏感信息,使用该密码可以调用小程序的所有后台接口,微信
手机客户端很容易被反编译并轻松获得AppSecret造成重大威胁,开发者应该密钥保存到后台的服务器当中,所以所有对于“api.weixin.qq.com”

域名下的接口请求请全部通过后台服务器发起,请勿直接通过小程序的前端代码发起


微信小程序启动时,调用生命周期方法为:onLaunch方法(app.js)---onS
how方法(app.js)---onLoad方法(首页面:index.js的onLoad方法)

当将小程序置于后台(开发工具左下角有模拟后台按钮)时,系统回调生命周期方法:onHide


1.APP.js


我把常用且不会更改的参数放在APP.js的data里面了.在各个page中都可以拿到var app = getApp();


app上就可以拿到存在data中的参数.






2. wx.navigateTo({})中URL携带参数


demo中已经写出:


 wx.navigateTo({
      url: "../newpage/newpage?infofromindex=" + this.data.infofromindex,
  });


页面间传递参数的笔记






3.wx.setStorage(OBJECT) 数据缓存


微信开发文档中的数据缓存方法:


①存储数据


 try {
      wx.setStorageSync('infofrominput', this.data.infofrominput)
    } catch (e) {
 }


②获取数据


  //获取
        wx.getStorage({
            key: 'infofrominput',
            success: function (res) {
                _this.setData({
                    infofromstorage: res.data,
                })
            }
        })






key是本地缓存中的指定的 key,data是需要存储的内容.


详情见微信小程序开发文档:文档






贴上代码:


1.index.js




[javascript] view plain copy
//index.js  
//获取应用实例  
var app = getApp()  
Page({  
  data: {  
    info: app.data.info,  
    infofromindex: '来自index.js的信息',  
    infofrominput: ''  
  },  
  onLoad: function () {  
  },  
  //跳转到新页面  
  gotonewpage: function () {  
    wx.navigateTo({  
      url: "../newpage/newpage?infofromindex=" + this.data.infofromindex,  
    });  
  },  
  //获取输入值  
  searchInputEvent: function (e) {  
    console.log(e.detail.value)  
    this.setData({ infofrominput: e.detail.value })  
  },  
  //保存参数  
  saveinput: function () {  
    try {  
      wx.setStorageSync('infofrominput', this.data.infofrominput)  
    } catch (e) {  
    }  
  }  
})  
2.index.wxml
[html] view plain copy
<!--index.wxml-->  
<view>  
<button style="background-color:#00ff00;margin:20rpx" bindtap="gotonewpage">跳转</button>  
<input  style="background-color:#eee;margin:20rpx;height:80rpx" placeholder="请输入需要保存的参数" bindinput="searchInputEvent" />  
<button style="background-color:#ff0000;margin:20rpx" bindtap="saveinput">存入Storage</button>  
</view>  
3.newpage.js


[javascript] view plain copy
//newpage.js  
//获取应用实例  
var app = getApp()  
Page({  
    data: {  
        infofromapp: app.data.infofromapp,  
        infofromindex: '',  
        infofromstorage: '',  
    },  
    onLoad: function (options) {  
        var _this = this;  
        var infofromindex = options.infofromindex;  
        this.setData({  
            infofromindex: infofromindex  
        })  
        //获取  
        wx.getStorage({  
            key: 'infofrominput',  
            success: function (res) {  
                _this.setData({  
                    infofromstorage: res.data,  
                })  
            }  
        })  
    }  
})  
4.newpage.wxml


[html] view plain copy
<!--newpage.wxml-->  
<view style="width:100%;margin:30rpx">infofromapp:{{infofromapp}}</view>  
<view style="width:100%;margin:30rpx">infofromindex:{{infofromindex}}</view>  
<view style="width:100%;margin:30rpx">infofromstorage:{{infofromstorage}}</view>  
5.app.js


[javascript] view plain copy
//app.js  
App({  
  data: {  
    infofromapp: '来自APP.js的信息'  
  },  
  onLaunch: function () {  
  
  }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值