Vue实现锁屏功能

这篇具有很好参考价值的文章主要介绍了Vue实现锁屏功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这两天刚做了个新需求,要做个系统锁屏(当然锁的是当前的系统),就类似于电脑锁屏似的。

共两种情况下锁屏,一种是无操作一定时间后自动锁屏;第二种是可以按下组合键(快捷键)主动进行锁屏。下面具体来说一下该需求的想法、思路以及实现

然后再说下想法思路吧。首先实现锁屏一般也就两种方式:

一种是去写个页面,当达到条件时要跳转到该锁屏页面,但是有一些要注意的地方, 比如:如果跳转的时候使用的$router.push,那么我是可以通过点击浏览器的回退按钮回到上一个页面的,这个要做一下限制。还有一种可能是我如果直接在浏览器上输入某个页面的路径,那么是不是也会跳转?所以我们要有个全局的变量来记录当前是不是锁屏状态,如果是锁屏状态,我们要对其进行限制。当然这只是举例的两种情况,真实做起来或许还有其他情况,反正要考虑周全,不然后面会出现你意想不到的bug

第二种就是直接去写遮罩层了,也是我当前实现锁屏的方式。这种方式相对上面来讲,会比较简单一些,也还算方便,我们只需要在达到条件后将该遮罩层显示出来就可以了,当然遮罩层的优先级肯定要设置最高的,要不然怎么覆盖掉任意当前的页面呢,也正是因为这个优先级最高,导致在这个遮罩层组件中有些$message这样的消息提示或弹窗显示不出来。这也算是一个缺陷。不过一般锁屏页面也没什么太多操作,主要是页面有个背景图,然后输入解锁密码进行解锁就可以了,所以影响并不大。还有一种需要注意,就是我现在已经锁屏页面了,我这时候打开控制台,然后是不是可以去修改这个遮罩层的样式呢?比如我给遮罩层加个display: none; 遮罩层是不是没了?答案是的,所以我们要做限制! 打开控制台的方式无非也就两种方式,一种是F12(Fn + F12),另一种是鼠标右键,然后点击检查。这样,我们锁屏出来的时候就监听键盘按下事件,阻止F12的按键,同时也阻止鼠标右键行为,这样就可以了,看上去简单粗暴哈,但也是为了实现这么个需求嘛。

下面再说一下实现的方式。

首先我把遮罩层单独写了个组件,里面也都是遮罩层的样式、逻辑。注意这是个组件,而不是个页面,哪里用到哪里引入就可以了。

然后就是遮罩层什么时候显示的问题了,既然是锁屏,那么肯定是跟登录没有关系的,也就是我们要刚一进系统就开始计时了,比如我们的需求是一分钟无操作后就要锁屏,那么我们只需要这个计时无操作的时间就可以了,什么算是操作了?什么算是无操作,鼠标点击就是操作了,鼠标双击是操作了,鼠标右键是操作了,鼠标移动是操作了,鼠标滚轮是操作了,键盘按下是操作了,基本就这些事件,也就是我们在刚进入系统时就要监听这些事件,同时也开始计时(计时就是定义变量初始值为0,然后setInterval每隔1s加1),如果有其中某个事件触发了,我们就要清除掉定时器,并将变量初始化为初始值也就是0,并重新计时,基本跟防抖差不多。然后我们无操作满足时间后会显示遮罩层,也就是进入锁屏状态,这个是,我们就要把那些事件监听移除掉,并清除掉定时器,但是注意不要将变量初始化为0,因为我们要通过这个变量和我们设置时间做对比来决定是否显示遮罩层,进入遮罩层之后就是遮罩层的操作了,解锁后呢,我们将变量的值初始化为0,隐藏遮罩层,并重新监听那些事件,重新计时就可以了。

哎哟,说太多了说太多了~    下面上代码了

我们首先在.env(development / production)的文件中定义个变量,这个变量就是无操作多长时间进入锁屏,单位 s。也就是可配置的

# 锁屏时间(s)
VUE_APP_LOCK_TIME = 300

这个也就是说无操作5分钟后进入锁屏状态 

然后我们需要在Vuex中保存一个计时时间lockTime,也就是当这个时间大于等于我们设置的那个时间就进入锁屏,即 lockTime >= parseInt(process.env.VUE_APP_LOCK_TIME)

我这里分了个模块 common (src/store/modules/common.js)

