老张跟着老许学前端之-------登录页面的闭环

最近在写许老师之前做的项目,写到了登录页面,我有一直以为登录页面就几个输入框,几个按钮,然后输入以后直接交互切换页面就行了,是个很简单的页面,结果,许老师给我说,登录页是一个闭环,它是即简单又复杂,登录页有几个选项,输入账号密码,然后去登录,忘记密码,更改新密码后,重新登录,注册账号,注册成功后,去登录,他们是一套,然后登录后,上方还得有退出,退出后更改上方头部样式,出现登录和注册两个按钮,点击登录回到哪个页面,点击注册又回到哪个页面,非常的麻烦,他是一个系统的方式,接下来,我就把我写出的登录闭环系统写成文章,方便未来查询和解惑。

登录页:

注册页: 

忘记密码页: 

登录后头部形态: 

退出后头部形态:

 以上就是ui画出的登录系统的一套,接下来,我们就开始代码逻辑:

1、 判断布局:

首先,看到这个设计稿,我们能清楚的知道,用户进入页面的第一选择,一定是登录页,登录页是两部分组成左边的背景图加logo,右边的登录的一套,那么我们可以知道,左边是不动的,动的只有右边的登录,注册和忘记密码,这样,我们就可以有一个主页面,里面写死的是左边的背景图和logo,而右边是由三个组件组成的,三个组件相互切换就可以了,接下来,我们就开始给vue配置他所需要的包

2、配置包:

因为我现在写的是登录,所以,其他的我们不管,先配置登录所需要的包,分别是vuex(状态管理器),less(css框架),router(路由),elementUi(ui框架),具体配置方式就不写了,前面的文章有写。配置好包以后,先把登录页作为主页面,就是首页,给他添加路由:

{
	path: "/",
	component: HomePage,
},

然后把数据结构整理出来:

很明显,登录后要跳转到另外一个页面,所以,要给另外一个页面也配置好路由:

{
	path: "/CapitalPage",
	component: CapitalPage,
},

 配置好后,就开始我们的代码。

3、代码书写:

1、封装公用组件baseButton和baseInput:

basebutton:

<template>
  <div class="BaseButton">
    <button :style="styles" class="BassButtonStyle" @click="buttonClick">
      <slot />
    </button>
  </div>
</template>
<script>
export default {
  name: "BaseButton",
  props: {
    styles: Object,
    buttonClick: {
      type: Function,
      default: () => {},
    },
  },
};
</script>
<style lang="less" scoped>
@import "@/baseStyle.less";
.BaseButton {
  .BassButtonStyle {
    border-radius: 12px;
    cursor: pointer;
    width: 73px;
    height: 32px;
    border: 1px solid @bg_color_yellow;
    background-color: @bg_color_yellow;
    font-size: 14px;
    box-sizing: border-box;
    .displayFLexAllCenter();
    border: 1px solid;
  }
}
.buttonErr {
  .BassButtonStyle {
    background-color: @bg_err;
    cursor: not-allowed;
  }
}
</style>

basebutton这个组件,我将style封装成了一个变量,并且既然是按钮就肯定有点击事件,所以我给他写了一个点击事件,并给点击事件赋值,当他没有被调用的时候,他就是一个空的函数。

baseInput:

<template>
  <div class="BaseInput">
    <el-input
      v-model="value"
      class="loginInput"
      :placeholder="placeholder"
      :style="inputStyle"
      @input="changeInputValue"
      :show-password="showPassword"
    >
      <button class="sendButton" slot="suffix" v-if="buttonShow">
        Send
      </button></el-input
    >
  </div>
</template>
<script>
export default {
  name: "BaseInput",
  props: {
    placeholder: String,
    inputValue: String,
    inputStyle: Object,
    changeInputValue: {
      type: Function,
      default: () => {},
    },
    buttonShow: {
      type: Boolean,
      default: false,
    },
    showPassword: Boolean,
  },
  data: function () {
    return {
      value: "",
    };
  },
  watch: {
    inputValue: function (val) {
      this.value = val;
      // localStorage.setItem("user", {
      //   email: "1",
      //   password: 123,
      // });
      // localStorage.getItem("name");
    },
  },
};
</script>
<style  lang="less" scoped>
.sendButton {
  width: 47px;
  height: 24px;
  background-color: rgba(242, 216, 85, 0.2);
  margin-top: 10px;
  border: none;
  border-radius: 8px;
  color: #f2d855;
  cursor: pointer;
  font-size: 12px;
  margin-right: 12px;
}
</style>

input里面的讲究就有点多了,首先,他是从elementUi调用的一个输入框,这个输入框接受几个变量:style,placeholder,show-passwprd,并且有一个onchange事件,但是ui框架是封装好的,他的onchange事件,名字就叫input,所以,这里是@input,并给onchange事件赋值,当他没有被调用的时候,他就是一个空的函数,然后在他的内部添加一个button按钮,给一个v-if,因为有收取邮箱验证码的选项,所以这个按钮就是为了点击给邮箱发送验证码,但是不是每一个输入框都有,所以给他一个v-if判断那个需要哪个不需要。这里最重要的一点就是elementUi的样式更改,需要打开控制台,然后看他自带的class类名,然后用他的class类名去更改样式才能生效。

2、书写登录页:

<template>
  <div class="signIn">
    <div class="signInHead">Sign in</div>
    <BaseInput
      class="signMargin"
      :placeholder="'Email'"
      :changeInputValue="email"
    />
    <BaseInput
      class="signMargin"
      :placeholder="'Password'"
      :changeInputValue="password"
      :showPassword="true"
    />
    <div class="loginErr" v-if="loginErr">您输入的账号密码有误</div>
    <BaseButton
      class="signMargin"
      :styles="{ width: 380 + 'px', height: 44 + 'px', fontSize: 16 + 'px' }"
      :buttonClick="loginPage"
    >
      Sign in
    </BaseButton>
    <div class="passWordAndNewUser signMargin">
      <div class="forgotPassword signFontSize" @click="forgot(3)">
        Forgot password
      </div>
      <div class="newUserSignUp">
        <div class="newUser signFontSize">New user?</div>
        <div class="SignUp signFontSize" @click="signUp(2)">Sign up</div>
      </div>
    </div>
  </div>
</template>
<script>
import BaseInput from "@/components/BaseInput.vue";
import BaseButton from "@/components/BaseButton.vue";
export default {
  name: "SignIn",
  data: () => {
    return {
      loginEmail: "",
      loginPassword: "",
      loginErr: false,
    };
  },
  components: {
    BaseInput,
    BaseButton,
  },
  props: {
    signUp: Function,
    forgot: Function,
  },
  methods: {
    email: function (eml) {
      this.loginEmail = eml;
    },
    password: function (pas) {
      this.loginPassword = pas;
    },
    loginPage: function () {
      const obj = JSON.parse(localStorage.getItem("user")); // 反序列化
      console.log(obj.userEmail);
      if (
        this.loginEmail === obj.userEmail &&
        this.loginPassword === obj.userPassword
      ) {
        this.loginErr = false;
        this.$router.push("/CapitalPage");
      } else {
        this.loginErr = true;
      }
    },
  },
};
</script>

在登录页中,提前写好点击事件,分别是下方的忘记密码和注册,点击的时候需要去切换组件,用v-if。

注册和忘记密码页代码:

<template>
  <div class="createAccount">
    <div class="signInHead">Sign in</div>
    <BaseInput
      class="signMargin"
      :placeholder="'Email'"
      :changeInputValue="emailChange"
    />
    <BaseInput
      class="signMargin"
      :placeholder="'Password'"
      :changeInputValue="passwordChange"
      :showPassword="true"
    />
    <BaseInput
      :class="
        this.changeInputBorder === true ? 'signMargin' : 'errInput signMargin'
      "
      :placeholder="'Re-enter password'"
      :changeInputValue="passwordEnter"
      :showPassword="true"
    />
    <div class="errTipOf" v-if="!changeInputBorder">您两次输入的密码不一致</div>
    <BaseInput
      class="signMargin"
      :placeholder="'Email verification code'"
      :changeInputValue="emailCode1"
      buttonShow
    />
    <BaseButton
      :class="
        this.changeInputBorder === true ? 'signMargin' : 'buttonErr signMargin'
      "
      :styles="{ width: 380 + 'px', height: 44 + 'px', fontSize: 16 + 'px' }"
      :buttonClick="getValue"
      :disabled="changeInputBorder"
      >Create account</BaseButton
    >
    <div class="doYouHaveAccount signMargin">
      <div class="inquire signFontSize">Already have account?</div>
      <div class="SignUp signFontSize" @click="haveAccount(1)">Sign in</div>
    </div>
  </div>
