Vue实战篇三十五:实现滑动拼图验证登录

news2025/1/23 12:57:19

系列文章目录

Vue基础篇一:编写第一个Vue程序
Vue基础篇二:Vue组件的核心概念
Vue基础篇三:Vue的计算属性与侦听器
Vue基础篇四:Vue的生命周期(秒杀案例实战)
Vue基础篇五:Vue的指令
Vue基础篇六:Vue使用JSX进行动态渲染
Vue提高篇一:使用Vuex进行状态管理
Vue提高篇二:使用vue-router实现静态路由
Vue提高篇三:使用vue-router实现动态路由
Vue提高篇四:使用Element UI组件库
Vue提高篇五:使用Jest进行单元测试
Vue提高篇六: 使用Vetur+ESLint+Prettier插件提升开发效率
Vue实战篇一: 使用Vue搭建注册登录界面
Vue实战篇二: 实现邮件验证码发送
Vue实战篇三:实现用户注册
Vue实战篇四:创建多步骤表单
Vue实战篇五:实现文件上传
Vue实战篇六:表格渲染动态数据
Vue实战篇七:表单校验
Vue实战篇八:实现弹出对话框进行交互
Vue实战篇九:使用省市区级联选择插件
Vue实战篇十:响应式布局
Vue实战篇十一:父组件获取子组件数据的常规方法
Vue实战篇十二:多项选择器的实际运用
Vue实战篇十三:实战分页组件
Vue实战篇十四:前端excel组件实现数据导入
Vue实战篇十五:表格数据多选在实际项目中的技巧
Vue实战篇十六:导航菜单
Vue实战篇十七:用树型组件实现一个知识目录
Vue实战篇十八:搭建一个知识库框架
Vue实战篇十九:使用printjs打印表单
Vue实战篇二十:自定义表格合计
Vue实战篇二十一:实战Prop的双向绑定
Vue实战篇二十二:生成二维码
Vue实战篇二十三:卡片风格与列表风格的切换
Vue实战篇二十四:分页显示
Vue实战篇二十五:使用ECharts绘制疫情折线图
Vue实战篇二十六:创建动态仪表盘
Vue实战篇二十七:实现走马灯效果的商品轮播图
Vue实战篇二十八:实现一个手机版的购物车
Vue实战篇二十九:模拟一个简易留言板
Vue项目实战篇一:实现一个完整的留言板(带前后端源码下载)
Vue实战篇三十:实现一个简易版的头条新闻
Vue实战篇三十一:实现一个改进版的头条新闻
Vue实战篇三十二:实现新闻的无限加载
Vue实战篇三十三:实现新闻的浏览历史
Vue实战篇三十四:给新闻WebApp加入模拟注册登录功能
Vue项目实战篇二:实现一个完整的新闻WebApp客户端(带前端源码下载)

文章目录

  • 系列文章目录
  • 一、背景
  • 二、引入滑动拼图验证组件
  • 三、修改登录页面
  • 四、效果演示
  • 五、源码地址


一、背景

  • 在前面的文章中,我们编写过登录页面。用户在登录时需要输入账号与密码,再点击登录按钮进行登录。
    在这里插入图片描述
  • 这次,我们将设置滑块拼图进行登录验证,以防止恶意的机器人登录。
    在这里插入图片描述

二、引入滑动拼图验证组件

  • 我们将引入vue-monoplasty-slide-verify组件,实现滑动拼图验证。
  • GitHub网址
  • 演示网址
    在这里插入图片描述
  • 安装组件
npm install --save vue-monoplasty-slide-verify
  • 在main.js文件中导入组件
import Vue from 'vue'
...
import SlideVerify from 'vue-monoplasty-slide-verify'

Vue.use(SlideVerify)
...
new Vue({
  el: '#app',
  router,
  store,
  render: h => h(App)
})