export default {
  namespaced: true,
  state: {
    // 无操作计时时间
    lockTime: 0,
    // 当前是否为锁屏状态
    isLock: sessionStorage.getItem('isLock') || 'false',
  },
  mutations: {
    updatelockTime(state, lockTime) {
      state.lockTime = lockTime
    },
    updateisLock(state, isLock) {
      state.isLock = isLock
      sessionStorage.setItem('isLock', isLock)
    }
  }
}

然后是遮罩层(锁屏)什么时候进行显示的逻辑: 

我这里是封装在了mixins中,这是为了可以把锁屏的逻辑单独抽离出来,逻辑更清晰一些,后面如果说我不想在整个系统锁屏了,我只要在某些页面中,也就是只在系统的A页面、B页面中才会有锁屏,其他都不需要锁屏,那我们直接将逻辑混入到组件就可以了。

// 引入锁屏遮罩层组件
import Lock from '@/components/lock'

export default {
  data() {
    return {
      timer: null
    }
  },
  components: { Lock },
  computed: {
    isLock: {
      get() {
        return this.$store.state.common.isLock
      },
      set(isLock) {
        this.$store.commit('common/updateisLock', isLock)
      }
    },
    lockTime: {
      get() {
        return this.$store.state.common.lockTime
      },
      set(lockTime) {
        this.$store.commit('common/updatelockTime', lockTime)
      }
    }
  },
  watch: {
    lockTime() {
      if (this.lockTime >= parseInt(process.env.VUE_APP_LOCK_TIME)) {
        this.isLock = 'true'
      } else {
        if(this.isLock != 'false') {
          this.isLock = 'false'
        }
      }
    },
    isLock() {
      if (this.isLock == 'true') {
        this.removeHandle()
      } else {
        this.init()
      }
    }
  },
  mounted() {
    if(this.isLock == 'true') { // 锁屏状态下 浏览器刷新后保持锁屏状态
      this.lockTime = parseInt(process.env.VUE_APP_LOCK_TIME)
    } else {
      this.init()
    }
  },
  destroyed() {
    this.removeHandle()
  },
  methods: {
    init() {
      this.reckonByTime()
      document.addEventListener('click', this.clickHandle)
      document.addEventListener('dblclick', this.dblclickHandle)
      document.addEventListener('contextmenu', this.contextmenuHandle)
      document.addEventListener('mousemove', this.mousemoveHandle)
      document.addEventListener('mousewheel', this.mousewheelHandle)
      document.addEventListener('keydown', this.keydownHandle)
    },
    // 移除事件监听、定时器等
    removeHandle() {
      if (this.timer) {
        clearInterval(this.timer)
        this.timer = null
      }
      document.removeEventListener('click', this.clickHandle)
      document.removeEventListener('dblclick', this.dblclickHandle)
      document.removeEventListener('contextmenu', this.contextmenuHandle)
      document.removeEventListener('mousemove', this.mousemoveHandle)
      document.removeEventListener('mousewheel', this.mousewheelHandle)
      document.removeEventListener('keydown', this.keydownHandle)
    },
    // 无操作计时
    reckonByTime() {
      if (this.timer) {
        this.lockTime = 0
        clearInterval(this.timer)
        this.timer = null
      }
      this.timer = setInterval(() => {
        this.lockTime += 1
      }, 1000)
    },
    // 鼠标点击
    clickHandle() {
      this.reckonByTime()
    },
    // 鼠标双击
    dblclickHandle() {
      this.reckonByTime()
    },
    // 鼠标右键
    contextmenuHandle() {
      this.reckonByTime()
    },
    // 鼠标移动
    mousemoveHandle() {
      this.reckonByTime()
    },
    // 鼠标滚轮
    mousewheelHandle() {
      this.reckonByTime()
    },
    // 键盘按下
    keydownHandle(event) {
      const { altKey, ctrlKey, keyCode } = event
      if (altKey && ctrlKey && keyCode == 76) {
        // Ctrl + Alt + L 快捷键直接锁屏
        this.lockTime = parseInt(process.env.VUE_APP_LOCK_TIME)
      } else {
        this.reckonByTime()
      }
    }
  }
}

然后是锁屏组件(遮罩层组件) 

@/components/lock/index.vue 

<template>
  <div class="lock">
    <div>
      <img src="../../assets/img/lock/lock-icon.png" alt="">
      <el-input class="lockPasswdInp" v-show="!passwdError" ref="lockPasswdInp" size="small" show-password placeholder="密码" v-model="passwd">
        <template slot="append">
          <el-button @click="unLock()" style="background: transparent;">
            <i class="el-icon-right"></i>
          </el-button>
        </template>
      </el-input>
      <div class="passwdError-container" v-show="passwdError">
        <div class="passwdError">密码不正确。请再试一次。</div>
        <div class="confirm-btn" @click="reset()">确认</div>
      </div>
    </div>
    <!-- <img @click="logout" class="logout" src="../../assets/img/system/logout.png"> -->
  </div>