</template>
<script>
import BaseInput from "@/components/BaseInput.vue";
import BaseButton from "@/components/BaseButton.vue";
export default {
  name: "SignIn",
  data: () => {
    return {
      email: "",
      password: "",
      enterPassword: "",
      emailCode: "",
      changeInputBorder: true,
    };
  },
  components: {
    BaseInput,
    BaseButton,
  },
  props: {
    haveAccount: Function,
  },
  watch: {},
  methods: {
    // 这下面四步都是在获取input里面的值
    emailChange: function (val) {
      this.email = val;
    },
    passwordChange: function (password) {
      this.password = password;
    },
    passwordEnter: function (enter) {
      // 这里是在判断,注册确认密码的时候必须要与上一次输入的密码一致,不然改变input状态和按钮的状态
      this.enterPassword = enter;
      console.log(this.password);
      if (
        (this.enterPassword !== this.password) &
        (this.enterPassword !== "")
      ) {
        this.changeInputBorder = false;
      } else {
        this.changeInputBorder = true;
      }
    },
    emailCode1: function (code) {
      this.emailCode = code;
    },
    // 这里是点击注册按钮后将input的值存入localStorage里面,并跳转至登录页面
    getValue: function () {
      localStorage.setItem(
        "user",
        JSON.stringify({
          // 序列化
          userEmail: this.email,
          userPassword: this.password,
          userEnterPas: this.enterPassword,
          userEmailCode: this.emailCode,
        })
      );
      this.haveAccount(1);
    },
  },
};
</script>
<template>
  <div class="createAccount">
    <div class="signInHead">Forgot password</div>
    <BaseInput
      class="signMargin"
      :placeholder="'Email'"
      :changeInputValue="changeEmail"
    />
    <BaseInput
      class="signMargin"
      :placeholder="'New password'"
      :changeInputValue="passwordNew"
      :showPassword="true"
    />
    <BaseInput
      :class="this.changeBoo === true ? 'signMargin' : 'errInput signMargin'"
      :placeholder="'Re-enter new password'"
      :changeInputValue="enterNewPassword"
      :showPassword="true"
    />
    <div class="errTipOf" v-if="!changeBoo">您两次输入的密码不一致</div>
    <BaseInput
      class="signMargin"
      :placeholder="'Email verification code'"
      :changeInputValue="codeNewPassword"
      buttonShow
    />
    <BaseButton
      :class="this.changeBoo === true ? 'signMargin' : 'buttonErr signMargin'"
      :styles="{ width: 380 + 'px', height: 44 + 'px', fontSize: 16 + 'px' }"
      :buttonClick="verifyPassword"
      :disabled="changeBoo"
      >Set up</BaseButton
    >
    <div class="doYouHaveAccount signMargin">
      <div class="SignUp signFontSize" @click="signIn(1)">Sign in</div>
    </div>
  </div>
</template>
<script>
import BaseInput from "@/components/BaseInput.vue";
import BaseButton from "@/components/BaseButton.vue";
export default {
  name: "SignIn",
  data: () => {
    return {
      email: "",
      newPassword: "",
      newPasswordEnter: "",
      newPasswordCode: "",
      changeBoo: true,
    };
  },
  components: {
    BaseInput,
    BaseButton,
  },
  props: {
    signIn: Function,
  },
  methods: {
    changeEmail: function (ema) {
      this.email = ema;
    },
    passwordNew: function (pas) {
      this.newPassword = pas;
    },
    enterNewPassword: function (ent) {
      this.newPasswordEnter = ent;
      if (
        (this.newPasswordEnter !== this.newPassword) &
        (this.newPasswordEnter !== "")
      ) {
        this.changeBoo = false;
      } else {
        this.changeBoo = true;
      }
    },
    codeNewPassword: function (cod) {
      this.newPasswordCode = cod;
    },
    verifyPassword: function () {
      if (
        this.email !== "" &&
        this.newPassword !== "" &&
        this.newPasswordEnter !== "" &&
        this.newPasswordCode !== ""
      ) {
        console.log(123);
        localStorage.setItem(
          "user",
          JSON.stringify({
            // 序列化
            userEmail: this.email,
            userPassword: this.newPassword,
            userEnterPas: this.newPasswordEnter,
          })
        );
        this.signIn(1);
      }
    },
  },
};
</script>

