这里使用的是全部引入,比较方便
安装 element ui :npm i element-ui -S
全部引入
在 main.js 中添加下面的代码
// element ui
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
按需引入
安装 babel-plugin-component
:npm install babel-plugin-component -D
修改 babel.config.js
文件:
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset',
['@babel/preset-env', { modules: false }]
],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk'
}
]
]
}
按需引入使用案例,在 main.js
中
// element ui
import { Button, Select } from 'element-ui'
Vue.component(Button)
Vue.component(Select)
头部导航
HeaderLogo
HeaderSearch
HeaderRight
主要用到 Element 组件的 Dialog对话框
参考了这篇博客: vue之登录弹框Dialog对话框实现
但是这里与此篇博客不同在于,这个弹窗有三个页面
(所以需要用到路由Router来进行切换):
Dialog 的使用
- 官方使用文档:
el-dialog
设置一个居中和宽度- 在弹出框
el-dialog
中加入一个占位符router-view
根据不同路径渲染不同组件- 未登录字眼链接默认跳转
/logincode
,也就是扫描二维码登录
<el-button class="noLogin" type="text" @click="loginVisible = true">
<router-link class="noLoginA" to="/logincode">未登录 router-link>
<i class="el-icon-caret-bottom">i>
el-button>
<el-dialog :visible.sync="loginVisible" center :append-to-body='true' :lock-scroll="false" width="350px">
<router-view>router-view>
el-dialog>
data () {
return {
loginVisible: false
}
}
路由使用步骤
占位符
router/index.js 引入组件,配置跳转路径对应的组件
import LoginByScanCode from '@/components/Header/User/LoginByScanCode.vue'
import LoginByPhoneNumber from '@/components/Header/User/LoginByPhoneNumber.vue'
import RegisterByPhoneNumber from '@/components/Header/User/RegisterByPhoneNumber.vue'
const routes = [
{path: '/logincode',component: LoginByScanCode},
{path: '/loginphone',component: LoginByPhoneNumber},
{path: '/register',component: RegisterByPhoneNumber}
]
页面中根据需要使用
/logincode
通过扫描二维码登录 LoginByScanCode
/loginphone
通过验证手机和手机密码登录 LoginByPhoneNumber
/register
注册新账号 RegisterByPhoneNumber
HTML 结构
<template>
<div id="login-code-container">
<p class="title">扫码登录p>
<div class="main-outer">
<div class="left-img-outer">
<img id="left-img" src="@/assets/images/left-img.png">
div>
<div class="right-code-outer">
<div id="right-code">
<img :src="QRBase64">
<div class="code-invalid" v-if="codeIsValid === false">
<p>二维码已失效p>
<h5><el-button type="primary" size="mini" @click="afreshGetQR()">点击刷新el-button>h5>
div>
<div class="code-loading" v-if="codeIsLoading === true">
<p><i class="el-icon-loading">i>p>
<p>登录中...... p>
div>
div>
<p>使用<a href="https://music.163.com/#/download">PT音乐a>APP版本扫码登录p>
div>
div>
<router-link to="/loginphone" class="other-way">选择其他登录模式 >router-link>
div>
template>
CSS 样式
因为需要使用 axios ,在
src
目录下utils/request.js
引入axios
,并且设置请求根路径。
import axios from 'axios'
// 调用 axios.create() 函数,创建一个 axios 的实例对象,用 request 来接收
const request = axios.create({
// 指定请求的根路径
baseURL: 'http://127.0.0.1:3000'
})
export default request
在在
src
目录下创建api
,用来封装函数
api/
LoginAndReguster/loginByCode.js 放扫码登录相关的请求api/
user/user.js 放与用户账户相关的请求
// 注册相关的 API 接口
import request from '@/utils/request.js'
// 每次请求都带上时间戳 timestamp 参数 防止缓存
// withCredentials 请求为跨域类型时是否在请求中协带cookie
// 获得 QR 的 key
export const getLoginQRKey = function () {
return request.get('/login/qr/key', {
params: {
timestamp: new Date().getTime(),
withCredentials: true
}
})
}
// 传入 key 生成二维码图片的 base64 和二维码信息
export const getLoginQR = function (key) {
return request.get('/login/qr/create', {
params: {
key: key,
qrimg: true,
timestamp: new Date().getTime(),
withCredentials: true
}
})
}
// 获取登录信息
export const getLoginStatus = function () {
return request.get('/login/status', {
params: {
timestamp: new Date().getTime(),
withCredentials: true
}
})
}
// 带上key 检查二维码是否过期
export const checkStatus = function (key) {
return request.get('/login/qr/check', {
params: {
key: key,
timestamp: new Date().getTime(),
withCredentials: true
}
})
}
import request from '@/utils/request.js'
// 获取用户信息
export const getUserAccount = function (cookier) {
return request.get('/user/account', {
params: {
cookie: cookier,
timestamp: new Date().getTime(),
withCredentials: true
}
})
}
写在前面:感觉整个页面逻辑确实没有什么问题,但是在扫描成功确认登录后再次去访问登录状态时还是没有登录,根据登录成功返回的 cookie 带着再去访问账号信息时还是得不到账号信息,对比官方文档给出的案例感觉并无差别,但是官方的案例登陆之后给浏览器设置了cookie,而我的登录成功之后浏览器并没有被设置cookie,导致检查状态一直是未登录。不知道该如何解决。如果有哪位大佬知道原因,还麻烦指点我一下。
getLoginQRImg
函数
getLoginQRKey
获取二维码的 key
getLoginQR
获取二维码的信息和 base64 格式的编码,可以直接作为 img 的src渲染到页面上
使用 setInterval
创建定时器 timer
,间隔 3000ms 便访问一次二维码的状态,根据不同的状态渲染页面样式
code === 800
二维码已经失效,渲染失效样式的DOM,并且清理 timercode === 802
正在等待确认中,渲染登录中的样式code === 803
登录成功,返回 cookie,,并且清理 timerafreshGetQR
函数 当二维码失效的时候点击点击刷新
的时候重新调用 getLoginQRImg
函数
将getLoginQRImg
函数放在 created
组件周期时
但是这里有一个问题,点击 Dialog 的关闭按钮的时候,timer 没有被清除,所以需要监听 Dialog 的状态,父组件中有一个 loginVisible
,当Dialog 关闭时为 false
,打开时为 true
。需要将此变量传递给子组件:
父组件中的占位符bind绑定变量给子组件:
<router-view :loginVisible="loginVisible">router-view>
子组件使用 props 接收,设置一个默认值 false:
props: {
loginVisible: {
type: Boolean,
default: false
}
}
在进入定时器 timer 的时候判断该值,如果位false则清除定时器,达到关闭Dialog 同时清除timer的作用。
// 导入获取 key 和 QR 的 API
import { getLoginQRKey, getLoginQR, getLoginStatus, checkStatus } from '@/api/LoginAndRegister/loginByQR.js'
// 导入 user.js
import { getUserAccount } from '@/api/user/user.js'
export default {
props: {
loginVisible: {
type: Boolean,
default: false
}
},
data () {
return {
codeIsValid: true,
codeIsLoading: false,
QRkey: '',
QRBase64: '',
cookier: ''
}
},
methods: {
// 获取登录二维码
async getLoginQRImg () {
// 获取 key
const { data: dataKeyObj } = await getLoginQRKey()
const keyObj = dataKeyObj.data
this.QRkey = keyObj.unikey
console.log('二维码的key:', keyObj.unikey)
// 获取 二维码
const { data: dataQRObj } = await getLoginQR(this.QRkey)
const QRObj = dataQRObj.data
this.QRBase64 = QRObj.qrimg
console.log('二维码base64格式:', QRObj.qrimg)
// 循环判断二维码是否过期 是否已经登录
const timer = setInterval(async () => {
// loginVisible 为 true 时定时器才有效
// 当 dialog 被删除时 定时器被消除
if (this.loginVisible === false) {
clearInterval(timer)
}
const { data: keyStatus } = await checkStatus(this.QRkey)
console.log(keyStatus)
if (keyStatus.code === 800) {
// 二维码过期
console.log('二维码已失效')
this.codeIsLoading = false
clearInterval(timer)
this.codeIsValid = false
} else if (keyStatus.code === 802) {
// 授权登录中
console.log('授权登录中...')
this.codeIsLoading = true
} else if (keyStatus.code === 803) {
this.codeIsLoading = false
// 登录成功 会返回 cookie
console.log('登录成功')
clearInterval(timer)
const { data: loginStatus } = await getLoginStatus()
console.log(loginStatus)
this.cookier = keyStatus.cookie
const { data: userAccount } = await getUserAccount(this.cookier)
console.log(userAccount)
}
}, 3000)
},
// 重新获取二维码
afreshGetQR () {
console.log('重新获取二维码')
this.getLoginQRImg()
this.codeIsValid = true
}
},
created () {
this.getLoginQRImg()
}
}