</template>
<script>
/**
 * 注意:由于遮罩层优先级太高 类似于$message之类的消息提示等会显示不出来
 */
export default {
  data() {
    return {
      passwd: '',
      passwdError: false
    }
  },
  computed: {
    lockPassword: () => process.env.VUE_APP_LOCK_PASSWORD || '123456'
  },
  mounted() {
    this.reset()
    document.addEventListener('keydown', this.keyDownHandle)
    document.addEventListener('contextmenu', this.contextmenuHandle)
  },
  destroyed() {
    document.removeEventListener('keydown', this.keyDownHandle)
    document.removeEventListener('contextmenu', this.contextmenuHandle)
  },
  methods:{
    // 重置初始化
    reset() {
      this.passwdError = false
      this.passwd = ''
      this.$nextTick(() => {
        this.$refs.lockPasswdInp.focus()
      })
    },
    // 解锁
    unLock() {
      if(this.passwd != this.lockPassword) {
        return this.passwdError = true
      }
      this.$store.commit('common/updatelockTime', 0)
    },
    // 监听鼠标按下事件,阻止 F12 事件
    keyDownHandle(event) {
      if(event.keyCode == 13) {
        if(this.passwdError) {
          this.reset()
        } else {
          this.unLock()
        }
      }
      return (event.keyCode !== 123 ) || (event.returnValue = false)
    },
    // 阻止鼠标右键事件
    contextmenuHandle(event) {
      return event.returnValue = false;
    },
    // // 退出登录
    // logout() {
    //   this.$store.commit('common/updatelockTime', 0)
    //   this.$router.replace('/login')
    //   /**
    //    * 走接口 清楚本地缓存等
    //    * ...
    //    */
    // }
  }
}
</script>
<style scoped>
.lock {
  width: 100%;
  height: 100vh;
  background: #ccc;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 999999;
  display: flex;
  justify-content: center;
  align-items: center;
  background-image: url('../../assets/img/lock/lock-bg.jpg');
  background-repeat: no-repeat;
  background-size: 100% 100%;
}
.lock > div {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.lockPasswdInp {
  margin-top: 8px;
}

/deep/ .el-input__inner {
  background-color: transparent !important;
  border: 1px solid #0076c8 !important;
  color: #fff;
}
/deep/ .el-input-group__append {
  background-color: rgba(6, 14, 22, .5);
  border: 1px solid #0076c8;
  border-left-color: transparent;
}

/deep/ .el-input-group__append:hover {
  background-color: rgba(6, 14, 22, .6);
  cursor: pointer;
}

.passwdError-container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.passwdError {
  width: 260px;
  text-align: center;
  color: #fff;
  font-size: 13px;
  margin: 10px 0;
}

.confirm-btn {
  width: 70px;
  height: 28px;
  text-align: center;
  line-height: 28px;
  color: #fff;
  font-size: 13px;
  background-color: rgba(6, 14, 22, .5);
  border: 1px solid #0076c8;
  border-radius: 3px;
  cursor: pointer;
}

.confirm-btn:hover {
  background-color: rgba(6, 14, 22, .8);
}

/* .logout {
  position: fixed;
  bottom: 20px;
  right: 20px;
  height: 40px;
  cursor: pointer;
} */
</style>

最后App.vue中混入上面的逻辑lock.js,然后引入lock.vue组件并使用 

因为我的需求是整个系统都要有锁屏的功能,所以我将其写在App.vue中 

<template>
  <div id="app">
    <router-view />
    <Lock v-if="isLock == 'true'" />
  </div>
</template>
<script>
import lockMixin from "@/mixins/lock";
export default {
  mixins: [lockMixin]
}
</script>
<style lang="scss">
* {
  margin: 0;
  padding: 0;
}

#app {
  width: 100vw;
  height: 100vh;
  overflow-y: hidden;
}
</style>

最好再给大家上个锁屏遮罩层的样式效果吧,我这个当然是在无操作5分钟才显示出来的哈 

Vue实现锁屏功能  

好了,这篇就这么多^v^ 文章来源地址https://www.toymoban.com/news/detail-475669.html

