微信小程序之表單頁(yè)面優(yōu)化

1、前言

長(zhǎng)表單錄入信息在業(yè)務(wù)系統(tǒng)中是非常常見(jiàn)的一個(gè)場(chǎng)景,然而長(zhǎng)表單加業(yè)務(wù)系統(tǒng),那流暢度,簡(jiǎn)直不忍直視。所以趁著現(xiàn)在空閑,想了一些關(guān)于長(zhǎng)表單頁(yè)面的優(yōu)化方案。

2、優(yōu)化方案一: 減少綁定方法

我們平時(shí)寫(xiě)小程序頁(yè)面的時(shí)候,可能會(huì)不太注意,會(huì)有這樣的寫(xiě)法。

<!-- html頁(yè)面 -->
<view class='content2'>
    <view class='item'>
      <text class='item_title'>姓名</text>
      <input  type='text' value ='{{name}}' bindinput ="getName"></input>
    </view>
    <view class='item'>
      <text class='item_title'>手機(jī)號(hào)</text>
      <input type='text' value ='{{phone}}' bindinput ="getPhone"></input>
    </view>
</view>


// js頁(yè)面如下
 getName(e){
    this.setData({
      name : e.detail.value
    })
  },

  getPhone(e){
    this.setData({
      name: e.detail.value
    })
  }
  // 其他 ....

表單少的時(shí)候還好,如果你想一下業(yè)務(wù)系統(tǒng)中,有些頁(yè)面有2/3十個(gè)字段呢?難道每個(gè)input都給一個(gè)相應(yīng)方法嗎?

不僅代碼重復(fù)多,而且js頁(yè)面中定義的方法過(guò)多占用內(nèi)存、占用體積、而且還導(dǎo)致代碼多閱讀困難等,而且哪一天如果要對(duì)輸入的內(nèi)容做檢查處理,就算可以把檢查的代碼抽象出來(lái),難道還要調(diào)用二三十次?

當(dāng)然,上一種方法也不是沒(méi)有優(yōu)點(diǎn),優(yōu)點(diǎn)就是:職責(zé)單一,哪天不小心把某個(gè)方法改bug也不影響其他的使用。

但從性能方面考慮,我們就可以對(duì)某一類(lèi)相似的輸入方法就行優(yōu)化,綁定同一個(gè)方法,像下面這樣:

<!-- html頁(yè)面 -->
<view class='content2'>
    <view class='item'>
      <text class='item_title'>姓名</text>
      <input  type='text' value ='{{name}}' data-type="name" bindinput ="getValue"></input>
    </view>
    <view class='item'>
      <text class='item_title'>手機(jī)號(hào)</text>
      <input type='text' value ='{{phone}}' data-type="phone" bindinput ="getValue"></input>
    </view>
</view>


// js頁(yè)面如下
  getValue(res){
    let type = res.currentTarget.dataset.type;
    switch(type)
    {
      case 'name':
        this.setData({
          name : res.detail.value
        })
      break;

      case 'phone':
        this.setData({
          phone : res.detail.value
        })
      break;

      // 其他...

      default:
      break;
    }
  },
  // 其他 ....

3、優(yōu)化方案二: 不使用this.setData

在方案一中,我們主要針對(duì)長(zhǎng)表單頁(yè)面進(jìn)行了簡(jiǎn)單的優(yōu)化,而事實(shí)上你優(yōu)化后運(yùn)行,也感覺(jué)不出性能有什么提升,但從邏輯上來(lái)說(shuō),性能確實(shí)提升了一些,只是效果不明顯而已。

而方案二,才是優(yōu)化的重點(diǎn)。

想想,我們?cè)趘ue中一般都是使用雙向數(shù)據(jù)綁定,vue幫我們處理了許多邏輯。而在小程序中,頁(yè)面并不是雙向數(shù)據(jù)綁定的,而且由于小程序中獲取不到dom節(jié)點(diǎn),我們無(wú)法在點(diǎn)提交的時(shí)候才去獲取各個(gè)input里的值,所以我們一般都會(huì)習(xí)慣性地把各個(gè)input的值存入data中,每次存數(shù)據(jù)到data中都要調(diào)用this.setData這個(gè)方法,并且由于小程序雙線(xiàn)程的構(gòu)架,this.setData調(diào)用后,js邏輯線(xiàn)程就會(huì)通知渲染線(xiàn)程去渲染數(shù)據(jù)更新頁(yè)面,而2個(gè)線(xiàn)程之間的通信及渲染層渲染才是造成性能下降的罪魁禍?zhǔn)住?/strong>

比如,輸入名字中,我輸入一個(gè): 任 字。

由于使用拼音的緣故,我要輸入 ren,然后選擇 任 字。你在getValue()方法中打印一下,看getValue()被調(diào)用了多少次?

