前端笔记之微信小程序(三)GET请求案例&文件上传和相册API&配置https
一、信息流小程序-get请求案例
1.1服务端接口开发
一定要养成接口的意识,前端单打独斗出不来任何效果,必须有接口配合,写一个带有分页、关键词查询的接口:
分页接口:
查询接口:
详情接口:
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);