到了这里,关于Vue实现锁屏功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 13.0 SystemUI下拉状态栏定制二 锁屏页面横竖屏时钟都居中功能实现一

    在13.0的系统rom定制化开发中,在关于systemui的锁屏页面功能定制中,由于在平板横屏锁屏功能中,时钟显示的很大,并且是在左旁边居中显示的, 由于需要和竖屏显示一样,所以就需要用到小时钟显示,然后同样需要居中,所以就来分析下相关的源码,来实现具体的功能 在

    2024年01月17日
    浏览(57)
  • Android 13.0 SystemUI下拉状态栏定制二 锁屏页面横竖屏通知栏都居中功能实现

    在13.0的系统rom定制化开发中,在关于systemui的锁屏页面功能定制中,由于在平板横屏通知栏功能中,通知栏总是显示在右边,并且是在右边居中显示的, 由于需要和竖屏显示一样,所以就需要用到在时钟下面显示通知栏,然后同样需要居中显示通知栏,所以就来分析下相关的

    2024年02月20日
    浏览(51)
  • Android 10.0 SystemUI定制之通过系统属性控制锁屏页面通知栏显示与隐藏功能实现

    在10.0的系统产品开发中,在一些SystemUI的系统定制化开发中,在对锁屏页面的通知栏在某些情况下不需要显示通知栏,所以就需要 在systemui的通知栏布局页面中,通过属性来控制是否在锁屏页面的时候显示通知,具体就分析下systemui然后开发相关功能 在systemui系统中最主要的

    2024年02月04日
    浏览(58)
  • 做了个 chrome 插件实现 B 站视频截图功能,直接从当前视频帧无损复制

    起因是看 B 站视频想截个图很麻烦,右下角暂停按钮无法去除,于是写了一行代码把暂停按钮隐藏。 后经提醒,发现可以通过 canvas 获取视频帧来截取图片,于是写了如下代码完美获取视频帧。 用法:f12 打开 console 把这段代码粘贴回车执行即可下载视频帧。 完成后又稍作改

    2024年02月07日
    浏览(67)
  • 微信小程序 跳转页面经常会遇到判断是否登录情况。基于此需求,做了一个路由跳转拦截的jump组件

    组件代码非常简单 在根目录创建components目录 在components目录新建jump目录 在jump目录新建四个文件 index.js index.json index.wxml index.wxss 这个样式文件内容空就行

    2024年02月09日
    浏览(53)
  • 【业务功能篇20】Springboot java逻辑实现动态行转列需求

    在此前,我也写过一个行转列的文章,是用存储过程sql处理的一个动态的逻辑 Mysql 存储过程Mybatis框架call调用 实现动态行转列 那么后面我们同样又接收了业务的一个新需求,针对的是不同的业务数据,做的同样的一个展示数据报表,同样还是产品归属信息表头,拼接查询年

    2024年02月09日
    浏览(44)
  • 用Vue做个简单的比较两个数字的大小页面

    1、 考核知识点 创建vue实例和对v-model内置指令的使用 2、 练习目标 创建vue实例 掌握v-model内置指令的使用。 3、 需求分析 初始状态下,“比较”按钮不可点击,输入一个数字,按钮仍然不可点击,当两个数字输入完后,按钮变为可点击状态;点击下方“比较”按钮,显示比

    2024年02月11日
    浏览(36)
  • 【spring】集成Web、druid、jdbcTemple实现免登录时长两天半

    CSDN话题挑战赛第2期 参赛话题:学习笔记 *学习之路,长路漫漫,写学习笔记的过程就是把知识讲给自己听的过程。这个过程中,我们去记录思考的过程,便于日后复习,梳理自己的思路。学习之乐,独乐乐,不如众乐乐,把知识讲给更多的人听,何乐而不为呢? 🌕博客x主页

    2024年02月13日
    浏览(31)
  • 百度语音识别(语音转文字)vue版本 前端(后端需要做个请求转发即可)

    这个项目需要用到语音识别,最后选择的是百度语音识别。原因第一是项目中用到的地方不大,属于微型和小型功能点,第二就是属于临时增加的需求,没有太多的时间去开发,第三就是后端对于自主开发语音识别觉得较为困难,浪费时间。 加载语音识别的文件 下载recorde

    2024年02月12日
    浏览(53)
  • 我用Vue做了一个天气壁纸

    Hello大家好,我是李小白,是 b站 和 wallpaper engine 的同名作者,更多精彩请关注bilibili 会功夫的李白 ,本期带来的是 wallpaper engine 上面的一款天气壁纸,开发使用的是Vue,然后打包发到wallpaper engine,项目已经发到了github jl15988 ,请参考github perfect-weather ,欢迎Star。 目前该项

    2024年02月12日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包