開發微信小程式-目錄解析(二)
文件:https://developers.weixin.qq.com/miniprogram/dev/quickstart/basic/file.html#js-互動邏輯
普通快速模板
開發目錄
├── app.js
├── app.json
├── app.wxss
├── pages
│ │── index
│ │ ├── index.wxml
│ │ ├── index.js
│ │ ├── index.json
│ │ └── index.wxss
│ └── logs
│ ├── logs.wxml
│ └── logs.js
└── utils
.json 字尾的 JSON 配置檔案
.wxml 字尾的 WXML 模板檔案
.wxss 字尾的 WXSS 樣式檔案
.js 字尾的 JS 指令碼邏輯檔案
分析圖片 從下往上 =>
project.config.json:整個專案的配置檔案。
app.js:整個應用程式入口檔案。
app.json:入口檔案配置資訊。
app.wxss:應用程式全域性樣式檔案。
wxss = WeiXin Style Sheet微信樣式表,類似於css檔案。
utils資料夾:工具包檔案所在目錄。自行封裝的模組。供其他小程式頁面使用。類似於vue中的過濾器概念,工具包中可以定義一些格式化的函式等。
pages資料夾:小程式各個頁面的檢視,業務邏輯,樣式,配置檔案所在目錄。特別注意:在小程式中每一個頁面都擁有獨立的檢視,業務邏輯,樣式,配置檔案。和vue的類比如下:
index/index.js相當於vue中的
wxml = WeiXian Markup Language微信標記語言,類似於html或xml。
各檔案之間的關聯關係:
pages資料夾下的每一個資料夾,如index,logs等,內部包含四個檔案,但四個檔案並不是必須的,如.json檔案就可以沒有。並且每個檔案的檔名稱(不包含字尾名稱)一般約定對應資料夾的名稱,如:index資料夾中四個檔案命名分別為:index.json,
index.js, index.wxss,
index.wxml。這是一種約定好的風格。每個資料夾相當於vue中定義的一個頁面級元件。和當前小程式的入口配置檔案app.json有對應(很重要的關聯),如:
“pages”: [ “pages/index/index”, “pages/logs/logs” ]
每個資料夾中的四個檔案之間的關聯關係,微信已幫我們做過封裝,不用開發者再引入。如index.json,index.js,index.wxml,index.wxss自去產生關係。在渲染檢視index.wxml時會自動使用index.wxss樣式檔案,自動使用index.js業務邏輯檔案及配置檔案index.json。工具包檔案是自行封裝的模組包,要想在其他頁面中使用,必須引入。 引入方法如:const util =
require(’…/…/utils/util.js’) 類似於node.js中的引入模組包。
project.config.json - 專案配置檔案
應用程式啟動時候,會自動讀取配置檔案,約定一些規則
()裡面是解釋
{
"description": "專案配置檔案(什麼專案,包含哪些功能)",
"packOptions(包選項)": {
"ignore": []
},
"setting": {
"urlCheck(是否校驗url地址)": true,
"es6": true,
"postcss(css格式化)": true,
"minified(壓縮)": true,
"newFeature(版本迭代新特性)": true
},
"compileType(編譯型別-定義的專案名稱)": "miniprogram",
"libVersion": "2.0.4",
"appid(開發和上線的AppID有可能不一樣)": "wx7acb670e00b40e5b",
"projectname": "demo-%E6%99%AE%E9%80%9A%E6%A8%A1%E6%9D%BF",
"debugOptions": {
"hidedInDevtools(本地)": []
},
"isGameTourist(遊戲是true)": false,
"condition": {
"search": {
"current": -1,
"list": []
},
"conversation": {
"current": -1,
"list": []
},
"game": {
"currentL": -1,
"list": []
},
"miniprogram": {
"current": -1,
"list": []
}
}
}
執行時候最先執行的是
app.js(唯一的入口地址)
小程式裡面三大物件:1,應用程式App({ }) 2,頁面page({}) 3,元件component({})
元件開發
就一個App({ })
在其他頁面呼叫可以:
const app = getApp() 獲取
//app.js整個應用程式的入口檔案
//App()物件,是應用程式物件,在其他頁面可以通過getApp()方法獲取當前應用程式物件例項。
//如:index/index.js中const app = getApp()
App({
// 應用程式啟動時執行的鉤子事件。只執行一次。
onLaunch: function () {
// 展示本地儲存能力getStorageSync()是微信提供的兩步獲取快取的api,以後看到wx.開頭的都是微信的api,具體有檔案可參考。setStorageSync()用來設定快取。
var logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
// 登入
wx.login({
success: res => {
// 傳送 res.code 到後臺換取 openId, sessionKey, unionId
console.log(res)
}
})
// 獲取使用者資訊
wx.getSetting({
success: res => {
console.log(res)
if (res.authSetting['scope.userInfo']) {
// 已經授權,可以直接呼叫 getUserInfo 獲取頭像暱稱,不會彈框
wx.getUserInfo({
success: res => {
// 可以將 res 傳送給後臺解碼出 unionId
console.log(res)
this.globalData.userInfo = res.userInfo
// 由於 getUserInfo 是網路請求,可能會在 Page.onLoad 之後才返回
// 所以此處加入 callback 以防止這種情況
if (this.userInfoReadyCallback) {
console.log('1234567890-')
this.userInfoReadyCallback(res)
}
}
})
}
}
})
},
// 全域性資料,在app.js的配置項中定義的資料可以供所有的頁面使用,在其他頁面中通過const app = getApp()獲取當前應用程式例項後,就可以通過app.globalData.userInfo訪問此處定義的資料。
globalData: {
userInfo: null,
person: {
name: 'dsh2',
age: 20
}
},
//自定義的屬性也可以在其它頁面中訪問。一般不建議這樣使用,建議把資料放到globalData中。
person: {
name: 'dsh1',
age: 19
}
})
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;
}
rpx 是微信小程式解決自適應螢幕尺寸的尺寸單位。微信小程式規定螢幕的寬度為750rpx。
app.json-當前應用程式的配置檔案
{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle":"black"
}
}
配置各個項的含義:
pages欄位 —— 用於描述當前小程式所有頁面路徑,這是為了讓微信客戶端知道當前你的小程式頁面定義在哪個目錄。
window欄位 —— 定義小程式所有頁面的頂部背景顏色,文字顏色定義等。
project.config.json
{
"description": "專案配置檔案",
"packOptions": {
"ignore": []
},
"setting": {
"urlCheck": true,
"es6": true,
"postcss": true,
"minified": true,
"newFeature": true
},
"compileType": "miniprogram",
"libVersion": "2.3.0",
"appid": "wx671ce38d22d3c5ae",
"projectname": "demo",
"debugOptions": {
"hidedInDevtools": []
},
"isGameTourist": false,
"condition": {
"search": {
"current": -1,
"list": []
},
"conversation": {
"current": -1,
"list": []
},
"game": {
"currentL": -1,
"list": []
},
"miniprogram": {
"current": -1,
"list": []
}
}
}
- 開發文件
wxml 模板
在網頁的一般開發流程中,我們通常會通過 JS 操作 DOM (對應 HTML 的描述產生的樹),以引起介面的一些變化響應使用者的行為。
例如,使用者點選某個按鈕的時候,JS 會記錄一些狀態到 JS 變數裡邊,同時通過 DOM API 操控 DOM 的屬性或者行為,進而引起介面一些變化。當專案越來越大的時候,你的程式碼會充斥著非常多的介面互動邏輯和程式的各種狀態變數,顯然這不是一個很好的開發模式,
因此就有了 MVVM 的開發模式(例如 React, Vue),提倡把渲染和邏輯分離。簡單來說就是不要再讓 JS 直接操控 DOM,JS 只需要管理狀態即可,然後再通過一種模板語法來描述狀態和介面結構的關係即可。
需要把一個 Hello World 的字串顯示在介面上。
WXML 是這麼寫 :
<text>{{msg}}</text>
JS 只需要管理狀態即可:
this.setData({ msg: "Hello World" })
通過 {{ }} 的語法把一個變數繫結到介面上,我們稱為資料繫結。
完整的描述狀態和介面的關係,還需要 if/else, for等控制能力
,在小程式裡邊,這些控制能力都用 wx: 開頭的屬性來表達。
js互動
在前邊的 QuickStart 例子中,在 pages/index/index.js 就呼叫了 wx.getUserInfo 獲取微信使用者的頭像和暱稱,最後通過 setData 把獲取到的資訊顯示到介面上
<view>{{ msg }}</view>
<button bindtap="clickMe">點選我</button>
點選 button 按鈕的時候,我們希望把介面上 msg 顯示成 "Hello World"
,於是
我們在 button 上宣告一個屬性: bindtap ,
在 JS 檔案裡邊聲明瞭 clickMe 方法來響應這次點選操作:
Page({
clickMe: function() {
this.setData({ msg: "Hello World" })
}
})
小程式啟動
首先 把整個小程式的程式碼包下載到本地
緊接著通過 app.json 的 pages獲得所有頁面路徑
寫在 pages 欄位的第一個頁面就是這個小程式的首頁
微信客戶端就把首頁的程式碼裝載進來,通過小程式底層的一些機制,就可以渲染出這個首頁。
小程式啟動之後,在 app.js 定義的 App 例項的 onLaunch 回撥會被執行:
App({
onLaunch: function () {
// 小程式啟動之後 觸發
}
})
舉個例子
<!-- This is our View -->
<view> Hello {{name}}! </view>
<button bindtap="changeName"> Click me! </button>
// This is our App Service.
// This is our data.
var helloData = {
name: 'WeChat'
}
// Register a Page.
Page({
data: helloData,
changeName: function(e) {
// sent data change to view
this.setData({
name: 'MINA'
})
}
})
開發者通過框架將邏輯層資料中的 name 與檢視層的 name 進行了繫結
,所以在頁面一開啟的時候會顯示 Hello WeChat!;
當點選
按鈕的時候,檢視層會傳送 changeName 的事件給邏輯層
,邏輯層找到並執行對應的事件處理函式
;
回撥函式觸發後,邏輯層執行 setData
的操作,將 data 中的 name 從 WeChat 變為 MINA,因為該資料和檢視層已經綁定了,從而檢視層會自動改變為 Hello MINA!。