一. 前言
微信小程序出来很久了,一直想探探究竟,之前都是从各方报道中知晓它的威力,也曾使用过一些小程序,如摩拜单车,大众点评网等等,虽说没有原生体验好,但节 省了应用的安装成本,对于一些不长用的app而言,还是能按时按需产出它的效果。借着前段时间学习了web前端相关知识,下面我将结合开发一款简单的资讯 app,来一探其究竟。
二. 知识库
1. 了解前端知识点html、css、js
2. 小程序语法框架教程:https://mp.weixin.qq.com/debug/wxadoc/dev/framework/MINA.html
三. Demo实现
1. 实现功能效果预览
广告横幅
Tab、网格、列表布局
下拉刷新、上拉加载更多
页面跳转、toast显示
扫一扫、相册、地图等功能
2. 代码结构
2.1. 主工程文件app.js、app.json、app.wxss
app.js:注册一个小程序,初始化全局属性,控制小程序的生命周期(类似Android中的Application)
app.json:文件用来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。(类似Android中的AndroidManifest.xml)
app.wxss:小程序公共样式(类似Android中的style.xml)
2.2 单个页面构成元素
js: 页面逻辑,控制页面的生命周期(类似Android中的Activity)
json: 页面配置,导航栏、窗口背景色等等(类似Android中的theme.xml)
wxml: 页面布局(类似Android中的layout.xml)
wxss: 页面样式(类似Android中的style.xml)
2.3. 功能实现
2.3.1. 主框架实现:app.json中配置页面和tabBar,以及相关页面配置
{ "pages": [ "pages/home/home", "pages/index/index", "pages/logs/logs", "pages/mine/mine", "pages/detect/detect", "pages/details/details" ], "window": { "backgroundTextStyle": "dark", "navigationBarBackgroundColor": "#000", "navigationBarTitleText": "WeChat", "navigationBarTextStyle": "white" }, "tabBar": { "list": [ { "pagePath": "pages/home/home", "iconPath": "res/tab_home_n.png", "selectedIconPath": "res/tab_home_p.png", "text": "首页" }, { "pagePath": "pages/detect/detect", "iconPath": "res/tab_detect_n.png", "selectedIconPath": "res/tab_detect_p.png", "text": "探索" }, { "pagePath": "pages/mine/mine", "iconPath": "res/tab_me_n.png", "selectedIconPath": "res/tab_me_p.png", "text": "我的" } ], "backgroundColor": "#ffffff", "color": "#666666", "selectedColor": "#49cb5f", "borderStyle": "white" } }
2.3.2. 首页实现:(广告横幅、网格、列表、下拉刷新和上拉加载更多)
布局:
<!--home.wxml--> <!-- 导入模板 --> <import src="../../utils/template.wxml"/> <view class="body"> <!-- 滚动View --> <scroll-view scroll-y="true" style="height: {{windowHeight}}px; width: {{windowWidth}}px;" bindscrolltolower="loadMore" bindscrolltoupper="refresh" bindscroll="scroll" scroll-top="{{scrollTop}}"> <!-- header --> <view wx:if="{{isRefreshing}}" style="display: flex;flex-direction: row;align-items: center;align-self: center;justify-content: center;"> <icon type="waiting" size="20"/> <text>刷新中...</text> </view> <view wx:else style="display:none"><text></text></view> <!-- banner --> <swiper indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}"> <block wx:for="{{bannerList}}" wx:key="*this"> <swiper-item> <view data-item="{{item}}" bindtap="bannerItemClick"> <image src="{{item.imgUrl}}" class="slide-image" /> </view> </swiper-item> </block> </swiper> <!-- 网格栏 --> <view class="grid"> <block wx:for="{{items}}" wx:key="*this"> <view class="grid-view"> <block wx:for="{{item}}" wx:key="*this"> <view class='grid-row' data-item="{{item}}" bindtap='gridItemClick'>{{item.text}}</view> </block> </view> </block> </view> <!-- 列表栏 --> <view> <block wx:for="{{list}}" wx:key="*this"> <!--用is 使用模版--> <view data-item="{{item}}" bindtap='listItemClick'> <template is="postItem" data="{{...item}}"/> </view> </block> </view> <!-- bottom --> <view style="display: flex;flex-direction: row;align-items: center;align-self: center;justify-content: center;"> <view wx:if="{{hasMore}}"> <icon type="waiting" size="20"/> <text>玩命的加载中...</text> </view> <view wx:elif="{{isRefreshing}}"><text></text></view> <view wx:else><text>没有更多内容了</text></view> </view> </scroll-view> </view>
样式:
/* home.wxss */ .body { background-color: #f7f7f7; } .slide-image { width: 100%; height: 300rpx; } .grid { background-color: #f0f0f0; padding: 30rpx 10rpx 30rpx 10rpx; } .grid-view { display: flex; flex-direction: row; } .grid-row { width: 100%; height: 100rpx; line-height: 100rpx; background-color: white; margin: 10rpx; text-align: center; color: #666666; }
代码逻辑:
// home.js Page({ /** * 页面的初始数据 */ data: { bannerList: [ { imgUrl: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1870203556,2400775406&fm=200&gp=0.jpg', link:'http://www.mob.com' }, { imgUrl: 'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=492336717,911941398&fm=26&gp=0.jpg', link: 'https://mp.weixin.qq.com' }, { imgUrl: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=2536162506,232284120&fm=26&gp=0.jpg', link: 'https://mp.weixin.qq.com/debug/wxadoc/dev/framework/client-lib.html' } ], indicatorDots: true, autoplay: true, interval: 5000, duration: 1000, items: [ [{text:"推荐"}, {text:"热门"}, {text:"精华"}], [{ text: "八卦" }, { text: "体育" }, { text: "游戏" }] ], list: [], page: 1, pageSize: 20, loading: false, isRefreshing: false, scrollTop: 0, hasMore: false, windowHeight: 0, windowWidth: 0 }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { var that = this; wx.getSystemInfo({ success: function (res) { that.setData({ windowHeight: res.windowHeight, windowWidth: res.windowWidth }) } }); that.refresh(); }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { }, /** * 生命周期函数--监听页面显示 */ onShow: function () { }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { }, /** * 滚动监听回调 */ scroll: function (e) { var that = this; that.setData({ scrollTop: e.detail.scrollTop }); console.log(that.data.scrollTop); }, /** * 下拉刷新回调 */ refresh: function (e) { var that = this; if (that.data.loading) return; that.setData({ loading: true, scrollTop: 0, isRefreshing: true }); //请求网络,回调后执行setData setTimeout(function(){ that.loadData(1, function (tempList, tempHasMore) { that.setData({ page: 1, list: tempList, isRefreshing: false, loading: false, hasMore: tempHasMore }); }) }, 2000); }, /** * 加载更多回调 */ loadMore: function(e) { var that = this; if (!that.data.hasMore || that.data.loading) return; //请求网络,回调执行setData that.setData({ loading: true }); setTimeout(function(){ that.loadData(that.data.page + 1, function (tempList, tempHasMore) { that.setData({ page: that.data.page + 1, list: tempList, loading: false, hasMore: tempHasMore }); }) }, 2000); }, /** * 加载数据 */ loadData: function(page, callback) { var that = this; var tempList = []; if (page > 1) { tempList = that.data.list; } var imgs = [ "<a href="https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2476805174,2083338804&fm=27&gp=0.jpg" "="" style="color: rgb(59, 115, 175); text-decoration: none; border-radius: 0px !important; background: none !important; border: 0px !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; line-height: 20px !important; margin: 0px !important; outline: 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important; box-sizing: content-box !important; min-height: auto !important;">https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2476805174,2083338804&fm=27&gp=0.jpg", "<a href="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2906346913,2678799258&fm=27&gp=0.jpg" "="" style="color: rgb(59, 115, 175); text-decoration: none; border-radius: 0px !important; background: none !important; border: 0px !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; line-height: 20px !important; margin: 0px !important; outline: 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important; box-sizing: content-box !important; min-height: auto !important;">https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2906346913,2678799258&fm=27&gp=0.jpg", "<a href="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=836703398,352953767&fm=27&gp=0.jpg" "="" style="color: rgb(59, 115, 175); text-decoration: none; border-radius: 0px !important; background: none !important; border: 0px !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; line-height: 20px !important; margin: 0px !important; outline: 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important; box-sizing: content-box !important; min-height: auto !important;">https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=836703398,352953767&fm=27&gp=0.jpg", "<a href="http://img1.imgtn.bdimg.com/it/u=508214869,280178022&fm=27&gp=0.jpg" "="" style="color: rgb(59, 115, 175); text-decoration: none; border-radius: 0px !important; background: none !important; border: 0px !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; line-height: 20px !important; margin: 0px !important; outline: 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important; box-sizing: content-box !important; min-height: auto !important;">http://img1.imgtn.bdimg.com/it/u=508214869,280178022&fm=27&gp=0.jpg", "<a href="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2466198091,908973858&fm=27&gp=0.jpg" "="" style="color: rgb(59, 115, 175); text-decoration: none; border-radius: 0px !important; background: none !important; border: 0px !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; line-height: 20px !important; margin: 0px !important; outline: 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important; box-sizing: content-box !important; min-height: auto !important;">https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2466198091,908973858&fm=27&gp=0.jpg" ]; for (var i = 1; i <= that.data.pageSize; i++) { tempList.push( { icon: imgs[i%imgs.length], title: "标题_" + page + "_" + i, content: "我是内容区域", time: that.getDate() }); //FOR TEST 三页到底 if (page == 3 && i == that.data.pageSize / 2) { break; } } if (callback) { callback(tempList, tempList.length % that.data.pageSize == 0); } }, /** * 获取日期 */ getDate: function() { var date = new Date(); return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate(); }, /** * banner点击事件回调 */ bannerItemClick: function(event) { wx.setStorageSync("link", event.currentTarget.dataset.item.link); wx.navigateTo({ url: '../../pages/details/details' }) }, /** * 网格点击事件回调 */ gridItemClick: function (event) { wx.showToast({ title: event.currentTarget.dataset.item.text, }) }, /** * 列表点击事件回调 */ listItemClick: function (event) { console.log(event.currentTarget.dataset); wx.setStorageSync("listItem", event.currentTarget.dataset.item); wx.navigateTo({ url: '../../pages/details/details' }) } })
文/Mob开发者平台 Android开发专家 吴文军