4.1,項(xiàng)目代碼結(jié)構(gòu)
點(diǎn)擊開發(fā)者工具上側(cè)導(dǎo)航的“編輯器”,我們可以看到這個(gè)項(xiàng)目,已經(jīng)初始化并包含了一些簡(jiǎn)單的代碼文件。最關(guān)鍵也是必不可少的,是 app.js、app.json、app.wxss 這三個(gè)。其中,.js
后綴的是腳本文件,.json
后綴的文件是配置文件,.wxss
后綴的是樣式表文件。微信小程序會(huì)讀取這些文件,并生成小程序?qū)嵗?/p>
下面我們簡(jiǎn)單了解這三個(gè)文件的功能,方便修改以及從頭開發(fā)自己的微信小程序。
? 1、app.js是小程序的腳本代碼。我們可以在這個(gè)文件中監(jiān)聽并處理小程序的生命周期函數(shù)、聲明全局變量。調(diào)用框架提供的豐富的 API,如本例的同步存儲(chǔ)及同步讀取本地?cái)?shù)據(jù)。
2、? app.json 是對(duì)整個(gè)小程序的全局配置。我們可以在這個(gè)文件中配置小程序是由哪些頁(yè)面組成,配置小程序的窗口背景色,配置導(dǎo)航條樣式,配置默認(rèn)標(biāo)題。注意該文件不可添加任何注釋。
3、app.wxss 是整個(gè)小程序的公共樣式表。我們可以在頁(yè)面組件的 class 屬性上直接使用 app.wxss 中聲明的樣式規(guī)則。
我們注意到,在實(shí)例程序的代碼中還有2個(gè)文件夾,一個(gè)是pages,一個(gè)是style,其中style是放通用樣式的一個(gè)文件夾,pages是存放所有頁(yè)面的文件夾。我們著重講一下這個(gè)pages.
4.2,小程序頁(yè)面文件構(gòu)成
在這個(gè)示例中,我們有七個(gè)頁(yè)面,index 頁(yè)面,即歡迎頁(yè),他們都在 pages 目錄下。微信小程序中的每一個(gè)頁(yè)面的【路徑+頁(yè)面名】都需要寫在 app.json 的 pages 中,且 pages 中的第一個(gè)頁(yè)面是小程序的首頁(yè)。
每一個(gè)小程序頁(yè)面是由同路徑下同名的四個(gè)不同后綴文件的組成,如:index.js、index.wxml、index.wxss、index.json。.js
后綴的文件是腳本文件,.json
后綴的文件是配置文件,.wxss
后綴的是樣式表文件,.wxml
后綴的文件是頁(yè)面結(jié)構(gòu)文件。
? index.wxml 是頁(yè)面的結(jié)構(gòu)文件:
1 <!--index.wxml-->
2 <view class="container">
3
4 <!-- 用戶 openid -->
5 <view class="userinfo">
6 <button
7 open-type="getUserInfo"
8 bindgetuserinfo="onGetUserInfo"
9 class="userinfo-avatar"
10 style="background-image: url({{avatarUrl}})"
11 ></button>
12 <view>
13 <text>jackson影琪</text>
14 </view>
15 </view>
16
17 <view class="text-title">
18 <text>Hello world</text>
19 </view>
20 </view>
? 本例中使用了<view/>
、<button/>
、<text/>
來搭建頁(yè)面結(jié)構(gòu),綁定數(shù)據(jù)和交互處理函數(shù)。
? index.js 是頁(yè)面的腳本文件,在這個(gè)文件中我們可以監(jiān)聽并處理頁(yè)面的生命周期函數(shù)、獲取小程序?qū)嵗暶鞑⑻幚頂?shù)據(jù),響應(yīng)頁(yè)面交互事件等。
1 //index.js
2 const app = getApp()
3
4 Page({
5 data: {
6 avatarUrl: './user-unlogin.png',
7 userInfo: {},
8 logged: false,
9 takeSession: false,
10 requestResult: ''
11 },
12
13 onLoad: function() {
14 if (!wx.cloud) {
15 wx.redirectTo({
16 url: '../chooseLib/chooseLib',
17 })
18 return
19 }
20
21 // 獲取用戶信息
22 wx.getSetting({
23 success: res => {
24 if (res.authSetting['scope.userInfo']) {
25 // 已經(jīng)授權(quán),可以直接調(diào)用 getUserInfo 獲取頭像昵稱,不會(huì)彈框
26 wx.getUserInfo({
27 success: res => {
28 this.setData({
29 avatarUrl: res.userInfo.avatarUrl,
30 userInfo: res.userInfo
31 })
32 }
33 })
34 }
35 }
36 })
37 },
38
39 onGetUserInfo: function(e) {
40 if (!this.logged && e.detail.userInfo) {
41 this.setData({
42 logged: true,
43 avatarUrl: e.detail.userInfo.avatarUrl,
44 userInfo: e.detail.userInfo
45 })
46 }
47 },
48
49 onGetOpenid: function() {
50 // 調(diào)用云函數(shù)
51 wx.cloud.callFunction({
52 name: 'login',
53 data: {},
54 success: res => {
55 console.log('[云函數(shù)] [login] user openid: ', res.result.openid)
56 app.globalData.openid = res.result.openid
57 wx.navigateTo({
58 url: '../userConsole/userConsole',
59 })
60 },
61 fail: err => {
62 console.error('[云函數(shù)] [login] 調(diào)用失敗', err)
63 wx.navigateTo({
64 url: '../deployFunctions/deployFunctions',
65 })
66 }
67 })
68 },
69
70 // 上傳圖片
71 doUpload: function () {
72 // 選擇圖片
73 wx.chooseImage({
74 count: 1,
75 sizeType: ['compressed'],
76 sourceType: ['album', 'camera'],
77 success: function (res) {
78
79 wx.showLoading({
80 title: '上傳中',
81 })
82
83 const filePath = res.tempFilePaths[0]
84
85 // 上傳圖片
86 const cloudPath = 'my-image' + filePath.match(/\.[^.]+?$/)[0]
87 wx.cloud.uploadFile({
88 cloudPath,
89 filePath,
90 success: res => {
91 console.log('[上傳文件] 成功:', res)
92
93 app.globalData.fileID = res.fileID
94 app.globalData.cloudPath = cloudPath
95 app.globalData.imagePath = filePath
96
97 wx.navigateTo({
98 url: '../storageConsole/storageConsole'
99 })
100 },
101 fail: e => {
102 console.error('[上傳文件] 失?。?#39;, e)
103 wx.showToast({
104 icon: 'none',
105 title: '上傳失敗',
106 })
107 },
108 complete: () => {
109 wx.hideLoading()
110 }
111 })
112
113 },
114 fail: e => {
115 console.error(e)
116 }
117 })
118 },
119
120 })
index.wxss 是頁(yè)面的樣式表:
1 /**index.wxss**/
2
3 page {
4 background: #f6f6f6;
5 display: flex;
6 flex-direction: column;
7 justify-content: center;
8 }
9 .userinfo, .uploader, .tunnel {
10 margin-top: 40rpx;
11 height: 140rpx;
12 width: 100%;
13 background: #fff;
14 border: 1px solid rgba(0, 0, 0, 0.1);
15 border-left: none;
16 border-right: none;
17 display: flex;
18 flex-direction: row;
19 align-items: center;
20 transition: all 300ms ease;
21 }
22
23 .userinfo-avatar {
24 width: 100rpx;
25 height: 100rpx;
26 margin: 20rpx;
27 border-radius: 50%;
28 background-size: cover;
29 background-color: white;
30 }
31
32 .userinfo-avatar:after {
33 border: none;
34 }
35
36 .userinfo-nickname {
37 font-size: 32rpx;
38 color: #007aff;
39 background-color: white;
40 background-size: cover;
41 }
42
43 .userinfo-nickname::after {
44 border: none;
45 }
46
47 .uploader, .tunnel {
48 height: auto;
49 padding: 0 0 0 40rpx;
50 flex-direction: column;
51 align-items: flex-start;
52 box-sizing: border-box;
53 }
54
55 .uploader-text, .tunnel-text {
56 width: 100%;
57 line-height: 52px;
58 font-size: 34rpx;
59 color: #007aff;
60 }
61
62 .uploader-container {
63 width: 100%;
64 height: 400rpx;
65 padding: 20rpx 20rpx 20rpx 0;
66 display: flex;
67 align-content: center;
68 justify-content: center;
69 box-sizing: border-box;
70 border-top: 1px solid rgba(0, 0, 0, 0.1);
71 }
72
73 .uploader-image {
74 width: 100%;
75 height: 360rpx;
76 }
77
78 .tunnel {
79 padding: 0 0 0 40rpx;
80 }
81
82 .tunnel-text {
83 position: relative;
84 color: #222;
85 display: flex;
86 flex-direction: row;
87 align-content: center;
88 justify-content: space-between;
89 box-sizing: border-box;
90 border-top: 1px solid rgba(0, 0, 0, 0.1);
91 }
92
93 .tunnel-text:first-child {
94 border-top: none;
95 }
96
97 .tunnel-switch {
98 position: absolute;
99 right: 20rpx;
100 top: -2rpx;
101 }
102
103 .disable {
104 color: #888;
105 }
106
107 .service {
108 position: fixed;
109 right: 40rpx;
110 bottom: 40rpx;
111 width: 140rpx;
112 height: 140rpx;
113 border-radius: 50%;
114 background: linear-gradient(#007aff, #0063ce);
115 box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3);
116 display: flex;
117 align-content: center;
118 justify-content: center;
119 transition: all 300ms ease;
120 }
121
122 .service-button {
123 position: absolute;
124 top: 40rpx;
125 }
126
127 .service:active {
128 box-shadow: none;
129 }
130
131 .request-text {
132 padding: 20rpx 0;
133 font-size: 24rpx;
134 line-height: 36rpx;
135 word-break: break-all;
136 }
137 .text-title{
138 margin-top: 50%;
139 }
140 .text-title text{
141 font-size: 96rpx;
142 font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
143 }
頁(yè)面的樣式表是非必要的。當(dāng)有頁(yè)面樣式表時(shí),頁(yè)面的樣式表中的樣式規(guī)則會(huì)層疊覆蓋 app.wxss 中的樣式規(guī)則。如果不指定頁(yè)面的樣式表,也可以在頁(yè)面的結(jié)構(gòu)文件中直接使用 app.wxss 中指定的樣式規(guī)則。
? index.json 是頁(yè)面的配置文件:
? 頁(yè)面的配置文件是非必要的。當(dāng)有頁(yè)面的配置文件時(shí),配置項(xiàng)在該頁(yè)面會(huì)覆蓋 app.json 的 window 中相同的配置項(xiàng)。如果沒有指定的頁(yè)面配置文件,則在該頁(yè)面直接使用 app.json 中的默認(rèn)配置。
1 {
2 "pages": [
3 "pages/index/index",
4 "pages/userConsole/userConsole",
5 "pages/storageConsole/storageConsole",
6 "pages/databaseGuide/databaseGuide",
7 "pages/addFunction/addFunction",
8 "pages/deployFunctions/deployFunctions",
9 "pages/chooseLib/chooseLib"
10 ],
11 "window": {
12 "backgroundColor": "#F6F6F6",
13 "backgroundTextStyle": "light",
14 "navigationBarBackgroundColor": "#F6F6F6",
15 "navigationBarTitleText": "jackson影琪",
16 "navigationBarTextStyle": "black"
17 }
18 }
運(yùn)行結(jié)果如下:
手機(jī)預(yù)覽
? 開發(fā)者工具上側(cè)菜單欄,點(diǎn)擊"預(yù)覽",掃碼后即可在微信客戶端中體驗(yàn)。