一直从事安卓开发,前不久公司突然让我研究一下微信小程序。微信小程序的需求现在越来越多了,各种大小公司现在一开口就是来给我做个小程序,微信小程序以其“即用即走”的超便利特性受到越来越多用户的青睐,毕竟有些时候你并不想花时间或者流量去下载一个app,小程序能够以一种极轻的方式展现在用户面前,最终完成一定的业务流程。而且现在的小程序功能及UI已经不比原生的应用差太多了。我觉得小程序应该是以后的发展方向吧(这几年的发展已经印证了这一点)好了废话不多说,马上开始。
微信小程序的基本结构
先来下载开发者工具 新建项目,选择一个空的目录作为项目路径,没有appid的选择使用测试号
项目建立之后的项目结构如下
App全局文件
1、app.js 是小程序的逻辑,一个小程序只能在这里注册一个App
App({//生命周期 onLaunch: function() { },//监听初始化 onShow: function() { },//监听显示(进入前台) onHide: function() { },//监听隐藏(进入后台:按home离开微信) onError: function(msg) { },//监听错误 //自定义的全局方法和全局变量 globalFun:function(){}, globalData: 'I am global data' })
2、app.json 是当前小程序的全局配置,包括了小程序的所有页面路径、界面表现、网络超时时间、底部 tab 等.page.json对于page进行单独的页面设置可覆盖app.json的属性值
{ "pages":[ "pages/index/index", "pages/logs/logs" ], "window":{ "backgroundTextStyle":"light", "navigationBarBackgroundColor": "#fff", "navigationBarTitleText": "WeChat", "navigationBarTextStyle":"black" } }
3、app.wxss 是小程序的全局样式,wxss对应到web上的css
.container { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: space-between; padding: 200rpx 0; box-sizing: border-box; }
Page包含的文件
pages是小程序所包含的页面,在pages文件夹下面新建空目录,右键选择生成页面即可生成页面所需要的文件,即page.js、page.json、page.wxss、page.wxml,page.json和page.wxss为非必须
1、page.js 一个page一个Page入口,用于管理页面的生命周期、自定义方法和参数
Page({ data: {text: "This is page data."},//页面数据,用来维护视图,json格式 onLoad: function(options) { },//监听加载 onReady: function() { },//监听初次渲染完成 onShow: function() { },//监听显示 onHide: function() { },//监听隐藏 onUnload: function() { },//监听卸载 onPullDownRefresh: function() { },//监听下拉 onReachBottom: function() { },//监听上拉触底 onShareAppMessage: function () { },//监听右上角分享 //如下为自定义的事件处理函数(视图中绑定的) viewTap: function() {//setData设置data值,同时将更新视图 this.setData({text: 'Set some data for updating view.'}) } })
2、page.wxml 为page的view 用于数据的展示,view对应于我们html的div,text则对应于span,自动生成的index.wxml如下,实现一个点击登录的功能
<view class="container"> <view class="userinfo"> <button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 </button> <block wx:else> <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image> <text class="userinfo-nickname">{{userInfo.nickName}}</text> </block> </view> <view class="usermotto"> <text class="user-motto">{{motto}}</text> </view> </view>
3、数据的绑定,结合官方示例,写一个简单的page demo
page.wxml
<!-- 简单绑定 --> <view> {{ message }} </view> <!-- 组件属性 --> <view id="item-{{id}}">{{id}}</view> <!-- 控制属性 --> <view wx:if="{{condition}}"> condition</view> <!--关键字(需要在双引号之内) true:boolean 类型的 true,代表真值。 false: boolean 类型的 false,代表假值。--> <checkbox checked="{{false}}"> </checkbox> <!-- 字符串运算 --> <view>{{"hello" + name}}</view> <!-- 数据路径运算 --> <view>{{object.key}} {{array[0]}}</view> <!-- 循环遍历 --> <view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName"> {{idx}}: {{itemName.message}} </view> <!-- 模板 --> <template name="msgItem"> <view> <text> {{index}}: {{msg}} </text> <text> Time: {{time}} </text> </view> </template> <template is="msgItem" data="{{...item}}"/> <!-- 点击事件 --> <view id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </view>
page.js
Page({ data: { message: 'Hello MINA!', id: 0, condition: true, name: 'MINA', object: { key: 'Hello ' }, array: ['MINA'], array: [{ message: 'foo', }, { message: 'bar' }], item: { index: 0, msg: 'this is a template', time: '2016-09-15' } }, tapName: function (event) { console.log(event) } })
豆瓣Top250
一直都喜欢用豆瓣电影的接口来做一些新技术的学习,哈哈
可以看看我之前的这篇文章,Python3 爬取豆瓣电影Top250
豆瓣接口对于微信小程序的访问做了限制,用了一个其他的接口,返回的数据是一致的 douban.uieee.com/v2/movie/to…
此外在开发时ide记得勾选不校验域名,正式上线以后要把域名配到合法域名当中去
下面直接上代码
app.json
{ "pages": [ "pages/list/list", "pages/detail/detail" ], "window": { "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#072", "navigationBarTitleText": "豆瓣电影", "navigationBarTextStyle": "light" } }
list.wxml
<!--pages/list/list.wxml--> <wxs module="filters" src="./list.wxs"></wxs> <view wx:for="{{movies}}" wx:key="{{item.id}}" data-index="{{index}}" class ="movie_item" bindtap="goDetail"> <image class="image" src="{{item.images.small}}"></image> <view class="movie_info"> <text class="title">{{item.title}}</text> <view class="star"> <text class="{{filters.getRating(item.rating.average)}}"></text> <text class="rating_num">{{filters.toFix(item.rating.average)}}</text> </view> </view> </view>
list.js
var start = 0; Page({ start: 0, /** * 页面的初始数据 */ data: { movies: [] }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { var that = this; this.loadMore(that); }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { }, /** * 生命周期函数--监听页面显示 */ onShow: function () { }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { start = 0; var that = this; this.loadMore(that); wx.stopPullDownRefresh(); }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { var that = this; this.loadMore(that); }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { }, loadMore:function(that){ that.getMovie(function (d) {//回调函数,根据数据设置页面data,更新到视图 wx.hideToast();//隐藏加载框 var list = that.data.movies; for(var i=0;i<d.length;i++){ list.push(d[i]); } that.setData({ movies: list })//更新数据,视图将同步更新 }) }, getMovie:function(fn) { wx.showToast({ title: '加载中', icon: 'loading', duration: 10000 }) wx.request({//请求服务器,类似ajax url: 'https://douban.uieee.com/v2/movie/top250?start='+start, header: { 'content-type': 'json' }, success: function (res) { start=start+20; console.log(res) fn(res.data.subjects) }//成功后将数据传给回调函数执行 }) }, goDetail:function(e) { var that = this //拿到点击的index下标 var index = e.currentTarget.dataset.index var movie = JSON.stringify(that.data.movies[index]) wx.navigateTo({ url: '../detail/detail?movie='+movie, }) } })
list.wxss
.movie_item { margin: 8px; border-radius: 5px; background-color: #fff; box-shadow: 1px 1px 1px #cccccc; position: relative; display: block; padding: 8px; overflow: hidden; box-sizing: border-box; } .image { width: 64px; height: 100px; margin-right: 15px; background-color: #eeeeee; float: left; } .movie_info { float: left } .title { font: 12px Arial, Helvetica, sans-serif; line-height: 150%; color: #669; } .rating10-t, .rating15-t, .rating20-t, .rating25-t, .rating30-t, .rating35-t, .rating40-t, .rating45-t, .rating50-t, .rating-t{ display: inline-block; zoom: 1; background: url(https://img3.doubanio.com/f/shire/b8f4c3672ef81106701071831e22422a745d3b74/pics/rating_icons/ic_rating_s.png) no-repeat; width: 55px; height: 11px; margin: 0 3px 0 0; overflow: hidden; } .rating50-t { background-position: 0 0px; } .rating45-t { background-position: 0 -11px; } .rating40-t{ background-position: 0 -22px; } .rating_num { color: #e09015; padding: 0 5px 0 0; font-size: 12px; }
list.wxs
var filters = { getRating:function(value){ return "rating"+Math.round(value)*5+"-t"; }, toFix: function (value) { return value.toFixed(1)//此处2为保留两位小数 } } module.exports = { getRating: filters.getRating, toFix: filters.toFix }
讲几个注意点
1、在页面的js里面修改数据
setData({ movies: list })
2、在显示豆瓣评分星级的时候不同分数电影的星标的class是不一样的,我们需要根据分数得到class,计算的方法写在wxs文件中 在wxml这样引入方法
<text class="{{filters.getRating(item.rating.average)}}"></text>
3、页面的跳转并传递数据可以用query的方式
var movie = JSON.stringify(that.data.movies[index]) wx.navigateTo({ url: '../detail/detail?movie='+movie, })
在下个页面的onload方法里面可以将数据提取出来
onLoad: function (options) { var that = this var movie = JSON.parse(options.movie) console.log(movie.images.small) that.setData({ movie: movie }) },
效果图如下