您的位置:首页 > 技术中心 > 前端框架 >

基于Vue3和elementplus如何实现登录功能

时间:2023-05-10 17:20

登录页面:

基于Vue3和elementplus如何实现登录功能

注册页面:

基于Vue3和elementplus如何实现登录功能

(1)引入element-plus组件库

引入组件库的方式有好多种,在这里我就在main.js全局引入了.

npm i element-plus -S

main.js中代码:

import { createApp } from "vue";//element-plusimport ElementPlus from "element-plus";import "element-plus/dist/index.css";import App from "./App.vue";import router from "./router";import axios from "axios";import store from "./store";//创建实例const app = createApp(App);//全局应用配置app.config.globalProperties.$axios = axios; app.use(ElementPlus).use(store).use(router).mount("#app");

引入之后自己可以用几个按钮测试一下是否引入成功.

(2)登录及注册页面

html部分

views/account/Login.vue

<template>  <div id="login">    <div>      <div class="form-wrap">        <ul class="menu-tab">          <li            :class="{ current: current_menu === item.type }"            v-for="item in data.tab_menu"            :key="item.type"            @click="toggleMenu(item.type)"          >            {{ item.label }}          </li>        </ul>        <el-form          :model="data.form"          ref="account_form"          :rules="data.form_rules"          label-width="80px"        >          <el-form-item prop="username">            <label class="form-label">用户名</label>            <el-input type="password" v-model="data.form.username" />          </el-form-item>          <el-form-item prop="password">            <label class="form-label">密码</label>            <el-input type="password" v-model="data.form.password" />          </el-form-item>          <el-form-item v-show="current_menu === 'register'" prop="passwords ">            <label class="form-label">确认密码</label>            <el-input type="password" v-model="data.form.passwords" />          </el-form-item>          <el-form-item prop="code">            <label class="form-label">验证码</label>            <el-row :gutter="10">              <el-col :span="14">                <el-input v-model="data.form.code"></el-input>              </el-col>              <el-col :span="10">                <el-button                  type="success"                  class="el-button-block"                  @click="handleGetCode"                  >获取验证码</el-button                ></el-col              >            </el-row>          </el-form-item>          <el-form-item>            <el-button              type="danger"              class="el-button-block"              :disabled="data.submit_button_disabled"              :loading="data.submit_button_loading"              @click="submitForm"              >{{ current_menu === "login" ? "登录" : "注册" }}</el-button            >          </el-form-item>        </el-form>      </div>    </div>  </div></template>

js部分

