微信小程序官方DEMO解讀

    咱們在開始微信小程序開發的時候,對JS,HTML等前端知識一無所知,完徹底全就是門外漢在嘗試一個新的方向。javascript

    在下載好開發工具,微信就已經提供了一個DEMO例子:前端

    

    從程序開發的角度來看這個陌生的目錄結構,pages是存放頁面的,utils是存放工具類的,而app開頭的三個文件既然放在根目錄級別,那麼按理講,應該是和配置有關。java

    咱們看app.js文件的內容:json

//app.js
App({
  onLaunch: function () {
    //調用API從本地緩存中獲取數據
    var logs = wx.getStorageSync('logs') || []
    logs.unshift(Date.now())
    wx.setStorageSync('logs', logs)
  },
  getUserInfo:function(cb){
    var that = this
    if(this.globalData.userInfo){
      typeof cb == "function" && cb(this.globalData.userInfo)
    }else{
      //調用登陸接口
      wx.login({
        success: function () {
          wx.getUserInfo({
            success: function (res) {
              that.globalData.userInfo = res.userInfo
              typeof cb == "function" && cb(that.globalData.userInfo)
            }
          })
        }
      })
    }
  },
  globalData:{
    userInfo:null
  }
})

    根據官方文檔的說明,這個文件用於編寫微信小程序的頁面邏輯。小程序

    App函數用於註冊一個小程序,onLanuch用於處理小程序的初始化,當小程序初始化完成的時候會調用一次。微信小程序

    onLanuch這裏的處理是取出wx中的log,而後再把當前日期添加進去。數組

    wx是一個命名空間,至關於一個庫,它有不少公共方法。緩存

    咱們這裏的操做和Android中使用SP(SharePreferences)是差很少的,wx有個本地緩存,這個緩存能夠根據相關的key值取出對應的內容。這裏有個有趣的語法:|| [],在javascript中,表示若是這個變量若是是undefined,null,NAN,false,0中的任意一種,就設置爲一個空的數組,能夠理解爲?:的用法。而後調用javascript的unshift方法,把當前日期插入數組的第一個元素。微信

    getUserInfo是自定義的函數,傳入一個函數做爲參數,並且這裏還定義了全局對象globalData,它有一個字段userInfo,初始值爲null,經過判斷userInfo是否爲空,非空則在cb爲函數類型的狀況下調用cb,空的狀況下,則經過調用wx.login方法,在success的狀況下調用wx的getUserInfo獲取userInfo。網絡

    這個js文件已經大概的展現了javascript的不少基本語法,由於javascript是動態語言,它是面向函數語言,所以和java這種面嚮對象語言在語義實現上,差異至關大,咱們能夠簡單的理解爲java操做的是對象,而javascript操做的是函數,而wx.login中的參數就是一個對象,所以用{}包起來,函數其實也是一個對象,因此它後面一樣也有{},這個對象就是loginObject,在它success的時候調用wx.getUserInfo函數。

    不管是面向對象仍是面向函數,本質上都是體現開發人員理解問題的思路,只是語義實現上不一樣而已,畢竟javascript和java要解決的問題所在的領域有着至關大的差別。

    咱們再看看app.json這個文件:

{
  "pages":[
    "pages/index/index",
    "pages/logs/logs"
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "WeChat",
    "navigationBarTextStyle":"black"
  }
}

   根據文檔的解釋,這個文件是對微信小程序進行全局配置,決定頁面文件的路徑、窗口表現、設置網絡超時時間、設置多tab等。

   pages用於設置頁面的路徑,是一個數組,咱們這個DEMO的頁面只有兩個:index和logs,其中第一個元素,index,是小程序的第一個頁面,每次新增或者刪除某個頁面,都要在這裏進行修改。

   window用來設置默認的窗口的屬性,顯然app.json是設置整個小程序窗口的默認屬性,會被具體頁面的相關屬性覆蓋。

   最後是app.wxss:   

/**app.wxss**/
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 200rpx 0;
  box-sizing: border-box;
} 

   這個文件其實就是CSS文件,不過微信本身自己作了一些處理,這個文件的內容就是設置了container這個節點視圖的公共屬性。

   從這三個根目錄的文件,咱們也大概知道一個小程序的頁面的組成結構,可是還少了一個文件,那就是頁面視圖的文件。

   DEMO的logs頁面就包含了四個文件:.json,.js,.wxss和.wxml。

   咱們看一下logs.wxml這個文件:

<!--logs.wxml-->
<view class="container log-list">
  <block wx:for="{{logs}}" wx:for-item="log" wx:key="*this">
    <text class="log-item">{{index + 1}}. {{log}}</text>
  </block>
