Vue.js 实战系列之实现视频类WebApp的项目开发——12. 引入Vuex实现数据管理以及登录流程的实现

如果想看该实战系列的其他内容,请移步至 Vue.js 实战系列之实现视频类WebApp的项目开发。

项目仓库地址,欢迎 Star


实现效果

Vue.js 实战系列之实现视频类WebApp的项目开发——12. 引入Vuex实现数据管理以及登录流程的实现_第1张图片


功能实现

  1. 引入 Vuex

    什么是 Vuex?
    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
    通俗点说:此时有一个根组件和两个子组件,如果根组件与子组件之间通信,可以通过 props 传值的方式来实现;但是如果想要让两个子组件进行通信,此时实现起来就比较复杂,在未引入 Vuex 之前,可以将子组件A的内容传给父组件,然后父组件接收到再传递给子组件B,相当于父组件作为一个中介进行传递,但是引入 Vuex 之后实现起来就比较简单啦。

    Vuex 官网

    1. 安装 Vuex

      yarn add vuex 
      
    2. Vuex 核心

      1. state: 存放状态
      2. mutationsstate成员的操作
      3. actions: 异步操作 (actionmutation 的区别在于 action 技能执行异步操作又能执行同步操作,而 mutations 只能执行同步操作)
      4. getters: 加工 state 成员给外界
      5. modules: 模块化状态管理
    3. Vuex 流程图
      Vue.js 实战系列之实现视频类WebApp的项目开发——12. 引入Vuex实现数据管理以及登录流程的实现_第2张图片

  2. 使用 modules 模块化管理数据

    src/store 文件夹下,新建 modules 文件夹,创建 sign.js 模块

    const sign = {
           
        // 命名空间
        namespaced: true,
        state: {
           
            // 默认的验证码
            verifyCode: '000000',
        },
        mutations: {
            },
        actions: {
            },
        getters: {
            },
    };
    export default sign;
    

    更新 src/store/index.js
    将刚才创建的 sign 模块导入

    import Vue from 'vue';
    import Vuex from 'vuex';
    import sign from './modules/sign';
    
    Vue.use(Vuex);
    
    export default new Vuex.Store({
           
      state: {
            },
      mutations: {
            },
      actions: {
            },
      modules: {
           
        sign,
      },
    });
    
  3. 验证码登录流程实现

    正常流程下,验证码是由后端为我们返回的,此时我们没有真实的后端接口,所以现在我们将后端返回的验证码值写死在 state 中,后期将通过 nodejs 来实现一个后端接口,欢迎关注。

    1. 创建验证码页面 Code.vue

      <template>
        <div class="sign">
          <div class="sign-header">
            <span class="iconfont icon-guanbi" style="font-size: 30px">span>
            <span style="color: #686868"> 帮助span>
          div>
          <div class="sign-content">
            <div class="des">
              <h2>请输入验证码h2>
              <p>验证码已通过短信发送至+8615998362261p>
            div>
          div>
          <div class="sign-box">
            <div class="inp">
              <input
                v-model="code"
                @input="changeCode"
                type="number"
                class="inp-controll"
                placeholder="请输入验证码"
              />
            div>
            <div class="time">
              {
              { time }}
            div>
          div>
          <div class="not-dx">
            <p>收不到短信?<a>获取语言验证码a>p>
          div>
          <div class="code-btn">
            <button
              :disabled="disabled"
              :class="btnBg ? 'active' : ''"
              @click="getCode"
            >
              登录
            button>
          div>
        div>
      template>
      
      <script>
      export default {
                
          data() {
                
              return {
                
                  // 短信发送倒计时
                  time: 60,
              };
          },
      };
      script>
      
      <style lang="less" scoped>
      .sign {
                
        padding: 30px;
        background: #fff;
        .sign-header {
                
          display: flex;
          justify-content: space-between;
          align-items: center;
          font-size: 18px;
        }
        .sign-content {
                
          padding: 20px 10px;
          h2 {
                
            margin: 0;
            font-size: 22px;
            font-weight: bold;
          }
          p {
                
            font-size: 14px;
            line-height: 20px;
            color: #adadad;
          }
        }
        .sign-box {
                
          display: flex;
          height: 50px;
          margin: 0;
          align-items: center;
          background-color: #f9f9f9;
          .inp {
                
            height: 36px;
            width: 90%;
            margin-left: 10px;
            .inp-controll {
                
              caret-color: #fe2c55;
              height: 36px;
              background-color: #f9f9f9;
              width: 90%;
              font-size: 16px;
              border: none;
              outline: none;
            }
          }
          .time {
                
            text-align: right;
            width: 80px;
            font-size: 16px;
            line-height: 80px;
            margin-right: 10px;
          }
        }
        .not-dx {
                
          margin-top: 10px;
          p {
                
            color: #b9b9b9;
            font-size: 14px;
            a {
                
              color: #3d79b4;
            }
          }
        }
        .code-btn {
                
          button {
                
            margin: 10px 0;
            width: 100%;
            padding: 15px 0;
            border: none;
            letter-spacing: 1px;
            font-size: 17px;
            color: #fff;
            font-weight: 600;
            background: #dbdbdb;
            border-radius: 2px;
          }
          .active {
                
            color: #ffffff;
            background-color: #fe2c55;
          }
        }
      }
      style>
      
    2. 更新 src/store/modules/sign.js

      import router from '../../router';
      const sign = {
               
          // 命名空间
          namespaced: true,
          state: {
               
              // 默认的验证码
              verifyCode: '000000',
          },
          mutations: {
                },
          actions: {
               
              // 登录操作
              sign({
                state, commit, rootState }, params) {
               
                  // 登录成功之后 session 中缓存登录标识
                  sessionStorage.setItem('isLogin', JSON.stringify(true));
                  // 登录成功之后 跳转到 webApp 主页
                  router.replace({
                path: '/' });
              },
          },
          getters: {
                },
      };
      export default sign;
      
    3. 更新 Code.vue 完成登录

      引入 mapActions,调用 sign.js 中的 sign 方法实现登录
      使用 this.$store.state. 获取 state 中的值
      使用 van-loading 实现加载中动画

      <template>
        <div class="sign">
          <div class="sign-header">
            <span
              class="iconfont icon-fanhui"
              style="font-size: 30px"
              @click="goBack"
            >span>
            <span style="color: #686868"> 帮助span>
          div>
          <div class="sign-content">
            <div class="des">
              <h2>请输入验证码h2>
              <p>验证码已通过短信发送至+86{
              { tel }}p>
            div>
          div>
          <div class="sign-box">
            <div class="inp">
              <input
                v-model="code"
                @input="changeCode"
                type="number"
                class="inp-controll"
                placeholder="请输入验证码"
              />
            div>
            <div class="time">
              {
              { time }}
            div>
          div>
          <div class="not-dx">
            <p>收不到短信?<a>获取语言验证码a>p>
          div>
          <div class="code-btn">
            <button
              :disabled="disabled"
              :class="btnBg ? 'active' : ''"
              @click="Login"
            >
              <div v-if="!loading">
                {
              { msg }}
              div>
              <div v-else class="loading">
                <van-loading color="#1989fa" size="16px" />
                {
              { msg }}
              div>
            button>
          div>
        div>
      template>
      
      <script>
      import {
                 mapActions } from 'vuex';
      
      export default {
                
          data() {
                
              return {
                
                  tel: '',  // 电话号码
                  code: '',  // 验证码
                  verifyCode: '',  // state中提供的默认验证码
                  time: 60,  // 短信发送倒计时
                  disabled: true,
                  btnBg: false,
                  loading: false,
                  msg: '登录',
              };
          },
          created() {
                
              this.getCode();
              this.tel = this.$route.query.tel;
          },
          methods: {
                
              ...mapActions('sign', ['sign']),
              // 监听输入验证码
              changeCode(e) {
                
                  this.code = e.target.value;
                  if (this.code === this.verifyCode) {
                
                      this.disabled = false;
                      this.btnBg = true;
                  } else {
                
                      console.log('验证码输入错误');
                  }
              },
              // 获取验证码
              getCode() {
                
                  this.verifyCode = this.$store.state.sign.verifyCode;
                  this.countDown();
              },
              // 倒计时
              countDown() {
                
                  if (this.time > 0) {
                
                      this.time -= 1;
                      setTimeout(this.countDown, 1000);
                  } else {
                
                      this.time = '重新发送';
                  }
              },
              // 登录按钮点击事件
              Login() {
                
                  this.loading = true;
                  this.msg = '登录中';
                  setTimeout(() => {
                
                      this.loading = false;
                      this.msg = '登录成功';
                  }, 1500);
                  setTimeout(() => {
                
                      this.sign({
                 code: this.code });   // 登录跳转操作
                  }, 2000);
              },
              // 返回上个页面
              goBack() {
                
                  this.$router.go(-1);
              },
          },
      };
      script>
      
      <style lang="less" scoped>
      .sign {
                
        ...
        .code-btn {
                
          button {
                
            .loading {
                
              display: flex;
              justify-content: center;
              align-items: center;
            }
          }
        }
      }
      style>
      

总结

本章节需要注意的几个点:

  • Vuex 的使用
  • 使用 modules 模块化管理数据
  • SessionStorage 前端数据存储
  • 登录流程实现

上一章节: 11. 手机号登录、密码登录、其它方式登录的实现

下一章节: 13. 自定义弹出框组件的实现

项目整体介绍:Vue.js 项目实战之实现视频播放类WebApp的项目开发(仿抖音app)


项目仓库地址,欢迎 Star。

有任何问题欢迎评论区留言讨论。

你可能感兴趣的:(新星计划,Vue,实战系列,vue,java,html,javascript,新星计划)