0 前言
本文將介紹如何使用微信小程序編寫動態(tài)表單,最終實現(xiàn)房屋租賃系統(tǒng)中多租客錄入的業(yè)務(wù)。
在閱讀本文前,您需要對微信小程序的開發(fā)有一個初步的了解,以便更容易的學(xué)會開發(fā)動態(tài)表單。
作者主頁:Designer 小鄭
作者簡介:浙江某公司軟件工程師,負責(zé)開發(fā)管理公司OA、CRM業(yè)務(wù)系統(tǒng),全棧領(lǐng)域優(yōu)質(zhì)創(chuàng)作者,CSDN學(xué)院、藍橋云課認證講師,開發(fā)過20余個前后端分離實戰(zhàn)項目,主要發(fā)展方向為Vue、SpringBoot、微信小程序,期待你我共同成長!
主打方向:Vue、SpringBoot、微信小程序
1 什么是表單
表單是一種數(shù)據(jù)采集工具,可以用來收集或呈現(xiàn)數(shù)據(jù)或者特定字段,可運用到不同的業(yè)務(wù)場景中,如調(diào)查問卷等。
簡單來說,表單就是收集用戶數(shù)據(jù)的主要方式,通過在線采集信息并且一鍵生成想要的數(shù)據(jù),如下圖所示。
還有一個概念是表格,表格和表單有著一定的區(qū)別和聯(lián)系。
-
表單:主要用于搜集信息。
-
表格:主要用來存放數(shù)據(jù)。
當(dāng)然還有更加花里胡哨的表單,一些主流的組件庫都支持單選框、多選框、下拉選擇框、開關(guān)、滑塊等表單組件,如下圖所示。
2 何為動態(tài)表單
動態(tài)表單顧名思義就是動態(tài)的表單,也就是表單的個數(shù)不是固定的,而是由具體的業(yè)務(wù)去決定。
比如對于一個房屋租賃系統(tǒng),在登記某個房間的租客數(shù)據(jù)時,甲方往往會要求在一個界面中完成所有租客數(shù)據(jù)的登記,如下圖所示。
用戶添加完成主租客后,還需要錄入從租客的數(shù)據(jù),并且從租客的數(shù)量不固定。
我們點擊了“新增從租客”按鈕,系統(tǒng)自動渲染出一個子表單界面,如下圖所示。
再次點擊,繼續(xù)新增,如下圖所示。
再次點擊,繼續(xù)新增,如下圖所示。
如果添加多了,還需要可以點擊每一個子表單的刪除按鈕,實現(xiàn)局部刪除,如下圖所示。
3 動態(tài)表單的實現(xiàn)
實現(xiàn)上面介紹的動態(tài)表單,總體來說分為以下三個步驟
- 編寫添加按鈕
- 編寫一個子表單
- 使用 wx:for 語法實現(xiàn)循環(huán)渲染
- 表單提交
接下來我們逐一講解。
3.1 編寫添加按鈕
第一步非常簡單,新建一個按鈕即可,界面代碼如下所示。
<button type="primary" bindtap="addCongItem" class='weui-btn weui-btn_primary'>新增從租客</button>
在實現(xiàn)動態(tài)表單之前首先建立一個數(shù)組變量,如下所示。
const app = getApp();
Page({
data: {
congList: []
},
})
點擊按鈕后,我們需要初始化一個子表單界面,也就是 new 一個 item 子項,其中表單的房間 ID、起租時日期、終止日期要被初始化,如下所示。
addCongItem() {
var newDate = new Date();
var item = {
lesseeName: "",
lesseeMobile: "",
lesseeCard: "",
photo: "",
registerDate: newDate.getFullYear() + "-" + (newDate.getMonth() < 9 ? "0" + (newDate.getMonth() + 1) : (newDate.getMonth() + 1)) + "-" + (newDate.getDate() < 10 ? "0" + newDate.getDate() : newDate.getDate()),
outDate: (newDate.getFullYear() + 1) + "-" + (newDate.getMonth() < 9 ? "0" + (newDate.getMonth() + 1) : (newDate.getMonth() + 1)) + "-" + (newDate.getDate() < 10 ? "0" + newDate.getDate() : newDate.getDate()),
roomId: JSON.parse(app.data.addRoomObj)
};
var list = this.data.congList;
list.push(item);
this.setData({
congList: list
})
console.log(this.data.congList);
},
3.2 編寫一個子表單
子表單的界面如下圖所示,包括租賃人的姓名、電話、身份證和人臉信息。
簡單分析一下界面,第一行是一個靜態(tài)文本,即 請登記從租客 N 的信息
,和一個刪除按鈕,這個直接使用循環(huán)編譯語法讀取下標(biāo)即可。
代碼如下所示。
<view class="weui-cells__title tishi">
請登記從租客 N 的信息:
<button type="warn" size="mini" class='buttomm' bindtap="deleteCongItem">刪除</button>
</view>
第二行是姓名表單,普普通通的一個輸入框即可。
<view class="weui-cell weui-cell_active hang">
<view class="weui-cell__hd"><label class="weui-label">姓名</label></view>
<view class="weui-cell__bd">
<input class="weui-input" placeholder="從租客姓名" bindblur="lesseeName2" value="張三" placeholder-class="weui-input__placeholder" />
</view>
</view>
第三行是電話表單,也是普普通通的一個輸入框即可。
<view class="weui-cell weui-cell_active hang">
<view class="weui-cell__hd"><label class="weui-label">電話</label></view>
<view class="weui-cell__bd">
<input class="weui-input" placeholder="從租客電話" bindblur="lesseeMobile2" value="17800000001" placeholder-class="weui-input__placeholder" />
</view>
</view>
第四行是身份證表單,更是普普通通的一個輸入框即可。
<view class="weui-cell weui-cell_active hang">
<view class="weui-cell__hd"><label class="weui-label">身份證</label></view>
<view class="weui-cell__bd">
<input class="weui-input" placeholder="從租客身份證" bindblur="lesseeCard2" value="330200200001010000" placeholder-class="weui-input__placeholder" />
</view>
</view>
前面三個輸入型表單,都需要將用戶輸入的值綁定到某個變量,這時就需要用到一個變化監(jiān)聽事件。
如身份證的 input 表單中,有 bindblur="lesseeCard2"
的屬性復(fù)制,也就是當(dāng)這個輸入框的數(shù)據(jù)發(fā)生變化時,會執(zhí)行 lesseeCard2
事件。
lesseeCard2: function (e) {
this.setData({
lesseeCard2: e.detail.value
})
},
這樣就可以間接實現(xiàn)數(shù)據(jù)的雙向綁定。
第五行是人臉上傳,這是一個文件上傳,可以分為上傳按鈕和上傳圖片的預(yù)覽框,界面代碼如下圖所示。
<view class='upload_img'>
<view class='upload_img_btn'>
<view class='title'>
<view class='shu'></view>
<text>人臉</text>
</view>
<button type="primary" bindtap="chooseImageItem" data-itemid="{{idx}}" class='btn'>添加</button>
</view>
<view wx:if="{{item.photo != ''}}" class='img_box' id='imgs' style='display:flex;justify-content: space-between;padding-top:10px;'>
<view class="q-image-wrap imgs">
<image class="q-image" src="{{item.photo}}" mode="aspectFit" data-idx="{{item.photo}}" bindtap="handleImagePreviewItem"></image>
<view class="q-image-remover delete" data-idx="{{idx}}" bindtap="removeImageItem">刪除</view>
</view>
</view>
</view>
上傳后的預(yù)覽效果如下圖所示。
在用戶點擊 添加
按鈕時,觸發(fā) chooseImageItem
方法,調(diào)用系統(tǒng)的相冊選擇,代碼如下圖所示。
chooseImageItem: function (e) {
var that = this;
var itemId = e.currentTarget.dataset.itemid;
wx.chooseImage({
sizeType: ['compressed'], //可選擇原圖或壓縮后的圖片
sourceType: ['camera'],
// sourceType: ['album', 'camera'], //可選擇性開放訪問相冊、相機
success: res => {
console.log(res.tempFilePaths);
console.log(res.tempFilePaths[0]);
that.uploadImageItem(res.tempFilePaths[0], itemId);
}
})
},
其中 uploadImageItem
是自己實現(xiàn)的上傳圖片方法,即將用戶上傳到微信的臨時性圖片持久化存儲到自己的業(yè)務(wù)系統(tǒng),最終返回一個圖片網(wǎng)址(即字符串,回寫到圖片數(shù)組中)。
uploadImageItem(e, itemId) {
var that = this;
wx.uploadFile({
url: app.data.appUrl + '/upload/uploadAppletImages?g=api&m=banana&a=upload_info',
filePath: e,
method: 'GET',
name: 'file',
header: {
"Content-Type": "application/x-www-form-urlencoded",
'accessToken': app.data.token
},
success: function (res) {
console.log(JSON.parse(res.data));
var imageUrl = JSON.parse(res.data).result;
if(imageUrl == undefined) {
imageUrl = res.data.result;
}
var list = that.data.congList;
list[itemId].photo = imageUrl;
console.log(list);
that.setData({
congList: list
})
},
fail: function (res) {
console.log(res);
},
})
},
3.3 使用 wx:for 語法實現(xiàn)循環(huán)渲染
在 Vue
中可以使用 v-for
實現(xiàn)循環(huán)渲染,在微信小程序中也一樣可以。
在組件上使用 wx:for 控制屬性綁定一個數(shù)組,即可使用數(shù)組中各項的數(shù)據(jù)重復(fù)渲染該組件。
默認數(shù)組的當(dāng)前項的下標(biāo)變量名默認為 index,數(shù)組當(dāng)前項的變量名默認為 item。
比如有一個租客數(shù)組 leaveList
,其中姓名字段為 name,就可以這么去表示。
<view wx:for="{{leaveList}}">
租客{{index}}: {{item.name}}
</view>
我們可以用 wx:for-item
可以指定租賃數(shù)組當(dāng)前元素的別名,下面的代碼執(zhí)行效果等同于上面。
<view wx:for="{{leaveList}}" wx:for-item="myItem">
租客{{index}}: {{myItem.name}}
</view>
我們可以用 wx:for-index
可以指定數(shù)組當(dāng)前下標(biāo)的變量名,下面的代碼執(zhí)行效果等同于上面。
<view wx:for="{{leaveList}}" wx:for-index="myIndex">
租客{{myIndex}}: {{item.name}}
</view>
另外在循環(huán)渲染時還需要提供一個 wx:key
,文檔說明如下。
如果列表中項目的位置會動態(tài)改變或者有新的項目添加到列表中,并且希望列表中的項目保持自己的特征和狀態(tài)(如 input 中的輸入內(nèi)容,switch 的選中狀態(tài)),需要使用 wx:key 來指定列表中項目的唯一的標(biāo)識符。
如不提供 wx:key,會報一個 warning, 如果明確知道該列表是靜態(tài),或者不必關(guān)注其順序,可以選擇忽略
所以我們需要改造成這樣:
<view wx:for="{{leaveList}}" wx:key="index">
租客{{index}}: {{item.name}}
</view>
我們最終的目標(biāo)是實現(xiàn)從租客的循環(huán)渲染,所以只需要在第二步的代碼上套一層循環(huán),代碼如下所示。
<view class="box" wx:for="{{congList}}" wx:for-item="item" wx:for-index="idx" wx:key="idx">
<view class="weui-cells__title tishi">
請登記從租客{{idx + 1}}的信息:
<button type="warn" size="mini" class='buttomm' bindtap="deleteCongItem" data-idx="{{idx}}">刪除</button>
</view>
<!-- 開始 -->
<view class="weui-cell weui-cell_active hang">
<view class="weui-cell__hd"><label class="weui-label">姓名</label></view>
<view class="weui-cell__bd">
<input class="weui-input" placeholder="從租客姓名" data-itemid="{{idx}}" bindblur="lesseeName2" value="{{item.lesseeName}}" placeholder-class="weui-input__placeholder" />
</view>
</view>
<!-- 結(jié)尾 -->
<!-- 開始 -->
<view class="weui-cell weui-cell_active hang">
<view class="weui-cell__hd"><label class="weui-label">電話</label></view>
<view class="weui-cell__bd">
<input class="weui-input" placeholder="從租客電話" data-itemid="{{idx}}" bindblur="lesseeMobile2" value="{{item.lesseeMobile}}" placeholder-class="weui-input__placeholder" />
</view>
</view>
<!-- 結(jié)尾 -->
<!-- 開始 -->
<view class="weui-cell weui-cell_active hang">
<view class="weui-cell__hd"><label class="weui-label">身份證</label></view>
<view class="weui-cell__bd">
<input class="weui-input" placeholder="從租客身份證" data-itemid="{{idx}}" bindblur="lesseeCard2" value="{{item.lesseeCard}}" placeholder-class="weui-input__placeholder" />
</view>
</view>
<!-- 結(jié)尾 -->
<view class='upload_img'>
<view class='upload_img_btn'>
<view class='title'>
<view class='shu'></view>
<text>人臉</text>
</view>
<button type="primary" bindtap="chooseImageItem" data-itemid="{{idx}}" class='btn'>添加</button>
</view>
<view wx:if="{{item.photo != ''}}" class='img_box' id='imgs' style='display:flex;justify-content: space-between;padding-top:10px;'>
<view class="q-image-wrap imgs">
<image class="q-image" src="{{item.photo}}" mode="aspectFit" data-idx="{{item.photo}}" bindtap="handleImagePreviewItem"></image>
<view class="q-image-remover delete" data-idx="{{idx}}" bindtap="removeImageItem">刪除</view>
</view>
</view>
</view>
</view>
對于數(shù)據(jù)的雙向綁定,以姓名為例,代碼如下所示。
<view class="weui-cell weui-cell_active hang">
<view class="weui-cell__hd"><label class="weui-label">姓名</label></view>
<view class="weui-cell__bd">
<input class="weui-input" placeholder="從租客姓名" data-itemid="{{idx}}" bindblur="lesseeName2" value="{{item.lesseeName}}" placeholder-class="weui-input__placeholder" />
</view>
</view>
使用 data-itemid="{{idx}}"
語法,可以將當(dāng)前下標(biāo)值作為 itemid
參數(shù),傳到 lesseeName2
事件中,事件的代碼如下所示。
lesseeName2: function (e) {
console.log(e);
var itemId = e.currentTarget.dataset.itemid;
var list = this.data.congList;
list[itemId].lesseeName = e.detail.value;
this.setData({
congList: list
})
},
首先根據(jù)下標(biāo)讀取到當(dāng)前子表單的數(shù)據(jù),然后賦值,最后再會寫,完成雙向數(shù)據(jù)綁定操作。
3.4 表單提交
當(dāng)表單的數(shù)據(jù)全部輸入完成,也綁定到相應(yīng)的變量后,就可以對表單數(shù)據(jù)進行提交,由后端持久化到數(shù)據(jù)庫。
對于提交按鈕,只是一個普普通通的按鈕,一行代碼即可。
<button type="primary" bindtap="addTenant" loading="{{submitLoading}}" disabled="{{submitLoading}}" class='weui-btn weui-btn_primary'>提交</button>
用戶點擊提交按鈕后,首先需要對數(shù)據(jù)進行判空,如果沒問題了直接傳到 API 接口,繼續(xù)下步的業(yè)務(wù)邏輯,相關(guān)代碼如下所示。
addTenant: function () {
var that = this;
if (that.data.lesseeName == '') {
wx.showToast({
title: '租賃人姓名為空',
icon: "none"
})
} else if (that.data.lesseeMobile == '') {
wx.showToast({
title: '租賃人電話為空',
icon: "none"
})
} else if (that.data.lesseeCard == '') {
wx.showToast({
title: '租賃人身份證為空',
icon: "none"
})
}
else if (that.data.images2.length < 1) {
wx.showToast({
title: '請上傳租客人臉',
icon: "none"
})
} else {
that.setData({
submitLoading: true
})
wx.showLoading({});
var form = {};
form.lesseeName = that.data.lesseeName;
form.lesseeMobile = that.data.lesseeMobile;
form.lesseeSex = that.data.sexList[that.data.sexIndex];
form.mainFlag = that.data.mainList[that.data.mainIndex];
form.lesseeCard = that.data.lesseeCard;
form.province = that.data.province;
form.city = that.data.city;
form.county = that.data.county;
form.lesseeAddress = that.data.lesseeAddress;
form.workUnit = that.data.workUnit;
form.address = that.data.address;
form.roomId = that.data.roomId;
form.registerDate = that.data.registerDate;
form.outDate = that.data.outDate;
form.photo = that.data.images2[0];
form.leaseContract = that.data.images[0];
form.remark = that.data.remark;
form.roomId = that.data.roomId;
form.auditMessage = JSON.stringify(this.data.congList);
wx.request({
url: app.data.appUrl + '/leaseRecord/insertOnApp',
method: 'POST',
data: form,
header: {
"Content-Type": "application/x-www-form-urlencoded",
'accessToken': app.data.token
},
success(res) {
console.log(res);
if (res.data.success) {
that.setData({
errMsg: ""
})
wx.showModal({
title: "登記成功",
content: "租客登記成功,請等待審核!是否返回房間頁面?",
success() {
if (res.confirm) {
} else {
wx.navigateBack({
delta: 1,
})
}
}
})
} else {
that.setData({
errMsg: res.data.message
})
wx.showToast({
title: "添加失敗",
icon: "error"
})
}
},
complete: function () {
wx.hideLoading();
that.setData({
submitLoading: false
})
}
})
}
},
4 總結(jié)
本文將介紹如何使用微信小程序編寫動態(tài)表單,最終實現(xiàn)房屋租賃系統(tǒng)中多租客錄入的業(yè)務(wù)。
業(yè)務(wù)驅(qū)動式學(xué)習(xí)是一種高效的學(xué)習(xí)方法,希望同學(xué)們不要只埋頭于技術(shù)上,多多關(guān)注一些業(yè)務(wù)場景,因為業(yè)務(wù)和技術(shù)同等重要!文章來源:http://www.zghlxwxcb.cn/news/detail-493558.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-493558.html
到了這里,關(guān)于微信小程序的動態(tài)表單,實現(xiàn)房屋租賃的多租客錄入的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!