欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于vue封裝一個安全鍵盤組件

 更新時間:2023年12月06日 10:47:56   作者:摸魚君111  
大部分中文應用彈出的默認鍵盤是簡體中文輸入法鍵盤,在輸入用戶名和密碼的時候,如果使用簡體中文輸入法鍵盤,用戶的輸入記錄會被緩存下來所以我們需要一個安全鍵盤,本文給大家介紹了如何基于vue封裝一個安全鍵盤組件,需要的朋友可以參考下

為什么需要安全鍵盤

大部分中文應用彈出的默認鍵盤是簡體中文輸入法鍵盤,在輸入用戶名和密碼的時候,如果使用簡體中文輸入法鍵盤,輸入英文字符和數(shù)字字符的用戶名和密碼時,會自動啟動系統(tǒng)輸入法自動更正提示,然后用戶的輸入記錄會被緩存下來。

系統(tǒng)鍵盤緩存最方便拿到的就是利用系統(tǒng)輸入法自動更正的字符串輸入記錄。 緩存文件的地址是:

/private/var/mobile/Library/Keyboard/dynamic-text.dat

導出該緩存文件,查看內(nèi)容,欣喜的發(fā)現(xiàn)一切輸入記錄都是明文存儲的。因為系統(tǒng)不會把所有的用戶輸入記錄都當作密碼等敏感信息來處理。 一般情況下,一個常規(guī) iPhone 用戶的 dynamic-text.dat 文件,高頻率出現(xiàn)的字符串就是用戶名和密碼。

使用自己定制的安全鍵盤的原因主要有:

  • 避免第三方讀取系統(tǒng)鍵盤緩存
  • 防止屏幕錄制 (自己定制的鍵盤按鍵不加按下效果)

實現(xiàn)方案

封裝組件

首先建一個文件safeKeyboard.vue安全鍵盤子組件.

<template>
  <div class="keyboard">
    <div class="key_title">
      <p><img src="../../../../static/img/ic_logo@2x.png"><span>小猴子的安全鍵盤</span></p>
    </div>
    <p v-for="keys in keyList" :style="(keys.length<10&&keys.indexOf('ABC')<1&&keys.indexOf('del')<1&&keys.indexOf('suc')<1)?'padding: 0px 20px;':''">
      <template v-for="key in keys">
        <i v-if="key === 'top'" @click.stop="clickKey" @touchend.stop="clickKey" class="tab-top"><img class="top" :src='top_img'></i>
        <i v-else-if="key === 'del'" @click.stop="clickKey" @touchend.stop="clickKey" class="key-delete"><img class="delete" src='刪除圖標路徑'></i>
        <i v-else-if="key === 'blank'" @click.stop="clickBlank" class="tab-blank">空格</i>
        <i v-else-if="key === 'suc'" @click.stop="success" @touchend.stop="success" class="tab-suc">確定</i>
        <i v-else-if="key === '.?123' || key === 'ABC'" @click.stop="symbol" class="tab-sym">{{(status==0||status==1)?'.?123':'ABC'}}</i>
        <i v-else-if="key === '123' || key === '#+='" @click.stop="number" class="tab-num">{{status==3?'123':'#+='}}</i>
        <i v-else @click.stop="clickKey" @touchend.stop="clickKey">{{key}}</i>
      </template>
    </p>
  </div>
</template>
 
