一、信息流小程式-GET請求案例 1.1服務端介面開發 一定要養成介面的意識,前端單打獨鬥出不來任何效果,必須有介面配合,寫一個帶有分頁、關鍵詞查詢的介面: 分頁介面:http://127.0.0.1:3000/info?page=1 查詢介面:http://127.0.0.1:3000/searc ...
一、信息流小程式-GET請求案例
1.1服務端介面開發
一定要養成介面的意識,前端單打獨鬥出不來任何效果,必須有介面配合,寫一個帶有分頁、關鍵詞查詢的介面:
分頁介面:http://127.0.0.1:3000/info?page=1
查詢介面:http://127.0.0.1:3000/search?word=李
詳情介面:http://127.0.0.1:3000/xiangqing?id=2
const express = require("express"); const app = express(); const url = require("url"); const info = require("./info.js"); app.use(express.static("www")); //顯示分頁的明星信息 app.get("/info" , (req,res) => { const page = url.parse(req.url , true).query.page; //得到GET請求的page參數 //提供分頁的介面 res.json({ "arr" : info.slice((page-1) * 4 , page * 4) }); }); //關鍵字篩選查詢 app.get("/search" , (req,res) => { //得到用戶的查詢詞 var word = url.parse(req.url , true).query.word; //將字元串word變為正則表達式 var wordExp = new RegExp(word); //遍歷,篩選 res.json({ "arr" : info.filter(item => wordExp.test(item.name)) }); }); //某明星詳情 app.get("/xiangqing" , (req,res) => { //得到用戶的查詢的明星id var id = url.parse(req.url , true).query.id; //遍歷,篩選 res.json({ "xiangqing" : info.filter(item => item.id == id)[0] }); }) app.listen(3000);
1.2小程式開發
學習scrioll-view容器(可滾動視圖區域)和發起請求。
<scroll-view style="height:{{wH}}px;" scroll-y bindscrolltolower="tolower"> <view>亂起八早</view> <view>亂起八早</view> <view>亂起八早</view> ..... </scroll-view>
bindscrolltolower表示滾動到底部的事件,但這個盒子必須有高度。
如果希望這個盒子的高度和視窗的高度一樣,此時調用微信API,讀取設備視窗高度。
app.js使用微信小程式的API得到屏幕的高度:
//app.js App({ //用戶首次打開小程式,觸發 onLaunch函數(全局只觸發一次) onLaunch(){ var self = this; //讀取設備信息的API wx.getSystemInfo({ success: function(res){ self.globalData.gWH = res.windowHeight; //獲取視窗高度賦值給全局gWH對象 } }); }, //全局數據 globalData : { gWH : 0 } });
index.js中可以獲取app.js的全局數據
//每個頁面可以無條件、不引包的,直接使用getApp()函數,表示調用小程式的主體 var app = getApp(); Page({ //當頁面載入的時候 onLoad(){ //得到視窗的高度,globalData.gWH數據是從全局獲取的 this.setData({ wH: app.globalData.gWH }); }, //局部數據 data:{ wH: 0 //當前屏幕的高度 } tolower(){ console.log("已經滾到底部了") } });
1.3頁面佈局
<!--index.wxml--> <view class="container"> <scroll-view style="height:{{wH}}px" scroll-y bindscrolltolower="tolower"> <view class="mingxing"> <view class="box" wx:for="{{mingxing}}" wx:key="{{index}}"> <view class="left"> <image src="{{baseURL}}/images/{{item.pic}}"></image> {{item.name}} </view> <view class="right"> {{item.b_info}} </view> </view> </view> </scroll-view> </view>
index.wxss
page { background-color:#36b3ff; } .box{ width:720rpx;display: flex;margin:10px auto;font-size: 14px; line-height:24px;color:#333; padding:10px; background: #fff; box-sizing:border-box; border-radius:6px; box-shadow: 1px 1px 1px rgba(0,0,0,0.5); } .left{flex:1;} .left image{width:180rpx; height:180rpx;} .right{flex:3;box-sizing: border-box;padding-left:10px;}示例代碼
1.4請求分頁數據-顯示頁面效果
index.js中載入預設數據
Page({ //當頁面載入的時候 onLoad(){ //得到視窗的高度,是從全局來的 this.setData({ wH: appInstance.globalData.wH }); //核心語句:請求伺服器的數據,參數page表示第幾頁,當前第幾頁就請求第幾頁 var self = this; wx.request({ //請求的地址 url: 'http://127.0.0.1:3000/info?page=' + this.data.page, //成功的回調 success({data}){ self.setData({ mingxing: [ ...self.data.mingxing, ...data.arr ] }); } }); }, data : { wH : 0, //當前屏幕的高度 mingxing: [], //信息流,現在是空的,等伺服器返回 page : 1, //當前第幾頁,預設第一頁 } });
index.js下拉請求更多
var app = getApp(); //請求伺服器上某一個頁面的明星,參數page表示第幾頁 function queryServer(page){ //顯示一個Toast,Toast就是提示文本,黑色背景的方框。 wx.showToast({ title: '正在載入更多', icon: 'loading', duration: 2000000 //持續時間,非常長,因為靠回調函數給它隱藏。 }); var self = this; //核心語句,請求伺服器的數據,分頁請求,當前第幾頁就請求第幾頁 wx.request({ //請求的地址 url: this.data.baseURL + '/info?page=' + page, //成功的回調 success({ data }){ //隱藏Toast wx.hideToast(); //看一下請求的數組長度是不是0,如果是0此時就改變信號量 if(data.arr.length == 0){ self.setData({ isMore : false }); return; } //如果不是0,改變值,追加數據 self.setData({ mingxing: [ ...self.data.mingxing, ...data.arr ] }); } }); } Page({ onLoad(){ //指定queryServer函數的上下文,綁定好後,調用時上下文自動就是這裡的this了 //不需要queryServer.call(this)了。 queryServer = queryServer.bind(this); //得到視窗的高度,是從全局來的 this.setData({ wH: app.globalData.wH }); //請求第1頁的數據 queryServer(1); }, data : { wH : 0 , mingxing: [], page : 1, baseURL:"http://127.0.0.1/3000", //基路徑 isMore : true //是否還有更多? }, tolower(){ if(this.data.isMore){ //頁面數加1 this.setData({ page : this.data.page + 1 }); //下拉到底部請求更多 queryServer(this.data.page); } } });
1.5關鍵字查詢
<!--index.wxml--> <view class="container"> <view class="s_b"> <input value="{{searchWord}}" bindconfirm="doSearch" class="s_box" type="text" /> <button bindtap='clearSearch'>×</button> </view> </view>
index.wxss
.s_box{ background: white;width:700rpx;margin: 0 auto;} .s_b{ position:relative;} .s_b button{ position: absolute; right:10px;top:0; z-index: 999;padding:0; width:20px;height:20px;line-height: 20px;text-align: center; }示例代碼
index.js
Page({ data : { ... }, tolower(){ ... }, //執行查詢 doSearch(event){ var self = this; wx.request({ url: baseURL + "/search?word=" + event.detail.value , success({data}){ self.setData({ mingxing : data.arr }); } }); }, //清空查詢 clearSearch(){ this.setData({ searchWord : "", mingxing : [] }); //重新請求當前的頁碼,顯示全部 //迴圈請求,比如當前頁碼是2,此時就要請求2、1 for(let i = 1 ; i <= this.data.page ; i++){ queryServer(i); } } });
1.6點擊查看詳情頁
index.wxml
<view class="mingxing"> <view class="box" wx:for="{{mingxing}}" data-mid="{{item.id}}" bindtap='tapBox' > ..... </view> </view>
info.wxml詳情頁
<view> <view>{{name}}</view> <image wx:if="{{pic != ''}}" src="{{baseURL}}/images/{{pic}}"></image> <view> {{info}} </view> </view>
index.js
Page({ //點擊了一個小白框,進入詳情頁 tapBox(event){ //通過自己的data-mid標簽,知道自己是誰 var mid = event.currentTarget.dataset.mid; //帶給下一個頁面 wx.navigateTo({ //通過?傳參給info頁面,是微信小程式的語法約定,而並不是GET請求 url: '/pages/info/info?mid=' + mid }) } });
info.js
//基路徑 const baseURL = "http://127.0.0.1:3000"; Page({ onLoad({mid}){ var self = this; wx.request({ url : baseURL + "/xiangqing?id=" + mid , success({data}){ self.setData({ name: data.xiangqing[0].name, pic : data.xiangqing[0].pic, info: data.xiangqing[0].info }) } }) }, data : { name : "", pic : "", info : "", baseURL } });
二、文件上傳和相冊API
2.1小程式和Nodejs後端
前端是小程式,後端Nodejs,用formidable來處理POST請求,上傳圖片。
在小程式中發起POST請求:
<!--index.wxml--> <view class="container"> <button bindtap="fasong">按我將{a:8}這個信息用POST請求發給伺服器</button> </view>
index.js
Page({ fasong: function(){ wx.request({ //請求地址 url: 'http://127.0.0.1:3000/tijiao', //請求類型 method : "POST" , //提交給服務端的數據 data : { a : 8 }, //成功的回調函數 success : function({data}){ console.log(data.result); } }); } });
後端:
const express = require("express"); const app = express(); const formidable = require("formidable"); app.post("/tijiao", (req,res)=>{ var form = new formidable.IncomingForm(); form.parse(req, (err, data) => { console.log(data); res.json({result:"ok"}); }); }); app.listen(3000);示例代碼
2.2 圖片的上傳
在微信中是兩個事:
第一:調用wx.chooseImage()這個API,讓用戶選擇一個圖片文件或者拍照;
第二:調用wx.uploadFile()這個API,來傳輸文件。
從本地相冊選擇圖片或使用相機拍照的API:
wx.chooseImage();
上傳文件的API:
wx.uploadFile();
<!--index.wxml--> <view class="container"> <button bindtap="chooseImg">選擇圖片</button> </view>
前端代碼index.js:
Page({ chooseImg(){ //選擇圖片或者進行拍照 wx.chooseImage({ count : 1, //只能選擇1張 //選擇圖片成功之後做的事情 success({tempFilePaths}){ wx.uploadFile({ url : "http://127.0.0.1:3000/tijiao" , //上傳地址 filePath: tempFilePaths[0], //要上傳的文件,只有1張圖片也是數組,所以[0] name: "tupian", //key success({data}){ wx.showToast({ title: "上傳成功!" }); } }); } }); } });
後端formidable可以處理圖片的上傳,只需要加一句話:
const express = require("express"); const app = express(); const formidable = require("formidable"); app.post("/tijiao", (req,res)=>{ var form = new formidable.IncomingForm(); form.uploadDir = "./uploads"; //設置圖片的保存路徑 form.keepExtensions = true; //保留拓展名 form.parse(req, (err, fileds, file)=>{ res.json({result: "ok"}); }); }); app.listen(3000);
開啟下拉刷新,在需要下拉刷新的頁面中index.json中添加:
{ "enablePullDownRefresh" : true }
<!--index.wxml--> <view class="container"> <button bindtap="chooseImg">選擇圖片</button> <view wx:for="{{imgList}}" wx:key="{{index}}"> <image mode="center" src="http://127.0.0.1:3000/uploads/{{item}}"></image> </view> </view>
後端app.js
const express = require("express"); const app = express(); const formidable = require("formidable"); const fs = require("fs"); //靜態化圖片目錄 app.use("/uploads" , express.static("uploads")); //處理用戶的提交 app.post("/tijiao" , (req,res) => { var form = new formidable.IncomingForm(); form.uploadDir = "./uploads"; //設置圖片的保存路徑 form.keepExtensions = true; //保留拓展名 form.parse(req , (err , fileds , files) => { //將上傳文件改名為現在的時間戳,就是1970年1月1日到現在的毫秒數 var date = Date.parse(new Date()); var ext = path.extname(files.tupian.path); //獲取文件擴展名 //改名 fs.rename(`./${files.tupian.path}`, `./uploads/${date}${ext}`, function(){ res.json({result : "ok"}); }); }); }); //列出所有文件的清單 app.get("/list" , (req,res)=>{ fs.readdir("./uploads", (err, files) => { res.json({ imgList: files.reverse()}); }); }); app.listen(3000);
index.js
Page({ xuantu(){ ... }, //顯示所有已經上傳的圖片 onLoad(){ var self = this; wx.request({ url: "http://127.0.0.1:3000/list", success({data}){ self.setData({ imgList: data.imgList }) } }); }, //當下拉刷新的時候 onPullDownRefresh(){ var self = this; wx.request({ url: "http://127.0.0.1:3000/list", success({data}){ self.setData({ imgList: data.imgList }) } }); } });
2.3獲取微信用戶信息
//得到app本身,為什麼要得到,因為一會就能使用app.globalData.userInfo const app = getApp(); Page({ ... addPics(){ ... }, //*************這裡面的代碼是從HelloWorld案例抄的 start************* onLoad: function () { if (app.globalData.userInfo) { this.setData({ userInfo: app.globalData.userInfo, hasUserInfo: true }) } else if (this.data.canIUse){ // 由於 getUserInfo 是網路請求,可能會在 Page.onLoad 之後才返回 // 所以此處加入 callback 以防止這種情況 app.userInfoReadyCallback = res => { this.setData({ userInfo: res.userInfo, hasUserInfo: true }) } } else { //在沒有 open-type=getUserInfo 版本的相容處理 wx.getUserInfo({ success: res => { app.globalData.userInfo = res.userInfo; this.setData({ userInfo: res.userInfo, hasUserInfo: true }); } }) } }, getUserInfo: function(e) { app.globalData.userInfo = e.detail.userInfo; this.setData({ userInfo: e.detail.userInfo, hasUserInfo: true }); } //*************這裡面的代碼是從Hello World案例抄的 end************* })示例代碼
三、Nodejs配置https
首先,需要申請SSL證書,證書可以在阿裡雲、騰訊雲、寶塔等平臺申請,申請成功後會提供SSL證書下載地址,下載好SSL證書會看見一個壓縮包,裡面包含很多版本的證書文件(IIS、Apache、Nginx、Tomcat)等,Nodejs服務端採用Nginx版本即可,裡面有兩個文件分別是:.key和.pem文件。
將文件放在你的Node項目中的某個文件夾中,這裡我放在根目錄的ssl文件夾中。
然後寫以下Node代碼即可開啟https
註意:要修改自己的key和pem文件路徑和名稱
//使用node自帶的https模塊開啟https服務 var https = require("https"); //讀取https配置文件 //讀取https配置 var httpsOption = { key : fs.readFileSync("./ssl/0_iqd.webqianduan.cn.key"), cert: fs.readFileSync("./ssl/1_iqd.webqianduan.cn_bundle.pem") } //監聽埠 http.createServer(app).listen(80); https.createServer(httpsOption, app).listen(443);