<script>import { reactive, ref, getCurrentInstance, onBeforeUnmount } from "vue";import {  validate_email,  validate_password,  validate_code,} from "@/utils/validate";import { GetCode } from "@/api/common";import { Register, Login } from "@/api/account";import sha1 from "js-sha1"; //密码加密// ErrorHttpexport default {  setup() {    const instance = getCurrentInstance();    const { proxy } = getCurrentInstance();    console.log("instance", instance);    // console.log("proxy", proxy);    // 用户名校验    const validate_name_rules = (rule, value, callback) => {      let regEmail = validate_email(value);      if (value === "") {        callback(new Error("请输入邮箱"));      } else if (!regEmail) {        callback(new Error("邮箱格式不正确"));      } else {        callback();      }    };     //获取验证码    const handleGetCode = () => {      const username = data.form.username;      const password = data.form.password;      const passwords = data.form.passwords;      //校验用户名      if (!validate_email(username)) {        proxy.$message({          message: "用户名不能为空 或 格式不正确",          type: "error",        });        return false;      }       //校验密码      if (!validate_password(password)) {        proxy.$message({          message: "密码不能为空 或 格式不正确",          type: "error",        });        return false;      }       //判断为注册时,校验两次密码      if (data.current_menu === "redister" ** (password !== passwords)) {        proxy.$message({          message: "两次密码不一致",          type: "error",        });        return false;      }      //获取验证码接口      const requestData = {        username: data.form.username,        module: "register",      };       data.code_button_loading = true;      data.code_button_text = "发送中";      GetCode(requestData)        .then((res) => {          // console.log("123", res.data);验证码          // const data=res.resCode           const data = res;          if (data.resCode === 1024) {            proxy.$message.error(data.message);            return false;          }          // 成功 Elementui 提示          proxy.$message({            message: data.message,            type: "success",          });          //执行倒计时          countdown();        })        .catch((err) => {          console.log(err);          data.code_button_loading = false;          data.code_button_text = "发送验证码";        });       // ErrorHttp(requestData)      //   .then((res) => {      //     console.log(res.data);      //     // const data=res.resCode      //     const data = res.data;      //     if (data.resCode === 1024) {      //       proxy.$message.error(data.message);      //       return false;      //     }      //     // 成功 Elementui 提示      //     proxy.$message({      //       message: data.message,      //       type: "success",      //     });      //     //执行倒计时      //     countdown();      //   })      //   .catch((err) => {      //     console.log(err);      //     data.code_button_loading = false;      //     data.code_button_text = "发送验证码";      //   });    };     /** 倒计时 */    const countdown = (time) => {      if (time && typeof time !== "number") {        return false;      }      let second = time || 60; // 默认时间      data.code_button_loading = false; // 取消加载      data.code_button_disabled = true; // 禁用按钮      data.code_button_text = `倒计进${second}秒`; // 按钮文本      // 判断是否存在定时器,存在则先清除      if (data.code_button_timer) {        clearInterval(data.code_button_timer);      }      // 开启定时器      data.code_button_timer = setInterval(() => {        second--;        data.code_button_text = `倒计进${second}秒`; // 按钮文本        if (second <= 0) {          data.code_button_text = `重新获取`; // 按钮文本          data.code_button_disabled = false; // 启用按钮          clearInterval(data.code_button_timer); // 清除倒计时        }      }, 1000);    };     // 组件销毁之前 - 生命周期    onBeforeUnmount(() => {      clearInterval(data.code_button_timer); // 清除倒计时    });     // 校验确认密码    const validate_password_rules = (rule, value, callback) => {      let regPassword = validate_password(value);      if (value === "") {        callback(new Error("请输入密码"));      } else if (!regPassword) {        callback(new Error("请输入>=6并且<=20位的密码,包含数字、字母"));      } else {        callback();      }    };     // 校验确认密码    const validate_passwords_rules = (rule, value, callback) => {      // 如果是登录,不需要校验确认密码,默认通过      if (data.current_menu === "login") {        callback();      }      let regPassword = validate_password(value);      // 获取“密码”      const passwordValue = data.form.password;      if (value === "") {        callback(new Error("请输入密码"));      } else if (!regPassword) {        callback(new Error("请输入>=6并且<=20位的密码,包含数字、字母"));      } else if (passwordValue && passwordValue !== value) {        callback(new Error("两次密码不一致"));      } else {        callback();      }    };     const validate_code_rules = (rule, value, callback) => {      let regCode = validate_code(value);      // 激活提交按钮      data.submit_button_disabled = false;      if (value === "") {        callback(new Error("请输入验证码"));      } else if (!regCode) {        callback(new Error("请输入6位的验证码"));      } else {        callback();      }    };     // 提交表单    const submitForm = () => {      // let res = proxy.$refs.account_form;      proxy.$refs.account_form.validate((valid) => {        if (valid) {          console.log("提交表单", current_menu.value);          current_menu.value === "login" ? login() : register();          // register();        } else {          alert("error submit!");          return false;        }      });      // console.log(" 提交表单", res);    };    /** 登录 */    const login = () => {      const requestData = {        username: data.form.username,        password: sha1(data.form.password),        code: data.form.code,      };      data.submit_button_loading = true;      Login(requestData)        .then((response) => {          console.log("login", response);          data.submit_button_loading = false;          proxy.$message({            message: response.message,            type: "success",          });           reset();        })        .catch((error) => {          console.log("登录失败", error);          data.submit_button_loading = false;        });    };    //注册    const register = () => {      const requestData = {        username: data.form.username,        password: sha1(data.form.password),        code: data.form.code,      };      data.submit_button_loading = true;      Register(requestData)        .then((res) => {          proxy.$message({            message: res.message,            type: "success",          });        })        .catch((error) => {          console.log("注册错误", error);          data.submit_button_loading = false;        });    };     /** 重置 */    const reset = () => {      // 重置表单      proxy.$refs.form.resetFields();      // 切回登录模式      data.current_menu = "login";      // 清除定时器      data.code_button_timer && clearInterval(data.code_button_timer);      // 获取验证码重置文本      data.code_button_text = "获取验证码";      // 获取验证码激活      data.code_button_disabled = false;      // 禁用提交按钮      data.submit_button_disabled = true;      // 取消提交按钮加载      data.submit_button_loading = false;    };     const data = reactive({      form_rules: {        username: [{ validator: validate_name_rules, trigger: "change" }],        password: [{ validator: validate_password_rules, trigger: "change" }],        passwords: [{ validator: validate_passwords_rules, trigger: "change" }],        code: [{ validator: validate_code_rules, trigger: "change" }],      },      form: {        username: "", // 用户名        password: "", // 密码        passwords: "", // 确认密码        code: "", // 验证码      },      tab_menu: [        { type: "login", label: "登录" },        { type: "register", label: "注册" },      ],      /**       * 获取验证码按钮交互       */      code_button_disabled: false,      code_button_loading: false,      code_button_text: "获取验证码",      code_button_timer: null,      // 提交按钮      submit_button_disabled: true,    });     const toggleMenu = (type) => {      current_menu.value = type;    };    let current_menu = ref(data.tab_menu[0].type);    // const dataItem = toRefs(data);    return {      // ...dataItem,      data,      current_menu,      toggleMenu,      handleGetCode,      submitForm,      register,      reset,      login,    };  },};</script>

