微信小程序开发,快捷方便,容易上手,学习成本不高,但是好的程序员必须要经常开发来积攒经验才为上策。在我的微信小程序上手篇中,笔者把微信小程序的demo通读了一遍,可以说收获良多,很多东西只有在自己理解的情况下才能牢牢记住,在文章的最后一篇中笔者也说了,学会了就得举一反三,通过现有的知识做出能力范围内可以实现的东西,这对于开发者来说是最好的实践。因此笔者在这里特别推出一个初级教程,而其中的知识基本上都是在demo中就可以获得的,只要你通读了我之前的文章,我相信你也能开发出一个简单的小程序。
好了,废话不多说,先上小程序示例的效果图:
由于demo能学到的有限,笔者暂时能想出来的实例就是类似这样的应用,不过技术都是一步一步增长的,从小做起,然后才能强大。
前期准备:
1.准备好图片,百度搜索多的是。
2.准备好json格式内容,我们的内容是以json形式存储的。
笔者是一名app开发,本想以json格式文件存储模型,但是一直找不到好的读取项目中本地json的方法,如有所知,能够评论告诉笔者,笔者先在此谢过。
这里笔者给大家一份自己写的json,仅供参考:
[
{"url":"http://www.huizhou.cn/food/rdtj/201211/W020121126369710784664.jpg",
"name":"猪肉",
"price":"32.4"},
{"url":"http://www.sc115.com/wenku/uploads/allimg/131201/214G63238-0.jpg",
"name":"水果",
"price":"17.5"},
{"url":"http://img1.gtimg.com/jiangsu/pics/hv1/78/113/1901/123641418.jpg",
"name":"蔬菜",
"price":"10.2"},
{"url":"http://image.enmuo.com/CMS/2011/12/12/1/CMS_111212141009773_0E_400x267.jpg",
"name":"玩具",
"price":"50.1"},
{"url":"http://pic.58pic.com/58pic/15/68/58/80Q58PIC2Yz_1024.jpg",
"name":"电脑",
"price":"4500.2"}
]
大家以这样的格式写就好,内容自定。
做好前期准备,就正式进入敲代码阶段。
首先创建项目,然后将项目中没有用的东西删除掉:
1.utils的文件夹删除,此项目用不到;
2.pages中的logs文件夹删除,此项目用不到;
3.app.js中删除无用代码,留下一个空白的onLaunch方法和空白的globalData对象,app.json中删除"pages/logs/logs","navigationBarTitleText"改为我们的“小型超市购物”,app.wxss中我们将padding改为50rpx 0;
4.index的每一个文件都清空;
我们先从app.js文件着手,此时你的代码应该和我的一样:
App({
onLaunch: function () {
},
globalData:{
}
})
很空,且让我们慢慢添加。在这里,我希望复习一下之前demo中运用的传值方法,记得demo中有个方法是:
getUserInfo:function(cb)
很多读者应该都记得,而且对于新手来说这个方法不好用,很难理解,因此我们在这里再复习一遍,自己来使用它(cb这个参数笔者现在才知道全称应该是callback,回传值)。
我们现在也写一个方法,名为getItem,用来获取我们商品的列表数据:
getItem : function (callback) {
},
这个方法就是获取我们的商品数据的,在这里,我们仿照demo中的写法,在globalData中设置一个值(有一些读者可能会想的比较明白,可能事后会发现这个值根本用不到,只不过我们是为了模仿demo的写法才用的这个值):
globalData:{
items:null
}
在这里我们有个空的items,这个就是我们的商品数据,然后我们再模仿getUserInfo中的写法:
if (this.globalData.items) {
typeof callback == "function" && callback(this.globalData.items)
}
else {
this.globalData.items = [
{"url":"http://www.huizhou.cn/food/rdtj/201211/W020121126369710784664.jpg",
"name":"猪肉",
"price":"32.4"},
{"url":"http://www.sc115.com/wenku/uploads/allimg/131201/214G63238-0.jpg",
"name":"水果",
"price":"17.5"},
{"url":"http://img1.gtimg.com/jiangsu/pics/hv1/78/113/1901/123641418.jpg",
"name":"蔬菜",
"price":"10.2"},
{"url":"http://image.enmuo.com/CMS/2011/12/12/1/CMS_111212141009773_0E_400x267.jpg",
"name":"玩具",
"price":"50.1"},
{"url":"http://pic.58pic.com/58pic/15/68/58/80Q58PIC2Yz_1024.jpg",
"name":"电脑",
"price":"4500.2"}
]
typeof callback == "function" && callback(this.globalData.items)
}
因为我们的items此时为空的,所以第一个if我们是走不进去的,然后在else中我们直接设置了items,用我们前期准备的json赋值给它,它就成了一个数组,数组中包含对象。在这之后我们回传这个值给callback的参数,让其能够获取我们的商品数据。
到这里,我们的app的代码都码好了,很简单,这里的逻辑只是让app公开一个方法回调,拿到我们设置的json(这里又可以举一反三,用请求同理)。接下来我们就要开始处理index文件了。
在文件中我们输入page,系统自动会给我们拼接上Page({...})代码,回车即可:
Page({
data:{
String1
},
onLoad:function(options){
// 生命周期函数--监听页面加载
String2
},
onReady:function(){
// 生命周期函数--监听页面初次渲染完成
String3
},
onShow:function(){
// 生命周期函数--监听页面显示
String4
},
onHide:function(){
// 生命周期函数--监听页面隐藏
String5
},
onUnload:function(){
// 生命周期函数--监听页面卸载
String6
},
onPullDownRefresh: function() {
// 页面相关事件处理函数--监听用户下拉动作
String7
},
onReachBottom: function() {
// 页面上拉触底事件的处理函数
String8
},
onShareAppMessage: function() {
// 用户点击右上角分享
return {
title: 'title', // 分享标题
desc: 'desc', // 分享描述
path: 'path' // 分享路径
}
}
})
内容很多,我们将多余代码删除,只留下:
Page({
data:{
String1
},
onLoad:function(options){
// 生命周期函数--监听页面加载
String2
}
})
在这里我们不需要options这个参数(这个参数后面会用到),删除即可。
现在来说一下逻辑,我们需要在这个首页显示的是一个列表,因此我要拿到数据来展示,而数据在app的实例中我们写了一个方法叫做getItem来获取,为了保存这个数据,我们需要一个变量来存储它,既然如此,我们先在data中设定一个存储用的变量:
data: {
items:[]
},
为什么是数组?我们的json和getItem返回的本来就是一个数组,所以我们创建一个数组去存储它。
之后我们就要去获取它,很简单在onLoad方法中,我们去调用app的getItem方法,因此别忘了先获取app实例:
var app = getApp()
然后在onLoad中调用:
onLoad: function () {
var that = this
app.getItem(function(item){
that.setData({
items:item,
})
})
},
这个方法很眼熟,跟demo中几乎一样吧。记得getItem的参数我们已经定义为了function,所以在这里我们需要传入一个function,其次既然它符合了function,别忘了我们后面还有回调用的callback(this.globalData.items)方法,所以我们要用一个参数去接收它,我在这里用了item(在实际开发中使用items更好,这里是方便读者区分)。在我们的获取到商品数据的同时,我们使用setData将它传输给我们index中的items变量进行存储,这样我们就可以在wxml中获取我们的数据了。
来到wxml中,我们需要一个大容器来展示数据:
<view class="container">
</view>
这个容器是根据container的样式,而container是保存在app.wxss中,如果你不知道具体内容,可以回去看一下。既然有了容器,我们就需要展示。我们的目的是展示一个列表,我之前的文章说了,block是我们将来经常用到的东西,在这里我们正好使用它:
<block wx:for="{{items}}" wx:for-item ="item" wx:key ="*this">
</block>
因为我们的items是一个数组,所以我们得需要用for语句去显示它,我们这里的用法与demo中无二,这样我们就能获取到items中每一个数据。其次,我希望每一条数据为一大块,而且需要有一定的间隔如:
我们首先要用一个view来承载一行一行的格子:
<block wx:for="{{items}}" wx:for-item ="item" wx:key ="*this">
<view>
</view>
</block>
当然,这么简单是无法达成我们要的效果的,需要修改样式,在index.wxss中添加一个样式:
.item {
display: flex;
background-color: white;
flex-direction: row;
align-items: flex-start;
margin: 20rpx auto;
padding: 5rpx;
box-sizing: border-box;
border: 1px solid #d0d0d0;
border-radius: 2px;
width: 90%;
}
这个是我们整个一行的样式,如此一来我们就基本达到我们的效果,然后把样式表加入wxml中的view:
<block wx:for="{{items}}" wx:for-item ="item" wx:key ="*this">
<view class="item">
</view>
</block>
这步完成,大的框架已经搭好了,我们现在添加数据。首先添加商品名称,我希望序列号和商品名称显示在左上角:
<block wx:for="{{items}}" wx:for-item ="item" wx:key ="*this">
<view class="item">
<text>{{index + 1}}.{{item.name}}</text>
</view>
</block>
然后,我们需要添加我们的商品图片,没有图片顾客怎么浏览商品呢:
<block wx:for="{{items}}" wx:for-item ="item" wx:key ="*this">
<view class="item">
<text>{{index + 1}}.{{item.name}}</text>
<image src="{{item.url}}" mode="aspectFit"></image>
</view>
</block>
现在看起来整个显示不够美观,商品名和图片紧贴在一起,图片太大,没事,我们添加样式就行:
.p{
padding-right:10rpx;
}
.image{
box-sizing: border-box;
border: 1px solid #d0d0d0;
width: 100px;
height: 80px;
background-color: 'white';
}
然后将样式加入:
<block wx:for="{{items}}" wx:for-item ="item" wx:key ="*this">
<view class="item">
<text class='p'>{{index + 1}}.{{item.name}}</text>
<image class='image' src="{{item.url}}" mode="aspectFit"></image>
</view>
</block>
好了,看上去美观多了是不是?最后我们把价格添加:
<block wx:for="{{items}}" wx:for-item ="item" wx:key ="*this">
<view class="item">
<text class='p'>{{index + 1}}.{{item.name}}</text>
<image class='image' src="{{item.url}}" mode="aspectFit"></image>
<text>{{item.price}} 元</text>
</view>
</block>
这样子整体效果还不是特别好,我们继续添加样式:
.price{
line-height: 80px;
width: 50%;
text-align: center;
}
加入样式:
<block wx:for="{{items}}" wx:for-item ="item" wx:key ="*this">
<view class="item">
<text class='p'>{{index + 1}}.{{item.name}}</text>
<image class='image' src="{{item.url}}" mode="aspectFit"></image>
<text class='price'>{{item.price}} 元</text>
</view>
</block>
差不多了,我们的长相看的过去了,现在我的需求变成了点击每一行进去可以看详情,所以我们得新建一个页面来显示详情,添加item的文件,.js .wxss .wxml创建好。
记得需要在app.json中配置我们的新页面,不然无法显示和添加页面:
"pages":[
"pages/index/index",
"pages/item/item"
],
我们等等处理item文件,我们先来添加点击处理,来到index.js中,我们添加一个点击方法:
itemTap: function (event){
}
我现在的需求是点击哪一行,哪一行的内容就要传到第二个页面,这样该如何实现呢?这个方法在demo中并没有体现,但是官方文档中有说明,在这里你们可以直接看我代码,在index.wxml中添加itemTap:
<block wx:for="{{items}}" wx:for-item ="item" wx:key ="*this">
<view bindtap="itemTap" data-item="{{item}}" class="item">
<text class='p'>{{index + 1}}.{{item.name}}</text>
<image class='image' src="{{item.url}}" mode="aspectFit"></image>
<text class='price'>{{item.price}} 元</text>
</view>
</block>
为了获取我们点击到的数据,我们需要用到data-这个语句,这个语句data-之后是我们自定义的key,然后=之后是我们的value,这样我们就可以在js中以key-value的形式获取我们的数据,我们在这里传过去的是一个对象。
在index.js中我们修改点击事件的代码:
itemTap: function (event){
var item = event.currentTarget.dataset.item
wx.navigateTo({
url: '../item/item?name=' + item.name + '&url=' + item.url + '&price=' + item.price,
})
}
event这个参数有哪些变量,我怎么知道里面有currentTarget这个变量?这里有个小技巧,先console.log(event),运行一遍,然后在调试中看console信息,你就能知道event里面包含哪些变量。总之我们拿到了我们的数据,之后我们跳转到新的页面。在这里我们看到与demo中不同的代码?name='+之后的代码,在这里笔者走了很多弯路,本来想要正向传值,但是系统又拿不到item的实例,后来我通过搜索别人大神和官方文档,我才知道微信小程序传值是以类似get方法的url拼接传值,真是有点意想不到。
这里传值在哪里接收呢,哈哈,这就要用到我们之前删除的options参数(往上拉,你会看到我说的参数)。
来到item.js,创建Page({...})代码:
Page({
data:{
String1
},
onLoad:function(options){
// 生命周期函数--监听页面加载
String2
}
})
看到了么,options参数,这里就能接收之前页面传过来的内容,它本身就是一个对象,因此我们直接创建一个对象去接收它:
Page({
data: {
item:{}
},
onLoad: function (options) {
this.setData({
item:options,
})
}
})
这样我们就获取了商品数据,然后我希望标题也能够变成商品的名字,虽然demo中没有用到这个方法,不过很幸运,系统正好给了这样一个接口:
wx.setNavigationBarTitle({
title: options.name,
})
哈哈,简单,我们已经处理好所有的逻辑了,现在就来展示吧,item.wxml中:
<view class="container item">
<image class="image" src="{{item.url}}" mode="aspectFit"></image>
<text class="title">{{item.name}}</text>
<text class="price">{{item.price}} 元</text>
</view>
item.wxss中:
.item {
align-items: center;
box-sizing: border-box;
border: 1px solid lightgrey;
border-radius: 5px;
margin: 0rpx 10rpx;
padding: 100rpx 0rpx 10rpx 10rpx;
background-color: lightcyan;
}
.image {
width: 100%;
}
.title {
border-bottom: 1px solid lightgray;
width: 80%;
line-height: 100px;
text-align: center;
}
.price {
line-height: 80px;
text-align: right;
width: 80%;
font-family: "YouYuan";
font-size: 30px;
font-weight: bold;
font-style:oblique;
}
在这里关于wxml中的代码和wxss中的代码我就不多加阐述,因为我希望读者你自己去显示,用不同的方法来显示内容,在这里笔者感谢公司前端二胡同志友情帮助我编写部分css代码,毕竟笔者css还是个雏~