关于如何在vue中使用typescript(第二天)

本文档展示了如何在Vue.js项目中实现一个登录模块,利用axios进行接口调用,结合Vuex管理状态,并通过Element UI组件库创建用户界面。登录过程中涉及了prop传递、组件使用、路由跳转以及错误处理。同时,还涵盖了typescript在Vue组件中的应用,包括数据模型定义、方法定义等。
摘要由CSDN通过智能技术生成

实现登录模块

知识点

  • axios如何在typescript中使用
  • 组件的基本使用
  • prop实践
  • 路由跳转
  • vuex的基本使用
  • methods基本使用

目录介绍

在这里插入图片描述

登录界面

<!--
 * @Description: 
 * @Version: 1.0
 * @Autor: solid
 * @Date: 2022-03-25 11:15:35
 * @LastEditors: solid
 * @LastEditTime: 2022-04-04 16:04:32
-->
<template>
    <div class="login">
    <el-card style="width: 550px">
     <Header :title="title"></Header>

      <el-form
        status-icon
        ref="ruleForm"
        label-width="100px"
        class="ruleForm"
      >
        <el-form-item label="管理用户名" prop="username">
          <el-input v-model="user.username"></el-input>
        </el-form-item>
        <el-form-item label="管理密码" prop="password">
          <el-input
            type="password"
            v-model="user.password"
            autocomplete="off"
            @keyup.enter.native="HandlerLogin"
          ></el-input>
        </el-form-item>
        <el-form-item>
          <el-button
            type="primary"
            :loading="isLoading"
            @click="HandlerLogin"
            >登录</el-button
          >
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>

<script lang="ts">
import {Component,Vue} from "vue-property-decorator"
import Header from '@/components/Header.vue'
import {UserModule} from '@/store/modules/user'
@Component({
  name:"login",
  components:{
    Header
  }
})
export default class Login extends Vue{
    private user={
        username:"",
        password:"",
    }
    private title="登录界面"
    private isLoading=false
    private async HandlerLogin(){
        if(this.user.username=="" ||this.user.password==""){
            this.$message.warning("用户名或密码不能为空")
            return
        }
        await UserModule.Login(this.user)
       
    }
} 
</script>
<style  scoped>
.login {
  height: 100%;
  text-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
}

.issuer {
  font-size: 26px;
  font-weight: bold;
  margin-bottom: 50px;
}
</style>

request.ts

/*
 * @Description: 
 * @Version: 1.0
 * @Autor: solid
 * @Date: 2022-03-25 10:49:36
 * @LastEditors: solid
 * @LastEditTime: 2022-03-25 12:31:18
 */
import axios from 'axios'
import { Message } from "element-ui";
const baseURL = process.env.VUE_APP_BASE_API
    ? process.env.VUE_APP_BASE_API
    : "";
const service = axios.create({
    baseURL,
    timeout: 30000
})
// request interceptor
service.interceptors.request.use(
    (config) => {
        return config
    },
    (error) => {
        // do something with request error
        console.log(error) // for debug
        return Promise.reject(error)
    }
)
service.interceptors.response.use(
    response => {
        // Some example codes here:
        // You can change this part for your own usage.
        const res = response.data;
        if (res.code !== 0) {
            Message({
                message: res.message || "Error",
                type: "error",
                duration: 5 * 1000
            });
            return Promise.reject(new Error(res.message || "Error"));
        } else {
            return response;
        }
    },
    error => {
        Message({
            message: error.message,
            type: "error",
            duration: 5 * 1000
        });
        return Promise.reject(error);
    }
);
export function getData(url: string, params: object) {
    return service({
        url,
        method: 'get',
        params
    })
        .then(res => res.data)
        .catch(error => error.response)
}
export function postData(url: string, data: object) {
    return service({
        url,
        method: 'post',
        data
    })
        .then(res => res.data)
        .catch(error => error.response)
}

store/index.ts

/*
 * @Description: 
 * @Version: 1.0
 * @Autor: solid
 * @Date: 2022-04-04 15:02:25
 * @LastEditors: solid
 * @LastEditTime: 2022-04-04 15:12:37
 */
import Vue from "vue";
import Vuex from "vuex";
import { IUserState } from "./modules/user";

Vue.use(Vuex);

export interface IRootState {
  user: IUserState;
}

