第三方登录+LoginForm组件封装
现代管理后台通常支持多种登录方式——除了传统的用户名密码,还可能集成微信、支付宝、GitHub 等第三方 OAuth 登录。本节将登录表单封装为独立的 LoginForm 组件,并在底部添加第三方登录入口。
LoginForm 组件封装
将登录表单从页面中抽取为独立组件,好处是:
- 页面文件更简洁,只负责布局和工具栏
- LoginForm 可以在多个页面复用(如弹窗登录)
- 注册表单 RegisterForm 也可以独立封装
组件接口设计
// login-form.vue
interface LoginFormProps {
loading?: boolean
}
const emit = defineEmits<{
submit: [data: { username: string; password: string; remember: boolean }]
switchToRegister: []
}>()
typescript
Props 只接收 loading(外部控制加载状态),其他数据在组件内部管理。事件包括 submit(提交表单)和 switchToRegister(切换到注册表单)。
组件结构
<template>
<div class="login-form">
<!-- Logo / 系统名称 -->
<h2 class="text-2xl font-bold text-center mb-6">
{{ t('login.title') }}
</h2>
<!-- 表单 -->
<el-form ref="formRef" :model="formData" :rules="formRules">
<!-- 用户名 -->
<el-form-item prop="username">
<el-input v-model="formData.username" :placeholder="t('login.username')">
<template #prefix>
<Iconify icon="ep:user" />
</template>
</el-input>
</el-form-item>
<!-- 密码 -->
<el-form-item prop="password">
<el-input v-model="formData.password" type="password" show-password>
<template #prefix>
<Iconify icon="ep:lock" />
</template>
</el-input>
</el-form-item>
<!-- 记住密码 + 忘记密码 -->
<el-form-item>
<div class="flex justify-between w-full">
<el-checkbox v-model="formData.remember">
{{ t('login.remember') }}
</el-checkbox>
<el-link type="primary">{{ t('login.forgot') }}</el-link>
</div>
</el-form-item>
<!-- 登录按钮 -->
<el-form-item>
<el-button
type="primary"
class="w-full"
:loading="loading"
@click="handleSubmit"
>
{{ t('login.submit') }}
</el-button>
</el-form-item>
</el-form>
<!-- 第三方登录 -->
<el-divider>{{ t('login.thirdParty') }}</el-divider>
<div class="flex justify-center gap-4 mb-4">
<Iconify icon="ri:wechat-fill" class="text-2xl text-green-500 cursor-pointer" />
<Iconify icon="ri:alipay-fill" class="text-2xl text-blue-500 cursor-pointer" />
<Iconify icon="ri:github-fill" class="text-2xl cursor-pointer" />
</div>
<!-- 切换注册 -->
<div class="text-center">
<span>{{ t('login.noAccount') }}</span>
<el-link type="primary" @click="emit('switchToRegister')">
{{ t('login.register') }}
</el-link>
</div>
</div>
</template>
vue
第三方登录的实现方案
第三方登录通常有三种实现方案:
| 方案 | 原理 | 适用场景 |
|---|---|---|
| OAuth 跳转 | 重定向到第三方授权页 | 微信、支付宝、GitHub |
| 扫码登录 | 展示二维码,轮询扫码状态 | 微信扫码 |
| JWT Token | 后端验证后返回 token | 自有系统 |
OAuth 跳转的基本流程
用户点击"微信登录"
→ 前端构造授权 URL
→ window.location.href = `https://open.weixin.qq.com/connect/qrconnect?appid=${appId}&redirect_uri=${redirectUri}`
→ 用户在微信页面授权
→ 微信重定向回 redirect_uri 并携带 code
→ 前端将 code 发送给后端
→ 后端用 code 换取 access_token
→ 后端创建/登录用户,返回 JWT
text
前端的职责是构造授权 URL 和处理回调页面中的 code 参数。
图标插槽 vs prefix-icon
Element Plus 的 el-input 支持两种方式添加前缀图标:
<!-- 方式一:prefix-icon 属性 -->
<el-input prefix-icon="User" />
<!-- 方式二:prefix 插槽(推荐) -->
<el-input>
<template #prefix>
<Iconify icon="ep:user" />
</template>
</el-input>
vue
推荐使用插槽方式,因为可以传入 Iconify 的任意图标(Element Plus 内置图标库有限)。
本节小结
- 组件封装:LoginForm 独立封装,通过 props 和 emit 与页面通信。
- 第三方登录:OAuth 跳转方案,前端负责构造授权 URL 和处理回调。
- 图标方式:推荐使用
#prefix插槽 + Iconify 图标,灵活度更高。 - 事件设计:
submit传递表单数据,switchToRegister触发表单切换。
↑