4次?。。?/p>

不僅是getValue()被調(diào)用了4次,this.setData()也被調(diào)用了4次!!

如果我要輸入的內(nèi)容超多,打字速度超快(20多年的手速...),然后你就會(huì)看到,頁(yè)面卡頓...

然后分析我們的wxml代碼,發(fā)現(xiàn)有一行 value = '{{name}}' 。

嗯??? 我們?yōu)槭裁匆O(shè)置這一行代碼?為了使頁(yè)面所渲染的數(shù)據(jù)和data中保持同步!但本身input數(shù)據(jù)是剛從渲染層(Input是原生組件,實(shí)際是native層,不過(guò)這不重要)傳遞到邏輯層,數(shù)據(jù)本身就是同步的了!?。?/strong>

所以,對(duì)于input這種輸入性標(biāo)簽,我們只需要保存數(shù)據(jù)就好了!而不用多此一舉再次通知渲染層渲染?。?!

如果我們不需要通知渲染層渲染,那就不需要用data來(lái)存儲(chǔ)數(shù)據(jù),那么代碼將會(huì)變成下面這樣:

<!-- html頁(yè)面 -->
<view class='content2'>
    <view class='item'>
      <text class='item_title'>姓名</text>
      <input  type='text' data-type='name' bindinput ="getValue"></input>
    </view>
    <view class='item'>
      <text class='item_title'>手機(jī)號(hào)</text>
      <input type='text'  data-type='phone' bindinput ="getValue"></input>
    </view>
    <view class='item'>
      <text class='item_title'>身份證</text>
      <input  type='text' bindinput ="getBankName"></input>
    </view>
</view>


//js頁(yè)面如下
data:{

},

// 這里才是核心!?。?// 本質(zhì)上Page()是一個(gè)方法,傳進(jìn)來(lái)的是一個(gè)對(duì)象,
// 那么既然能存在data,肯定也可以使用自定義mydata來(lái)存數(shù)據(jù)啦。
mydata:{
  phone:'',
  name:'',
  cardId:'',
  barnchName:'',
  bankCardNo:'',
  linkName:'',
  linkShip:'',
  linkPhone:''
},
getValue(res){
    let type = res.currentTarget.dataset.type;
  // 如果你不需要對(duì)輸入的內(nèi)容各自處理的話(huà),甚至還可以這樣做,
   // 這樣就可以去掉裹腳布一樣的switch了
   // this.mydata[type] = res.detail.value;
    switch(type)
    {
      case 'name':
        this.mydata.name = res.detail.value
      break;

      case 'phone':
        this.mydata.phone = res.detail.value
      break;

      default:
      break;
    }
  },

在這份代碼中,主要使用了mydata來(lái)存儲(chǔ)數(shù)據(jù),頁(yè)面顯示的就是用戶(hù)輸入的數(shù)據(jù),不過(guò)我們把數(shù)據(jù)備份了一份,同時(shí)切斷了他們之間的“同步”。就這樣,沒(méi)有了“同步”,沒(méi)有了this.setData(),也沒(méi)有了卡頓。

然后在下一步的方法中,打印一下數(shù)據(jù),發(fā)現(xiàn)數(shù)據(jù)也能完整取到,如下圖:

image.png

4、完整代碼

<!-- html -->
<!--pages/task/information/information.wxml-->
<!-- <view class='showTips' animation="{{animation}}">{{message}}</view> -->
<view class='container2'>
  <view class='pageItem'>
      <!-- <text>1/3</text> -->
      <view class='content2'>
        <view class='item'>
          <text class='item_title'>姓名</text>
          <input  type='text' data-type='name' bindinput ="getValue"></input>
        </view>
        <view class='item'>
          <text class='item_title'>手機(jī)號(hào)</text>
          <input type='text'  data-type='phone' bindinput ="getValue"></input>
        </view>
        <view class='item'>
          <text class='item_title'>身份證</text>
          <input  type='text' data-type='cardId' bindinput ="getValue"></input>
        </view>
        <!-- <view class='item'>
          <text class='item_title'>開(kāi)戶(hù)行</text>
           <select prop-array='{{myBankArr}}' bind:myget='getBank'></select> 
        </view> -->
        <view class='item'>
          <text class='item_title'>支行名稱(chēng)</text>
          <input  type='text' data-type='branchName' bindinput ="getValue" ></input>
          
        </view>
        <view class='item'>
          <text class='item_title'>銀行卡號(hào)</text>
          <input  type='text' data-type='cardNo' bindinput ="getValue"></input>
          
        </view>
        <view class='item'>
          <text class='item_title'>緊急聯(lián)系人</text>
          <input  type='text' data-type='linkName' bindinput ="getValue"></input>
          <!-- <text class='tips_1'>*</text> -->
        </view>
        <view class='item'>
          <text class='item_title'>聯(lián)系人關(guān)系</text>
          <input  type='text' data-type='linkShip' bindinput ="getValue"></input>
          <!-- <text class='tips_1'>*</text> -->
        </view>
        <view class='item'>
          <text class='item_title'>聯(lián)系人電話(huà)</text>
          <input  type='text' data-type='linkPhone' bindinput ="getValue" ></input>
          <!-- <text class='tips_1'>*</text> -->
        </view>
      </view>

      <button bindtap='next'>下一步</button>
  </view>
  <view class='pageItem'>
  </view>
  <view class='pageItem'>
  </view>
  <button bindtap='nextStep'>下一步</button>