三、修改登录页面

  • 我们需要在登录页面中加入该组件,并且设置只有滑动验证成功后,才能点击登录按钮(也可以根据个人需要,取消该登录按钮,变成滑动验证成功后,即可直接登录
    在这里插入图片描述
  • 以下是修改后的登录页面源码:
<template>
  <div v-if="logined == true" class="content">
    <div class="header">
      <div class="user">
        <img class="avatar" src="@/assets/images/avatar.png">
        <p class="user-name">{{ loginForm.username }}</p>
        <img class="right" src="@/assets/images/right.png">
      </div>
      <div class="info">
        <div class="histroy" @click="toHistroy()">
          <span class="histroy-count">{{ histroryCount }}</span>
          <span class="histroy-text">{{ '浏览历史' }}</span>
        </div>
        <div class="fav">
          <span class="fav-count">{{ favCount }}</span>
          <span class="fav-text">{{ '我的收藏' }}</span>
        </div>
      </div>
    </div>
    <div class="logout">
      <el-button
        size="medium"
        type="danger"
        style="width: 90%"
        @click.native.prevent="logout"
      >
        <span>退 出 登 录</span>
      </el-button>
    </div>
  </div>
  <div v-else>
    <el-form
      ref="loginForm"
      :model="loginForm"
      :rules="loginRules"
      label-position="left"
      label-width="0px"
      class="login-form"
    >
      <h2 class="title">欢迎使用</h2>
      <el-form-item prop="username">
        <el-input
          v-model="loginForm.username"
          type="text"
          auto-complete="off"
          placeholder="账号"
        >
          <svg-icon
            slot="prefix"
            icon-class="user"
            class="el-input__icon input-icon"
          />
        </el-input>
      </el-form-item>
      <el-form-item prop="password">
        <el-input
          v-model="loginForm.password"
          type="password"
          auto-complete="off"
          placeholder="密码"
          @keyup.enter.native="handleLogin"
        >
          <svg-icon
            slot="prefix"
            icon-class="password"
            class="el-input__icon input-icon"
          />
        </el-input>
      </el-form-item>
      <!-- 滑动拼图验证区 -->
      <el-form-item style="">
        <slide-verify
          :l="42"
          :r="10"
          :w="350"
          :h="155"
          slider-text="向右滑动"
          @success="onSuccess"
          @fail="onFail"
        />
      </el-form-item>
       <!-- ---- -->
      <el-form-item style="width: 100%">
        <el-button
          :disabled="!verified"
          :loading="loading"
          size="medium"
          type="danger"
          style="width: 100%"
          @click.native.prevent="handleLogin"
        >
          <span v-if="!loading">登 录</span>
          <span v-else>登 录 中...</span>
        </el-button>
      </el-form-item>

      <p class="register">
        <!-- <span class="memo">请使用Chrome,Firefox,IE 10+  </span> -->
        还没有帐号?
        <a href="/register" type="primary">立即注册</a>
      </p>
    </el-form>
  </div>
</template>

<script>

export default {
  data() {
    return {
      loginForm: {
        username: '',
        password: ''
      },
      loginRules: {
        username: [
          { required: true, trigger: 'blur', message: '用户名不能为空' }
        ],
        password: [
          { required: true, trigger: 'blur', message: '密码不能为空' }
        ]
      },
      loading: false,
      // 图形验证是否通过
      verified: false
    }
  },
  computed: {
    histroryCount() {
      return this.$store.state.my.histroy.length
    },
    favCount() {
      return this.$store.state.my.favourite.length
    },
    logined() {
      return this.$store.state.my.logined
    }
  },
  methods: {
    // 模拟登录成功
    handleLogin() {
      this.$refs.loginForm.validate((valid) => {
        if (valid) {
          this.loading = true
          this.$store.commit('SET_LOGIN', true)
          this.loading = false
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },
    // 模拟注销登录
    logout() {
      this.$store.commit('SET_LOGIN', false)
      this.loginForm.username = ''
      this.loginForm.password = ''
      this.verified = false
    },
    toHistroy() {
      if (this.histroryCount > 0) {
        this.$router.push('/list')
      }
    },
    // 图形验证通过后,将登录按钮置为可用
    onSuccess() {
      this.verified = true
    }
  }
}

</script>

<style lang="scss"  scoped>
.login-form {
  border-radius: 6px;
  background: #ffffff;
  width: 100%;
  padding: 25px 25px 5px 25px;
  margin-top: 25px;
  .el-input {
    height: 38px;
    input {
      height: 38px;
    }
  }
  .input-icon {
    height: 39px;
    width: 14px;
    margin-left: 2px;
  }
}

.title {
  margin: 0 auto 30px auto;
  text-align: center;
  color: #707070;
}

.register {
  float: right;
  font-size: 13px;
  // color: rgb(24, 144, 255);
}
a {
  color: #e72521;
  text-decoration: none;
  background-color: transparent;
  outline: none;
  cursor: pointer;
  transition: color 0.3s;
}
a:hover {
  color: #e72521;
}

.content {
  width: 100%;
  height: 100%;
  background-color: rgb(252, 248, 248);
}
.header {
  width: 100%;
  height: 5.33rem;
  background-color: #fff;
}

.user {
  margin-top: 0.5rem;
  overflow: hidden;
  padding: 0.5rem;
  height: 2.5rem;
  width: 100%;
}

.avatar {
  float: left;
  width: 1.8rem;
  height: 1.8rem;
  border-radius: 50%;
}

.user-name {
  float: left;
  margin-top: 0.6rem;
  margin-left: 0.5rem;
  color: #404040;
  font-size: 18px;
}

.right {
  float: right;
  width: 0.8rem;
  height: 0.8rem;
  margin-top: 0.6rem;
}

.info {
  float: left;
  padding: 1rem;
  height: 2.5rem;
  width: 100%;
}
.histroy {
  display: flex;
  float: left;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.histroy-count {
  color: #404040;
  font-size: 18px;
}

.histroy-text {
  margin-top: 0.1rem;
  color: #9b9191;
  font-size: 14px;
}

.fav {
  display: flex;
  float: right;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.fav-count {
  color: #404040;
  font-size: 18px;
}

.fav-text {
  margin-top: 0.1rem;
  color: #9b9191;
  font-size: 14px;
}

.logout {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 2rem;

}
</style>

四、效果演示

在这里插入图片描述

五、源码地址

  • 请关注文末的微信公众号,回复“新闻客户端”,即可前端完整源码。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/408182.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Please set spring.main.web-application-type=reactive or remove spring-boot-starter-web dependency.

一、问题在启动springcloud的gateway模块的时候报错Please set spring.main.web-application-typereactive or remove spring-boot-starter-web dependency.二、问题产生的原因gateway组件中的 spring-boot-starter-webflux 和 springboot作为web项目启动必不可少的 spring-boo…

前端如何将静态页面部署到服务器,并可以通过公网ip访问。

问题描述 作为卑微的前端页面仔。在我们公司项目上线的时候&#xff0c;一般都是我们前端 npm run build&#xff0c;然后直接把打出来的dist包丢给后端&#xff0c;后端上传到服务器完成前端的部署。这个时候我就很好奇&#xff0c;页面是怎么上传到服务器的呢&#xff1f;上…

vue使用pinia (vue2/vue3)

pinia是什么&#xff1f;Pinia 是 Vue.js 的轻量级状态管理库 官方网站&#xff1a;Pinia 中文文档: 介绍 | Pinia 中文文档 pinia与vuex4 相同 是vue 官方 状态管理工具(作者是 Vue 核心团队成员&#xff09;是vue开发者工具支持pinia 不同 pinia相比vuex4&#xff0c…

云E办Springboot+vue——前端项目完整版(含源码)

一、项目简介 项目背景&#xff1a;受疫情的影响&#xff0c;许多企业由线上办公转为线下办公。随着线上办公的人数的增多&#xff0c;线上办公的优点逐步凸显&#xff1a;通过实现工作流程的自动化、节省企业办公费用、实现绿色办公&#xff0c;同时提升办公效率。 项目介绍…

uniapp在小程序中登录,获取用户信息,获取手机号逻辑记录

这里写目录标题概述uniapp小程序的授权描述授权的详细说明及使用1、微信小程序通过uni.login()方法可以获取到微信提供的code2、通过登录获取的code码可以以获取用户唯一标识openid以及会话密钥sessionkey用于解密获取手机的加密信息3、通过微信提供的获取微信手机号的方法getp…

ELK企业级日志分析平台(二)

文章目录一、kibana数据可视化1.部署2.定制数据可视化&#xff08;1&#xff09;网站访问量&#xff08;2&#xff09;访问量排行榜&#xff08;3&#xff09;创建dashboard&#xff0c;大屏展示二、ES集群监控1.启用xpack认证2.metricbeat监控3.filebeat日志采集一、kibana数据…

【玩转CSS】一文带你了解浮动

&#x1f525;一个人走得远了&#xff0c;就会忘记自己为了什么而出发&#xff0c;希望你可以不忘初心&#xff0c;不要随波逐流&#xff0c;一直走下去&#x1f3b6; &#x1f98b; 欢迎关注&#x1f5b1;点赞&#x1f44d;收藏&#x1f31f;留言&#x1f43e; &#x1f984; …

牛客前端刷题(六)—— JS基础

还在担心面试不通过吗?给大家推荐一个超级好用的刷面试题神器:牛客网,里面涵盖了各个领域的面试题库,还有大厂真题哦! 赶快悄悄的努力起来吧,不苒在这里衷心祝愿各位大佬都能顺利通过面试。 面试专栏分享,感觉有用的小伙伴可以点个订阅,不定时更新相关面试题:面试专栏…

前端面试中经常提到的LRU缓存策略详解

&#x1f431; 个人主页&#xff1a;不叫猫先生 &#x1f64b;‍♂️ 作者简介&#xff1a;2022年度博客之星前端领域TOP 2&#xff0c;前端领域优质作者、阿里云专家博主&#xff0c;专注于前端各领域技术&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &am…

微信小程序解决view点击事件穿透地图map触发markertap

微信小程序中使用map组件&#xff0c;ios手机中点击地图上的view&#xff0c;会触发底下的markertap&#xff0c;只要底下如果有marker点的话。 这就造成了用户体验不是很好。 然后无意间我发现点击能滑动的scroll-view反而不会触发底下的markertap&#xff0c;就等于是一个不…

HTML介绍以及常用代码

HTML 网页基础 html(Hyper Text Markup Language)超文本标 记语言&#xff0c;发明者: Tim Berners-leehtml主要是定义网页内容和结构的。html是编 写网页的语言。html只能运行在浏览器上面网页的技术包含: html(编写网页结构&#xff0c;类似人 的骨架)&#xff0c;css(层叠…

前端启动项目npm run dev报错npm ERR! missing script: dev

今天遇到了这样一个nt问题 突然前端跑不起来后面发现是进行npm run dev 命令的时候少进入一层目录 进去之后就可以了对此遇到这个bug我还查了很多blog 发现还有以下两种原因1.打开的是当前文件夹&#xff0c;但是文件夹package.js里的scripts确实没有dev,输入vue init webpack …

【node进阶】深入浅出前后端身份验证(下)---JWT

✅ 作者简介&#xff1a;一名普通本科大三的学生&#xff0c;致力于提高前端开发能力 ✨ 个人主页&#xff1a;前端小白在前进的主页 &#x1f525; 系列专栏 &#xff1a; node.js学习专栏 ⭐️ 个人社区 : 个人交流社区 &#x1f340; 学习格言: ☀️ 打不倒你的会使你更强&a…

【JavaScript】JS实用案例分享:选择器组件 | 简易计算器

&#x1f5a5;️ NodeJS专栏&#xff1a;Node.js从入门到精通 &#x1f5a5;️ 博主的前端之路&#xff08;源创征文一等奖作品&#xff09;&#xff1a;前端之行&#xff0c;任重道远&#xff08;来自大三学长的万字自述&#xff09; &#x1f5a5;️ TypeScript知识总结&…

Axure RP9使用指南

1、快捷键 选中图层移动到上一层 ctrl [ 选中图层移动到下一层 ctrl ] 选中图层移动到顶层 ctrl shift [ 选中图层移动到底层 ctrl shift ] 合并为一组 ctrl G 取消合并 ctrl shift G 锁定位置和尺寸 ctrl K 解锁 ctrl shift K 拖动页面可以按住空格再通过鼠标拖动…

CSS实现文字颜色渐变

三行代码即可实现&#xff1a; background: linear-gradient(to bottom, #ffff, #f8fdff, #acf5ff, #67eeff, #24d8ff);-webkit-background-clip: text;color: transparent; 一 先设置背景颜色渐变 background 渐变属性可选值&#xff1a; 1 linear-gradient 为线性渐变…

JavaScript的节点操作 —— 增加节点

目录 JavaScript中的节点操作分为&#xff1a;增、删、改、查&#xff08;获取&#xff09;&#xff0c;四大类型。 我们直接利用案例来学习&#xff1a; HTML布局代码&#xff1a; JavaScript代码实现&#xff1a; 第一步&#xff1a;获取所有要用到的元素对象&#xff…

Vue3中toRef以及toRefs的基本使用

toRef以及toRefs 作用:创建一个ref对象&#xff0c;其value值指向另一个对象中的某个属性。 语法&#xff1a;const name toRef(obj,name) 应用&#xff1a;要将响应式对象中的某个属性单独提供给外部使用时 拓展:toRefs与toRef功能一致&#xff0c;但可以批量创建多个ref对…

vue报错 Error in render: “TypeError: Cannot read properties of undefined (reading ‘nickname‘)“

起因&#xff1a;我用axios请求数据&#xff08;可以看见数据了&#xff0c;已经请求成功的&#xff09;&#xff0c;最后加载在模板上&#xff08;页面模板上有内容&#xff09;&#xff0c;但是控制台出现了一个奇怪的错误 在created()钩子函数请求接口并报错数据&#xff0…

css 如何实现文本竖排、横排展示

writing-mode 该属性定义了文本在水平或垂直方向上如何排布 writing-mode:horizontal-tb | vertical-rl | vertical-lr | sideways-rl | sideways-lr接下来和我一起看看各个属性值的用法吧&#xff01;Go! <style>.root {border: 1px solid green;width: 400px;height: 4…