小程序的基本使用
小程序文件類型
小程序主要提供了 4 種文件類型:
類型名稱 | 作用 | 是否必須存在 |
---|---|---|
.wxml | 用于頁面的布局結(jié)構(gòu),相當(dāng)于網(wǎng)頁中 .html 文件 | 是 |
.wxss | 用于頁面的樣式,相當(dāng)于網(wǎng)頁中的 .css 文件 | 否 |
.js | 用于頁面的邏輯 | 是 |
.json | 用于頁面的配置 | 否 |
文件作用
文件名 | 作用 | 是否必須存在 |
---|---|---|
app.js | 小程序入口(首先執(zhí)行的文件) | 是 |
app.json | 小程序的全局配置 | 是 |
app.wxss | 小程序的全局樣式 | 否 |
project.config.json | 小程序開發(fā)者工具配置 | 是(會(huì)自動(dòng)創(chuàng)建) |
sitemap.json | 小程序搜索優(yōu)化 | 否 |
要點(diǎn)
-
data
初始化頁面中的數(shù)據(jù) -
setData
更新數(shù)據(jù) -
{{}}
插值語法可以實(shí)現(xiàn)數(shù)據(jù)的渲染 bind:事件類型=事件回調(diào)
Page({ //index.js
// 約定格式,使用data定義數(shù)據(jù)
data: {
message: 'nihao!'
},
changeMessage() {
// this.setData修改數(shù)據(jù)
this.setData({
message: 'new!'
})
}
})
index.wxml
<view>{{message}}</view>
<button bind:tap="changeMessage" type="primary" size="mini">點(diǎn)我試試</button>
如何注冊(cè)小程序事件監(jiān)聽?
Page({
處理函數(shù)() {}
})
<button bind:事件名=“處理函數(shù)”>
配置文件
分類:
全局 app.json
頁面 page.json
全局配置
app.json 是當(dāng)前小程序的全局配置,包括了:
- 小程序首頁
- 界面表現(xiàn)
- 網(wǎng)絡(luò)超時(shí)時(shí)間
- 底部 tab
- …等配置
全局配置pages
用于指定小程序由哪些頁面組成。
- 每一項(xiàng)都對(duì)應(yīng)一個(gè)頁面的 路徑(含文件名) 信息。
- 小程序中的每一個(gè)頁面都必須在pages下登記一下。
- 文件名不需要寫文件后綴,框架會(huì)自動(dòng)去尋找對(duì)應(yīng)位置的 .json, .js, .wxml, .wxss 四個(gè)文件進(jìn)行處理。
是一個(gè)數(shù)組,每一項(xiàng)表示一個(gè)頁面
{
pages:[
"pages/index/index",
"pages/logs/logs"
]
}
數(shù)組中的第一個(gè)元素表示小程序啟動(dòng)時(shí)默認(rèn)打開的頁面-主頁
頁面跳轉(zhuǎn)
<navigator url="/pages/logs/logs">跳轉(zhuǎn)到log頁面</navigator>
新建頁面(自動(dòng)優(yōu)先)
新建頁面-手動(dòng)
共三步:
- 新建空目錄
- 新建頁面(4個(gè)文件)
- 在pages下手動(dòng)補(bǔ)充頁面地址
要點(diǎn):
- 頁面都放在pages下,一個(gè)頁面一個(gè)文件夾。
- 新建page時(shí),不需要寫文件后綴名。
新建頁面-自動(dòng)
在pages下補(bǔ)充一項(xiàng) pages/page1/page1
,然后保存,則會(huì)自動(dòng)添加一個(gè)頁面。
app.json
{
pages:[
"pages/index/index",
"pages/logs/logs",
"pages/page1/page1"
]
}
小程序配置-全局配置—window
用于設(shè)置小程序的狀態(tài)欄、導(dǎo)航條、標(biāo)題、窗口背景色。
https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html#window
常見配置:
小程序配置-全局配置—tabBar
tabBar
tabBar 定義小程序 tab 欄的表現(xiàn),如下圖即所謂的 tab 欄:
常見配置屬性
屬性 | 類型 | 默認(rèn)值 | 是否必須 | 說明 |
---|---|---|---|---|
list | array | 無 | 是 | tab 的列表,詳見 list 屬性說明,最少 2 個(gè)、最多 5 個(gè) tab |
color | 16 進(jìn)制顏色 | 無 | 否 | tab 上的文字默認(rèn)顏色,僅支持十六進(jìn)制顏色 |
selectedColor | 16 進(jìn)制顏色 | 無 | 否 | tab 上的文字選中時(shí)的顏色,僅支持十六進(jìn)制顏色 |
backgroundColor | 16 進(jìn)制顏色 | 無 | 否 | tab 的背景色,僅只持 16 進(jìn)制顏色 |
borderStyle | string | black | 否 | tabbar 上邊框的顏色, 僅支持 black / white |
position | string | bottom | 否 | tabBar 的位置,僅支持 bottom / top |
上述配置中 list 具體又包含以下內(nèi)容:
屬性 | 類型 | 默認(rèn)值 | 是否必須 | 說明 |
---|---|---|---|---|
pagePath | string | 是 | 頁面路徑,必須在 pages 中先定義 | |
text | string | 是 | tab 上按鈕文字 | |
iconPath | string | 否 | 圖片路徑,icon 大小限制為 40kb,建議尺寸為 81px * 81px,不支持網(wǎng)絡(luò)圖片,當(dāng) position 為 top 時(shí),不顯示 icon | |
selectedIconPath | string | 否 | 選中時(shí)的圖片路徑,icon 大小限制為 40kb,建議尺寸為 81px * 81px,不支持網(wǎng)絡(luò)圖片,當(dāng) position 為 top 時(shí),不顯示 icon |
參考代碼(app.josn)
{
......
"tabBar": {
"color": "#999",
"selectedColor": "#e93b3d",
"backgroundColor": "#fff",
"list": [
{
"pagePath": "pages/index/index",
"text": "首頁",
"iconPath": "static/tabbar/home-default.png",
"selectedIconPath": "static/tabbar/home-active.png"
},
{
"pagePath": "pages/logs/logs",
"text": "日志",
"iconPath": "static/tabbar/video-default.png",
"selectedIconPath": "static/tabbar/video-active.png"
},
{
"pagePath": "pages/index/demo",
"text": "示例",
"iconPath": "static/tabbar/face-default.png",
"selectedIconPath": "static/tabbar/face-active.png"
}
]
}
}
小程序配置-頁面配置
- 頁面配置只針對(duì)某個(gè)頁面生效
-
- 如 index.json 是針對(duì) index 頁面生效,demo.json 只針對(duì)頁面 demo 生效
- 不用寫window字段
- 優(yōu)先級(jí)比全局配置高
常用配置:
屬性 | 類型 | 默認(rèn)值 | 是否必須 | 說明 |
---|---|---|---|---|
navigationBarTitleText | string | 空白 | 否 | 導(dǎo)航欄標(biāo)題文字內(nèi)容 |
navigationBarTextStyle | string | black | 否 | 導(dǎo)航欄標(biāo)題顏色,僅支持 black / white |
navigationBarBackgroundColor | 16 進(jìn)制顏色 | #00000 | 否 | 導(dǎo)航欄背景顏色,如 #000000 |
navigationStyle | string | default | 否 | 導(dǎo)航欄樣式,僅支持 default / custom |
enablePullDownRefresh | boolean | false | 否 | 是否開啟全局的下拉刷新 |
小程序適配-響應(yīng)式單位rpx
rpx ,responsive pixel:
在小程序中的單位rpx,它的特點(diǎn)是能夠自動(dòng)地適配置不同尺寸的手機(jī)屏幕。
原理:不管手機(jī)屏幕具體多寬,100%的屏幕寬度就是750rpx
100%屏幕的寬度 = 750rpx
- 所有的設(shè)備寬度都是750rpx
- 在實(shí)際使用中只需要將設(shè)計(jì)稿調(diào)整為 750px 寬,然后 1:1 的比例來寫長(zhǎng)度(單位使用 rpx),如:設(shè)計(jì)稿中某個(gè)區(qū)域(盒子)的大小為 18090px ,寫成小程序的尺寸為 18090rpx。
注:上述的規(guī)則僅適用于設(shè)計(jì)稿寬度為 750px
rpx (responsive pixel):規(guī)定不管屏幕為多少px,100%的屏幕寬度就是750rpx
100%屏幕的寬度 = 750rpx
內(nèi)置組件—navigator(跳轉(zhuǎn))
navigator 是小程序中的導(dǎo)航標(biāo)簽,類似以前web中的a標(biāo)簽。通過 url 來指定跳轉(zhuǎn)的頁面
- url: 頁面路徑
-
- 支持相對(duì)和絕對(duì)路徑
- 路徑為空會(huì)報(bào)錯(cuò)
- 還可以跳到其他小程序
- hover-class:點(diǎn)擊態(tài)的樣式
-
- none 禁用點(diǎn)擊效果
- open-type:跳轉(zhuǎn)方式
-
- navigate。默認(rèn)值
- switchTab。跳轉(zhuǎn)到tabbar頁
屬性名 | 類型 | 默認(rèn)值 | 說明 |
---|---|---|---|
url | string | 當(dāng)前小程序內(nèi)的跳轉(zhuǎn)鏈接 | |
open-type | string | navigate | 跳轉(zhuǎn)方式 |
target | String | self | 在哪個(gè)目標(biāo)上發(fā)生跳轉(zhuǎn),默認(rèn)當(dāng)前小程序 |
內(nèi)置組件-image(圖片)
格式
<image
src="圖片資源地址"
mode="圖片裁剪,縮放方式"></image>
image組件是一個(gè)有默認(rèn)大小(320*240)的盒子。
- src: 圖片資源地址。相對(duì)地址,絕對(duì)地址(外網(wǎng)地址)。
- mode: 默認(rèn)值為scaleToFill,用來設(shè)置圖片裁剪、縮放的模式。
-
- scaleToFill。不保證縮放比,圖片拉伸填滿容器
- aspectFit。保證縮放比,使圖片的長(zhǎng)邊顯示出來
- aspectFill。保證縮放比,使圖片的短邊顯示出啦
- lazy-load:默認(rèn)為false,是否開啟懶加載模式。(3屏)
內(nèi)置組件—swiper(輪播圖)
swiper可以理解為小程序內(nèi)置的輪播圖標(biāo)簽,可以讓方便快速地實(shí)現(xiàn)輪播功能。
<swiper>
<swiper-item> 第1屏的內(nèi)容 </swiper-item>
<swiper-item> 第2屏的內(nèi)容 </swiper-item>
<swiper-item> 第3屏的內(nèi)容 </swiper-item>
<swiper-item> 第4屏的內(nèi)容 </swiper-item>
</swiper>
- swiper:滑塊容器。內(nèi)只能寫swiper-item。它的默認(rèn)高度是150px;
- swiper-item:滑塊單元。它的大小是: 寬度 和 高度 為 100% * 100%;
表單相關(guān)
- 輸入框:input
-
- password密碼類型,placeholder占位文字
- 單選框:radio-group和radio
-
- value指定表單數(shù)據(jù),checked選中狀態(tài)
- 復(fù)選框:checked-group和checkbox
-
- value指定表單數(shù)據(jù),checked選中狀態(tài)
- 選擇框:picker
-
- mode:指定不同類型的選擇框
scroll-view(滾動(dòng))
``scroll-view 在頁面中指定一個(gè)**可以滾動(dòng)**的區(qū)域,并且這個(gè)可滾動(dòng)的區(qū)域能夠?qū)崿F(xiàn)一些高級(jí)的交互,比如:
下拉刷新`等。
scroll-view
中嵌套任意需要滾動(dòng)的內(nèi)容,要求內(nèi)容必須有溢出(scroll-view有固定的尺寸),垂直滾動(dòng)時(shí) scroll-view
必須要指定高度。
屬性
-
scroll-x
屬性是否允許水平方面滾動(dòng) -
scroll-y
屬性是否允許垂直方向滾動(dòng) -
refresher-enable
屬性是否開啟下拉刷新的交互
小程序樣式-全局樣式
app.wxss
定義全局樣式,該文件中的樣式會(huì)在所有的頁面生效。
注:page
在每個(gè)頁面中都有,它是由小程序自動(dòng)添加上的,相當(dāng)于網(wǎng)頁中的 body
標(biāo)簽。
小程序樣式-靜態(tài)資源
小程序中 .wxss
文件中不支持使用本地路徑的資源,比如背景圖片是不允許使用本地圖片路徑的,必須使用網(wǎng)絡(luò)路徑(https:// 或 http:// 開頭)或者轉(zhuǎn)換成 base64 編碼。
小程序樣式-字體圖標(biāo)(iconfont)
小程序中字體圖片的使用與網(wǎng)頁中基本上是一致的,唯一的區(qū)別是小程序的 .wxss
文件中不支持使用本地字體文件,我們使用 iconfont 平臺(tái)提供的服務(wù)生成字體文件后,直接使用其線上的字體文件地址。
資源參考:https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=4061819
小程序基本使用-請(qǐng)求數(shù)據(jù)并渲染
小程序模板語法-數(shù)據(jù)綁定
在js中定義數(shù)據(jù)
Page({
data: {
isOpen: true,
message: 'hello world!'
}
})
小程序的data是一個(gè)對(duì)象,不同于vue的data是一個(gè)函數(shù)
在模塊中獲取使用數(shù)據(jù)
小程序中使用 {{}}
實(shí)現(xiàn)數(shù)據(jù)與模板的綁定
- 內(nèi)容綁定:
<view>{{ 屬性名 }}</view>
- 屬性綁定:
<input value="{{屬性名}}" />
{{}} 內(nèi)寫的是表達(dá)式
簡(jiǎn)易雙向綁定
-
小程序中提供了
model:value="{{數(shù)據(jù)名}}"
語法來實(shí)現(xiàn)雙向的數(shù)據(jù)綁定 -
目前只能用在
input
和textarea
組件中。只能是一個(gè)單一字段的綁定,不能嵌套對(duì)象.否則出現(xiàn)以下報(bào)錯(cuò):
[pages/index/index] Two-way binding does not support complex data paths currently. This two-way binding is ignored.
雙向綁定目前不支持復(fù)雜的數(shù)據(jù)路徑。這種雙向綁定將被忽略。
小程序修改數(shù)據(jù)
格式:
<元素 bind:事件名="處理函數(shù)">
this.setData({
屬性名1: 新值1,
屬性名2: 新值2
})
this.setData({
"屬性1.屬性2": 值
})
模板語法—條件渲染
小程序中的條件渲染的方式有兩種
1.wx:if
-
- 在小程序中,使用wx:if="{{條件}}"來判斷是否需要渲染該代碼塊
- 也可以用wx:elif 和 wx:else來添加else判斷
2.hidden
-
- 在小程序中,使用hidden="{{條件}}"也能控制元素的顯示與隱藏
- 條件為true則隱藏,否則則顯示
wx:if 與 hidden區(qū)別
1.區(qū)別
-
- wx:if是通過動(dòng)態(tài)創(chuàng)建或移除元素來控制元素是否可見
- hidden 是通過樣式(none/block)來控制元素是否可見
2.要點(diǎn)
- 如果一個(gè)標(biāo)簽頻繁切換顯示,建議使用 hidden。例如:折疊面板,抽屜面板等等
- 如果不頻繁切換,建議使用wx:if,它有更好的初始化性能。
模板語法—列表渲染—基礎(chǔ)
格式
<元素 wx:for="{{列表數(shù)據(jù)}}" >
<!-- wx:for 結(jié)構(gòu)內(nèi)可以使用兩個(gè)變量(1)item:循環(huán)項(xiàng)(2)index:循環(huán)索引 -->
{{item}}, {{index}}
</元素>
手動(dòng)指定索引名和當(dāng)前項(xiàng)的變量名
<view wx:for="{{list}}" wx:for-item="value" wx:for-index="key">
{{key}}-{{value}}
</view>
模板語法-列表渲染-wx:key
wx:key 針對(duì)不同的數(shù)組類型有不同的寫法
- 普通數(shù)組 wx:key=“*this”
- 數(shù)組對(duì)象 wx:key=“具有唯一性的某個(gè)屬性名”
小程序內(nèi)置API-網(wǎng)絡(luò)請(qǐng)求
網(wǎng)絡(luò)請(qǐng)求
調(diào)用 wx.request
能夠在小程序中發(fā)起網(wǎng)絡(luò)請(qǐng)求與后端接口進(jìn)行數(shù)據(jù)的交互,其語法格式如下:
wx.request({
url: '這里是接口的地址',
method: '這里是請(qǐng)求的方法',
data: '請(qǐng)求時(shí)提交的數(shù)據(jù)',
header: {/* 請(qǐng)求頭信息 */},
success: () => {/* 成功的回調(diào) */},
fail: () => {/* 失敗的回調(diào) */},
complete: () => {/* 成功或失敗的回調(diào) */}
})
配置網(wǎng)絡(luò)請(qǐng)求合法域名
域名必須是https
小程序內(nèi)置api-界面交互
showLoading效果
配合網(wǎng)絡(luò)請(qǐng)求來使用
wx.showLoading
顯示 loading 提示框
-
title
文字提示內(nèi)容 -
mask
是否顯示透明蒙層,防止觸摸穿透
hideLoading
-
wx.hideLoading
隱藏 loading 提示框
showToast
wx.showToast
消息提示框(輕提示)
-
title
提示的標(biāo)題 -
mask
是否顯示透明蒙層,防止觸摸穿透 -
duration
延遲時(shí)間(提示框顯示多久,單位是毫秒) -
icon
指定圖標(biāo),none
不使用圖標(biāo)
操作注意:
- 發(fā)請(qǐng)求之前,showLoading
- 請(qǐng)求結(jié)束之后(無論成敗),hideLoading
- 數(shù)據(jù)渲染成功之后,showToast
微信小程序本地存儲(chǔ)
-
wx.setStorageSync(key, value)
存入一個(gè)數(shù)據(jù),復(fù)雜類型數(shù)據(jù)不需要JSON.stringify
處理 -
wx.getStorageSync(key)
讀取本地key數(shù)據(jù),復(fù)雜類型數(shù)據(jù)不需要JSON.parse
處理 -
wx.removeStorageSync(key)
刪除本地key數(shù)據(jù) -
wx.clearStorageSync()
清空本地全部數(shù)據(jù)
微信小程序API的特征
API的用法分類三類:
- 異步的api
- 同步的api
- 支持promise的api
異步 API
絕大部分的 API 都是異步方式,通過回調(diào)函數(shù)獲取 API 執(zhí)行的結(jié)果
-
success
API 調(diào)用成功時(shí)執(zhí)行的回調(diào) -
fail
API 調(diào)用失敗時(shí)執(zhí)行的回調(diào) -
complete
API 調(diào)用結(jié)束時(shí)執(zhí)行的回調(diào)(無論成功或失?。?/li>
基本格式:
wx.api名稱({success(res){ console.log(成功執(zhí)行api的結(jié)果) }})
支持promise的api
部分異步的 API 也支持以 Promise 方式返回結(jié)果,此時(shí)可以配合 asyc/await
來使用。
例如:支持Promise格式的異步api有:
- wx.getSystemInfoSync()
- wx.getStorage
支持Promise格式的異步api有:
- wx.request()
同步 API
部分 API 支持以同步方式獲取結(jié)果,這些 API 的名稱都以 **Sync**
結(jié)尾。如
-
wx.getStorageSync
: 獲取本地存儲(chǔ) - wx.getSystemInfoSync: 獲取系統(tǒng)信息
基本格式:
const result = wx.api名稱()
事件處理-事件對(duì)象&傳參
事件對(duì)象
bind:事件類型=事件回調(diào) //回調(diào)函數(shù)第1個(gè)參數(shù)即為事件對(duì)象
事件回調(diào)傳參
小程序的事件回調(diào)不支持傳參數(shù)
因此要將模板中的數(shù)據(jù)傳遞到事件回調(diào)中就必須要通過事件對(duì)象來實(shí)現(xiàn)。
方式1:
-
補(bǔ)充參數(shù):
<button bind:tap="eventHandler" **mark:屬性名="值"**>點(diǎn)擊我看看</button>
-
獲取值:
eventHandler(ev){ console.log(**ev.mark.屬性名**)
方式2:
-
補(bǔ)充參數(shù) :
<button bind:tap="eventHandler" **data-屬性名="值"** >點(diǎn)擊我看看</button>
-
獲取值:
eventHandler(ev){ console.log(**ev.target.dataset.屬性名**) }
事件處理-組件事件
事件類型只屬于某個(gè)組件,我們將其稱為組件事件
前面介紹的 tap
事件可以在絕大部分組件是監(jiān)聽,我們可以將其理解為通用事件類型,然而也有事件類型只屬于某個(gè)組件,我們將其稱為組件事件。
組件不同,支持的事件也不同
scroll-view組件中的事件
-
bind:scrolltolower
當(dāng)滾動(dòng)內(nèi)容到達(dá)底部或最右側(cè)時(shí)觸發(fā) -
bind:refresherrefresh
執(zhí)行下拉操作時(shí)觸發(fā)
另外,還有注意一個(gè)特別的屬性
refresher-triggered
用它來控制下拉刷新狀態(tài)
事件處理-表單組件中的事件
如何獲取表單中,用戶選擇的值?
- input: 簡(jiǎn)易雙向綁定
- radioGroup: 綁定change事件,在事件對(duì)象中detail.value拿到值
- checkboxGroup: 綁定change事件,在事件對(duì)象中detail.value拿到值
- picker: 綁定change事件,在事件對(duì)象中detail.value拿到值
-
change
表單數(shù)據(jù)發(fā)生改變時(shí)觸發(fā)(input 不支持)
? 5.整體表單提交
- form:
submit事件
表單提交時(shí)觸發(fā),button
按鈕必須指定form-type
屬性
生命周期-頁面生命周期
- 分類
-
- 應(yīng)用生命周期
- 頁面生命周期
- 組件生命周期
生命周期是一些名稱固定,會(huì)自動(dòng)執(zhí)行的函數(shù)。
頁面生命周期-基本使用
-
onLoad
在頁面加載完成時(shí)執(zhí)行,只會(huì)執(zhí)行 1 次,常用于獲取地址參數(shù)和網(wǎng)絡(luò)請(qǐng)求 -
onReady頁面初次渲染完成
-
onShow
在頁面處于可見狀態(tài)時(shí)執(zhí)行,常用于動(dòng)態(tài)更新數(shù)據(jù)或狀態(tài) -
onHide
在頁面處于不見狀態(tài)時(shí)執(zhí)行,常用于銷毀長(zhǎng)時(shí)間運(yùn)行的任務(wù),如定時(shí)器頁面生命周期-應(yīng)用場(chǎng)景
onLoad(){ // 發(fā)起請(qǐng)求 }
onShow(){ // 動(dòng)態(tài)更新數(shù)據(jù)或狀態(tài) }
onHide
在頁面處于不見狀態(tài)時(shí)執(zhí)行,常用于銷毀長(zhǎng)時(shí)間運(yùn)行的任務(wù),如定時(shí)器
onReady
在頁面初次渲染完成時(shí)執(zhí)行,只會(huì)執(zhí)行 1 次,常用于節(jié)點(diǎn)操作或動(dòng)畫交互等場(chǎng)景
生命周期-應(yīng)用生命周期
app.js
-
onLaunch
小程序啟動(dòng)時(shí)執(zhí)行1次,常用于獲取場(chǎng)景值或者啟動(dòng)時(shí)的一些參數(shù)(如自定義分享) -
onShow
小程序前臺(tái)運(yùn)行時(shí)執(zhí)行,常用于更新數(shù)據(jù)或狀態(tài) -
onHide
小程序后臺(tái)運(yùn)行時(shí)執(zhí)地,常用于銷毀長(zhǎng)時(shí)間運(yùn)行的任務(wù),如定時(shí)器。
// pages/lifetimes/index.js
Page({
// 小程序轉(zhuǎn)發(fā)/分享
onShareAppMessage() {
return {
title: '小程序?qū)W習(xí)',
path: '/pages/index/index?test=測(cè)試數(shù)據(jù)',
imageUrl: '/static/images/cover.png'
}
}
})
小程序基礎(chǔ)-分包加載&&自定義組件&&&項(xiàng)目全流程
小程序分包加載
小程序分包加載-為什么要分包加載
- 微信平臺(tái)對(duì)小程序單個(gè)包的代碼體積限制為 2M,超過 2M 的情況下可以采用分包來解決
- 即使小程序代碼體積沒有超過 2M 時(shí)也可以拆分成多個(gè)包來實(shí)現(xiàn)按需加載
- 配置文件能忽略的只有靜態(tài)資源,代碼無法被忽略
配置忽略文件
project.config.json
{
"description": "項(xiàng)目配置文件",
"packOptions": {
"ignore": [
{
"value": "static/uploads",
"type": "folder"
}
],
"include": []
},
type: 表示要忽略的資源類型
value: 表示具體要忽略的
小程序分包加載-使用分包配置
分類:
- 主包:
-
每個(gè)小程序必定含有一個(gè)主包。
-
默認(rèn)啟動(dòng)頁面、TabBar 頁面,以及公共資源/JS 腳本必須放在主包;
2.分包 https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages.html
-
通過subPackages來配置
-
所有包的大小之和不超過20M
app.json
{
// 省略其他的...
"subPackages": [
{
"root": "subpkg_user", // 分包代碼的目錄,其實(shí)就是一個(gè)獨(dú)立的文件夾
"pages": [
"pages/profile/profile"
]
},
{
"root": "subpkg_order", // 文件夾
"pages": [
"pages/order_list/index",
"pages/order_list/index"
]
}
]
}
注意: 寫完分包之后,如果對(duì)應(yīng)的文件夾和頁面不存在,它會(huì)自動(dòng)創(chuàng)建文件夾和頁面。
小程序分包—預(yù)加載
https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages/preload.html
在打開小程序啟動(dòng)的時(shí)候只下載主包代碼,分包并不會(huì)下載,因此能夠提升小程序啟動(dòng)時(shí)的打開速度,但是分包的代碼只有在訪問到分包的頁面時(shí)才去下載,這樣用戶就需要有一定時(shí)間的等待(一般不太影響),通過分包預(yù)加載技術(shù)可以實(shí)現(xiàn)提前去下載分包的代碼,這樣分包頁面的訪問速度也會(huì)得到提升。
小程序通過 preloadRule 配置需要預(yù)加載的分包。
app.json
{ ......
"preloadRule": {
"頁面地址,進(jìn)入這個(gè)頁面就需要預(yù)加載分包": { // pages/index/index
"network": "網(wǎng)絡(luò)環(huán)境", // "wifi"
"packages": ["要預(yù)加載的包名"] //["goods_pkg"]
}
}, ......
} //當(dāng)用戶訪問到 pages/index/index 時(shí),在 wifi 網(wǎng)絡(luò)前提下預(yù)先下載 goods_pkg 分包的代碼。
- 指定某個(gè)頁面路徑做為 key,含義是當(dāng)訪問這個(gè)頁面時(shí)會(huì)去預(yù)加載一個(gè)分包
- network 預(yù)加載分包的網(wǎng)絡(luò)條件,可選值為 all、wifi,默認(rèn)為 wifi
- packages 指定要預(yù)下載的分包名或根路徑
配置完成之后,訪問指定頁面時(shí),就會(huì)在控制臺(tái)輸出提示。
自定義組件—基本使用
創(chuàng)建組件
通常將項(xiàng)目中的組件都放在一個(gè)獨(dú)立的目錄下,并且一般就給這個(gè)文件夾取名為:components 。這個(gè)目錄需要我們手動(dòng)進(jìn)行創(chuàng)建。
-
新建一個(gè)目錄:components
-
在components上點(diǎn)擊鼠標(biāo)右鍵,選擇「新建Component」
-
填入組件的名字。它會(huì)自動(dòng)創(chuàng)建4個(gè)同名的文件。(這一點(diǎn)和創(chuàng)建頁面是一樣的)
組件和頁面的結(jié)構(gòu)區(qū)別:
- 組件的配置文件(.json文件)中,有一個(gè)配置項(xiàng):component: true
- 組件的 .js 文件中調(diào)用 Component 函數(shù),頁面的.js文件中調(diào)用Page函數(shù)
注冊(cè)組件
- 頁面注冊(cè)是在使用組件的(xxxx.json)中通過 usingComponents 進(jìn)行注冊(cè),只能在當(dāng)前頁面中組件
- 全局注冊(cè)是在 app.json 文件中通過 usingComponents 對(duì)自定義組件進(jìn)行注冊(cè),可以在任意頁面中使用
"usingComponents": {
"my-test": "/components/MyTest/index"
}
使用組件
在wxml中,直接通過標(biāo)簽的方式使用即可。
自定義組件—組件樣式
- 組件中的樣式不要使用標(biāo)簽選擇器
- 組件中,樣式默認(rèn)是隔離的: 自定義組件的樣式只受到自定義組件 wxss 的影響
- 通過對(duì)組件的配置,可以取消這個(gè)隔離的狀態(tài)。
樣式隔離注意點(diǎn)
- app.wxss中的全局樣式對(duì)組件無效
- 只有class選擇器具有樣式隔離效果,id選擇器、屬性選擇器、標(biāo)簽選擇器不受樣式隔離的影響
建議:在組件和引用組件的頁面中建議使用class選擇器,不要使用id、屬性、標(biāo)簽選擇器
修改組件樣式的隔離選項(xiàng)
默認(rèn)情況下,自定義組件的樣式隔離特性能夠防止組件內(nèi)外樣式互相干擾的問題。但有時(shí),我們希望外界能夠控制組件內(nèi)部的樣式,此時(shí),可以通過在組件的.js文件中設(shè)置: options → addGlobalClass 為true
XX.js
Component({
options: {
addGlobalClass: true
}
})
在頁面中設(shè)置的同類名的選擇器就能作用于子組件內(nèi)部的元素。但是,組件內(nèi)的class選擇器,不能影響頁面的元素。
自定義組件—組件樣式-外部樣式類
組件希望接受外部傳入的樣式類。此時(shí)可以在 Component 中用 externalClasses 定義若干個(gè)外部樣式類。
在開發(fā)組件時(shí),主動(dòng)暴露給組件使用者,修改組件內(nèi)部樣式
組件 custom-component.js
/* 組件 custom-component.js */
Component({
externalClasses: ['my-class']
});
組件 custom-component.wxml
<!-- 組件的wxml -->
<!-- 這里的my-class相當(dāng)于一個(gè)占位符 -->
<view class="my-class">components/MyTest/index.wxml</view>
頁面的 WXML
<!-- 頁面的 WXML -->
<custom-component my-class="red-text" />
<custom-component my-class="large-text" />
頁面的wxss
.red-text{ color: red; }
.large-text {font-size: 50px; }
外部樣式類相當(dāng)于用一個(gè)類名去當(dāng)占位符,以便于在后期使用時(shí)替換成真實(shí)的類名,方便添加額外的樣式。
參考:https://vant-contrib.gitee.io/vant-weapp/#/button#wai-bu-yang-shi-lei
自定義組件—數(shù)據(jù)方法
組件的典型結(jié)構(gòu)
// borderImage.js
Component({
/**
* 組件的屬性列表
*/
properties: {
},
/**
* 組件的初始數(shù)據(jù)
*/
data: {
},
/**
* 組件的方法列表
*/
methods: {
}
})
定義數(shù)據(jù)
在小程序中,用于組件模板渲染的私有數(shù)據(jù),需要定義到data中
methods方法
在小程序的組件中,事件處理函數(shù)和自定義方法需要定義到methods中
自定義組件—組件插槽
單個(gè)插槽
在小程序中,默認(rèn)情況下每個(gè)自定義組件中只允許使用一個(gè)插槽進(jìn)行占位。
<!--components/MyTest2/index.wxml-->
<view>
<text>components/MyTest2/index.wxml</text>
<!-- 對(duì)于不確定的內(nèi)容,可以使用slot進(jìn)行占位,具體內(nèi)容交給使用者確定 -->
<slot></slot>
</view>
使用組件
<my-test2>
<!-- 這里的內(nèi)容將被放到組件中<slot>的位置 -->
<view>
這里是slot里的內(nèi)容
</view>
</my-test2>
多插槽(具名插槽)
組價(jià).js
Component({
options: {
multipleSlots: true // 在組件定義時(shí)的選項(xiàng)中啟用多 slot 支持
},
// ... 省略其他
})
此時(shí),可以在這個(gè)組件的 wxml 中使用多個(gè) slot ,以不同的 name 來區(qū)分。
定義插槽
<view>
<text>components/MyTest2/index.wxml</text>
<!-- 對(duì)于不確定的內(nèi)容,可以使用slot進(jìn)行占位,具體內(nèi)容交給使用者確定 -->
<!-- <slot></slot> -->
<slot name="before"></slot>
<view>
---------這里是分割線--------
</view>
<slot name="after"></slot>
</view>
使用組件
<my-test2>
<!-- 這里的內(nèi)容將被放到組件中<slot>的位置 -->
<!-- <view>
這里是slot里的內(nèi)容
</view> -->
<view slot="before">
這里是before slot里的內(nèi)容
</view>
<view slot="after">
這里是after slot里的內(nèi)容
</view>
</my-test2>
自定義組件—生命周期
組件生命周期-lifetimes
生命周期 | 參數(shù) | 描述 |
---|---|---|
created | 無 | 在組件實(shí)例剛剛被創(chuàng)建時(shí)執(zhí)行,此時(shí)還不能調(diào)用 setData,一般用于給組件的this添加一些自定義的屬性字段 |
attached | 無 | 在組件實(shí)例進(jìn)入頁面節(jié)點(diǎn)樹時(shí)執(zhí)行,絕大多數(shù)初始化工作可以在這個(gè)時(shí)機(jī)進(jìn)行,例如發(fā)請(qǐng)求獲取初始數(shù)據(jù) |
ready | 無 | 在組件在視圖層布局完成后執(zhí)行 |
moved | 無 | 在組件實(shí)例被移動(dòng)到節(jié)點(diǎn)樹另一個(gè)位置時(shí)執(zhí)行 |
detached | 無 | 在組件實(shí)例被從頁面節(jié)點(diǎn)樹移除時(shí)執(zhí)行,適合做一些清理工作 |
error | Object Error | 每當(dāng)組件方法拋出錯(cuò)誤時(shí)執(zhí)行 |
生命周期函數(shù)要寫在lifetimes里邊
lifetimes: {
created() {
console.log('組件被created') // 這里使用setData不會(huì)引起視圖的更新
this.setData({ msg: 'abc!' })
},
attached() {
this.setData({ msg: 'abcd' })
}
}
自定義組件-屬性(父?jìng)髯?
在小程序中,properties是組件的對(duì)外屬性,用于接收外界傳遞到組件中的數(shù)據(jù)
父組件傳入屬性值
<my-test isOpen max="9" min="1" />
子組件.js中接收
Component({
properties: {
isOpen: Boolean,
min: Number, // 直接寫類型
max: { // 寫類型 + 初始值
type: Number,
value: 10 // value用于指定默認(rèn)值
}
}
})
自定義組件-組件通訊-自定義事件triggerEvent(子傳父)
Vant組件庫(kù)
官方文檔:https://vant-contrib.gitee.io/vant-weapp/#/quickstart
步驟一 通過 npm 安裝
npm i @vant/weapp -S --production
步驟二 修改 app.json
將 app.json 中的 "style": "v2"
去除
步驟三 修改 project.config.json
開發(fā)者工具創(chuàng)建的項(xiàng)目,miniprogramRoot
默認(rèn)為 miniprogram
,package.json
在其外部,npm 構(gòu)建無法正常工作。
需要手動(dòng)在 project.config.json
內(nèi)添加如下配置,使開發(fā)者工具可以正確索引到 npm 依賴的位置。
{
...
"setting": {
...
"packNpmManually": true,
"packNpmRelationList": [
{
"packageJsonPath": "./package.json",
"miniprogramNpmDistDir": "./miniprogram/"
}
]
}
}
步驟四 構(gòu)建 npm 包(重點(diǎn))
開發(fā)者工具上 > “工具” > “構(gòu)建npm”
使用
去app.json(全局注冊(cè))或頁面.json(局部注冊(cè))中注冊(cè)
"usingComponents": {
"van-button": "@vant/weapp/button/index"
}
在頁面中使用
<van-button type="primary">按鈕</van-button>
小程序開發(fā)環(huán)境-優(yōu)化目錄結(jié)構(gòu)
項(xiàng)目的根目錄
├── miniprogram // 項(xiàng)目相關(guān)的代碼夾
├── node_modules // npm包目錄
├── package.json
├── project.config.json
├── package-lock.json
└── sitemap.json
修改 project.config.json
中的配置項(xiàng)
{
// 省略其他......
"setting": {
// 省略其他......
"packNpmManually": true,
"packNpmRelationList": [
{
"miniprogramNpmDistDir": "./miniprogram",
"packageJsonPath": "package.json"
}
]
},
"miniprogramRoot": "miniprogram/"
}
啟用 less/sass
通過 less/sass 可以更好的管理 css 樣式,通過 project.config.json
可以啟用對(duì) less/sass 的支持。
{
"setting": {
"useCompilerPlugins": ["sass"]
}
}
然后將 .wxss
文件后綴改換成 .scss
即可。
啟動(dòng)項(xiàng)目
- 拉取代碼
- 導(dǎo)入項(xiàng)目
使用小程序開發(fā)者工具導(dǎo)入【項(xiàng)目】的代碼
3. 使用小程序開發(fā)者工具構(gòu)建 npm
- 安裝包:npm install
- 手動(dòng)構(gòu)建: 【工具】→【構(gòu)建npm】
project.config.json的幾個(gè)配置
{
"miniprogramRoot": "miniprogram/",
"setting": {
"useCompilerPlugins": ["sass"],
"packNpmManually": true,
"packNpmRelationList": [
{
"packageJsonPath": "./package.json",
"miniprogramNpmDistDir": "./miniprogram"
}
],
}
}
-
miniprogramRoot
項(xiàng)目的根目錄為miniprogram
-
setting.useCompilerPlugins
啟用了sass
支持 -
packNpmRelationList
指定了 npm 構(gòu)建時(shí)所需的package.json
的位置以及構(gòu)建后代碼的生成位置
4. 改成自己的appid
這個(gè)項(xiàng)目中的appid是別人的,如果我們需要改成自己的。
基礎(chǔ)封裝-消息反饋
將所有通用的工具方法封裝到 utils/utils.js 中
/**
* 用戶消息反饋
* @param {string} title 文字提示的內(nèi)容
*/
export const toast = (title = '數(shù)據(jù)加載失敗...') => {
wx.showToast({
title,
mask: true,
icon: 'none',
})
}
// 掛載到全局對(duì)象 wx
wx.$toast = toast
app.js
// 在入口中執(zhí)行 utils.js
import './utils/utils.js'
App({
// ...
})
使用
wx.$toast('//提示文字', "icon圖標(biāo)")
基礎(chǔ)封裝-網(wǎng)絡(luò)請(qǐng)求
安裝第三方的包-構(gòu)建
- npm install wechat-http
- 安裝完成后還必須要構(gòu)建 npm后才可以使用
wechat-http用法與 axios
類似:
-
http.baseURL
配置接口基礎(chǔ)路徑 -
http.get
以GET
方法發(fā)起請(qǐng)求 -
http.post
以POST
方法發(fā)起請(qǐng)求 -
http.put
以PUT
方法發(fā)起請(qǐng)求 -
http.delete
以DELETE
方法發(fā)起請(qǐng)求 -
http.intercept
配置請(qǐng)求和響應(yīng)攔截器 -
http
本身做為函數(shù)調(diào)用也能用于發(fā)起網(wǎng)絡(luò)請(qǐng)求
二次封裝
新建 utils/http.js
文件
// 導(dǎo)入 http 模塊
import http from 'wechat-http'
// 基礎(chǔ)路徑
http.baseURL = 'https://live-api.itheima.net'
// 掛載到全局對(duì)象
wx.http = http
// 普通的模塊導(dǎo)出
export default http
以全局對(duì)象方式調(diào)用時(shí)需要在入口中執(zhí)行 utils/http.js
// 執(zhí)行 uitls/http.js
import './utils/http.js'
App({
// ...
})
配置響應(yīng)攔截器
// 配置響應(yīng)攔截器
http.intercept.response = function ({ data, config }) {
// 檢測(cè)接口是否正常返回結(jié)果
if (data.code !== 10000) {
wx.$toast()
return Promise.reject(data)
}
// 只保留data數(shù)據(jù),其它的都過濾掉
return data.data
}
跳轉(zhuǎn)傳參
點(diǎn)擊公告列表后將公告的ID通過地址參數(shù)傳遞到公告詳情頁面,在公告詳情頁 onLoad 生命周期中讀取到公告 ID,然后調(diào)用接口獲取公告詳情的數(shù)據(jù)。
van-count-down 組件(倒計(jì)時(shí))的應(yīng)用
<van-count-down use-slot time="{{6000}}" bind:change="countDownChange">
<text>{{timeData.seconds}}秒后重新獲取</text>
</van-count-down>
time: 指定了倒計(jì)時(shí)多少毫秒
bind:change每隔一秒的回調(diào),它會(huì)傳出來當(dāng)前的倒計(jì)時(shí)信息
countDownChange(ev) {
console.log(ev.detail)
this.setData({
timeData: ev.detail,
getCodeBtnVisible: ev.detail.minutes === 0 && ev.detail.seconds === 0,
})
},
表單驗(yàn)證插件使用
先在data中設(shè)置mobile,再在模板中進(jìn)行雙向綁定
model:value=“{{mobile}}”
-
安裝 并 構(gòu)建 表單驗(yàn)證碼插件
wechat-validate
npm install wechat-validate
- 將插件導(dǎo)入到項(xiàng)目中
-
behaviors
將插件注入到頁面中 -
rules
由插件提供的屬性,用來定義數(shù)據(jù)驗(yàn)證的規(guī)則(類似于 Element UI) -
validate
由插件提供的方法,根據(jù)rules
的規(guī)則來對(duì)數(shù)據(jù)進(jìn)行驗(yàn)證
// 導(dǎo)入表單驗(yàn)證插件
import validate from 'wechat-validate'
Page({
data: {
mobile: '' // 省略其他
},
behaviors: [validate], // 將插件注入到頁面實(shí)例中
rules: {
mobile: [
{required: true, message: '請(qǐng)?zhí)顚懯謾C(jī)號(hào)碼!'},
{pattern: /^1[3-8]\d{9}$/, message: '請(qǐng)?zhí)顚懻_的手機(jī)號(hào)碼!'}
]
},
getSMSCode() {
// 獲取驗(yàn)證結(jié)果
const { valid, message } = this.validate('mobile')
// 如果驗(yàn)證不合法則不再執(zhí)行后面的邏輯
if (!valid) return wx.$toast(message)
console.log('getCode')
this.setData({ getCodeBtnVisible: false })
},
})
保存token-跳轉(zhuǎn)
- 在app.js中設(shè)置setToken方法,保存到本地存儲(chǔ)
App({
// ...
setToken(key, token) {
// 將 token 記錄在應(yīng)用實(shí)例中
this[key] = token
// 將 token 存入本地
wx.setStorageSync(key, token)
}
})
2.點(diǎn)擊登錄 | 注冊(cè)發(fā)送請(qǐng)求成功之后
const app = getApp() //小程序中獲取全局的實(shí)例對(duì)象
app.setToken('token', res.token)
app.setToken('refreshToken', res.refreshToken)
// 跳轉(zhuǎn)
const url = '/pages/profile/index'
wx.redirectTo({ url })
登錄檢測(cè)-鑒權(quán)組件
1.在根目錄中創(chuàng)建 components
文件夾用來存放全局的組件,然后通過小程序開發(fā)者工具創(chuàng)建一個(gè)名為 authorization
的組件
2.接下來全局來注冊(cè)這個(gè)組件,保證任何頁面中都可以直接應(yīng)用 authorization
組件
{
"usingComponents": {
"authorization": "/components/authorization/index"
},
}
3.到用戶信息頁面中應(yīng)用 authorization
使用做為頁面根節(jié)點(diǎn)
<authorization>
...
</authorization>
4.在authorization中補(bǔ)充插槽和狀態(tài)
<!--components/authorization/index.wxml-->
<slot wx:if="{{isLogin}}"></slot>
data: {
isLogin: false
},
讀取本地存儲(chǔ)token
讀取本地存儲(chǔ)的 token
數(shù)據(jù),用于判斷是否曾登錄過
// app.js
App({
......
getToken() {
// 將 token 數(shù)據(jù)記到應(yīng)用實(shí)例中
// return this.token = wx.getStorageSync('token')
return this.token
}
})
在組件內(nèi)讀token并處理
data: {
isLogin: false
},
lifetimes: {
attached() {
const isLogin = !!getApp().getToken()
//const app = getApp() const isLogin = !!app.getToken()
this.setData({ isLogin })
if (!isLogin) {
wx.redirectTo({ url: '/pages/login/index' })
}
}
},
地址重定向,登錄成功后跳回到原來的頁面
在 authoirzation
組件檢測(cè)登錄時(shí)獲取當(dāng)前頁面棧實(shí)例,并在跳轉(zhuǎn)到登錄頁面時(shí)在 URL 地址上拼湊參數(shù):
// /components/authorization/index.js
Component({
// ...
lifetimes: {
attached() {
// 獲取登錄狀態(tài)
const isLogin = !!getApp().token
// 變更登錄狀態(tài)
this.setData({ isLogin })
// 獲取頁面棧
const pageStack = getCurrentPages()
// 獲取頁面路徑
const currentPage = pageStack.pop()
// 未登錄的情況下跳轉(zhuǎn)到登錄頁面
if (!isLogin) {
wx.redirectTo({
url: '/pages/login/index?redirectURL=/' + currentPage.route,
})
}
},
},
})
用戶管理-顯示默認(rèn)值
app.js中添加初始值
App({
globalData: {},
userInfo: { avatar: '', nickName: '微信用戶1' }
}
在onLoad中加載值
data: {
avatar: '',
nickName: ''
},
onLoad() {
const app = getApp()
console.log(app.userInfo)
const { avatar, nickName } = app.userInfo
this.setData({ avatar, nickName })
// 用戶未登錄時(shí)不必請(qǐng)求
app.token && this.getUserProfile()
},
配置請(qǐng)求攔截器
將用戶的登錄狀態(tài)通過自定義的頭信息 Authorization
隨接口調(diào)用時(shí)一起發(fā)送到服務(wù)端。
// 導(dǎo)入 wechat-http 模塊
import http from 'wechat-http'
// 配置接口基礎(chǔ)路徑
http.baseURL = 'https://live-api.itheima.net'
// 配置請(qǐng)求攔截器
http.intercept.request = function (options) {
console.log('請(qǐng)求攔截器', options.header)
// 擴(kuò)展頭信息
const defaultHeader = {}
// 身份認(rèn)證
const token = getApp().getToken()
if (token) {
defaultHeader.Authorization = 'Bearer ' + getApp().getToken()
}
// 與默認(rèn)頭信息合并
options.header = Object.assign({}, defaultHeader, options.header)
// 處理后的請(qǐng)求參數(shù)
return options
}
注:傳遞 token
時(shí)需要拼湊字符串前綴 "Bearer "
文件上傳(例:更新用戶頭像)
獲取用戶選擇的頭像地址,通過 wx.uploadFile
將圖片上傳到服務(wù)端。
wx.uploadFile
的基本語法:
-
url
上傳接口地址 -
filePath
待上傳文件的臨時(shí)路徑(該路徑只能用于小程序內(nèi)部) -
name
接口接收上傳文件的數(shù)據(jù)名稱(由后端指定) -
formData
除上傳文件外的其它數(shù)據(jù) -
header
自定義頭信息 -
success
上傳成功的回調(diào)函數(shù) -
fail
上傳失敗后的回調(diào)函數(shù) -
complete
上傳完成時(shí)的回調(diào)(無論成功或失?。?/li>
注:該 API 不支持返回 Promise,調(diào)用該 API 時(shí),需要提前在小程序管理后臺(tái)添加服務(wù)器域名。
<!-- pages/profile/index.wxml -->
<authorization>
<view class="profile">
<van-cell center title="頭像">
<van-icon slot="right-icon" name="arrow" size="16" color="#c3c3c5" />
<button
class="button"
size="mini"
hover-class="none"
bind:chooseavatar="updateUserAvatar" //事件,事件名全部小寫,A千萬不要大寫,不會(huì)觸發(fā)
open-type="chooseAvatar"> //與上邊事件對(duì)應(yīng)
<image class="avatar" src="{{avatar}}"></image>
</button>
</van-cell>
...
</view>
</authorization>
// pages/profile/index.js
const pageStack = getCurrentPages()
Page({
...
// 更新用戶頭像
updateUserAvatar(ev.detail.avatarUrl) {
// 調(diào)用 API 上傳文件
wx.uploadFile({
// 接口地址
url: wx.$http.baseURL + '/upload',
// 待上傳的文件路徑
filePath: avatar,
name: 'file',// wx.uploadFile 要求必傳。
header: {
Authorization: 'Bearer ' + getApp().getToken() // 用戶登錄狀態(tài)
},
formData: { // 是我們自己的接口文檔的要求??梢圆粋鳎J(rèn)就是avatar
type: 'avatar'
},
success: (result) => {
console.log(JSON.parse(result.data))
const res = JSON.parse(result.data)
// console.log(res.data.url)
const avatar = res.data.url
// 1. 在頁面上顯示
this.setData({ avatar })
// 2. 更新全局?jǐn)?shù)據(jù)
const app = getApp()
app.userInfo.avatar = avatar
// 3. 通過頁面棧找到my/index頁面,更新它的avatar信息
const pages = getCurrentPages()
// pages[0].data.nickName = nickName 直接修改數(shù)據(jù)不會(huì)讓視圖更新
// 調(diào)用setData更新
pages[0].setData({ avatar })
}
})
}
})
上述代碼中通過 wx.http.baseURL
獲取接口服務(wù)器地址,通過應(yīng)用實(shí)例獲取 token
。
refresh_token使用
- token:
-
- 作用:在訪問一些接口時(shí),需要傳入token,就是它。
- 有效期:2小時(shí)(安全)。
- refresh_token
-
- 作用: 當(dāng)token的有效期過了之后,可以使用它去請(qǐng)求一個(gè)特殊接口(這個(gè)接口也是后端指定的,明確需要傳入refresh_token),并返回一個(gè)新的token回來(有效期還是2小時(shí)),以替換過期的那個(gè)token。
- 有效期:14天。(最理想的情況下,一次登陸可以持續(xù)14天。)
1.用戶在首次完成登錄時(shí)會(huì)分別得到 token 和 refresh_token
2.當(dāng) token 失效后(例如2小時(shí)之后),調(diào)用接口A會(huì)返回 401 狀態(tài)碼(這是與后端約定好的規(guī)則)
3.檢測(cè)狀態(tài)碼是否為 401**,如果是,則攜帶refreshToken去調(diào)用刷新token的接口
4.刷新 token 的接口后會(huì)返回新的 token 和 refreshToken
5.把401的接口A重新發(fā)送一遍
注意:
refresh_token也是有過期時(shí)間的,只不過一般會(huì)比token過期時(shí)間更長(zhǎng)一些。這就是為啥如果某個(gè)應(yīng)用我們天天打開,則不會(huì)提示我們登錄,如果是有幾周或更長(zhǎng)時(shí)間去打開時(shí),會(huì)再次要求我們登錄。
refresh_token一個(gè)更常見的名字叫token無感刷新。
refreshToken功能-基本實(shí)現(xiàn)
// 響應(yīng)攔截器
http.intercept.response = async ({ statusCode, data, config }) => {
console.log(statusCode, data, config)
// console.log(statusCode) // http 響應(yīng)狀態(tài)碼
// console.log(config) // 發(fā)起請(qǐng)求時(shí)的參數(shù)
if (data.code === 401) {
const app = getApp()
// 調(diào)用接口獲取新的 token
const res = await http({
url: '/refreshToken',
method: 'POST',
header: {
Authorization: 'Bearer ' + app.getToken('refreshToken'),
}
})
app.setToken('token', res.token)
app.setToken('refreshToken', res.refreshToken)
// 獲得新的token后需要重新發(fā)送剛剛未完成的請(qǐng)求
config = Object.assign(config, {
header: {
// 更新后的 token
Authorization: 'Bearer ' + res.token,
},
})
// 重新發(fā)請(qǐng)求
return http(config)
}
// 攔截器處理后的響應(yīng)結(jié)果
if (data.code === 10000) {
return data.data
} else {
wx.$toast(data.message || '請(qǐng)求失敗')
return Promise.reject(data.message)
}
}
refreshToken也過期的特殊處理
完整版響應(yīng)攔截器
// 響應(yīng)攔截器
http.intercept.response = async ({ statusCode, data, config }) => {
console.log(statusCode, data, config)
// console.log(statusCode) // http 響應(yīng)狀態(tài)碼
// console.log(config) // 發(fā)起請(qǐng)求時(shí)的參數(shù)
if (data.code === 401) {
++ if (config.url.includes('/refreshToken')) {
++ console.log('/refreshToken過期了')
++ // 獲取當(dāng)前頁面的路徑,保證登錄成功后能跳回到原來頁面
++ const pageStack = getCurrentPages()
++ const currentPage = pageStack.pop()
++ const redirectURL = currentPage.route
++ // 跳由跳轉(zhuǎn)(登錄頁面)
++ wx.redirectTo({
++ url: '/pages/login/index?redirectURL=/' + redirectURL,
++ })
++ return Promise.reject('refreshToken也過期了,就只能重新登錄了')
++ }
const app = getApp()
// 調(diào)用接口獲取新的 token
const res = await http({
url: '/refreshToken',
method: 'POST',
header: {
Authorization: 'Bearer ' + app.getToken('refreshToken'),
}
})
app.setToken('token', res.token)
app.setToken('refreshToken', res.refreshToken)
config = Object.assign(config, {
header: {
// 更新后的 token
Authorization: 'Bearer ' + res.token,
},
})
// 重新發(fā)請(qǐng)求
return http(config)
}
// 攔截器處理后的響應(yīng)結(jié)果
else if (data.code === 10000) {
return data.data
} else {
wx.$toast(data.message || '請(qǐng)求失敗')
return Promise.reject(data.message)
}
}
騰訊位置服務(wù)-需要提前注冊(cè)
文檔地址:https://lbs.qq.com/miniProgram/jsSdk/jsSdkGuide/jsSdkOverview
使用步驟(共4步)
- 申請(qǐng)開發(fā)者密鑰(key):申請(qǐng)密鑰(地址:https://lbs.qq.com/dev/console/application/mine)
- 開通webserviceAPI服務(wù):控制臺(tái) ->應(yīng)用管理 -> 我的應(yīng)用->添加key-> 勾選WebServiceAPI -> 保存(小程序SDK需要用到webserviceAPI的部分服務(wù),所以使用該功能的KEY需要具備相應(yīng)的權(quán)限)
3.下載微信小程序JavaScriptSDK,微信小程序JavaScriptSDK v1.1(https://mapapi.qq.com/web/miniprogram/JSSDK/qqmap-wx-jssdk1.1.zip) JavaScriptSDK v1.2(https://mapapi.qq.com/web/miniprogram/JSSDK/qqmap-wx-jssdk1.2.zip) js文件
4.安全域名設(shè)置,在小程序管理后臺(tái)-> 開發(fā) -> 開發(fā)管理 -> 開發(fā)設(shè)置 -> “服務(wù)器域名” 中設(shè)置request合法域名,添加https://apis.map.qq.com
地理定位-wx.getLocation
獲取用戶所在位置的經(jīng)緯度。在小程序中調(diào)用這個(gè)接口時(shí)必須先在 app.json 中申請(qǐng)調(diào)用權(quán)限(開發(fā)環(huán)境可以省略)。
//app.json
{
"requiredPrivateInfos": [
++ "getLocation"
],
"permission": {
"scope.userLocation": {
"desc": "你的位置信息將用于小程序位置接口的效果展示"
}
},
}
Page({
onLoad() {
this.getLocation()
},
async getLocation() {
const res = await wx.getLocation() // 要提前申請(qǐng)權(quán)限
console.log(res)
},
})
wx.getLocation返回的結(jié)果格式大致如下:
accuracy: 65
errMsg: "getLocation:ok"
horizontalAccuracy: 65
latitude: 30.88131
longitude: 114.37509
speed: -1
verticalAccuracy: 65
wx.getLocation 只能得到經(jīng)緯度信息
逆地址解析-reverseGeocoder
由坐標(biāo) → 坐標(biāo)所在位置的文字描述的轉(zhuǎn)換,輸入坐標(biāo)返回地理位置信息和附近poi列表
文檔地址:https://lbs.qq.com/miniProgram/jsSdk/jsSdkGuide/methodReverseGeocoder
1. 導(dǎo)入 QQMapWX 并設(shè)置好 key
2.在代碼中補(bǔ)充getPoint方法:
- 調(diào)用接口把經(jīng)緯度轉(zhuǎn)換成對(duì)應(yīng)位置的文字
- 保存文字到address
// 導(dǎo)入位置服務(wù)實(shí)例
import QQMap from '../../../utils/qqmap'
Page({ ......
onLoad() {
this.getLocation()
},
async getLocation() {
// 調(diào)用小程序API獲取經(jīng)緯度等信息
const { latitude, longitude } = await wx.getLocation() //獲取用戶經(jīng)緯度
this.getPoint(latitude, longitude)
},
getPoint(latitude, longitude) {
// 逆地址解析(根據(jù)經(jīng)緯度來獲取地址)
QQMap.reverseGeocoder({
location: [latitude, longitude].join(','),
success: (result) => {
const address = res.address
this.setData({ address })
},
})
}
})
3.渲染頁面
<van-cell-group border="{{false}}" title="當(dāng)前地點(diǎn)">
<van-cell title="{{address}}" border="{{false}}"> //border="{{false}}"設(shè)置無邊框樣式
<text bind:tap="chooseLocation" class="enjoy-icon icon-locate">重新定位</text>
</van-cell>
</van-cell-group>
QQMap地點(diǎn)搜索—search
根據(jù)當(dāng)前的定位,調(diào)用 QQMap.search() 找到周邊的信息。
搜索周邊poi(Point of Interest),比如:“酒店” “餐飲” “娛樂” “學(xué)?!?等等
文檔地址:https://lbs.qq.com/miniProgram/jsSdk/jsSdkGuide/methodSearch
在小程序中調(diào)用這個(gè)接口時(shí)必須要在 app.json 中申請(qǐng)調(diào)用權(quán)限
//app.json
{
"requiredPrivateInfos": [
++ "chooseLocation"
]
}
// 選擇新的位置
async chooseLocation() {
// 調(diào)用小程序 API 獲取新的位置
const { latitude, longitude } = await wx.chooseLocation()
this.getPoint(latitude, longitude) // 獲取新的位置經(jīng)緯度
},
getPoint(latitude, longitude) {
wx.showLoading({
title: '正在加載...', // 顯示loading提示
})
// 逆地址解析(根據(jù)經(jīng)緯度來獲取地址)
QQMap.reverseGeocoder({
location: [latitude, longitude].join(','),
success: ({ result: { address } }) => {
this.setData({ address })
},
})
QQMap.search({
keyword: '住宅小區(qū)', //搜索關(guān)鍵詞
location: [latitude, longitude].join(','), //設(shè)置周邊搜索中心點(diǎn)
page_size: 5, //只顯示5條信息,不設(shè)置此項(xiàng)默認(rèn)為10
success: (result) => { //success 是一個(gè)回調(diào)函數(shù),表示搜索成功后的處理邏輯。
const points = result.data
this.setData({ points }) // 渲染數(shù)據(jù)
},
fail: (err) => { //fail 是一個(gè)回調(diào)函數(shù),表示搜索失敗后的處理邏輯。
console.log(err.message)
},
complete: () => {//complete 是一個(gè)回調(diào)函數(shù),表示搜索結(jié)束后的處理邏輯(無論搜索成功還是失?。?/span>
wx.hideLoading() // 隱藏loading提示
},
})
},
重新定位-wx.chooseLocation
申請(qǐng)權(quán)限
獲取用戶指定位置的經(jīng)緯度。在小程序中調(diào)用這個(gè)接口時(shí)必須要在 app.json 中申請(qǐng)調(diào)用權(quán)限
{
"requiredPrivateInfos": [
"chooseLocation"
]
}
示例代碼:
// 選擇新的位置
async chooseLocation() {
// 調(diào)用小程序 API 獲取新的位置
const { latitude, longitude } = await wx.chooseLocation()
// 獲取新的位置附近的小區(qū)
this.getPoint(latitude, longitude)
console.log('起點(diǎn)位置:', latitude, longitude)
},
getPoint(latitude, longitude) {
// 顯示loading提示
wx.showLoading({
title: '正在加載...',
})
// 逆地址解析(根據(jù)經(jīng)緯度來獲取地址)
QQMap.reverseGeocoder({
location: [latitude, longitude].join(','),
success: ({ result: { address } }) => {
// console.log(address)
// 數(shù)據(jù)數(shù)據(jù)
this.setData({ address })
},
})
QQMap.search({
keyword: '住宅小區(qū)', //搜索關(guān)鍵詞
location: [latitude, longitude].join(','), //設(shè)置周邊搜索中心點(diǎn)
page_size: 5,
success: (result) => {
// console.log(result)
// 過濾掉多余的數(shù)據(jù)
const points = result.data.map(({ id, title, _distance }) => {
return { id, title, _distance }
})
// console.log(points)
// 渲染數(shù)據(jù)
this.setData({ points })
},
fail: (err) => {
console.log(err.message)
},
complete: () => {
// 隱藏loading提示
wx.hideLoading()
},
})
},
圖片收集(收集身份證信息)
小程序沒有input type="file"用于選擇文件,要實(shí)現(xiàn)類似功能,用以下api:
wx.chooseMedia**:**拍攝或從手機(jī)相冊(cè)中選擇圖片或視頻。
低版本請(qǐng)用wx.chooseImage。
1.綁定事件選擇身份證圖片上傳。
2.發(fā)送請(qǐng)求上傳圖片,拿到上傳后的圖片地址。
Page({
...
async uploadPicture(ev) {
// 獲取圖片臨時(shí)地址
const res = await wx.chooseMedia({
count: 1,
mediaType: ['image'],
sizeType: ['compressed'],
})
const tempPath = res.tempFiles[0].tempFilePath
const type = ev.mark.type
// 上傳圖片到服務(wù)器
wx.uploadFile({
url: wx.$http.baseURL + '/upload',
filePath: tempPath,
name: 'file',
header: {
Authorization: 'Bearer ' + getApp().getToken(),
},
success: (res) => {
const res = JSON.parse(result.data)
console.log(res.data.url) // 上傳成功的回調(diào)
this.setData({ [type]: res.data.url })
},
})
},
})
校驗(yàn)表單信息
獲取了全部的表單數(shù)據(jù)后再對(duì)數(shù)據(jù)進(jìn)行驗(yàn)證,說明如下:
- 房屋的信息是通過url地址獲取的不需要驗(yàn)證
- 性別可以指定默認(rèn)值也不需要驗(yàn)證
- 剩下的數(shù)據(jù)通過
wechat-validate
插件進(jìn)行驗(yàn)證:
// house_pkg/pages/form/index.js
// 導(dǎo)入表單驗(yàn)證插件
import wxValidate from 'wechat-validate'
Page({
behaviors: [wxValidate],
data: {
point: '',
building: '',
room: '',
name: '',
gender: 1,
mobile: '',
idcardFrontUrl: '',
idcardBackUrl: '',
},
rules: {
name: [
{ required: true, message: '業(yè)主姓名不能為空!' },
{ pattern: /^[\u4e00-\u9fa5]{2,5}$/, message: '業(yè)主姓名只能為中文!' },
],
mobile: [
{ required: true, message: '業(yè)主手機(jī)號(hào)不能為空!' },
{ pattern: /^1[3-8]\d{9}$/, message: '請(qǐng)?zhí)顚懻_的手機(jī)號(hào)!' },
],
idcardFrontUrl: [
{ required: true, message: '請(qǐng)上傳身份證國(guó)徽面!' }
],
idcardBackUrl: [
{ required: true, message: '請(qǐng)上傳身份證照片面!' }
],
},
})
表單收集—收集預(yù)約日期
1.時(shí)間選擇控件:van-datetime-pickerhttps://vant-contrib.gitee.io/vant-weapp/#/datetime-picker
2.彈出層控件:van-popuphttps://vant-contrib.gitee.io/vant-weapp/#/popup
- 給選擇日期單元綁定事件——顯示選擇日期彈層(van-popup)
2.給日期控件綁定確認(rèn)事件confirm
3.在確認(rèn)回調(diào)中獲取時(shí)間戳
4.將時(shí)間戳格式化并顯示
selectDate(ev) {
// console.log(ev)
this.setData({
currentDate: ev.detail,
appointment: wx.$utils.formatDate(ev.detail), // 格式化日期
})
this.closeDateLayer()
},
補(bǔ)充格式化日期的函數(shù)
formatDate(time) {
const d = new Date(time)
const year = d.getFullYear()
let month = d.getMonth() + 1 // 獲取月份,月份從0開始,所以加1
let day = d.getDate()
month = month < 10 ? '0' + month : month
day = day < 10 ? '0' + day : day
return `${year}-${month}-${day}`
},
wxml
<van-cell title-width="100" title="預(yù)約日期" value-class="{{appointment && 'active-cell'}}" bind:click="openDateLayer"
is-link value="{{appointment || '請(qǐng)選擇上門維修日期'}}" />
...省略
<van-popup bind:close="closeDateLayer" round show="{{ dateLayerVisible }}" position="bottom">
<van-datetime-picker bind:cancel="closeDateLayer" bind:confirm="selectDate" type="date" value="{{ currentDate }}"
min-date="{{ 1664582400000 }}" />
</van-popup>
加載更多
在scroll-view上添加 bindscrolltolower=“l(fā)oadMore”
<scroll-view
bindscrolltolower="loadMore"
show-scrollbar="{{false}}" enhanced scroll-y>
<view class="repairs">
<view class="repairs-title">我的報(bào)修</view>
loadMore() {
// if(是否有更多的數(shù)據(jù))
if (this.data.total <= this.data.list.length)
return
console.log('更多的數(shù)據(jù)')
// 把頁碼+1,發(fā)請(qǐng)求,請(qǐng)求回來的數(shù)據(jù)要 追加 到原數(shù)組
// [5] → [10]
this.data.page++
this.getList()
},
async getList() {
// 發(fā)請(qǐng)求
const { pageTotal, total, rows: list } = await wx.$http.get('/repair', { current: this.data.page, pageSize: this.data.pageSize })
console.log(list, pageTotal, total)
// 渲染數(shù)據(jù)
// 在原來的基礎(chǔ)上添加數(shù)據(jù)
this.setData({ total, list: [...this.data.list, ...list] })
},
路線規(guī)劃
路線規(guī)劃是常見的一個(gè)功能,它用來在地圖上展示兩點(diǎn)間路線,要使用這個(gè)功能需要用到兩部分的知識(shí):
- 小程序提供的 map 組件用來在頁面渲染地圖
map | 微信開放文檔https://developers.weixin.qq.com/miniprogram/dev/component/map.html)
- 騰訊位置服務(wù)計(jì)算兩點(diǎn)路線的所有坐標(biāo)點(diǎn)(經(jīng)緯度)
首先來看小程序提供的地圖組件 map
- latitude 指定地圖中心點(diǎn)的緯度
- longitude 指定地圖中心點(diǎn)的經(jīng)功
- scale 指定地圖初始的縮放比例,取值范圍 3 - 20
- markers 地圖上的標(biāo)記點(diǎn)
- polyline 地圖上的路線
latitude、longitude、scale 相對(duì)容易理解,重點(diǎn)來看一下 markers 的使用:
repqir_pkg/pages/detail/index.js
Page({
data: {
markers: [
{
id: 1,
latitude: 40.22077,
longitude: 116.23128,
width: 24,
height: 30,
},
{
id: 2,
latitude: 40.225857999999995,
longitude: 116.23246699999999,
iconPath: '/static/images/marker.png',
width: 40,
height: 40,
},
],
}
})
在定義標(biāo)記點(diǎn)時(shí)每個(gè)標(biāo)記點(diǎn)必須要指定 ID 屬性,否則會(huì)有錯(cuò)誤產(chǎn)生,通過 iconPath 可以自定義標(biāo)記點(diǎn)的圖片,width/height 定義標(biāo)記點(diǎn)的大小尺寸。
polyline
polyline 用來在在圖上展示兩點(diǎn)間的行進(jìn)路線,需要傳遞給它路線對(duì)應(yīng)的坐標(biāo)點(diǎn)(很多個(gè)點(diǎn)組成的線),獲取這些坐標(biāo)點(diǎn)需要通過位置服務(wù)計(jì)算得到。
計(jì)算兩點(diǎn)間路線的坐標(biāo)點(diǎn)需要用到位置服務(wù)的[路線規(guī)劃]https://lbs.qq.com/miniProgram/jsSdk/jsSdkGuide/methodDirection方法
repqir_pkg/pages/detail/index.js
// repqir_pkg/pages/detail/index.js
Page({
data: {},
onLoad() {
// 生成路線
this.getPolyline()
},
// 調(diào)用位置服務(wù)(路線規(guī)劃)
getPolyline() {
qqMap.direction({
mode: 'bicycling',
from: '40.227978,116.22998',
to: '40.22077,116.23128',
success: ({ result }) => {
const coors = result.routes[0].polyline
const points = []
//坐標(biāo)解壓(返回的點(diǎn)串坐標(biāo),通過前向差分進(jìn)行壓縮)
for (let i = 2; i < coors.length; i++) {
coors[i] = Number(coors[i - 2]) + Number(coors[i]) / 1000000
}
// 獲取經(jīng)緯度
for (let i = 0; i < coors.length; i += 2) {
points.push({ latitude: coors[i], longitude: coors[i + 1] })
}
// 渲染數(shù)據(jù)
this.setData({
latitude: points[30].latitude,
longitude: points[30].longitude,
polyline: [
{points, color: '#5591af', width: 4},
],
})
},
})
},
})
計(jì)算出來的坐標(biāo)點(diǎn)是經(jīng)過壓縮的,需要按著官方指定的方式對(duì)數(shù)據(jù)進(jìn)行解壓才可以獲取真正的坐標(biāo)點(diǎn),并且為了適應(yīng)小程序地圖組件的用法,還需要對(duì)數(shù)據(jù)進(jìn)行二次的加工。
關(guān)于數(shù)據(jù)的處理大家只需要參考文檔來實(shí)現(xiàn)就可以,可以說之所這么操作是騰訊位置服務(wù)規(guī)訂好的,做為開發(fā)者按著官方提從的方法來應(yīng)用即可。
自定義分享
[onShareAppMessage]https://developers.weixin.qq.com/miniprogram/dev/reference/api/Page.html#onShareAppMessage-Object-object
監(jiān)聽用戶點(diǎn)擊頁面內(nèi)轉(zhuǎn)發(fā)按鈕(button 組件 open-type=“share”)或右上角菜單“轉(zhuǎn)發(fā)”按鈕的行為,并自定義轉(zhuǎn)發(fā)內(nèi)容。
注意:只有定義了此事件處理函數(shù),右上角菜單才會(huì)顯示“轉(zhuǎn)發(fā)”按鈕
Page({
onLoad({ id, encryptedData }) {
this.getPassport(id)
this.getPassportShare(encryptedData)
},
// 獲取訪客詳情(通行證)
async getPassport(id) {
// 檢測(cè)是否存在 id
if (!id) return
// 調(diào)用接口
const passport = await wx.$http.get('/visitor/' + id)
// 渲染數(shù)據(jù)
this.setData({ ...passport })
}
async getPassportShare(encryptedData) {
// 檢測(cè)是否存在 id
if (!encryptedData) return
// 調(diào)用接口
const passport = await wx.$http.get('/visitor/share/' + this.data.encryptedData)
// 渲染數(shù)據(jù)
this.setData({ passport })
},
onShareAppMessage() {
return {
title: '查看通行證',
path: '/visitor_pkg/pages/passport/index?encryptedData=' + encryptedData,
imageUrl: 'https://enjoy-plus.oss-cn-beijing.aliyuncs.com/images/share_poster.png',
}
},
})
保存到本地api介紹
[saveImageToPhotosAlbum]https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.saveImageToPhotosAlbum.html
保存圖片到系統(tǒng)相冊(cè)。
[getImageInfo]https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.getImageInfo.html
獲取圖片信息。網(wǎng)絡(luò)圖片需先配置 download 域名才能生效。
保存到本地實(shí)現(xiàn)
1.給按鈕綁定事件,調(diào)用getImageInfo獲取圖片臨時(shí)路徑文章來源:http://www.zghlxwxcb.cn/news/detail-495075.html
2.調(diào)用saveImageToPhotosAlbum傳入臨時(shí)路徑完成保存功能文章來源地址http://www.zghlxwxcb.cn/news/detail-495075.html
// 保存圖片
async saveQRCode() {
try {
// 讀取圖片信息
const { path } = await wx.getImageInfo({
src: this.data.url,
})
// 保存圖片到相冊(cè)
wx.saveImageToPhotosAlbum({ filePath: path })
} catch (err) {
wx.$toast('保存圖片失敗,稍后重試!')
}
},
ush({ latitude: coors[i], longitude: coors[i + 1] })
}
// 渲染數(shù)據(jù)
this.setData({
latitude: points[30].latitude,
longitude: points[30].longitude,
polyline: [
{points, color: ‘#5591af’, width: 4},
],
})
},
})
},
})
計(jì)算出來的坐標(biāo)點(diǎn)是經(jīng)過壓縮的,需要按著官方指定的方式對(duì)數(shù)據(jù)進(jìn)行解壓才可以獲取真正的坐標(biāo)點(diǎn),并且為了適應(yīng)小程序地圖組件的用法,還需要對(duì)數(shù)據(jù)進(jìn)行二次的加工。
關(guān)于數(shù)據(jù)的處理大家只需要參考文檔來實(shí)現(xiàn)就可以,可以說之所這么操作是騰訊位置服務(wù)規(guī)訂好的,做為開發(fā)者按著官方提從的方法來應(yīng)用即可。
### 自定義分享
**[onShareAppMessage]https://developers.weixin.qq.com/miniprogram/dev/reference/api/Page.html#onShareAppMessage-Object-object**
監(jiān)聽用戶點(diǎn)擊頁面內(nèi)轉(zhuǎn)發(fā)按鈕([button](https://developers.weixin.qq.com/miniprogram/dev/component/button.html) 組件 open-type="share")或右上角菜單“轉(zhuǎn)發(fā)”按鈕的行為,并自定義轉(zhuǎn)發(fā)內(nèi)容。
**注意:只有定義了此事件處理函數(shù),右上角菜單才會(huì)顯示“轉(zhuǎn)發(fā)”按鈕**
```js
Page({
onLoad({ id, encryptedData }) {
this.getPassport(id)
this.getPassportShare(encryptedData)
},
// 獲取訪客詳情(通行證)
async getPassport(id) {
// 檢測(cè)是否存在 id
if (!id) return
// 調(diào)用接口
const passport = await wx.$http.get('/visitor/' + id)
// 渲染數(shù)據(jù)
this.setData({ ...passport })
}
async getPassportShare(encryptedData) {
// 檢測(cè)是否存在 id
if (!encryptedData) return
// 調(diào)用接口
const passport = await wx.$http.get('/visitor/share/' + this.data.encryptedData)
// 渲染數(shù)據(jù)
this.setData({ passport })
},
onShareAppMessage() {
return {
title: '查看通行證',
path: '/visitor_pkg/pages/passport/index?encryptedData=' + encryptedData,
imageUrl: 'https://enjoy-plus.oss-cn-beijing.aliyuncs.com/images/share_poster.png',
}
},
})
保存到本地api介紹
[saveImageToPhotosAlbum]https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.saveImageToPhotosAlbum.html
保存圖片到系統(tǒng)相冊(cè)。
[getImageInfo]https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.getImageInfo.html
獲取圖片信息。網(wǎng)絡(luò)圖片需先配置 download 域名才能生效。
[外鏈圖片轉(zhuǎn)存中…(img-M8SkNwoO-1687267859406)]
保存到本地實(shí)現(xiàn)
1.給按鈕綁定事件,調(diào)用getImageInfo獲取圖片臨時(shí)路徑
2.調(diào)用saveImageToPhotosAlbum傳入臨時(shí)路徑完成保存功能
// 保存圖片
async saveQRCode() {
try {
// 讀取圖片信息
const { path } = await wx.getImageInfo({
src: this.data.url,
})
// 保存圖片到相冊(cè)
wx.saveImageToPhotosAlbum({ filePath: path })
} catch (err) {
wx.$toast('保存圖片失敗,稍后重試!')
}
},
到了這里,關(guān)于原生微信小程序全流程(基礎(chǔ)知識(shí)+項(xiàng)目全流程)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!