移动端页面键盘弹出后导致body高度变低背景图片被挤上去解决方法

文章描述了在Vue组件中设置背景图片时如何解决键盘弹出导致的页面布局问题,通过调整`main`元素的高度保持在100%,确保背景图片不会被键盘遮挡。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本身在设置背景图片的时候是将html,body的高度设为100%,然后

原来的代码最外层直接设置百分之百:

<template>
  <div class="back">
    <div style="padding-top: 5%;padding-bottom: 5%; height: 100%">
      <div class="box-card bar-margin bar-card">
        <el-form
          v-if="loginState === 0"
          ref="ruleForm"
          :label-position="labelPosition"
          :model="ruleForm"
          :rules="rules"
          style="margin-top: 68%"
        >
          <el-row style="padding-left: 25px">
            <el-col :span="20">
              <el-form-item label="身份证号" prop="idCard" label-width="80px">
                <el-input v-model="ruleForm.idCard" size="small" maxlength="18" />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row style="padding-left: 25px">
            <el-col :span="20">
              <el-form-item label="密码" prop="password" label-width="80px">
                <el-input v-model="ruleForm.password" auto-complete="off" size="small" maxlength="18" type="password" />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row style="padding-left: 50%">
            <el-col :span="20">
              <el-checkbox v-model="checked" style="color:#a0a0a0;margin:0 0 20px 0">记住密码</el-checkbox>
            </el-col>
          </el-row>

          <el-row style="padding-top: 0px">
            <el-col :span="24">
              <el-button
                round
                style="width: 180px"
                size="default"
                type="primary"
                :loading="logining"
                class="button-login"
                @click="submitForm('ruleForm')"
              >登录
              </el-button>
            </el-col>
          </el-row>
          <el-row style="padding-top: 20px">
            <el-col :span="24" style="padding-top: 10px;text-align: center;">
              <el-link style="color: #e4b9b9" @click="clickState(2)"><span>重置密码</span></el-link>
              |
              <el-link style="color: #e4b9b9" @click="clickState(1)"><span>注册</span></el-link>
            </el-col>
          </el-row>
        </el-form>
        <Register v-if="loginState === 1" @clickState="clickState" />
        <Retrieve v-if="loginState === 2" @clickState="clickState" />
      </div>
    </div>
  </div>
</template>

<script>
import { login } from '@/api/app/login/index'
import { idCardNoVerify } from '@/utils/my-validate'
import CryptoJS from 'crypto-js'

export default {
  components: {
    Register: () => import('./register.vue'),
    Retrieve: () => import('./retrieve.vue')
  },
  data() {
    // 身份证号码校验
    const checkIDCard = (rule, value, callback) => {
      if (!idCardNoVerify(value)) callback(new Error('请输入正确的身份证号码'))
      callback()
    }
    var validatePass = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('请输入密码'))
      } else {
        if (this.ruleForm.checkPassword !== '') {
          this.$refs.ruleForm.validateField('checkPassword')
        }
        callback()
      }
    }
    return {
      logining: false,
      checked: true,
      labelPosition: 'right',
      loginState: 0, // 0登录页面 1 注册页面 2重置密码
      activeName: 'first',
      key: 'secret key 5452',
      ruleForm: {
        idCard: '',
        password: ''
      },
      rules: {
        idCard: [{
          required: true,
          message: '请输入身份证号',
          trigger: 'blur'
        }, {
          validator: checkIDCard,
          trigger: 'blur'
        }],
        password: [{
          required: true,
          validator: validatePass,
          trigger: 'blur'
        }]
      }
    }
  },
  mounted() {
    this.account()
  },

  methods: {
    clickState(value) {
      this.loginState = value
    },
    account() {
      this.getCookie()
    },
    // 提交表单
    submitForm(formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          this.logining = true
          if (this.checked === true) {
            // 存入cookie
            this.setCookie(this.ruleForm.idCard, this.ruleForm.password, 7) // 保存1天
          } else {
            this.clearCookie()
          }
          this.login()
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },
    resetForm(formName) {
      this.$refs[formName].resetFields()
    },
    // 登录成功存储信息到store
    async login() {
      const res = await login({
        idCard: this.ruleForm.idCard,
        password: this.ruleForm.password
      })
      if (res.code === '200') {
        if (res.data.success) {
          const exdate = new Date()
          exdate.setTime(exdate.getTime() + 24 * 60 * 60 * 1000 * 1)
          window.document.cookie =
              'App-Token' + '=' + res.data.token + ';path=/;expires=' + exdate.toGMTString()
          const text = CryptoJS.AES.encrypt(res.data.basicId, this.key)
          window.document.cookie =
              'basicId' + '=' + text + ';path=/;expires=' + exdate.toGMTString()
          // this.$message({
          //   type: 'success',
          //   message: '登录成功'
          // })
          this.$router.push('/App-view/home')
        }
      } else {
        this.logining = false
      }
    },

    setCookie(c_idCard, c_pwd, exdays) {
      const text = CryptoJS.AES.encrypt(c_pwd, this.key)
      const exdate = new Date()
      exdate.setTime(exdate.getTime() + 24 * 60 * 60 * 1000 * exdays)
      // 字符串拼接cookie
      window.document.cookie =
          'idCard' + '=' + c_idCard + ';path=/;expires=' + exdate.toGMTString()
      window.document.cookie =
          'userPwd' + '=' + text + ';path=/;expires=' + exdate.toGMTString()
    },
    getCookie: function () {
      if (document.cookie.length > 0) {
        const arr = document.cookie.split('; ')
        for (let i = 0; i < arr.length; i++) {
          const arr2 = arr[i].split('=')
          if (arr2[0] === 'idCard') {
            this.ruleForm.idCard = arr2[1]
          } else if (arr2[0] === 'userPwd') {
            const bytes = CryptoJS.AES.decrypt(arr2[1].toString(), this.key)
            const plaintext = bytes.toString(CryptoJS.enc.Utf8)
            this.ruleForm.password = plaintext
          }
        }
      }
    },
    // 清除cookie
    clearCookie: function () {
      this.setCookie('', '', -1)
    }

  }
}
</script>

