小程序整理雜篇

微信的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 () {  
  
  }  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章