<script>
export default {
  data () {
    return {
      keyList: [],
      status: 0, // 0 小寫 1 大寫 2 數(shù)字 3 符號
      topStatus: 0, // 0 小寫 1 大寫
      top_img: require('小寫圖片路徑'),
      lowercase: [
        ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'],
        ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'],
        ['top', 'z', 'x', 'c', 'v', 'b', 'n', 'm', 'del'],
        ['.?123', 'blank', 'suc']
      ],
      numbercase: [
        ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
        ['-', '/', ':', ';', '(', ')', '$', '&', '@', '"'],
        ['#+=', '.', ',', '?', '!', "'", 'del'],
        ['ABC', 'blank', 'suc']
      ],
      symbolcase: [
        ['[', ']', '{', '}', '#', '%', '^', '*', '+', '='],
        ['_', '\\', '|', '~', '<', '>', '€', '`', '¥', '·'],
        ['123', '.', ',', '?', '!', "'", 'del'],
        ['ABC', 'blank', 'suc']
      ],
      uppercase: [
        ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
        ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
        ['top', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', 'del'],
        ['.?123', 'blank', 'suc']
      ],
      equip: !!navigator.userAgent.toLocaleLowerCase().match(/ipad|mobile/i)// 是否是移動設備
    }
  },
  props: {
    option: {
      type: Object
    }
  },
 
  mounted () {
    this.keyList = this.lowercase
  },
 
  methods: {
    tabHandle ({value = ''}) {
      if (value.indexOf('tab-num') > -1) {
        if (this.status === 3) {
          this.status = 2
          this.keyList = this.numbercase
        } else {
          this.status = 3
          this.keyList = this.symbolcase
        }
        // 數(shù)字鍵盤數(shù)據(jù)
      } else if (value.indexOf('delete') > -1) {
        this.emitValue('delete')
      } else if (value.indexOf('tab-blank') > -1) {
        this.emitValue(' ')
      } else if (value.indexOf('tab-point') > -1) {
        this.emitValue('.')
      } else if (value.indexOf('tab-sym') > -1) {
        if (this.status === 0) {
          this.topStatus = 0
          this.status = 2
          this.keyList = this.numbercase
        } else if (this.status === 1) {
          this.topStatus = 1
          this.status = 2
          this.keyList = this.numbercase
        } else {
          if (this.topStatus == 0) {
            this.status = 0
            this.top_img = require('小寫圖片路徑')
            this.keyList = this.lowercase 
          }else{
            this.status = 1
            this.keyList = this.uppercase
            this.top_img = require('大寫圖片路徑')
          }
        }
        // 符號鍵盤數(shù)據(jù)
      } else if (value.indexOf('top') > -1) {
        if (this.status === 0) {
          this.status = 1
          this.keyList = this.uppercase
          this.top_img = require('大寫圖片路徑')
        } else {
          this.status = 0
          this.keyList = this.lowercase
          this.top_img = require('小寫圖片路徑')
        }
      } else if (value.indexOf('tab-suc') > -1) {
        this.$emit('closeHandle', this.option) // 關閉鍵盤
      }
    },
    number (event) {
      this.tabHandle(event.srcElement.classList)
    },
    clickBlank (event) {
      this.tabHandle(event.srcElement.classList)
    },
    symbol (event) {
      this.tabHandle(event.srcElement.classList)
    },
    success (event) {
      this.tabHandle(event.srcElement.classList)
    },
    english (event) {
      this.tabHandle(event.srcElement.classList)
    },
    clickKey (event) {
      if (event.type === 'click' && this.equip) return
      let value = event.srcElement.innerText
      value ? this.emitValue(value) : this.tabHandle(event.srcElement.classList)
    },
 
    emitValue (key) {
      this.$emit('keyVal', key) // 向父組件傳值
    },
 
    closeModal (e) {
      if (e.target !== this.option.sourceDom) {
        this.$emit('closeHandle', this.option)
        this.keyList = this.lowercase
      }
    },
  }
}
</script>
<style scoped lang="scss">
.keyboard {
  width: 100%;
  margin: 0 auto;
  font-size: 18px;
  border-radius: 2px;
  background-color: #fff;
  box-shadow: 0 -2px 2px 0 rgba(89,108,132,0.20);
  user-select: none;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 999;
  pointer-events: auto;
  .key_title{
    height: 84px;
    font-size: 32px;
    color: #0B0B0B;
    overflow: hidden;
    margin-bottom: 16px;
    p{
      display: flex;
      justify-content: center;
      align-items: center;
      min-width: 302px;
      height: 32px;
      margin: 32px auto 0px;
      img{
        width: 32px;
        height: 32px;
        margin-right: 10px;
      }
    }
  }
  p {
    width: 99%;
    margin: 0 auto;
    height: 84px;
    margin-bottom: 24px;
    display: flex;
    display: -webkit-box;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: center;
    box-sizing: border-box;
    i {
      position: relative;
      display: block;
      margin: 0px 5px;
      height: 84px;
      line-height: 84px;
      font-style: normal;
      font-size: 48px;
      border-radius: 8px;
      width: 64px;
      background-color: #F2F4F5;
      box-shadow: 0 2px 0 0 rgba(0,0,0,0.25);
      text-align: center;
      flex-grow: 1;
      flex-shrink: 1;
      flex-basis: 0;
      -webkit-box-flex: 1;
      img{
        width: 48px;
        height: 48px;
      }
    }
    i:first-child{
      margin-left: 0px
    }
    i:last-child{
      margin-right: 0px
    }
    i:active {
      background-color: #A9A9A9;
    }
    .tab-top, .key-delete, .tab-num, .tab-eng, .tab-sym{
      background-color: #CED6E0;
    }
    .tab-top,.key-delete {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 84px;
      height: 84px;
    }
    .tab-top{
      margin-right: 30px;
      font-size: 32px;
    }
    .key-delete{
      margin-left: 30px;
    }
    .tab-num, .tab-eng, .tab-sym{
      font-size: 32px;
    }
    .tab-point {
      width: 70px;
    }
    .tab-blank, .tab-suc{
      text-align: center;
      line-height: 84px;
      font-size: 32px;
      color: #000;
    }
    .tab-blank{
      flex: 2.5;
    }
    .tab-suc{
      background-color: #CFA46A;
    }
  }
  p:last-child{
    margin-bottom: 8px;
  }
}
</style>

但是,鍵盤的特性是,點擊除鍵盤和輸入框以外的地方,鍵盤收起。

所以還需要一個clickoutside.js文件,用來自定義一個指令,實現(xiàn)需求:

代碼如下:

export default {
  bind(el, binding, vnode) {
    function documentHandler(e) {
      if (el.contains(e.target)) {
        return false;
      }
      if (binding.expression) {
        binding.value(e);
      }
    }
    el.__vueClickOutside__ = documentHandler;
    document.addEventListener('click', documentHandler);
  },
  unbind(el, binding) {
    document.removeEventListener('click', el.__vueClickOutside__);
    delete el.__vueClickOutside__;
  }
};

然后在safeKeyboard.vue中引入:

import clickoutside from './clickoutside'

并注冊局部指令:

directives: { clickoutside }

然后綁定方法:

<div class="keyboard" v-clickoutside="closeModal">

聲明方法:

closeModal (e) {
  if (e.target !== this.option.sourceDom) {
    this.$emit('closeHandle', this.option)
    this.keyList = this.lowercase
  }
},

安全鍵盤組件就構(gòu)建完成了,接下來是在需要用到安全鍵盤的頁面引入使用了。

使用組件

引入組件

import Keyboard from './safeKeyboard'

components: {
  Keyboard
}

使用范例

<input type="password" ref="setPwd" v-model='password'/> 

<Keyboard v-if="option.show" :option="option" @keyVal="getInputValue" @closeHandle="onLeave"></Keyboard>

鍵盤相關數(shù)據(jù)對象及方法

  • option
option: {
  show: false, // 鍵盤是否顯示
  sourceDom: '', // 鍵盤綁定的Input元素
  _type: '' // 鍵盤綁定的input元素ref
},
  • getInputValue

getInputValue(val)會接收鍵盤錄入的數(shù)據(jù),val是輸入的單個字符或者是刪除操作,由于是單個字符,所以需在方法中手動拼接成字符串。在方法中根據(jù)option._type區(qū)分是哪個輸入框的數(shù)據(jù)。

  • onLeave

onLeave()相當于blur,這是由于在移動端H5項目中,input獲取焦點時會調(diào)起手機軟鍵盤,所以需要禁止軟鍵盤被調(diào)起來,辦法是:

javascript

復制代碼

document.activeElement.blur() // ios隱藏鍵盤 this.$refs.setPwd.blur() // android隱藏鍵盤

就相當于強制使input元素處于blur狀態(tài),那么軟鍵盤就不會被調(diào)起,所以如果要做blur監(jiān)聽,就需要onLeave()。

但是這樣出現(xiàn)了一個新的問題,輸入框里面沒有光標??!雖然不影響業(yè)務邏輯,但是用戶用起來會很不舒服。

所以,只能和input元素說再見了,自己手寫一個吧:

輸入框組件

再來一個子組件cursorBlink.vue

<template>
  <div class="cursor-blink" @click.stop="isShow">
    <span v-if="pwd.length>0" :style="options.show?'':'border:0;animation:none;'" class="blink">{{passwordShow}}</span>
    <span v-else style="color: #ddd" :style="options.show?'':'border:0;animation:none;'" class="blink_left">{{options.desc}}</span>
  </div>
</template>
<script>
export default {
  props: {
    pwd: {
      type: String
    },
    options: {
      type: Object
    },
  },
  data(){
    return {
      passwordShow: '',
    }
  },
  mounted() {
    if(this.pwd.length > 0){
      for (let i = 0; i < this.pwd.length; i++) {
        this.passwordShow += '*' // 顯示為掩碼
      }
    }
  },
  watch: {
    pwd(curVal, oldVal){
      if (oldVal.length < curVal.length) {
        // 輸入密碼時
        this.passwordShow += '*'
      } else if (oldVal.length > curVal.length) {
        // 刪除密碼時
        this.passwordShow = this.passwordShow.slice(0, this.passwordShow.length - 1)
      }
    }
  },
  methods: {
    isShow(){
      this.$emit('cursor')
    }
  },
}
</script>
<style lang="scss" scoped>
  .cursor-blink{
    display: inline-block;
    width: 500px;
    height: 43px;
    letter-spacing: 0px;
    word-spacing: 0px;
    padding: 2px 0px;
    font-size: 28px;
    overflow: hidden;
    .blink,.blink_left{
      display: inline;
      margin: 0px;
    }
    .blink{ // 輸入密碼后
      border-right: 2px solid #000;
      animation: blink 1s infinite steps(1, start);
    }
    .blink_left{ // 輸入密碼前
      border-left: 2px solid #000;
      animation: blinkLeft 1s infinite steps(1, start);
    }
  }
  @keyframes blink {
    0%, 100% {
      border-right: 2px solid #fff;
    }
    50% {
      border-right: 2px solid #000;
    }
  }
  @keyframes blinkLeft {
    0%, 100% {
      border-left: 2px solid #fff;
    }
    50% {
      border-left: 2px solid #000;
    }
  }
</style>

引入之后光榮的接替input的位置:

<CursorBlink :pwd='password' ref="setPwd" :options='option2' @cursor="onFocus"></CursorBlink>

數(shù)據(jù)方法說明:

option2: {
  show: false,  // 區(qū)分輸入前輸入后
  desc: '請重復輸入密碼'  // 相當于placeholder
},

onFocus() 相當于input標簽的focus

這樣一個完美的安全鍵盤就做好了。

以上就是基于vue封裝一個安全鍵盤組件的詳細內(nèi)容,更多關于vue封裝鍵盤組件的資料請關注腳本之家其它相關文章!

相關文章

  • Vue Cli3 打包配置并自動忽略console.log語句的方法

    Vue Cli3 打包配置并自動忽略console.log語句的方法

    這篇文章主要介紹了Vue Cli3 打包配置并自動忽略console.log語句的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-04-04
  • vue項目安裝使用vconsole方式

    vue項目安裝使用vconsole方式

    這篇文章主要介紹了vue項目安裝使用vconsole方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • vue中如何配置proxy代理

    vue中如何配置proxy代理

    這篇文章主要介紹了vue中如何配置proxy代理問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • vue實現(xiàn)div拖拽互換位置

    vue實現(xiàn)div拖拽互換位置

    這篇文章主要為大家詳細介紹了vue實現(xiàn)div拖拽互換位置的方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • 前端數(shù)據(jù)存儲常用工具Vuex、Pinia、Redux詳解

    前端數(shù)據(jù)存儲常用工具Vuex、Pinia、Redux詳解

    Redux、Vuex 和 Pinia 都是用于狀態(tài)管理的流行框架,這篇文章主要介紹了前端數(shù)據(jù)存儲常用工具Vuex、Pinia、Redux的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-04-04
  • vue生成pdf文件步驟及pdf分頁隔斷處理方法

    vue生成pdf文件步驟及pdf分頁隔斷處理方法

    最近遇到一個需求,需要把內(nèi)容下載生成pdf文件,但轉(zhuǎn)換過程中內(nèi)容總是會被截斷,就很難受,從網(wǎng)上找到了解決辦法分享給大家,這篇文章主要給大家介紹了關于vue生成pdf文件步驟及pdf分頁隔斷處理的相關資料,需要的朋友可以參考下
    2024-02-02
  • Vue3中的h函數(shù)及使用小結(jié)

    Vue3中的h函數(shù)及使用小結(jié)

    這篇文章主要介紹了Vue3中的h函數(shù)及使用小結(jié),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • Vue ECharts設置主題實現(xiàn)方法介紹

    Vue ECharts設置主題實現(xiàn)方法介紹

    這篇文章主要介紹了Vue ECharts設置主題,本文通過實例代碼圖文相結(jié)合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-12-12
  • Vue集成和使用SQLite的完整指南

    Vue集成和使用SQLite的完整指南

    SQLite 是一種輕量級的關系型數(shù)據(jù)庫管理系統(tǒng),以其簡單易用、無需服務器等特點廣泛應用于嵌入式系統(tǒng)、移動應用和小型應用程序中,在 Vue.js 項目中使用 SQLite,可以將應用的數(shù)據(jù)存儲在客戶端,本文將介紹如何在 Vue 項目中集成 SQLite,需要的朋友可以參考下
    2024-11-11
  • vue中img標簽的src屬性總結(jié)(問題解決)

    vue中img標簽的src屬性總結(jié)(問題解決)

    初步接觸vue框架時,好多朋友使用img標簽時,設置動態(tài)src屬性時,可能都會遇到路徑不生效的問題,本文給大家介紹vue中img標簽的src屬性總結(jié),感興趣的朋友一起看看吧
    2023-11-11

最新評論