在前面的章節(jié)所用到的數(shù)據(jù)大多都是我們在js的data里寫好的,在這一節(jié)里,我們會來介紹如何讓用戶提交數(shù)據(jù)。無論是計算器、用戶注冊、表單收集、發(fā)表文章、評論等等,這些都是對用戶提交數(shù)據(jù)的獲取。
動態(tài)設(shè)置導(dǎo)航欄標(biāo)題是一個非常簡單的API,在技術(shù)文檔里面可以了解到,只要給wx.setNavigationBarTitle()的title對象賦值,就能改變小程序頁面的標(biāo)題。下面我們會使用多種方法來調(diào)用這個API,既是對前面知識的復(fù)習(xí),也讓大家了解API調(diào)用方法有什么不同。
技術(shù)文檔:wx.setNavigationBarTitle()
結(jié)合前面的知識,我們可以在頁面的生命周期函數(shù)里來調(diào)用API,使用開發(fā)者工具新建一個form頁面,然后在form.js里onLoad里添加代碼:
onLoad: function (options) {
wx.setNavigationBarTitle({
title:"onLoad觸發(fā)修改的標(biāo)題"
})
},
我們也還可以通過點擊button組件,觸發(fā)事件處理函數(shù)來調(diào)用API。在form.wxml里輸入以下代碼
<button type="primary" bindtap="buttonSetTitle">設(shè)置標(biāo)題</button>
然后再在js里添加buttonSetTitle事件處理函數(shù):
buttonSetTitle(e){
console.log(e)
wx.setNavigationBarTitle({
title: "button觸發(fā)修改的標(biāo)題"
})
},
然后點擊設(shè)置標(biāo)題,button就會觸發(fā)事件處理函數(shù)重新給title賦值,頁面的標(biāo)題就由“onLoad觸發(fā)修改的標(biāo)題”變成了“button觸發(fā)修改的標(biāo)題”,同時點擊組件就會收到一個事件對象,我們把這個事件對象e通過console.log打印出來發(fā)現(xiàn)并沒有什么特別有用的信息。這些都是前面我們學(xué)過的知識。
那我們?nèi)绾尾拍茏寴?biāo)題的內(nèi)容可以根據(jù)用戶提交的數(shù)據(jù)進行修改呢?這就涉及到表單的知識啦。小程序一個完整的數(shù)據(jù)表單收集通常包含一個form組件,一個輸入框或選擇器組件(比如input組件),一個button組件。
使用開發(fā)者工具在form.wxml里輸入以下代碼:
<form bindsubmit="setNaivgationBarTitle">
<input type="text" placeholder="請輸入頁面標(biāo)題并點擊設(shè)置即可" name="navtitle"></input>
<button type="primary" formType="submit">設(shè)置</button>
</form>
數(shù)據(jù)表單涉及到的組件多(至少三個),參數(shù)以及參數(shù)的類型也比較多,上面有幾個非常重要的點,大家可以結(jié)合上面的代碼來理解:
在form.js里添加事件處理函數(shù)setNaivgationBarTitle,同時我們把事件對象e給打印出來:
setNaivgationBarTitle(e) {
console.log(e)
const navtitle = e.detail.value.navtitle
wx.setNavigationBarTitle({
title:navtitle
})
},
編譯之后,在開發(fā)者工具的模擬器里輸入任意文本,點擊“設(shè)置”按鈕,我們發(fā)現(xiàn)導(dǎo)航欄標(biāo)題都會顯示為我們輸入的值。在控制臺里我們查看一下事件對象。此時的事件對象的type屬性為submit(以前的為tap),我們在input輸入框填寫的值就存儲在detail對象的value屬性的name名里,這里就是 detail.value.navtitle。
點擊button組件會執(zhí)行form綁定的事件處理函數(shù)setNaivgationBarTitle,打印事件對象e,將在input輸入的值賦值給navtitle,最后傳入wx.setNavigationBarTitle(),賦值給title。注意有兩個setNaivgationBarTitle,一個是事件處理函數(shù),一個是API,前者可以任意命名,后者小程序官方寫死不可更改。
對數(shù)據(jù)表單來說,使用console.log打印事件對象可以讓我們對表單提交的數(shù)據(jù)有一個非常清晰的了解;而使用賦值以及setData可以有效的把表單收集到的數(shù)據(jù)渲染到頁面。
我們也可以把上面的事件處理函數(shù)寫成如下,讓變量title與setNavigationBarTitle的屬性title同名,這樣 title:title可以簡寫成title。
setNaivgationBarTitle(e) {
const title = e.detail.value.navtitle
wx.setNavigationBarTitle({
title //等同于title:title
})
},
小程序的輸入框input主要用來處理文本和數(shù)字的輸入,下面我們就來結(jié)合實戰(zhàn)與技術(shù)文檔,來了解一下文本輸入框input的type、name、placeholder等屬性。
技術(shù)文檔:input技術(shù)文檔
使用開發(fā)者工具在form.wxml里輸入以下代碼,一個form組件里面可以包含多個選擇器或文本輸入框組件,提交數(shù)據(jù)時,會提交form里面填寫的所有數(shù)據(jù):
<form bindsubmit="inputSubmit">
<input type="text" name="username" placeholder="請輸入你的用戶名"></input>
<input password type="text" name="password" maxlength="6" placeholder="請輸入6位數(shù)密碼" confirm-type="next" />
<input type="idcard" name="idcard" placeholder="請輸入你的身份證賬號" />
<input type="number" name="age" placeholder="請輸入你的年齡" />
<input type="digit" name="height" placeholder="請輸入你身高多少米"/>
<button form-type="submit">提交</button>
</form>
然后在form.js里添加事件處理函數(shù)inputSubmit,主要是為了打印form事件對象:
inputSubmit:function(e){
console.log('提交的數(shù)據(jù)信息:',e.detail.value)
},
input輸入框會因為屬性的類型的不同,手機鍵盤外觀會有比較大的差異,所以需要點擊預(yù)覽,用微信掃描二維碼在手機上體驗(也可以啟用真機調(diào)試)。
在開發(fā)者工具的控制臺我們可以看到打印的事件對象里的value對象,屬性名即為input的name名,值即為我們輸入的數(shù)據(jù)。如果沒有name。
小任務(wù):給input輸入框配置confirm-type,分別輸入send、search、next、go、done,然后點擊預(yù)覽,用微信掃描二維碼體驗,注意輸入內(nèi)容時,手機鍵盤顯示的不同。
一個完整的數(shù)據(jù)收集表單,除了可以提交input文本框里面的數(shù)據(jù),還可以提交開關(guān)選擇器按鈕switch、滑動選擇器按鈕slider、單選按鈕radio、多選按鈕checkbox等組件里面的數(shù)據(jù)。
技術(shù)文檔:switch開關(guān)選擇、Slider滑動選擇、Radio單選、checkbox多選、form表單
使用開發(fā)者工具在form.wxml里添加以下代碼,這些組件都是我們?nèi)粘J褂肁pp、頁面等經(jīng)常會使用到的場景:
<form bindsubmit="formSubmit" bindrest="formReset">
<view>開關(guān)選擇器按鈕</view>
<switch name="switch"/>
<view>滑動選擇器按鈕slider</view>
<slider name="process" show-value ></slider>
<view>文本輸入框</view>
<input name="textinput" placeholder="要輸入的文本" />
<view>單選按鈕radio</view>
<radio-group name="sex">
<label><radio value="male"/>男</label>
<label><radio value="female"/>女</label>
</radio-group>
<view>多選按鈕checkbox</view>
<checkbox-group name="gamecheck">
<label><checkbox value="game1"/>王者榮耀</label>
<label><checkbox value="game2"/>歡樂斗地主</label>
<label><checkbox value="game3"/>連連看</label>
<label><checkbox value="game4"/>刺激戰(zhàn)場</label>
<label><checkbox value="game5"/>穿越火線</label>
<label><checkbox value="game6"/>天天酷跑</label>
</checkbox-group>
<button form-type="submit">提交</button>
<button form-type="reset">重置</button>
</form>
然后在form.js里添加formSubmit和formReset事件處理函數(shù)
formSubmit: function (e) {
console.log('表單攜帶的數(shù)據(jù)為:', e.detail.value)
},
formReset: function () {
console.log('表單重置了')
}
編譯之后,在開發(fā)者工具的模擬器里給選擇器組件和文本輸入組件做出選擇以及添加一些值,然后點擊提交按鈕。在控制臺console,我們可以看到事件對象e的value對象就記錄了我們提交的數(shù)據(jù)。也就是說,表單組件提交的數(shù)據(jù)都存儲在事件對象e的detail屬性下的value里。
點擊重置按鈕,即會重置表單,并不需要formReset事件處理函數(shù)做額外的處理。
我們發(fā)現(xiàn)上面button屬性,有時用的是form-type,有時用的是formType(注意兩者的大小寫),這兩種寫法都可以。我們也可以刪掉重置的事件處理函數(shù)formReset,以及form組件的 bindreset="formReset",只需要將button的form-type設(shè)置為reset,也就是
<button form-type="reset"&重置</button&
就可以達到重置的效果,綁定事件處理函數(shù)bindreset
只要我們知道form表單存儲的數(shù)據(jù)在哪里,就能夠結(jié)合前面的知識把數(shù)據(jù)取出來,不同的數(shù)據(jù)類型區(qū)別對待,所以掌握如何使用JavaScript操作不同的數(shù)據(jù)類型很重要。
在技術(shù)文檔里有這樣一句話“當(dāng)點擊 form 表單中 form-type 為 submit 的 button 組件時,會將表單組件中的 value 值進行提交,需要在表單組件中加上 name 來作為 key”。我們也發(fā)現(xiàn)Slider滑動選擇、Radio單選、checkbox多選等,都有自己的value值,也就是這些組件單獨使用時不需要name就可以在事件對象的detail里取到value值,而組合使用時,則必須加name才能取到值,大家可以把name都取消掉,看看結(jié)果如何。
在這里我們先來介紹一下擴展運算符的概念,它的寫法很簡單,就是三個點 ...。我們會用案例的方式讓大家先了解它的作用,以后會經(jīng)常用到的。
上面的gamecheck記錄了我們勾選的多選項的value值,它是一個數(shù)組Array。我們可以在formSubmit事件處理函數(shù)把選項value值給打印出來,給上面的formSubmit函數(shù)添加以下語句:
formSubmit: function (e) {
const gamecheck=e.detail.value.gamecheck
console.log('直接打印的gamecheck',gamecheck)
console.log('拓展運算符打印的gamecheck',...gamecheck)
},
然后我們再來填寫表單提交數(shù)據(jù),從控制臺可以看到直接打印gamecheck,它是一個數(shù)組Array,中括號[ ]就可以看出來,展開也有index值;而使用擴展運算符打印gamecheck,是將數(shù)組里的值都遍歷了出來。這就是擴展運算符…的作用,大家可以先只了解即可。
盡管我們提交了數(shù)據(jù),但是當(dāng)小程序重新編譯之后,所有的數(shù)據(jù)都會被重置,也就是提交的數(shù)據(jù)并沒有保存起來。小程序存儲數(shù)據(jù)有三種方式,一是保存在本地手機上;二是存儲到緩存里;三是存儲到數(shù)據(jù)庫。下面我們來介紹如何將數(shù)據(jù)存儲到手機。
添加手機通訊錄聯(lián)系人:wx.addPhoneContact()
使用開發(fā)者工具在form.wxml添加以下代碼,注意input的name名要和wx.addPhoneContact()里的屬性名對應(yīng)且一致,下面只舉幾個屬性,更多屬性都可以按照技術(shù)文檔添加
<form bindsubmit="submitContact">
<view>姓氏</view>
<input name="lastName" />
<view>名字</view>
<input name="firstName" />
<view>手機號</view>
<input name="mobilePhoneNumbe" />
<view>微信號</view>
<input name="weChatNumber" />
<button type="primary" form-type="submit">創(chuàng)建聯(lián)系人</button>
<button type="default" form-type="reset">重置</button>
</form>
然后在form.js文件里面輸入以下代碼,(注意添加手機聯(lián)系人的API在手機上使用有奇效哦)
submitContact:function(e) {
const formData = e.detail.value
wx.addPhoneContact({
...formData,
success() {
wx.showToast({
title: '聯(lián)系人創(chuàng)建成功'
})
},
fail() {
wx.showToast({
title: '聯(lián)系人創(chuàng)建失敗'
})
}
})
},
編譯之后,點擊開發(fā)者工具欄的預(yù)覽,微信掃描二維碼,然后給以上input填充數(shù)據(jù)并點擊創(chuàng)建聯(lián)系人,就可以把數(shù)據(jù)存儲到手機里了。
多寫回調(diào)函數(shù)success()、fail(),并在里面添加消息提示框wx.showToast()能夠大大增強用戶的體驗。在編程時多寫console.log,多寫回調(diào)函數(shù),可以讓我們對程序的運行進行診斷,這一點非常重要。不過為了教學(xué)方便,我們后面會少寫回調(diào)函數(shù)。
前面我們已經(jīng)介紹過數(shù)組的拓展運算符,對象的擴展運算符 ...也有類型的作用,它可以取出對象里所有可遍歷的屬性,拷貝到新的對象中。為了可以看得更加清楚,我們可以進行打印對比:
submitContact:function(e) {
const formData = e.detail.value
console.log('打印formData對象',formData)
console.log('擴展運算符打印', { ...formData })
},
盡管打印的結(jié)果好像并沒有區(qū)別,但是formData是一個變量,我們把對象賦值給了它,打印它的結(jié)果就是一個對象了,而 { ...formData }本身就是一個對象,相當(dāng)于把formData對象里的屬性和值給拷貝到了新的對象里面。
小任務(wù):把wx.addPhoneContact()里的…formData換成formData,看看什么結(jié)果?把…formData換成lastName,又是什么結(jié)果?為什么寫lastName會報錯,而寫formData不會報錯?
在form表單里,盡管表單里也有input組件,但是綁定事件處理函數(shù)的是form組件,input組件只提供value值,而input文本輸入組件本身也是可以綁定事件處理函數(shù)的。從技術(shù)文檔里我們了解到input可以綁定事件處理函數(shù)的屬性有:bindinput,鍵盤輸入時觸發(fā);bindfocus,輸入框聚焦時觸發(fā);bindblur,輸入框失焦時觸發(fā)等等,這里主要介紹一下bindinput。
使用開發(fā)者工具在form.wxml里輸入以下代碼,這里使用input的bindinput綁定的事件處理函數(shù)bindKeyInput(函數(shù)名可以自己命名),
<view>你輸入的是:{{inputValue}}</view>
<input bindinput="bindKeyInput" placeholder="輸入的內(nèi)容會同步到view中"/>
在Page的data里我們添加inputValue的初始值,
data: {
inputValue: '你還沒輸入內(nèi)容呢'
},
編譯之后,我們就可以看到data里的值渲染到了頁面,這是我們前面學(xué)過的知識。
我們再在form.js里給input綁定的事件處理函數(shù)bindKeyInput添加如下代碼(聲明一個和data里的屬性相同的變量名inputValue,并賦值,setData可以簡寫,本節(jié)就有了解過哈)
bindKeyInput: function (e) {
const inputValue = e.detail.value
console.log('響應(yīng)式渲染',e.detail)
this.setData({
inputValue
})
},
編譯之后,我們再在input里面填寫內(nèi)容,注意此時我們寫的內(nèi)容會實時渲染到頁面上,無論是添加內(nèi)容還是刪除內(nèi)容,都可以做出同步響應(yīng)。而在控制臺Console,我們也可以看到每輸入/刪除一個字符,實時的打印結(jié)果,其中cursor是focus時的光標(biāo)位置。
注意:回憶一下我們之前的數(shù)據(jù)渲染,有直接初始化寫在Page的data里,有使用頁面生命周期和button的方式來觸發(fā)事件處理函數(shù)用setData改變數(shù)據(jù)來渲染,也有form表單數(shù)據(jù)收集,這些數(shù)據(jù)渲染都沒有做到響應(yīng)式,也就是在不刷新頁面的情況下,數(shù)據(jù)會實時根據(jù)你的修改而渲染。
本節(jié)前面的添加手機聯(lián)系人是把收集到的數(shù)據(jù)存儲到本地手機的通訊錄里,而剪切板則是把數(shù)據(jù)存儲到本地手機的剪切板里。
技術(shù)文檔:設(shè)置剪切板內(nèi)容wx.setClipboardData()、獲取剪切板內(nèi)容wx.getClipboardData()
使用開發(fā)者工具在form.wxml輸入以下代碼:
<input type="text" name="copytext" value="{{initvalue}}" bindinput="valueChanged"></input>
<input type="text" value="{{pasted}}"></input>
<button type="primary" bindtap="copyText">復(fù)制</button>
<button bindtap="pasteText">粘貼</button>
然后在Page的data里我們添加initvalue、pasted的初始值,
data: {
initvalue: '填寫內(nèi)容復(fù)制',
pasted: '這里會粘貼復(fù)制的內(nèi)容',
},
然后在form.js中添加input綁定的事件處理函數(shù)valueChanged、button組件綁定的兩個事件處理函數(shù)copyText、pasteText:
valueChanged(e) {
this.setData({
initvalue: e.detail.value
})
},
copyText() {
wx.setClipboardData({
data: this.data.initvalue,
})
},
pasteText() {
const self = this
wx.getClipboardData({
success(res) {
self.setData({
pasted: res.data
})
}
})
},
在input里面輸入內(nèi)容,內(nèi)容會響應(yīng)渲染到頁面,點擊復(fù)制按鈕,copyText事件處理函數(shù)會調(diào)用API把數(shù)據(jù)賦值給剪切板的data(注意這里的data不是page頁面的data,是wx.setClipboardData API的屬性),而點擊粘貼按鈕,事件處理函數(shù)pasteText會調(diào)用接口,把回調(diào)函數(shù)res里面的數(shù)據(jù)賦值給Page頁面data里的pasted,而且頁面在沒有刷新的情況下實時地把data里的pasted給渲染了出來。
小任務(wù):上面我們用到的是input的value屬性,將value改成placeholder,對比一下兩者有什么不同。前面我們說過,剪切板是把數(shù)據(jù)存儲到了本地手機的剪切板里,使用預(yù)覽在手機里打開小程序復(fù)制內(nèi)容之后,再到微信聊天界面,使用粘貼看看效果。或者在手機上復(fù)制一段內(nèi)容,然后打開小程序點擊粘貼,看看有什么效果。
slider滑動選擇器也可以綁定事件處理函數(shù),有:bindchange完成一次拖動后觸發(fā)的事件以及bindchanging拖動過程中觸發(fā)的事件。
技術(shù)文檔:滑動選擇器slider
我們要先回顧一下事件對象里data-攜帶的數(shù)據(jù)和表單組件攜帶的數(shù)據(jù):首先組件data-屬性的數(shù)據(jù)會存儲在事件對象里的currentTarget下的dataset里的屬性名里,也就是data-color的值會存儲在 e.currentTarget.dataset.color里;而表單組件的數(shù)據(jù)則是存儲在事件對象的detail里,也就是e.detail.value里。
使用開發(fā)者工具在form.wxml里輸入以下代碼,這里會既涉及到data-*攜帶的數(shù)據(jù),也會涉及到表單組件攜帶的數(shù)據(jù):
<view style="background-color:rgb({{R}},{{G}},{{B}});width:300rpx;height:300rpx"></view>
<slider data-color="R" value='{{R}}' max="255" bindchanging='colorChanging' show-value>紅色</slider>
<slider data-color="G" value='{{G}}' max="255" bindchanging='colorChanging' show-value>綠色</slider>
<slider data-color="B" value='{{B}}' max="255" bindchanging='colorChanging' show-value>藍色</slider>
然后在Page的data里我們添加R、G、B的初始值(不了解RGB顏色值的童鞋可以搜索一下,它們的取值在0~255之間),這里的R、G、B初始值既是background-color的三個顏色的初始值,也是滑動選擇器的初始值,我們把它設(shè)置為綠色(小程序技術(shù)文檔的VI色)
data: {
R:7,
G:193,
B:96,
},
然后在form.js里添加slider組件綁定的事件處理函數(shù)colorChanging:
colorChanging(e) {
console.log(e)
let color = e.currentTarget.dataset.color
let value = e.detail.value;
this.setData({
[color]: value
})
},
編譯之后,當(dāng)我們滑動slider,view組件的背景顏色也會隨之改變。當(dāng)滑動slider時,colorChanging因為滑動的拖動會不斷觸發(fā)(類似于英文里的ing的狀態(tài),實時監(jiān)聽),也就會在控制臺Console里打印多個值,e.detail.value為拖動的值,而e.currentTarget.dataset.color始終只會有三個結(jié)果R、G、B,而[color]: value就是把值賦值給R、G、B這三個值。
picker滾動選擇器看起來樣式非常復(fù)雜,不過小程序已經(jīng)幫我們封裝好了,我們只需要用幾行簡單的代碼就可以做一個非常復(fù)雜而且類別多樣的滾動選擇器。
技術(shù)文檔:滾動選擇器picker
使用開發(fā)者工具在form.wxm里輸入以下代碼,只需要下面幾行代碼,就能從底部彈起一個日期的滾動選擇器。而里面的文字可以任意填寫,類似于button、navigator組件里的字,點擊即可執(zhí)行相應(yīng)的事件。
<picker mode="date" value="{{pickerdate}}" start="2017-09-01" end="2022-09-01" bindchange="bindDateChange">
選擇的日期為:{{pickerdate}}
</picker>
然后在Page的data里我們添加pickerdate的初始值
data: {
pickerdate:"2019-8-31",
},
然后在form.js中添加picker組件綁定的事件處理函數(shù)bindDateChange,我們先打印看看picker組件的事件對象:
bindDateChange: function (e) {
console.log('picker組件的value', e.detail.value)
},
編譯之后,當(dāng)我們彈起滾動選擇器時,日期選擇器默認(rèn)會指向初始值2019年8月31日,而當(dāng)我們滑動選擇一個日期確定之后,可以在控制臺console里看到選擇的日期。這個日期是一個字符串。
小任務(wù):那我們要如何把選擇的日期比如2019-10-21,從這里取出年月日呢(也就是2019、10、21)?這個就涉及到字符串的操作了,還記得字符串的操作么?可以看MDN技術(shù)文檔之JavaScript標(biāo)準(zhǔn)庫之String,取出具體數(shù)字的方法有很多種,你知道應(yīng)該怎么處理嗎?
在這個章節(jié)里,我們講了數(shù)據(jù)可以存儲到本地手機里,在后面的章節(jié),我們還會講數(shù)據(jù)存儲的其他方式,比如緩存、數(shù)據(jù)庫等。有沒有感覺到編程就是邏輯處理、調(diào)用API和玩弄數(shù)據(jù)…
更多建議: