踩坑:解決移動端點擊Input呼出鍵盤頁面被頂起和壓縮問題

1. 移動端適配,頁面高度沒有寫死,使用 input 標(biāo)簽時,喚起的虛擬鍵盤導(dǎo)致頁面頂起和壓縮

  • 原因:使用的 flex 布局,頁面的高度是所有的元素的高度都是自適應(yīng)的,高度未寫死,當(dāng)出現(xiàn)虛擬鍵盤時,會造成頁面布局混亂,底部元素被頂起及 input 的上一個元素被壓縮


    before.jpeg
    before.jpeg

    after.jpeg
    after.jpeg
  • 解決思路,既然是高度沒有寫死的造成的,那么將高度寫死不就好了么?

  • 但是高度寫死了,還怎么適配不同的手機?不能將高度寫死

  • 那么,它只在鍵盤喚起的那一刻需要高度,那么,我們在喚起鍵盤的那一刻將下面的元素隱藏掉,當(dāng)鍵盤消失時再將元素顯示出來

方案一: 使用 v-show 來控制元素的顯示與隱藏

  • click 時 isShow = false, 失去焦點時 isShow = true
// 帶有 input 元素的 FormItem.vue
<input type="text"
       class="input-notes"
       :value="value"
       @input="onValueChange($event.target.value)"
       :placeholder="placeholder"
       @click="$emit('update:isShow',false)"
       @blur="$emit('update:isShow',true)"
       >


// 調(diào)用 FormItem.vue 的組件 Money.vue
<Layout class-prefix="xxx" ref="layout"  :is-show="isShow"> <--! 因為把底部組件放 Layout組件里,要給其傳一個值-->  
  <NumberPad  v-show="isShow"/>  <--! 2. 控制要隱藏的變量 -->
  <FormItem  @update:isShow="(value) => {isShow=value}"/> <--! 3. 當(dāng)觸發(fā)input的click事件時,改變isShow的值 -->
  <Tags :data-source.sync="tagsList" @update:selectedTag="selectedTag"/>
</Layout>   


isShow = true // 1. 先定義一個變量 isShow,用來控制顯示和隱藏
  
// Layout.vue 組件
 <div class="layout-wrapper">
    ....
    <Nav v-show="isShow"/>
  </div>
  
  props:['isShow']

效果:是解決了頂起和壓縮問題,
引發(fā)問題:

  1. 但是要點擊其它地方使 input 失去焦點,不然就會變成右邊的圖
  2. 且點擊其它地方時頁面會出現(xiàn)閃爍問題
  3. 在這里,會影響其它頁面,為了實現(xiàn)這個,我必須在所有用到 Layout.vue 這個組件的地方,給其傳一個屬性v-show="true",不然的話,被isShow控制的那個組件就會不顯示。

總結(jié):這個方案既麻煩又不好用,特別是對于由好多組件組成的頁面


1.jpeg
1.jpeg

2.jpeg
2.jpeg

方案二: window.onresize 時結(jié)合 v-show 來隱藏元素

  • 那不通過判斷input的狀態(tài),而是通過監(jiān)聽resize事件,當(dāng)屏幕高度發(fā)生變化時,控制元素的隱藏展示
  • 其它的和方案一一樣
// Money.vue
height = document.body.clientHeight;
isShow = true
mounted(){
    window.addEventListener('resize', ()=>{
            if(document.body.clientHeight < height){ 
                this.isShow = false
            }else{
                this.isShow = true
            }
    })
}

效果:解決了頁面被頂起和壓縮的問題
問題:

  1. 當(dāng)虛擬鍵盤消失時,頁面會有閃爍的情況出現(xiàn)
  2. 還是和方案一的問題三一樣,維護比較麻煩

方案三:一進入頁面,就將頁面的高度固定下來

  • 一進入頁面就獲取瀏覽器可視區(qū)的高度,然后把高度賦給根元素
 // Money.vue
<Layout class-prefix="xxx" ref="layout" :style="{height:h+'px'}">
    <NumberPad @update:value="onUpdateAmount" @submit="saveRecord" :x="record.tags"/>
    <FormItem :value.sync="record.notes" name="備注" placeholder="請在這里輸入備注"/>
    <Tags :data-source.sync="tagsList" @update:selectedTag="selectedTag"/>
    <template #head>
      <Tabs :value.sync="record.type"/>
    </template>
  </Layout>

    h = document.body.clientHeight; 

效果: 所有問題完美解決,頁面也不會有閃爍問題,特別簡單.........

最后附上項目預(yù)覽地址:項目 simpleBilling

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

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