從微信小程序到鴻蒙JS開發(fā)-表單組件&注冊(cè)登錄模塊
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
https://harmonyos.51cto.com/#zz
牛年將至,祝大家行行無bug,頁頁so easy~
在微信小程序中,提供了form組件,可以將input、picker、slider、button等全部放在form中,并設(shè)置name屬性實(shí)現(xiàn)類似html的表單提交功能。
鴻蒙js目前是沒有form組件的,因此我們需要在提交時(shí)手動(dòng)獲取輸入框、選擇框等的值,自行構(gòu)建數(shù)據(jù)對(duì)象。
1、登錄模塊
這里接著上一篇,通過dialog組件實(shí)現(xiàn)了模態(tài)登錄和注冊(cè)的窗口。登錄窗口的效果如下:
每一行中,放置圖標(biāo)和input輸入框。input使用的是默認(rèn)樣式,看起來還是很清爽的。
hml視圖層:
- <dialog id="loginDialog">
- <div class="loginDialog">
- <div class="formItem">
- <image src="{{ phone ? (imgUrl + 'phone.png') : (imgUrl + 'phone1.png') }}"></image>
- <input id="phoneInput" type="number" placeholder="請(qǐng)輸入手機(jī)號(hào)" onchange="inputPhone"></input>
- </div>
- <div class="formItem">
- <image src="{{ pwd ? (imgUrl + 'password.png') : (imgUrl + 'password1.png') }}"></image>
- <input id="pwdInput" type="password" placeholder="請(qǐng)輸入密碼" onchange="inputPwd"></input>
- </div>
- <button class="inputBtn" onclick="login">登錄</button>
- </div>
- </dialog>
手機(jī)號(hào)的input設(shè)置type="number",在獲取焦點(diǎn)后鍵盤自動(dòng)彈出為數(shù)字鍵盤。密碼框type="password",彈出普通鍵盤,且輸入的字符會(huì)變?yōu)閳A點(diǎn),也可點(diǎn)擊右側(cè)眼睛圖標(biāo)查看密碼內(nèi)容。
在最開始使用input時(shí),嘗試使用this.$element("id").value獲取,但這樣是獲取不到的。
- // 登錄
- login() {
- prompt.showToast({
- message: "手機(jī)號(hào): " + this.$element("phoneInput").value +
- ", 密碼: " + this.$element("pwdInput").value,
- duration: 5000
- })
- }
因此需要使用input的onchange屬性綁定值改變的事件,通過e.value取到改變后的值,并賦給data中的變量。
順便提一下,今天突然找到了console打印日志的查看方式。需在最下方打開"HiLog"視圖,搜索"app Log"后即可查看。console.log()的內(nèi)容需設(shè)置日志等級(jí)"debug",console.info()則在"info"等級(jí)即可查看。
- // 手機(jī)號(hào)輸入框
- inputPhone(e) {
- this.phone = e.value;
- },
- // 密碼輸入框
- inputPwd(e) {
- this.pwd = e.value;
- },
- // 登錄
- login() {
- console.log("手機(jī)號(hào): " + this.phone + "密碼: " + this.pwd);
- }
這里能夠正常獲取輸入框的值了,就可以在點(diǎn)擊按鈕后將值傳給后臺(tái)服務(wù)器,進(jìn)行登錄的校驗(yàn)。按鈕的點(diǎn)擊方法通過onclick進(jìn)行綁定。
- // 登錄
- login() {
- fetch.fetch({
- url: this.url + "/litemall/user/login?phone=" + this.phone + "&pwd=" + this.pwd,
- responseType: "json",
- success: res => {
- let data = JSON.parse(res.data);
- console.info(JSON.stringify(data));
- if (0 != data.code) {
- prompt.showToast({
- message: data.msg,
- duration: 3000
- })
- } else {
- let userInfo = data.data;
- userInfo.age = this.getAge(userInfo.birthday);
- this.userInfo = userInfo;
- this.$element("loginDialog").close();
- }
- }
- })
- }
登錄失敗,用提示框提示用戶失敗原因:
登錄成功,用戶信息賦值給頁面并關(guān)閉dialog:
這里日志的打印需要使用JSON.stringify(),否則會(huì)打印"object"。
input組件和button組件都提供了豐富的type可供選擇,具體可參考官方文檔。
https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-components-basic-input-0000000000611673
css渲染層:
- .loginDialog {
- width: 80%;
- height: 400px;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- }
- .formItem {
- width: 100%;
- height: 100px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-bottom: 20px;
- }
- .formItem>image {
- width: 70px;
- height: 70px;
- margin: 0 10px 0 10px;
- }
- input {
- flex: 1;
- }
- .inputBtn {
- width: 200px;
- height: 70px;
- }
2、注冊(cè)模塊
注冊(cè)模塊同樣使用dialog彈窗,內(nèi)容比登錄要更豐富一些:
hml視圖層:
- <dialog id="registerDialog">
- <div class="registerDialog">
- <div class="formItem">
- <image src="{{ phone ? (imgUrl + 'phone.png') : (imgUrl + 'phone1.png') }}"></image>
- <input type="number" placeholder="請(qǐng)輸入手機(jī)號(hào)" onchange="inputPhone"></input>
- </div>
- <div class="formItem">
- <image src="{{ pwd ? (imgUrl + 'password.png') : (imgUrl + 'password1.png') }}"></image>
- <input type="password" placeholder="請(qǐng)輸入密碼" onchange="inputPwd"></input>
- </div>
- <div class="formItem">
- <image src="{{ username ? (imgUrl + 'username.png') : (imgUrl + 'username1.png') }}"></image>
- <input type="text" placeholder="請(qǐng)輸入姓名" onchange="inputUsername"></input>
- </div>
- <div class="formItem">
- <image src="{{ nickname ? (imgUrl + 'nickname.png') : (imgUrl + 'nickname1.png') }}"></image>
- <input type="text" placeholder="請(qǐng)輸入昵稱" onchange="inputNickname"></input>
- </div>
- <div class="formItem">
- <image src="{{ genderVal ? (imgUrl + 'gender.png') : (imgUrl + 'gender1.png') }}"></image>
- <picker type="text" range="{{ genders }}" onchange="chooseGender">{{ gender }}</picker>
- </div>
- <div class="formItem">
- <image src="{{ birthdayVal ? (imgUrl + 'birthday.png') : (imgUrl + 'birthday1.png') }}"></image>
- <picker type="date" start="1900-1-1" selected="2000-1-1" onchange="chooseBirthday">{{ birthday }}</picker>
- </div>
- <button class="inputBtn" onclick="register">注冊(cè)</button>
- </div>
- </dialog>
上面四個(gè)依然是input輸入框,隨后兩個(gè)使用了picker選擇框組件。需注意,選擇框組件標(biāo)記中需放置文本內(nèi)容,通過點(diǎn)擊這里的文本在頁面下方彈出選擇框。
type="text"是文本選擇框,通過range屬性綁定一個(gè)字符串?dāng)?shù)組,效果如下:
onchange屬性綁定選擇一項(xiàng)后的處理方法,e.newValue是選項(xiàng)值,e.newSelected是選項(xiàng)下標(biāo)。
性別選擇框js邏輯層代碼:
- export default {
- data: {
- ...
- gender: "點(diǎn)擊選擇性別",
- genderVal: "",
- genders: ['保密', '男', '女'],
- ...
- },
- ...
- // 性別選擇器
- chooseGender(e) {
- this.gender = e.newValue;
- this.genderVal = e.newSelected;
- },
- ...
- }
type="date"是日期選擇器,可以通過屬性指定開始、結(jié)束、當(dāng)前日期,通過onchange綁定選擇后的處理方法。效果如下:
e.year/month/day分別為選擇的年/月/日,注意month比實(shí)際月份小1。
生日選擇框js邏輯層:
- export default {
- data: {
- ...
- birthday: "點(diǎn)擊選擇生日",
- birthdayVal: ""
- },
- ...
- // 生日選擇器
- chooseBirthday(e) {
- let month = (e.month + 1) + "";
- if (month.length == 1) {
- month = "0" + month;
- }
- let day = e.day + "";
- if (day.length == 1) {
- day = "0" + day;
- }
- let birthday = e.year + "-" + month + "-" + day;
- this.birthday = birthday;
- this.birthdayVal = birthday;
- },
- ...
- }
這里開發(fā)者工具有一個(gè)bug,type="date"在提示時(shí)錯(cuò)誤拼寫成了"data"。
選擇器還有time, datetime, multi-text三種,鴻蒙的封裝確實(shí)很好看好用。
注冊(cè)的方法:
- // 注冊(cè)
- register() {
- fetch.fetch({
- url: this.url + "/litemall/user/register",
- method: "POST",
- data: {
- username: this.username,
- password: this.pwd,
- gender: this.genderVal,
- birthday: this.birthdayVal,
- nickname: this.nickname,
- mobile: this.phone
- },
- header: {
- "Content-Type": "application/json;charset=UTF-8"
- },
- responseType: "json",
- success: res => {
- let data = JSON.parse(res.data);
- console.info(JSON.stringify(data));
- if (0 != data.code) {
- prompt.showToast({
- message: data.msg,
- duration: 3000
- });
- } else {
- prompt.showToast({
- message: "注冊(cè)成功",
- duration: 3000
- });
- this.$element("registerDialog").close();
- }
- }
- })
- }
還需要注意,如果使用fetch發(fā)送請(qǐng)求,且data給的是一個(gè)對(duì)象時(shí),請(qǐng)求頭的Content-Type自動(dòng)設(shè)置為application/x-www-form-urlencoded。如果服務(wù)器接收json數(shù)據(jù),則需要設(shè)置請(qǐng)求頭,否則會(huì)報(bào)如下錯(cuò)誤。
- Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported]
注冊(cè)一下:
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
https://harmonyos.51cto.com/#zz