vue3项目实战---知乎日报----登录页

目录

网络请求

 vuex

封装标题栏

登录页


网络请求

poist请求通过body主体发送 (对象)默认json 其他格式在transformRequest中配置

每次发送请求 携带token axios.interceptors.request.use配置 获取本地存储的token

接口需要在请求头中携带TOKEN信息
authorzation:token「客户端登录成功后存储在本地的令牌信息(从服务器获取)」

 临时测试:生成的验证码可在「后端程序 -> code.txt」中查看

//获取验证码
export const PhoneCode = phone => {
    return axios.post('/api/phone_code', {
        phone
    })

}
//登录
export const login = (phone, code) => {
    return axios.post('/api/login ', {
        phone,
        code
    })

}
//检测是否登录
export const CheckLogin = () => {
    return axios.get('/api/check_login')
}

// 获取登录者信息
export const UserLnfo = () => {
    return axios.get('/api/user_info')
}

-----------------------
axios.interceptors.request.use(config => {
    // 设置请求头
    config.headers['authorzation'] = localStorage.getItem("token");
    return config;
});

 vuex

存储用户信息和登录状态

单项数据流 

state 存放数据

mutations修改state数据,,接收两个参数(state 仓库中的值, payload:要修改的值) 同步

actions 异步 获取数据 commit通知mutations修改数据 通过dispatch可以派发任务

import { createStore } from "vuex";
import { CheckLogin, UserLnfo } from '../api/index'
const store = createStore({
    state: {
        isLogin: null,
        info: null
    },
    mutations: {
        changeIsLogin(state, bool) {
            state.isLogin = bool
        },
        changeInfo(state, payload) {
            state.info = payload
        }
    },
    actions: {
        async changeIsLoginAsync({ commit }) {
            let bool = false
            let { code } = await CheckLogin()
            if (code == 0) bool = true
            commit('changeIsLogin', bool)
        },
        async changeInfoAstnc({ commit }) {
            let { code, data } = await UserLnfo()
            if (code == 0) {
                commit('changeInfo', data)
            }
        }
    },
})
export default store 

封装标题栏

通过router跳转

<template>
    <van-nav-bar :title="title" left-text="返回" left-arrow @click-left="onClickLeft"></van-nav-bar>
</template>

<script>
import { useRouter, useRoute } from 'vue-router'
export default {
    name: 'Nav',
    props: {
        title: {
            type: String,
            default: ''
        }
    },
    setup() {
        //路由实例对象控制路由跳转
        const router = useRouter()
        //路由信息对象,获取路径参数
        const route = useRoute()
        //点击跳转返回上一级
        const onClickLeft = (() => {
            router.back()
        })
        return {
            onClickLeft
        }
    }
}

</script>

<style lang="less" scoped>
/deep/ .van-icon,
/deep/ .van-nav-bar__text {
    color: #000;
}
</style>

登录页

通过ref获取dom元素  创建ref实例对象赋值

vant form表单的使用
 

submit 事件可以通果校验后触发 

每一项的表单项 有name属性可以指定校验项 (validate) 

 await formBox.value.validate("phone"); 返回对象为promise实例

rules校验规则 required 必填  message 提示信息 pattern通过正则校验

 获取数据成功后开启定时器 禁用按钮 设置秒数

每次秒数减一 为0之后清除定时器 恢复禁用

校验通过后请求登录接口 失败清空输入框和校验规则

登录成功后 使用locationstore 存储token  配置请求头携带token

  store.commit执行同步任务 修改登录状态  store.dispatch派发异步任务获取用户信息

<template>
  <Nav></Nav>
  <van-form ref="formBox" @submit="submit">
    <van-cell-group inset>
      <van-field
        v-model="phone"
        label="手机号"
        label-width="50px"
        name="phone"
        :rules="[
          { required: true, message: '手机号为必填项哦~' },
          { pattern: regPhone, message: '手机号格式不对哦~' },
        ]"
      >
        <template #button>
          <van-button
            class="form-btn"
            size="small"
            type="primary"
            @click="sendCode"
            :disabled="!enable"
            >{{ enable ? "发送验证码" : time }}
          </van-button>
        </template>
      </van-field>

      <van-field
        v-model="code"
        label="验证码"
        label-width="50px"
        :rules="[
          { required: true, message: '验证码为必填项哦~' },
          { pattern: regCode, message: '验证码必须是6位数字哦~' },
        ]"
      ></van-field>
    </van-cell-group>
    <div style="margin: 20px 40px">
      <van-button round block type="primary" native-type="submit"
        >立即登录/注册
      </van-button>
    </div>
  </van-form>
</template>

<script>
import { reactive, toRefs, ref } from "vue";
import { Toast } from "vant";
import { useStore } from "vuex";
import { PhoneCode, login } from "../api/index";
import { useRouter } from "vue-router";
import Nav from "../components/Nav.vue";
export default {
  name: "Login",
  components: {
    Nav,
  },
  setup() {
    let state = reactive({
      phone: "",
      code: "",
      enable: true,
      time: "60s",
    });
    //获取form表单
    let formBox = ref(null);
    const store = useStore();
    const router = useRouter();
    //发送验证码
    const sendCode = async () => {
      try {
        //校验手机格式
        await formBox.value.validate("phone");
        //发送请求
        let { code } = await PhoneCode(state.phone);
        if (code != 0) {
          Toast("当前网略繁忙,请稍后重试");
          return;
        }
        //开启按钮倒计时
        state.enable = false;
        let n = 60;
        let timer = setInterval(() => {
          n--;
          if (n == 0) {
            clearInterval(timer);
            state.enable = true;
          }
          state.time = `${n}秒`;
        }, 1000);
      } catch (err) {}
    };
    //
    const submit = async () => {
      let { code, token } = await login(state.phone, state.code);
      if (code != 0) {
        Toast("小主,很遗憾,当前登录失败了~");
        //重置表单检验&&清空数据
        formBox.value.resetValidation();
        state.code = "";
        return;
      }
      //本地存储token(localStorage 页面关闭也会有)
      localStorage.setItem("token", token);
      //修改vuex登陆者状态 同步用commit
      store.commit("changeIsLogin", true);
      store.dispatch("changeInfoAstnc");
      Toast("小主,当前登录成功哦~");
      router.back();
    };
    return {
      ...toRefs(state),
      regPhone: /^(?:(?:\+|00)86)?1\d{10}$/,
      regCode: /^\d{6}$/,
      formBox,
      sendCode,
      submit,
    };
  },
};
</script>

<style lang="less" scoped>
.van-form {
  margin-top: 30px;
}

.form-btn {
  width: 78px;
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值