</view>

   <view/>表示一個視圖的節點,至關於Android中的ViewGroup,而後經過class賦予這個view一個或多個類名,wxss就是經過這個class來控制對應視圖的渲染效果,這裏是兩個類名:container和log-list,目的就是在一些屬性上覆蓋.container的設置。

   <block/>表示這是一個多節點的視圖,也就是列表組件,經過wx:for表示這個列表組件的數組來源,在微信的設計中,{{}}表示數據綁定,這裏綁定了logs這個數組做爲數據來源。

    wx:for-item指定了當前數組的元素名,咱們能夠理解爲java中的加強for的用法:for(item : array)。

    wx:key表示一個惟一標識,由於這個數組是動態數組,會不斷增長本身自己的長度,而咱們不但願已經建立好的元素在從新渲染的時候會被修改,所以經過wx:key指定*this,表示for循環中的item只是被從新排序,而不是被從新建立,這樣是爲了提升渲染的效率。

    最後咱們看一下<block/>裏面的子視圖,是一個text視圖,渲染的內容是數組中的元素,默認數組的下標變量名是index,元素名稱是item,所以{{index + 1}}表示取當前元素的下標,由於下標是從0開始,因此這裏加1來和人類世界中下標從1開始的共識達成一致,而log就是logs中的元素的內容,由於咱們已經經過wx:for-item指定了item的名稱爲log。

    logs目錄下的logs.js也是至關有意思的:

//logs.js
var util = require('../../utils/util.js')
Page({
  data: {
    logs: []
  },
  onLoad: function () {
    this.setData({
      logs: (wx.getStorageSync('logs') || []).map(function (log) {
        return util.formatTime(new Date(log))
      })
    })
  }
})

    util.js是咱們utils目錄的文件,這裏的"../../utils/util.js"是經過相對路徑來導入這個js文件,按照咱們的理解,至關於import一個庫。

    Page函數是用來註冊一個頁面,data聲明頁面的初始數據,這裏是一個logs數組,而data裏面的數據是經過json傳遞到頁面,所以這裏面的格式要確保徹底符合json格式。而後調用onLoad函數,在加載頁面的時候經過setData將邏輯層的數據傳遞到視圖層,也就是所謂的數據綁定,而且改變this.data的內容。

    setData中的函數經過調用數組的map函數,將數組的內容從新映射成新的內容,這裏至關於初始化數組,map就是用來對數組內容進行賦值的。

    咱們看一下util.js的內容:

function formatTime(date) {
  var year = date.getFullYear()
  var month = date.getMonth() + 1
  var day = date.getDate()

  var hour = date.getHours()
  var minute = date.getMinutes()
  var second = date.getSeconds()


  return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}

function formatNumber(n) {
  n = n.toString()
  return n[1] ? n : '0' + n
}

module.exports = {
  formatTime: formatTime
}

     這裏的內容很簡單,就是對log的日期進行格式化,不過咱們注意到最後的內容,module.exports執行了賦值操做。

     這個實際上是和require搭配的,require返回的就是這個module.exports,而後定義了一個formatTime對象,也就是能夠調用的對象,而這個對象就是formatTime函數。

    經過require和module.exports來肯定了這個js文件暴露出來的API。

    咱們如今來關注一個很重要的語法:=和:這兩個操做符究竟是怎麼用的。

    =就是賦值操做符,這個毋庸置疑,而:其實也是賦值操做,對於a:function,其實表示key值爲a的value的內容爲function,因此formatTime:formatTime就是表示util.formatTime這個屬性對應的是formatTime函數。

    咱們再來看一下index目錄下的文件。

    先看一下index.js:

//index.js
//獲取應用實例
var app = getApp()
Page({
  data: {
    motto: 'Hell World',
    userInfo: {}
  },
  //事件處理函數
  bindViewTap: function() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },

  onLoad: function () {
    console.log('onLoad')
    var that = this
    //調用應用實例的方法獲取全局數據
    app.getUserInfo(function(userInfo){
      //更新數據
      that.setData({
        userInfo:userInfo
      })
    })
  }
})

    咱們經過getApp函數來獲取小程序實例,由於咱們須要調用app.js中的函數,這裏調用的是getUserInfo,能夠理解爲app.js中定義的方法都是公共方法,由於這裏並無require和module.exports的調用。

    這裏有一個新的知識點:bindViewTap。

    這個是一個事件處理函數,事件是邏輯層到視圖層的通信方式,將用戶的行爲反饋到邏輯層進行處理,bindViewTap這個事件函數是用戶在點擊時候觸發的,至關於onClick,wx.navigateTo表示跳轉到url指定的頁面。

     咱們看一下inde.wxml文件就知道了:     

<!--index.wxml-->
<view class="container">
  <view  bindtap="bindViewTap" class="userinfo">
    <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>
    <text class="userinfo-nickname">{{userInfo.nickName}}</text>
  </view>
  <view class="usermotto">
    <text class="user-motto">{{motto}}</text>
  </view>
 </view>

    要經過bindtap指定點擊事件函數。

    事件分爲兩種:冒泡事件和非冒泡事件,冒泡事件會把事件往上傳遞,而非冒泡則反之。冒泡事件前綴是bind,而非冒泡事件是catch。

    經過對這個DEMO,咱們大概瞭解到小程序的目錄結構,和一些相關的基礎知識,後面會在具體的開發工做中繼續補充相關的知識。

相關文章
相關標籤/搜索