在这个地方,他就形成了一个闭环,我进入页面的时候是登录页,点击注册后,输入邮箱密码和验证码后,注册成功,然后返回登录页,忘记密码页输入账号密码验证码后,依旧回到登录页。在这里用到了一个新东西,就是localStroage储存,这里把输入框输入的东西储存到变量中,然后将变量中的内容储存到localStorage里面,返回登录页后,去判断,你输入的账号密码和储存的账号密码是否一致,如果一致,那么就跳转页面,如果不一致,那么就给你说,你输入的账号密码有误,请重新输入。

3、书写路由跳转:

我们书写完登录系统以后,我们需要知道,账号密码输入正确有以后我们应该做什么,那么我们看项目ui,

很明显,下一个页面就是这个,输入正确的账号密码以后,路由跳转就应该跳转到这个页面中,因为我现在写的是登录系统,那么我们就看到这个页面的头部也是登录系统的一环,上面是我们登录成功以后的头部,然后继续看ui,我们会看到,点击退出以后,他会改变头部的状态:

那么我们先去书写登录后的头部形态,在写之前,我们先把页面布局出来,把路由跳转写好:

 

 新建一个文件夹,然后用来储存这个页面需要应用的文件,然后在page文件夹新启一个文档,用来做这个页面的主页面存储。

登录后头部形态书写:

<template>
  <!--这个是页面的头部-->
  <div class="homeHeadSecond">
    <img :src="headLogo" alt="" class="headLogo" />
    <div class="headNavigator">
      <div class="navigatorName">
        <div class="headName">Home</div>
        <div class="headName">Tasks</div>
        <div class="headName">Docs</div>
        <div class="headName">News</div>
      </div>
      <div class="logInAndLogOut">
        <img :src="userHead" alt="" />
        <div class="userEmail">{{ userEmail }}</div>
        <div class="loginOutElement">
          <el-col :span="12">
            <el-dropdown trigger="click">
              <span class="el-dropdown-link">
                <i class="el-icon-arrow-down el-icon--right"></i>
              </span>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item icon="el-icon-circle-check">
                  <div class="overLoginOut" @click="changeHead">
                    <img :src="overLoginOut" />
                    <div class="overLoginOutS">Sign out</div>
                  </div>
                </el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </el-col>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import headLogo from "../../assets/headLogo.png";
import userHead from "../../assets/userHead.png";
import getOut from "../../assets/getOut.png";
import overLoginOut from "../../assets/overLoginOut.png";
export default {
  name: "HomeHead",
  data: () => {
    return {
      headLogo: headLogo,
      userEmail: "",
      userHead: userHead,
      getOut: getOut,
      overLoginOut: overLoginOut,
    };
  },
  components: {},
  methods: {},
  beforeMount: function () {
    const obj = JSON.parse(localStorage.getItem("user"));
    this.userEmail = obj.userEmail;
  },
  props: {
    changeHead: Function,
  },
};
</script>

这篇代码中涉及了一个新知识:vue的生命周期中的其中一个函数:beforeMount,这里用到他是因为在头部登录形态中,我们看到了用户头像的后面增加了他的登录邮箱,所以我们需要再页面挂载前就获取到localStorage中的数据,然后将他存在变量中,赋值于上面。

然后书写退出后的头部形态:

<template>
  <!--这个是页面的头部-->
  <div class="homeHead">
    <img :src="headLogo" alt="" class="headLogo" />
    <div class="headNavigator">
      <div class="navigatorName">
        <div class="headName">Home</div>
        <div class="headName">Tasks</div>
        <div class="headName">Docs</div>
        <div class="headName">News</div>
      </div>
      <div class="logInAndLogOut">
        <BaseButton>Sign Out</BaseButton>
        <BaseButton
          :styles="{
            backgroundColor: 'transparent',
            width: '69px',
            borderColor: '#f2d855',
            color: '#f2d855',
            marginLeft: '10px',
          }"
          :buttonClick="logIn"
          >Sign in</BaseButton
        >
      </div>
    </div>
  </div>
</template>
<script>
import headLogo from "../../assets/headLogo.png";
import BaseButton from "@/components/BaseButton.vue";
export default {
  name: "HomeHead",
  data: () => {
    return {
      headLogo: headLogo,
    };
  },
  components: {
    BaseButton,
  },
  methods: {
    logIn: function () {
      this.$router.push("/");
    },
  },
};
</script>

这里不一样的是,退出后有两个按钮,一个登录,一个注册,那么这里就多了两个交互,点击登录,回到登录页面,这里就是切换路由到登录页就可以了,一个注册,也是切换路由,但是,需要切换路由后回到的页面是忘记密码页,而不是登录页

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值