文章目录
背景
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:setup
。setup
函数是一个在组件内部执行的函数,用于在组件开始挂载之前进行一些设置工作。它接收两个参数:
props
:一个对象,包含了从父组件传入的props。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中使用data
和methods
选项时可能遇到的一些问题。
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代码仓库,如有问题,欢迎提出讨论!