</view>
// js
// pages/t
Page({

  mydata:{
    phone:'',
    name:'',
    cardId:'',
    barnchName:'',
    bankCardNo:'',
    linkName:'',
    linkShip:'',
    linkPhone:''
  },
  data: {
    isChecked: false,
    animation: {},
    message: '銀行卡必須是本人的,用作發(fā)傭金',
    myBankArr:[
      {
        "id": 0,
        "text": '中國(guó)招商銀行'
      },
      {
        "id": 1,
        "text": '中國(guó)工商銀行'
      },
      {
        "id": 2,
        "text": '中國(guó)農(nóng)業(yè)銀行'
      },
      {
        "id": 3,
        "text": '中國(guó)銀行'
      },
      {
        "id": 4,
        "text": '中國(guó)建設(shè)銀行'
      },
      {
        "id": 5,
        "text": '中國(guó)郵政儲(chǔ)蓄銀行'
      }
    ]
  },

  onLoad: function (options) {
  },
  onShow: function () {
  },

  getValue(res){
    let type = res.currentTarget.dataset.type;
    switch(type)
    {
      case 'name':
        this.mydata.name = res.detail.value
      break;

      case 'phone':
        this.mydata.phone = res.detail.value
      break;

      case 'cardId':
      break;

      case 'barnchName':
      break;

      case 'bankCardNo':
      break;

      case 'linkName':
      break;

      case 'linkShip':
      break;

      case 'linkPhone':
      break;
      
      default:
      break;
    }
  },
  next(){
    console.log(this.mydata)
  }
})
/* css 部分 */
/* pages/task/information/information.wxss */
page,view{
  margin: 0;
  padding: 0;
}
.showTips{
  position: absolute;
  left: 0;
  top: -70rpx;
  width: 750rpx;
  height: 70rpx;
  line-height: 70rpx;
  text-align: center;
  background-color: #c6d0e3;
  color: #00276f;
}
.container2{
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  padding: 0;
  overflow: hidden;
}

.pageItem{
  width: 750rpx;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
  flex-shrink: 0;
}

.content2{
  width: 100%;
  /* border-top: solid 2rpx #333;
  border-bottom: solid 2rpx #333; */
  padding-left: 20rpx;
}

.item{
  margin-top: 10rpx;
  padding: 10rpx 10rpx;
  width: 100%;
  /* margin: 25rpx 0; */
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  border-bottom: solid 2rpx #EDEDED;
}
.item_title{
  width: 150rpx;
  flex-shrink: 0;
  text-align: right;
  font-size: 28rpx;
}

.item > input{
  text-align: left;
  font-size: 34rpx;
  height: 60rpx;
  line-height: 60rpx;
  padding: 0 20rpx;
  width: 490rpx;
  /* border-radius: 10rpx; */
  
}

.item > select{
  text-align: left;
  font-size: 34rpx;
  height: 60rpx;
  line-height: 60rpx;
  padding: 0 20rpx;
  width: 490rpx;
  /* border-radius: 10rpx; */
  /* border-bottom: solid 2rpx #EDEDED; */
}

.inputPlace{
  font-size: 30rpx;
}

.tips_1{
  color: red;
  margin-left: 10rpx;
  width: 10rpx;
}

.tips{
  height: 33rpx;
  line-height: 33rpx;
  margin-top: 180rpx;
}
.tips .img image{
  width: 27rpx;
  height: 33rpx;
  margin: 0 10rpx 0 150rpx;
}
.tips text{
  color: #1D4692;
  font-size: 25rpx;
}
button{
  margin-top: 50rpx;
}
.checkbox{
  text-align: center;
  color: #1D4692;
  margin: 50rpx 0;
}
.checkbox view,.checkbox navigator{
  font-size: 26rpx;
}
.checkbox navigator{
  display: inline;
  text-decoration: underline;
}
checkbox .wx-checkbox-input {
  width: 20rpx;
  height: 20rpx;
  margin-right: 30rpx;
}

5、目前我個(gè)人就想到這2個(gè)優(yōu)化方案,肯定也還存在其他的方案的,歡迎交流。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容