<style lang="scss">
  .back {
    background: url('/img/bottom.png');
    background-size: 100% 100%;
    margin: 0 auto;
    text-align: center;
    height: 100%;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    width: 100%;
  }

  .bar-card {
    margin: 0 auto;
    text-align: center;
    width: calc(100% - 40px);
  }

  .login-ruleForm {
    margin: 0 auto;
    text-align: center;
  }

  .van-dropdown-menu__bar {
    background-color: #eef3f3c7;
  }
</style>

现在的代码:

<template>
  <div class="backTemp" :style="{ height: bodyHeight + 'px' }">
    <div style="padding-top: 5%;padding-bottom: 5%; height: 100%">
      <div class="box-card bar-margin bar-card">
        <el-form
          v-if="loginState === 0"
          ref="ruleForm"
          :label-position="labelPosition"
          :model="ruleForm"
          :rules="rules"
          style="margin-top: 68%"
        >
          <el-row style="padding-left: 25px">
            <el-col :span="20">
              <el-form-item label="身份证号" prop="idCard" label-width="80px">
                <el-input v-model="ruleForm.idCard" size="small" maxlength="18" />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row style="padding-left: 25px">
            <el-col :span="20">
              <el-form-item label="密码" prop="password" label-width="80px">
                <el-input v-model="ruleForm.password" auto-complete="off" size="small" maxlength="18" type="password" />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row style="padding-left: 50%">
            <el-col :span="20">
              <el-checkbox v-model="checked" style="color:#a0a0a0;margin:0 0 20px 0">记住密码</el-checkbox>
            </el-col>
          </el-row>

          <el-row style="padding-top: 0px">
            <el-col :span="24">
              <el-button
                round
                style="width: 180px"
                size="default"
                type="primary"
                :loading="logining"
                class="button-login"
                @click="submitForm('ruleForm')"
              >登录
              </el-button>
            </el-col>
          </el-row>
          <el-row style="padding-top: 20px">
            <el-col :span="24" style="padding-top: 10px;text-align: center;">
              <el-link style="color: #e4b9b9" @click="clickState(2)"><span>重置密码</span></el-link>
              |
              <el-link style="color: #e4b9b9" @click="clickState(1)"><span>注册</span></el-link>
            </el-col>
          </el-row>
        </el-form>
        <Register v-if="loginState === 1" @clickState="clickState" />
        <Retrieve v-if="loginState === 2" @clickState="clickState" />
      </div>
    </div>
  </div>
</template>

<script>
import { login } from '@/api/app/login/index'
import { idCardNoVerify } from '@/utils/my-validate'
import CryptoJS from 'crypto-js'