// Declare empty store first, dynamically register all modules later.
export default new Vuex.Store<IRootState>({});

store/modules/user.ts

/*
 * @Description: 
 * @Version: 1.0
 * @Autor: solid
 * @Date: 2022-04-04 15:03:22
 * @LastEditors: solid
 * @LastEditTime: 2022-04-04 15:35:12
 */

import {
    VuexModule,
    Module,
    Action,
    Mutation,
    getModule
} from "vuex-module-decorators";
import store from "@/store";
import { UserLogin } from '@/api/login'
export interface IUserState {
    token: string;
}
// @Module 标记当前为module
// module本身有几种可以配置的属性
// 1、namespaced:boolean 启/停用 分模块
// 2、stateFactory:boolean 状态工厂
// 3、dynamic:boolean 在store创建之后,再添加到store中。 开启dynamic之后必须提供下面的属性
// 4、name:string 指定模块名称
// 5、store:Vuex.Store实体 提供初始的store
@Module({ dynamic: true, store, name: "user" })
class User extends VuexModule implements IUserState {
    // 在需要引用的地方单独引用该store文件即可注入。
    // 好处:灵活使用,仅仅在需要引入的地方才注入到store中去
    // 缺点:需要单独引入文件

    /* 这里代表的就是state里面的状态 */
    public token = sessionStorage.getItem("token") || "";
    // @Mutation 标注为mutation
    @Mutation
    private SET_TOKEN(token: string) {
        sessionStorage.setItem("token", token)
        // 设置token
        this.token = token;
    }
    @Mutation
    private REMOVE_TOKEN() {
        sessionStorage.removeItem('token')
        this.token = ""
    }
    // @Action 标注为action
    @Action
    public async Login(userInfo: { username: string; password: string }) {
        // 登录接口,拿到token
        const { code, data } = await UserLogin(userInfo)
        if (code == 0) {
            console.log(data);
            this.SET_TOKEN(data.token);
            return new Promise((resolve, reject) => {
                resolve({ code: 0, message: "登录成功!!!!" })
            })
        } else {
            return new Promise((resolve, reject) => {
                resolve({ code: data.code, message: "用户名或密码错误" })
            })
        }
    }
    @Action
    public async RemoveToken() {
        this.REMOVE_TOKEN()
    }
}
// getModule 得到一个类型安全的store,module必须提供name属性
export const UserModule = getModule(User);

router/index.ts

import Vue from 'vue';
import VueRouter, { RouteConfig } from 'vue-router';
import Home from '../views/Home.vue';
import { UserModule } from '@/store/modules/user'
Vue.use(VueRouter);

const routes: Array<RouteConfig> = [
  {
    path: '/',
    name: 'Home',
    component: Home,
  },
  {
    path: "/login",
    name: "login",
    component: () => import("@/views/login/Login.vue")
  },
];

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes,
});
router.beforeEach((to, form, next) => {
  // 判断要进入的路由是否需要认证

  const token = UserModule.token;

  // console.log(from)

  // 没有token,全都跳转到login
  if (!token) {
    if (to.path === "/login") {
      next();
      return;
    }

    next({
      path: '/login',
      query: {
        redirect: to.path
      }
    });
    return;
  }

  if (to.path === "/login") {
    next({ path: '/' });
    return;
  }

  // 有token情况下
  next();

})
export default router;

Header.vue

<!--
 * @Description: 
 * @Version: 1.0
 * @Autor: solid
 * @Date: 2022-04-04 15:49:09
 * @LastEditors: solid
 * @LastEditTime: 2022-04-04 16:04:09
-->
<template>
  <div>{{title}}</div>
</template>

<script lang="ts">
import {Component,Vue,Prop} from "vue-property-decorator"
@Component
export default class Header extends Vue{
    @Prop({default:"管理平台"}) private title!:string;
}
</script>

<style>

</style>

login.ts

/*
 * @Description: 
 * @Version: 1.0
 * @Autor: solid
 * @Date: 2022-03-25 11:04:08
 * @LastEditors: solid
 * @LastEditTime: 2022-03-25 12:30:00
 */
import { postData } from '@/utils/request'
const userApi = {
    Login: '/user/login',
}
export const UserLogin = (data: object) => postData(userApi.Login, data)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值