css部分(使用了scss)

<style lang="scss" scoped>#login {  height: 100vh;  background-color: #344a5f;}.form-wrap {  width: 320px;  padding-top: 100px;  margin: auto;}.menu-tab {  text-align: center;  li {    display: inline-block;    padding: 10px 24px;    margin: 0 10px;    color: #fff;    font-size: 14px;    border-radius: 5px;    cursor: pointer;    &.current {      background-color: rgba(0, 0, 0, 0.1);    }  }}.form-label {  display: block;  color: #fff;  font-size: 14px;}</style>

(3)封装一些公共方法及样式

新建styles文件夹,然后新建几个样式文件:

normalize.scss

/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ /* Document   ========================================================================== */ /** * 1. Correct the line height in all browsers. * 2. Prevent adjustments of font size after orientation changes in iOS. */ /* div的默认样式不存在padding和margin为0的情况*/ html, body, span, applet, object, iframe, h2, h3, h4, h5, h6, h7, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, fieldset, form, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed,  figure, figcaption, footer, header, hgroup,  menu, nav, output, ruby, section, summary, time, mark, audio, video {   margin: 0;   padding: 0;   font-size: 100%;   font: inherit;   vertical-align: baseline; } /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure,  footer, header, hgroup, menu, nav, section {   display: block; } html {    line-height: 1.15; /* 1 */    -webkit-text-size-adjust: 100%; /* 2 */  }    /* Sections     ========================================================================== */    /**   * Remove the margin in all browsers.   */    body {    margin: 0;    font-family: 'Microsoft YaHei';    font-size: 14px;  }    /**   * Render the `main` element consistently in IE.   */    main {    display: block;  }    /**   * Correct the font size and margin on `h2` elements within `section` and   * `article` contexts in Chrome, Firefox, and Safari.   */      /* Grouping content     ========================================================================== */    /**   * 1. Add the correct box sizing in Firefox.   * 2. Show the overflow in Edge and IE.   */    hr {    box-sizing: content-box; /* 1 */    height: 0; /* 1 */    overflow: visible; /* 2 */  }    /**   * 1. Correct the inheritance and scaling of font size in all browsers.   * 2. Correct the odd `em` font sizing in all browsers.   */    pre {    font-family: monospace, monospace; /* 1 */    font-size: 1em; /* 2 */  }    /* Text-level semantics     ========================================================================== */    /**   * Remove the gray background on active links in IE 10.   */    a {    background-color: transparent;    text-decoration: none;  }     /**   * 1. Remove the bottom border in Chrome 57-   * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.   */    abbr[title] {    border-bottom: none; /* 1 */    text-decoration: underline; /* 2 */    text-decoration: underline dotted; /* 2 */  }    /**   * Add the correct font weight in Chrome, Edge, and Safari.   */    b,  strong {    font-weight: bolder;  }    /**   * 1. Correct the inheritance and scaling of font size in all browsers.   * 2. Correct the odd `em` font sizing in all browsers.   */    code,  kbd,  samp {    font-family: monospace, monospace; /* 1 */    font-size: 1em; /* 2 */  }    /**   * Add the correct font size in all browsers.   */    small {    font-size: 80%;  }    /**   * Prevent `sub` and `sup` elements from affecting the line height in   * all browsers.   */    sub,  sup {    font-size: 75%;    line-height: 0;    position: relative;    vertical-align: baseline;  }    sub {    bottom: -0.25em;  }    sup {    top: -0.5em;  }    /* Embedded content     ========================================================================== */    /**   * Remove the border on images inside links in IE 10.   */    img {    display: block;    border-style: none;  }    /* Forms     ========================================================================== */    /**   * 1. Change the font styles in all browsers.   * 2. Remove the margin in Firefox and Safari.   */    button,  input,  optgroup,  select,  textarea {    font-family: inherit; /* 1 */    font-size: 100%; /* 1 */    margin: 0; /* 2 */  }    /**   * Show the overflow in IE.   * 1. Show the overflow in Edge.   */    button,  input { /* 1 */    overflow: visible;  }    /**   * Remove the inheritance of text transform in Edge, Firefox, and IE.   * 1. Remove the inheritance of text transform in Firefox.   */    button,  select { /* 1 */    text-transform: none;  }    /**   * Correct the inability to style clickable types in iOS and Safari.   */    button,  [type="button"],  [type="reset"],  [type="submit"] {    -webkit-appearance: button;  }    /**   * Remove the inner border and padding in Firefox.   */    button::-moz-focus-inner,  [type="button"]::-moz-focus-inner,  [type="reset"]::-moz-focus-inner,  [type="submit"]::-moz-focus-inner {    border-style: none;    padding: 0;  }    /**   * Restore the focus styles unset by the previous rule.   */    button:-moz-focusring,  [type="button"]:-moz-focusring,  [type="reset"]:-moz-focusring,  [type="submit"]:-moz-focusring {    outline: 1px dotted ButtonText;  }    /**   * Correct the padding in Firefox.   */    fieldset {    padding: 0.35em 0.75em 0.625em;  }    /**   * 1. Correct the text wrapping in Edge and IE.   * 2. Correct the color inheritance from `fieldset` elements in IE.   * 3. Remove the padding so developers are not caught out when they zero out   *    `fieldset` elements in all browsers.   */    legend {    box-sizing: border-box; /* 1 */    color: inherit; /* 2 */    display: table; /* 1 */    max-width: 100%; /* 1 */    padding: 0; /* 3 */    white-space: normal; /* 1 */  }    /**   * Add the correct vertical alignment in Chrome, Firefox, and Opera.   */    progress {    vertical-align: baseline;  }    /**   * Remove the default vertical scrollbar in IE 10+.   */    textarea {    overflow: auto;  }    /**   * 1. Add the correct box sizing in IE 10.   * 2. Remove the padding in IE 10.   */    [type="checkbox"],  [type="radio"] {    box-sizing: border-box; /* 1 */    padding: 0; /* 2 */  }    /**   * Correct the cursor style of increment and decrement buttons in Chrome.   */    [type="number"]::-webkit-inner-spin-button,  [type="number"]::-webkit-outer-spin-button {    height: auto;  }    /**   * 1. Correct the odd appearance in Chrome and Safari.   * 2. Correct the outline style in Safari.   */    [type="search"] {    -webkit-appearance: textfield; /* 1 */    outline-offset: -2px; /* 2 */  }    /**   * Remove the inner padding in Chrome and Safari on macOS.   */    [type="search"]::-webkit-search-decoration {    -webkit-appearance: none;  }    /**   * 1. Correct the inability to style clickable types in iOS and Safari.   * 2. Change font properties to `inherit` in Safari.   */    ::-webkit-file-upload-button {    -webkit-appearance: button; /* 1 */    font: inherit; /* 2 */  }    /* Interactive     ========================================================================== */    /*   * Add the correct display in Edge, IE 10+, and Firefox.   */    details {    display: block;  }    /*   * Add the correct display in all browsers.   */    summary {    display: list-item;  }    /* Misc     ========================================================================== */    /**   * Add the correct display in IE 10+.   */    template {    display: none;  }    /**   * Add the correct display in IE 10.   */    [hidden] {    display: none;  }   ul, li { list-style: none; }