export default {
  components: {
    Register: () => import('./register.vue'),
    Retrieve: () => import('./retrieve.vue')
  },
  data() {
    // 身份证号码校验
    const checkIDCard = (rule, value, callback) => {
      if (!idCardNoVerify(value)) callback(new Error('请输入正确的身份证号码'))
      callback()
    }
    var validatePass = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('请输入密码'))
      } else {
        if (this.ruleForm.checkPassword !== '') {
          this.$refs.ruleForm.validateField('checkPassword')
        }
        callback()
      }
    }
    return {
      bodyHeight: this.bodyHeight,
      logining: false,
      checked: true,
      labelPosition: 'right',
      loginState: 0, // 0登录页面 1 注册页面 2重置密码
      activeName: 'first',
      key: 'secret key 5452',
      ruleForm: {
        idCard: '',
        password: ''
      },
      rules: {
        idCard: [{
          required: true,
          message: '请输入身份证号',
          trigger: 'blur'
        }, {
          validator: checkIDCard,
          trigger: 'blur'
        }],
        password: [{
          required: true,
          validator: validatePass,
          trigger: 'blur'
        }]
      }
    }
  },
  mounted() {
    this.bodyHeight = document.documentElement.clientHeight
    this.account()
  },

  methods: {
    clickState(value) {
      this.loginState = value
    },
    account() {
      this.getCookie()
    },
    // 提交表单
    submitForm(formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          this.logining = true
          if (this.checked === true) {
            // 存入cookie
            this.setCookie(this.ruleForm.idCard, this.ruleForm.password, 7) // 保存1天
          } else {
            this.clearCookie()
          }
          this.login()
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },
    resetForm(formName) {
      this.$refs[formName].resetFields()
    },
    // 登录成功存储信息到store
    async login() {
      const res = await login({
        idCard: this.ruleForm.idCard,
        password: this.ruleForm.password
      })
      if (res.code === '200') {
        if (res.data.success) {
          const exdate = new Date()
          exdate.setTime(exdate.getTime() + 24 * 60 * 60 * 1000 * 1)
          window.document.cookie =
              'App-Token' + '=' + res.data.token + ';path=/;expires=' + exdate.toGMTString()
          const text = CryptoJS.AES.encrypt(res.data.basicId, this.key)
          window.document.cookie =
              'basicId' + '=' + text + ';path=/;expires=' + exdate.toGMTString()
          // this.$message({
          //   type: 'success',
          //   message: '登录成功'
          // })
          this.$router.push('/App-view/home')
        }
      } else {
        this.logining = false
      }
    },

    setCookie(c_idCard, c_pwd, exdays) {
      const text = CryptoJS.AES.encrypt(c_pwd, this.key)
      const exdate = new Date()
      exdate.setTime(exdate.getTime() + 24 * 60 * 60 * 1000 * exdays)
      // 字符串拼接cookie
      window.document.cookie =
          'idCard' + '=' + c_idCard + ';path=/;expires=' + exdate.toGMTString()
      window.document.cookie =
          'userPwd' + '=' + text + ';path=/;expires=' + exdate.toGMTString()
    },
    getCookie: function () {
      if (document.cookie.length > 0) {
        const arr = document.cookie.split('; ')
        for (let i = 0; i < arr.length; i++) {
          const arr2 = arr[i].split('=')
          if (arr2[0] === 'idCard') {
            this.ruleForm.idCard = arr2[1]
          } else if (arr2[0] === 'userPwd') {
            const bytes = CryptoJS.AES.decrypt(arr2[1].toString(), this.key)
            const plaintext = bytes.toString(CryptoJS.enc.Utf8)
            this.ruleForm.password = plaintext
          }
        }
      }
    },
    // 清除cookie
    clearCookie: function () {
      this.setCookie('', '', -1)
    }

  }
}
</script>

<style lang="scss">
  .backTemp {
    background: url('/img/bottom.png');
    background-size: 100% 100%;
    margin: 0 auto;
    text-align: center;
    height: 100%;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    width: 100%;
  }

  .bar-card {
    margin: 0 auto;
    text-align: center;
    width: calc(100% - 40px);
  }

  .login-ruleForm {
    margin: 0 auto;
    text-align: center;
  }

  .van-dropdown-menu__bar {
    background-color: #eef3f3c7;
  }
</style>

但是这样写就会导致键盘弹出的时候html和body的高度从原来的100%变为(100%-键盘高度),这样的话main的height:100%也会变成(100%-键盘高度),所以需要强行将main的高度设置为html原本的100%。

<div class="main" :style="{ height: bodyHeight + 'px' }">
</div>

mounted(){
 this.bodyHeight=document.documentElement.clientHeight
}

这样的话即使键盘弹起也只会改变html和body的高度,main的高度还是之前的100%,背景图片也就不会被挤上去了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值