1. 程式人生 > >微信小程式開發初級實踐篇

微信小程式開發初級實踐篇

  微信小程式開發,快捷方便,容易上手,學習成本不高,但是好的程式設計師必須要經常開發來積攢經驗才為上策。在我的微信小程式上手篇中,筆者把微信小程式的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還是個雛~