前言
通过前两篇的学习,我们实现了用户名片的设置和读取功能,其中包括图片的上传、压缩及存储在 Nginx 服务器上。本篇我们将在前端实现用户名片的设置和读取,并在不同的场景中分别获取头像的缩略图和原图。
知识准备
本篇内容主要是页面的布局,主要涉及到了 Vue 的生命周期以及 Element UI 中的组件,在学习前,先给大家做下简单介绍。
- Vue 生命周:Vue 对象从创建到销毁的全过程,其中的每个过程都有对应的钩子函数,我们可以通过这些钩子函数指定其在某个过程中要执行的动作。
- Container 布局容器:用于布局的容器组件,方便快速搭建页面的基本结构。
- Upload 上传:通过点击或者拖拽上传文件。
- Dropdown 下拉菜单:将动作或菜单折叠到下拉菜单中。
Vue 生命周期
Vue 对象从创建到销毁经历了以下过程,每个过程都有相应的钩子函数可供调用:
- beforeCreate:创建 Vue 对象前,初始化事件,生命周期的开始。
- created:Vue 对象创建完成,对语法格式和函数进行校验,创建 Vue 对象。
- beforeMount:Vue 对象挂载前,对模板
<template>
进行编译。 - mounted:Vue 对象挂载完成,模板、数据、方法均准备完毕,Vue 对象完全挂载到页面上。
- boforeDestory:销毁前,解除绑定,销毁子组件以及事件监听器。
- destoryed:销毁完毕,Vue 生命周期结束。
Container
Container 主要用来进行页面布局,主要包含以下几个标签:
<el-container>
:外层容器。当子元素中包含<el-header>
或<el-footer>
时,全部子元素会垂直上下排列,否则会水平左右排列<el-header>
:顶栏容器<el-aside>
:侧边栏容器<el-main>
:主要区域容器<el-footer>
:底栏容器
使用 Container 进行页面布局的优点在于兼顾了布局效果和语义化,云笔记项目中用户主页 Home.vue 使用 Container 按照如下格式进行页面布局:
<el-container>
<el-header>Header</el-header>
<el-container>
<el-aside width="200px">Aside</el-aside>
<el-aside width="200px">Aside</el-aside>
<el-main>Main</el-main>
</el-container>
</el-container>
效果如图:
整个页面分为上下两部分:页头和内容区。页头用来展示应用名、用户名片等,内容区又从左到右分为三部分:
- 左:笔记本列表
- 中:笔记列表
- 右:笔记内容
Upload
Upload 用于文件上传,提供了文件列表展示、头像展示、照片墙展示、缩略图列表展示等几种预定义的上传效果,同时支持文件点击上传和拖拽上传两种方式。使用方式如下:
<el-upload class="avatar-uploader" :action=uploadUrl :show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload">
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
- action:指定文件上传要调用的接口地址
- on-success:文件上传成功后的处理
- before-upload:文件上传前的处理,可用于校验文件格式、大小等
<img>
:图片上传成功后展示的缩略图<i>
:上传图片的图标
Dropdown
Dropdown 展示下拉菜单,支持 click 激活或 hover 激活,预置三种不同的尺寸,支持指令事件,使用方式如下:
<el-dropdown @command="handleCommand">
<span class="el-dropdown-link">
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="userCard">修改名片</el-dropdown-item>
<el-dropdown-item command="userPassword">修改密码</el-dropdown-item>
<el-dropdown-item command="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
- @command:指定当下拉选项被点击时触发的事件
- command:指定当该下拉选项被点击时回传给 @command 事件的参数
流程设计
用户名片的页面操作主要分为创建、展示和修改:
- 用户注册成功后,填写昵称、头像等个人信息,点击“完成”按钮后完成设置(接口:2001、2003)
- 设置完毕后,进入用户主页,主页里显示用户昵称、头像等信息(接口:2002)
- 用户主页里可以修改用户昵称、头像等信息(接口:2001、2003)
代码实现
本篇代码结构如下:
- api.js:根据接口文档声明要用到的接口
- views
- Register.vue:注册完毕后设置用户名片
- Home.vue:展示和修改用户名片
定义接口
在 api.js 中,按照接口文档中接口 2001 设置个人名片、接口 2002 获取个人名片的说明对接口做如下声明:
/**
* 设置个人名片 2001
*/
export const req_setUserCard = (user) => {
return axios.post(api, {
nickName:user.nickName,
email:user.email,
label:user.label
},{
headers:{
'method':'userCard',
'token' : window.localStorage.getItem("token")
}
}).then(res => res.data).catch(err => err);
};
/**
* 获取用户名片 2002
*/
export const req_getUserCard = () => {
return axios.get(form, {
headers:{
'method':'userCard',
'token' : window.localStorage.getItem("token")
}
}).then(res => res.data).catch(err => err);
};
在这两个接口的声明中,根据文档要求,在请求的 Header 中添加了登录时获取到的 JWT,作为用户身份验证的唯一凭据,并按照要求传入指定的参数。
接口 2002 传头像并未在此定义,是因为这是一个特殊的接口,通过 Upload 组价的 action 属性指定,在使用时再声明。
创建名片
接口声明完成后,按照顺序一一实现用户名片功能,首先是创建名片。
在注册页面我们留了最后一步待实现:需要在用户注册完成之后完善资料。这一步就是创建名片,需要用户设置昵称,并选择头像,界面设计如下:
<image src="https://images.gitbook.cn/4e870280-7a73-11ea-9792-81939fbf7f0c" width=80%>
打开 Register.vue,按照页面布局添加第三步的 HTML 标签,注意使用 Upload 组件,代码如下:
<!-- 第三步,设置昵称和头像,完善个人信息 -->
<el-row v-if="step == 2">
<el-form-item>
<!-- 昵称 -->
<span class="ColorCommon font-bold">设置昵称</span>
<el-input type="text" v-model="user.nickName" placeholder="往后余生" autofocus="autofocus"></el-input>
</el-form-item>
<el-form-item style="width:100%;">
<!--头像-->
<span class="ColorCommon font-bold">选择头像</span>
<el-upload class="avatar-uploader" :action= uploadUrl :show-file-list="false"
:on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>
<el-form-item style="width:100%;">
<el-button type="primary" style="width:100%;" @click="handleSetUserCard">完成</el-button>
</el-form-item>
</el-row>
在这里将 <el-upload>
标签中的 :action
属性设置为 uploadUrl,在这里需要对注册成功后的处理方法进行修改,使其保存 JWT 并对 uploadUrl 的值进行设置:
var userName = this.user.email;
this.$notify.success({
title: "注册成功",
message: "您的账号:" + userName + " 已成功注册"
});
this.step++;
window.localStorage.setItem("token", data);
this.uploadUrl = this.uploadUrl + "?token=" + data;
通过 :before-upload="beforeAvatarUpload"
绑定上传前的处理方法,可以对图片的格式和大小进行限制:
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!');
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!');
}
return isJPG && isLt2M;
}
最后,在 handleAvatarSuccess 方法中将图片地址赋值给 <img>
标签就可以展示出刚上传的图片了:
handleAvatarSuccess(res, file) {
this.imageUrl = URL.createObjectURL(file.raw);
}
至此,上传图片的功能完成。在点击“完成”按钮后,调用接口 2001 设置个人名片,设置成功后跳转到用户主页,设置失败则弹出错误提示,代码如下:
handleSetUserCard() {
req_setUserCard(this.user).then(response => {
//解析接口应答的json串
let {
message,
success
} = response;
//应答不成功,提示错误信息
if (success !== 0) {
this.$message({
message: message,
type: 'error'
});
} else {
//应答成功,提示验证码发送成功
this.$notify.success({
title: this.user.nickName,
message: "名片设置成功"
});
this.$router.push({
path: "/Home"
});
}
});
},
至此,用户名片创建完成。
显示名片
名片设置完成后跳转到用户主页,在主页中要显示用户昵称和头像,效果如下:
上面提到,用户主页用的是 Container 进行的页面布局。我们在 Container 组件的 <el-header>
标签中依次布局头像、昵称、个性签名和应用名。其中,昵称后面是个 Dropdown 组件,可以进行修改名片、修改密码、退出登录等操作。代码如下:
<!-- 页头 -->
<el-header class="header">
<el-row>
<el-col :span="4" :offset="4">
<div>
<!-- 头像,添加一个超连接,点击可以查看原图 -->
<a :href="user.protraitUrl" target="_blank">
<img class="span smallAvatar" :src="user.protraitThumUrl" />
</a>
<!-- 昵称 -->
<span class="span ColorInfo"> {{user.nickName}}</span>
<!-- 下拉菜单,用于进行修改名片、修改密码、退出登录等操作 -->
<el-dropdown @command="handleCommand">
<span class="el-dropdown-link">
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="userCard">修改名片</el-dropdown-item>
<el-dropdown-item command="userPassword">修改密码</el-dropdown-item>
<el-dropdown-item command="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</el-col>
<!-- 个性签名 -->
<el-col :span="8" class="ColorInfo">
{{user.label}}
</el-col>
<!-- 应用名 -->
<el-col :span="4" class="font20 ColorPrimary font-bold alignRight" >
Keller Notes
</el-col>
</el-row>
</el-header>
页面需要的昵称、头像等数据是在进入用户主页时就要展示出来的,不需要用户执行其他操作,这个时候就用到 Vue 生命周期的相关知识。通常,这些方法都要在 Vue 对象挂载完成后自动执行,也就是 mounted 阶段,钩子函数写法如下:
mounted() {
//进入用户主页,首先获取用户名片
this.getUserCard();
//将登录时保存的 JWT 取出来,在上传头像时使用
this.uploadUrl = this.uploadUrl + "?token=" + window.localStorage.getItem("token");
}
其中,getUserCard() 方法就是实际调用接口 2002 获取用户名片的方法——调用接口,将获取到的数据返回,代码如下:
getUserCard(){
req_getUserCard().then(response => {
//解析接口应答的json串
let {
data,
message,
success
} = response;
//应答不成功,提示错误信息
if (success !== 0) {
this.$message({
message: message,
type: 'error'
});
} else {
this.user = data;
}
});
}
至此,页面就可以显示出用户的名片了,大家可以将其 mounted 函数换成不用的钩子函数,观察页面不同的展示效果,以此来加深对 Vue 各个生命阶段的理解。
遮罩层
经过上一步操作后,鼠标放在昵称后的小箭头,就会弹出修改名片、修改密码、退出登录等操作,修改名片将使用遮罩层的方式。在 index.css 文件中是为项目统一定义的样式,可以在里面添加遮罩层的实现:
/* 遮罩层 */
.box {
width: 100%;
height: 100%;
background-color: #000000;
opacity: 0.4;
position: absolute;
top: 0;
left: 0;
}
/* 遮罩层里的内容 */
.boxCenter {
position: absolute;
top: 0;
left: 0;
width: 60%;
margin-left: 20%;
margin-top: 10%;
background-color: #FFFFFF;
opacity: 1;
border-radius: 20px;
padding: 20px;
z-index: 999;
}
在使用时,只需要引用这两个样式即可,如:
<div class="box"></div>
<div class="boxCenter"></div>
页面展示效果如下:
修改名片
修改名片页面效果如下:
这个功能的页面设计和调用的接口与创建名片一样,在这里就不再赘述了,大家可以参照创建名片来实现该功能,页面布局代码如下:
<!-- 遮罩层 -->
<div v-if="mask == 'userCard' || mask == 'userPassword'" class="box"></div>
<!-- 修改用户名片 -->
<div v-if="mask == 'userCard'" class="boxCenter">
<el-form label-position="left" label-width="0px">
<el-form-item>
<el-row>
<el-col :span="16" :offset="4" class="alignCenter font24 font-bold">
修改名片
</el-col>
<el-col :span="4" class="alignRight">
<i class="el-icon-circle-close font24" @click="handleCommand()"></i>
</el-col>
</el-row>
... ...
</el-form-item>
<el-form-item style="width:100%;">
<!-- 修改名片 -->
<el-button type="primary" style="width:100%;" @click = "handleSetUserCard()" :disabled="!checkEmail()">保存修改</el-button>
</el-form-item>
</el-form>
</div>
源码地址
完整的源码地址如下:
https://github.com/tianlanlandelan/KellerNotes/tree/master/17.用户名片3
小结
本篇通过 Element UI 组件的使用,完成了设置名片、显示名片、上传头像等功能,并在上传头像前实现了对文件格式、大小的限制。通过本篇的学习,能使大家对页面布局、文件上传、遮罩层等操作有深入的了解。其中,Upload 组件有多种不同的展示效果,大家在学习之余可以多多尝试,希望大家收获多多,快乐多多。