说点儿闲话
上周一,技术主管忽然分给我一个任务,是微信页面的开发任务,专门指明了让用 iView Weapp来做。
iView Weapp是一套高质量的微信小程序 UI 组件库
意思很明显了,是开发微信小程序呢,之前从没做过小程序项目,不过很久之前自己学过一点儿,上手起来不难,这里分享一下实现的过程。
最终效果 先睹为快
安装小程序开发者工具 并 新建一个小程序代码
首先,需要安装小程序开发者工具,如果已经装过了,直接用就可以了。
按照微信开放文档 你的第一个小程序 新建一个小程序,开发过程中,小程序的 AppID可以先试用测试号。
vs code 编写小程序代码
在vs code中进行代码编写,vs code需要安装以下插件:
1. minapp
支持微信小程序标签、属性的智能补全,并且提示中包含文档内容(同时支持原生小程序、mpvue 和 wepy 框架,并提供 snippets)。
2.wechat-snippet
这个插件主要的功能就是代码辅助,代码片段自动完成,可以作为上个插件的补充。
3.wxml
这款插件用于将wxml代码进行高亮显示,并且提供代码格式化的功能,可将代码格式化为较易阅读的样式。
4.vscode weapp api
为 VSCode 提供微信小程序 API 提示及代码片段。
搭建项目
整合目录结构
小程序目录结构 这里不再赘述,看官方文档就好。
新建的小程序默认已经有index和logs,那么,我这里是将index,复制一份改为mine,新建list,删除logs,list的数据将直接使用logs的数据做为例子,所以,logs可以先留着自己看看。在根目录下新建images,用于存放项目中的图片。
小程序配置
小程序配置 按照文档来配置小程序, 全局配置和页面配置等。
然后,做如下修改:
在app.json
:
pages:
"pages": [
"pages/index/index",
"pages/list/list",
"pages/mine/mine"
],
引入iView Weapp
快速上手 - iView Weapp按照文档,到 GitHub 下载 iView Weapp 的代码,将 dist 目录拷贝到自己的项目中。然后按需引用组件。
底部导航菜单
将需要用的图标放在images/tabBar/下,然后在app.json
增加 tabBar:
"tabBar": {
"color": "#333333",
"selectedColor": "#2e75b6",
"list": [
{
"pagePath": "pages/index/index",
"selectedIconPath": "images/tabBar/tabBar-s1.png",
"iconPath": "images/tabBar/tabBar-s2.png",
"text": "首页"
},
{
"pagePath": "pages/list/list",
"selectedIconPath": "images/tabBar/tabBar-k1.png",
"iconPath": "images/tabBar/tabBar-k2.png",
"text": "列表"
},
{
"pagePath": "pages/mine/mine",
"selectedIconPath": "images/tabBar/tabBar-w1.png",
"iconPath": "images/tabBar/tabBar-w2.png",
"text": "我的"
}
]
},
效果如图:
首页index页面实现
轮播图
首页上方先放一个轮播图,直接使用 组件中的视图容器—— swiper 滑块视图容器 即可实现轮播图,还是先把图片放置在images
中,然后在index.js中配置data,并设置swiper的属性。
index.js:
Page({
data: {
imgUrls: [
'../../images/index/pic1.jpg',
'../../images/index/pic2.png',
'../../images/index/pic3.jpg'
],
indicatorDots: true, // 是否显示面板指示点
autoplay: true, // 是否自动切换
interval: 2000, // 自动切换时间间隔
duration: 1000, // 滑动动画时长
},
})
在index.wxml中:
<swiper indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" class="swiper">
<block wx:for="{{imgUrls}}" wx:key="index">
<swiper-item>
<image src="{{item}}" class="slide-image" />
</swiper-item>
</block>
</swiper>
index.wxss:
/**index.wxss**/
.swiper {
height: 300rpx;
border-bottom: 1rpx solid #ccc;
}
.slide-image {
width: 100%;
height: 100%;
}
图标宫格、通告栏、信息卡片
图标宫格、通告栏、信息卡片这三个模块,直接使用 iView Weapp 的组件。
在index.json中:
{
"usingComponents": {
"i-grid": "../../dist/grid/index",
"i-grid-item": "../../dist/grid-item/index",
"i-grid-icon": "../../dist/grid-icon/index",
"i-grid-label": "../../dist/grid-label/index",
"i-icon": "../../dist/icon/index",
"i-row": "../../dist/row/index",
"i-card": "../../dist/card/index",
"i-panel": "../../dist/panel/index",
"i-notice-bar": "../../dist/notice-bar/index"
}
}
在index.wxml中,swiper下继续写:
<i-grid>
<i-row>
<i-grid-item>
<i-grid-icon>
<i-icon size="24" type="activity" />
<i-grid-label>宫格</i-grid-label>
</i-grid-icon>
</i-grid-item>
<i-grid-item>
<i-grid-icon>
<i-icon size="24" type="addressbook" />
<i-grid-label>宫格</i-grid-label>
</i-grid-icon>
</i-grid-item>
<i-grid-item>
<i-grid-icon>
<i-icon size="24" type="barrage" />
<i-grid-label>宫格</i-grid-label>
</i-grid-icon>
</i-grid-item>
</i-row>
<i-row>
<i-grid-item>
<i-grid-icon>
<i-icon size="24" type="collection" />
<i-grid-label>宫格</i-grid-label>
</i-grid-icon>
</i-grid-item>
<i-grid-item>
<i-grid-icon>
<i-icon size="24" type="computer" />
<i-grid-label>宫格</i-grid-label>
</i-grid-icon>
</i-grid-item>
<i-grid-item>
<i-grid-icon>
<i-icon size="24" type="coupons" />
<i-grid-label>宫格</i-grid-label>
</i-grid-icon>
</i-grid-item>
</i-row>
</i-grid>
<i-panel title="滚动 通告栏">
<i-notice-bar icon="systemprompt" loop speed="800">
2018年世界杯,将于6月14日至7月15日举行;2018年世界杯,将于6月14日至7月15日举行;
</i-notice-bar>
</i-panel>
<view style="margin: 16px">标题</view>
<i-card full title="卡片标题" extra="额外内容" thumb="![](file:///C:\Users\SSJ\AppData\Roaming\Tencent\QQTempSys\%W@GJ$ACOF(TYDYECOKVDYB.png)https://i.loli.net/2017/08/21/599a521472424.jpg">
<view slot="content">内容不错</view>
<view slot="footer">尾部内容</view>
</i-card>
首页布局就算是完成了,是不是还挺简单的呢?跟着做下去,你将得到一个简单的微信小程序Demo。
我的mine页面实现
获取用户信息:名字、头像,及 功能列表,直接上代码:
mine.js:
//mine.js
//获取应用实例
const app = getApp()
Page({
data: {
motto: 'Hello World',
userInfo: {},
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo')
},
//事件处理函数
bindViewTap: function() {
// 点击头像跳转
wx.navigateTo({
url: '../mine/mine'
})
},
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
})
},
fail: function () {
//获取用户信息失败后。请跳转授权页面
wx.showModal({
title: '警告',
content: '尚未进行授权,请点击确定跳转到授权页面进行授权。',
success: function (res) {
if (res.confirm) {
console.log('用户点击确定')
wx.navigateTo({
url: '../tologin/tologin',
})
}
}
})
}
})
}
},
getUserInfo: function(e) {
// console.log(e)
app.globalData.userInfo = e.detail.userInfo
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
}
})
mine.json:
{
"navigationBarTitleText": "个人中心",
"usingComponents": {
"i-panel": "../../dist/panel/index",
"i-cell-group": "../../dist/cell-group/index",
"i-cell": "../../dist/cell/index"
}
}
mine.wxml :
<!--mine.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>
<i-panel title="功能">
<i-cell-group>
<i-cell title="我的xx" is-link url="pages/mine/mine"></i-cell>
<i-cell title="xxxxxxx" is-link url="pages/mine/mine"></i-cell>
<i-cell title="xxxxxxx" is-link url="pages/mine/mine"></i-cell>
<i-cell title="消费记录" is-link url="pages/mine/mine"></i-cell>
</i-cell-group>
</i-panel>
mine.wxss:
/**mine.wxss**/
.container {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 20rpx 0;
box-sizing: border-box;
}
.userinfo {
display: flex;
flex-direction: column;
align-items: center;
}
.userinfo-avatar {
width: 128rpx;
height: 128rpx;
margin: 20rpx;
border-radius: 50%;
}
.userinfo-nickname {
color: #aaa;
}
.usermotto {
margin: 20px;
}
列表list页面实现
list.json:
{
"navigationBarTitleText": "列表页",
"enablePullDownRefresh": true, // 下拉刷新
"usingComponents": {
"i-card": "../../dist/card/index",
"i-spin": "../../dist/spin/index",
"i-load-more": "../../dist/load-more/index"
}
}
list实现
list.js:
//list.js
const util = require('../../utils/util.js')
Page({
data: {
logs: [],
},
onLoad: function() {
this.clearCache(); //清本页缓存
this.getArticles(0); //第一次加载数据
},
getArticles: function(pageno) {
this.setData({
logs: (wx.getStorageSync('logs') || []).map(log => {
return util.formatTime(new Date(log))
})
})
},
})
list.wxml:
<!-- list.wxml -->
<view class="container data-list">
<block wx:for="{{logs}}" wx:for-item="log" wx:key="index">
<i-card full title="{{index + 1}}.卡片标题" extra="额外内容" thumb="https://i.loli.net/2017/08/21/599a521472424.jpg">
<view slot="content">{{index + 1}}.内容不错</view>
<view slot="footer">{{log}}</view>
</i-card>
</block>
</view>
下拉刷新、上拉加载更多
实现原理:
1、下拉刷新:由于小程序数据是实时渲染的。我们把data{}内的数据清空重新加载即可实现下拉刷新。
2、上拉加载更多(页面上拉触底事件):新获取的数据追加到data{}内的原数据即可。由于小程序数据是实时渲染,小程序在保持原数据显示不变的基础上,自动追加渲染显示新数据。注意(小程序官方有说明):
1、上拉加载更多 不要用scroll-view,用普通的view即可。
2、下拉刷新需要在 当前页面.json 里配置{ "enablePullDownRefresh": true }
page()属性里有两个属性是关于页面下拉刷新 和 上拉加载更多的:
onPullDownRefresh Function 页面相关事件处理函数–监听用户下拉动作 onReachBottom Function 页面上拉触底事件的处理函数
主要参考了以上思路。
实现代码:
在list.wxml里view
的视图容器内的底部增加:
<i-spin size="large" fix wx:if="{{ spinShow }}"></i-spin>
<i-load-more tip="{{loadMoreTip}}" loading="{{ loadMore }}" />
list.js修改为如下:
//list.js
const util = require('../../utils/util.js')
var page = 0; //当前页
var totalPages = 3; //总页数
Page({
data: {
logs: [],
//加载样式是否显示
spinShow: true,
loadMore: true,
loadMoreTip: '加载中',
allLoaded: false
},
onLoad: function() {
this.clearCache(); //清本页缓存
this.getArticles(0); //第一次加载数据
},
getArticles: function(pageno) {
let vm = this
setTimeout(function() {
//要延时执行的代码
vm.setData({
spinShow: false
})
var res = (wx.getStorageSync('logs') || []).map(log => {
return util.formatTime(new Date(log))
});
var tmpArr = vm.data.logs;
tmpArr.push.apply(tmpArr, res);
vm.setData({
logs: tmpArr
})
vm.loadMore = true
}, 3000) //延迟时间 这里是3秒
},
// 下拉刷新
onPullDownRefresh: function() {
this.setData({
spinShow: true
})
this.clearCache();
this.getArticles(0); //第一次加载数据
},
// 页面上拉触底事件(上拉加载更多)
onReachBottom: function() {
page++;
if (!this.allLoaded) {
if (page > totalPages - 1) {
this.setData({
loadMore: false,
loadMoreTip: '没有更多了',
allLoaded: true // 若数据已全部获取完毕
})
} else {
this.setData({
loadMore: true,
loadMoreTip: '加载中',
allLoaded: false // 若数据未获取完毕
})
this.getArticles(page); //后台获取新数据并追加渲染
}
} else {
this.setData({
loadMore: false,
loadMoreTip: '没有更多了',
allLoaded: false // 若数据未获取完毕
})
}
},
// 清缓存
clearCache: function() {
page = 0; //分页标识归零
this.setData({
logs: [] //文章列表数组清空
});
},
})
list.wxss:
.loading{
display: inline-block;
margin-right: 12px;
vertical-align: middle;
width: 20px;
height: 20px;
background: transparent;
border-radius: 50%;
border: 2px solid #2d8cf0;
border-color: #2d8cf0 #2d8cf0 #2d8cf0 transparent;
animation: loading-spin 0.6s linear;
animation-iteration-count: infinite;
}
这里下拉的效果没做处理,上拉加载效果也比较粗糙。可以根据项目要求再进行美观优化,例如你可以自己在下拉时增加下拉到底、松开刷新、刷新中....等动态效果。
如果,最开始,你在看本篇文章时,一步一步跟着做,那么你也将得到一个小程序,实现的最终效果,如下图:
参考资料
微信开放文档 你的第一个小程序
微信开放文档 小程序配置
微信开放文档 小程序目录结构
微信开放文档 组件
微信开放文档 swiper 滑块视图容器
安利向:用Visual Studio Code编写微信小程序
vscode 小程序开发插件
小程序入坑(一)list列表以及item详情页,json传送时间戳转换成年月日
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。