elementui.scss(当时测试时用的)

.el-button-block{    display: block;    width: 100%;}

新建main.scss(引入上方两个样式文件)

@import "./normalize.scss";@import './elementui.scss'

vue.config.js配置一下样式文件

  css: {    // 是否使用css分离插件 ExtractTextPlugin    extract: true,    // 开启 CSS source maps?    sourceMap: false,    // css预设器配置项    loaderOptions: {      scss: {        additionalData: `@import "./src/styles/main.scss";`,      },    },    // requireModuleExtension: true,  },

登录中封装的校验方法

新建utils文件夹,

a.validate.js

// 校验邮箱export function validate_email(value) {  let regEmail = /^([a-zA-Z]|[0-9])(w|-)+@[a-zA-Z0-9]+.([a-zA-Z]{2,4})$/;  return regEmail.test(value);} // 校验密码export function validate_password(value) {  let regPassword = /^(?!D+$)(?![^a-zA-Z]+$)S{6,20}$/;  return regPassword.test(value);} // 校验验证码export function validate_code(value) {  let regCode = /^[a-z0-9]{6}$/;  return regCode.test(value);}

封装请求方法

npm i axios -S

记得先在main.js中引入axios

import axios from "axios";

utils中新建request.js

import axios from "axios";//引入element-plusimport { ElMessage } from "element-plus";console.log("11", process.env.VUE_APP_API); //undefined?? //创建实例const service = axios.create({  baseURL: "/devApi", //请求地址  timeout: 5000, //超时}); //添加请求拦截器service.interceptors.request.use(  function (config) {    //在发送请求之前做些什么    return config;  },  function (error) {    console.log(error.request);    const errorData = JSON.parse(error.request.response);    if (errorData.message) {      //判断是否具有message属性      ElMessage({        message: errorData.message,        type: "error",      });    }    //对请求错误做些什么    return Promise.reject(errorData);  }); //添加响  应拦截器service.interceptors.response.use(  function (response) {    //对响应数据做些什么    console.log("响应数据", response);    const data = response.data;    if (data.resCode === 0) {      return Promise.resolve(data);    } else {      ElMessage({        message: data.message,        type: "error",      });      return Promise.reject(data);    }  },  function (error) {    //对响应错误做些什么    const errorData = JSON.parse(error.request.response);    if (errorData.message) {      //判断是否具有message属性      ElMessage({        message: errorData.message,        type: "error",      });    }     return Promise.reject(errorData);  }); //暴露serviceexport default service;

(4)配置环境变量

和项目根路径同级,新建几个文件:

.env.development

VUE_APP_API = '/devApi'

可以自定义,但是必须是VUE_APP_XXX的格式

.env.production

VUE_APP_API = '/production'

.env.test

VUE_APP_API = '/test'

配置完后记得在axios文件中打印一下,看下能输出自己配置的环境变量吗.

基于Vue3和elementplus如何实现登录功能

(5)配置代理(跨域)

基本大同小异,代理地址改成自己的就可以了.

  devServer: {    open: false, //编译完成是否自动打开网页    host: "0.0.0.0", //指定使用地址,默认是localhost,0.0.0.0代表可以被外界访问    port: 8080,    proxy: {      "/devApi": {        target: "http://v3.web-jshtml.cn/api", //(必选)API服务器的地址        changeOrigin: true, //(必选) 是否允许跨域        ws: false, //(可选) 是否启用websockets        secure: false, //(可选) 是否启用https接口        pathRewrite: {          "^/devApi": "", //匹配开头为/devApi的字符串,并替换成空字符串        },      },    },  },

以上就是基于Vue3和elementplus如何实现登录功能的详细内容,更多请关注Gxl网其它相关文章!

热门排行

今日推荐

热门手游