vue3_ts setup语法糖做一个登录注册-CSDN博客

文章目录

背景

vue3 ts 搭建一个简单的登录系统平台

个人后台管理地址:yongma16.xyz/back-front/...

效果

注册

登录

实现

ts基础数据类型普及

TS的数据类型可以分为以下几种:

布尔类型(boolean):只有true和false两个值。

数字类型(number):整数和浮点数都属于数字类型。

字符串类型(string):可用单引号、双引号或模板字符串(`)定义字符串。

数组类型(array):包含多个值的有序列表,每个值可以是任意类型。

元组类型(tuple):表示已知元素数量和类型的数组。

枚举类型(enum):枚举类型用于定义一些有名字的常量。

Any类型(any):表示任意类型,可以在编程过程中动态改变类型。

Void类型(void):用于标识没有返回值的函数。

Null和Undefined类型(null和undefined):表示空值和未定义的值。

Object类型(object):表示非原始类型的属性集合,可以是任意类型的对象。

vue3的setup知识

Vue 3引入了一个新的函数API:setupsetup函数是一个在组件内部执行的函数,用于在组件开始挂载之前进行一些设置工作。它接收两个参数:

  1. props:一个对象,包含了从父组件传入的props。
  2. context:包含了一些有用的属性和函数,如attrs、emit等。

setup函数中,我们可以使用reactive、ref等函数创建响应式的数据,并返回一个包含组件模板中所需数据和方法的对象:

javascript 复制代码
import { reactive, ref } from 'vue'

export default {
  name: 'MyComponent',
  setup(props, context) {
    const state = reactive({
      count: 0,
      message: 'Hello, Vue 3!'
    })

    const handleClick = () => {
      state.count++
    }

    return {
      state,
      handleClick
    }
  }
}

在组件模板中,我们可以直接使用state.count等数据和handleClick等方法:

html 复制代码
<template>
  <div>
    <p>{{ state.message }}</p>
    <button @click="handleClick">Click Me</button>
    <p>Count: {{ state.count }}</p>
  </div>
</template>

通过setup函数,我们可以更加灵活地管理组件内的响应式数据和方法,并避免了Vue 2中使用datamethods选项时可能遇到的一些问题。

ts的interface定义数据类型

interface 定义类型

form表单(用户名、密码、记住的复选框)

form校验 (用户名、密码)

state类型抛到template的变量声明

代码如下:

typescript 复制代码
interface FormStateType {
  username: string;
  password: string;
  remember: boolean;
}
interface FormRuleType {
  username: Object;
  password: Object;
}
interface stateType {
  formState: FormStateType;
  formRule: FormRuleType;
  layoutConfig: any;
  wrapperCol: any;
  submitWrapperCol: any;
  spinning: boolean;
  backgroundImgUrl: string;
}

注意:

const定义函数和function定义函数区别

1.const 定义函数只能在函数被调用之前

2.function定义函数可以在函数被调用之后

3.setup语法糖中定义的属性变量和函数直接可以被template引用,无须return

4.setup语法糖缺少export default 的name组件名称定义(name默认为文件名)

完整代码块如下:

bash 复制代码
<template>
    <div class="container">
      <div class="loginUser-container">
        <div class="loginUser-title">管理平台</div>
        <a-form
          :model="state.formState"
          :label-col="state.layoutConfig.labelCol"
          :wrapper-col="state.layoutConfig.wrapperCol"
          :rules="state.formRule"
          ref="formRef"
          layout="vertical"
          autocomplete="off"
        >
          <a-form-item label="账号" name="username">
            <a-input
              v-model:value="state.formState.username"
              allowClear
              placeholder="请输入账号"
              :disabled="state.spinning"
            />
          </a-form-item>

          <a-form-item label="密码" name="password">
            <a-input-password
              v-model:value="state.formState.password"
              :disabled="state.spinning"
              allowClear
              placeholder="请输入密码"
            />
          </a-form-item>

          <a-form-item name="remember" :wrapper-col="state.wrapperCol">
            <a-checkbox v-model:checked="state.formState.remember" :disabled="state.spinning"
              >记住密码</a-checkbox
            >
          </a-form-item>

          <a-form-item :wrapper-col="state.submitWrapperCol" class="submit-box">
            <a-button
              type="primary"
              html-type="submit"
              @click="loginAction"
              :loading="state.spinning"
              style="width: 100%; font-size: 16px; font-weight: bolder"
              >登录</a-button
            >
          </a-form-item>
        </a-form>
        <div class="description">
          <span class="description-prefix">没账号?</span>
          <span @click="jumpRegister" class="description-after" :disabled="state.spinning">去注册</span>
        </div>
      </div>
    </div>
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted } from "vue";
import { useRouter } from "vue-router";
import { useStore } from "vuex";
import { message } from "ant-design-vue";
import { loginUser } from "../../service/user/userApi";

import type { FormInstance } from "ant-design-vue";

interface FormStateType {
  username: string;
  password: string;
  remember: boolean;
}
interface FormRuleType {
  username: Object;
  password: Object;
}
interface stateType {
  formState: FormStateType;
  formRule: FormRuleType;
  layoutConfig: any;
  wrapperCol: any;
  submitWrapperCol: any;
  spinning: boolean;
  backgroundImgUrl: string;
}
// 路由
const router = useRouter();
//store
const store = useStore();
const formRef = ref<FormInstance>();
const state: stateType = reactive({
  formState: {
    username: "",
    password: "",
    remember: false,
  },
  spinning: false,
  formRule: {
    username: [{ required: true, message: "请输入账号!" }],
    password: [{ required: true, message: "请输入密码!" }],
  },
  layoutConfig: {
    labelCol: {
      span: 8,
    },
    wrapperCol: {
      span: 24,
    },
  },
  wrapperCol: { offset: 0, span: 24 },
  submitWrapperCol: { offset: 0, span: 24 },
  backgroundImgUrl:
    "http://www.yongma16.xyz/staticFile/common/img/background.png",
});
/**
 * 初始化表单内容
 */
const initForm = () => {
  const userInfoItem: any = window.localStorage.getItem("userInfo");
  interface userInfoType {
    username: string;
    password: string;
    remember: boolean;
  }
  const userInfo: userInfoType = userInfoItem
    ? JSON.parse(userInfoItem)
    : {
        username: "",
        password: "",
        remember: false,
      };
  if (userInfo.username && userInfo.password) {
    state.formState.username = userInfo.username;
    state.formState.password = userInfo.password;
    state.formState.remember = userInfo.remember;
  }
};
/**
 * 前往注册!
 */
const jumpRegister = () => {
  // 带 hash,结果是 /about#team
  router.push({ path: "/register" });
};

/**
 * 前往home!
 */
const jumpHome = () => {
  // 带 hash,结果是 /about#team
  router.push({ path: "/" });
};
/**
 * 记住密码
 * @param params
 */
const rememberAction = (params: Object) => {
  window.localStorage.setItem("userInfo", JSON.stringify(params));
};
/**
 * 登录
 */
const loginAction = () => {
  if (formRef.value) {
    formRef.value.validate().then((res: any) => {
      state.spinning = true;
      const params = {
        username: state.formState.username,
        password: state.formState.password,
      };
      if (state.formState.remember) {
        rememberAction({ ...params, remember: state.formState.remember });
      }
      loginUser(params)
        .then((res: any) => {
          console.log("res", res);
          const { data: response } = res;
          state.spinning = false;
          if (response.code === 200) {
            store.commit("user/setUserInfo", response.data);
            // 跳转
            setTimeout(() => {
              jumpHome();
            }, 500);
            message.success(response.message);
          } else {
            message.warning(response.message);
          }
        })
        .catch((r: any) => {
          state.spinning = false;
          message.error(JSON.stringify(r));
          throw Error(r);
        });
    });
  }
};

onMounted(() => {
  //初始化
  initForm();
});
</script>

结束

感谢阅读,下面是我的gitcoe代码仓库,如有问题,欢迎提出讨论!

代码仓库:gitcode.net/qq_38870145...

相关推荐
小政爱学习!22 分钟前
封装axios、环境变量、api解耦、解决跨域、全局组件注入
开发语言·前端·javascript
魏大帅。27 分钟前
Axios 的 responseType 属性详解及 Blob 与 ArrayBuffer 解析
前端·javascript·ajax
花花鱼33 分钟前
vue3 基于element-plus进行的一个可拖动改变导航与内容区域大小的简单方法
前端·javascript·elementui
k093337 分钟前
sourceTree回滚版本到某次提交
开发语言·前端·javascript
web行路人1 小时前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架
番茄小酱0011 小时前
Expo|ReactNative 中实现扫描二维码功能
javascript·react native·react.js
子非鱼9211 小时前
【Ajax】跨域
javascript·ajax·cors·jsonp
超雄代码狂2 小时前
ajax关于axios库的运用小案例
前端·javascript·ajax
周亚鑫2 小时前
vue3 pdf base64转成文件流打开
前端·javascript·pdf
落魄小二2 小时前
el-table 表格索引不展示问题
javascript·vue.js·elementui