用户名片 3:页面实现

前言

通过前两篇的学习,我们实现了用户名片的设置和读取功能,其中包括图片的上传、压缩及存储在 Nginx 服务器上。本篇我们将在前端实现用户名片的设置和读取,并在不同的场景中分别获取头像的缩略图和原图。

知识准备

本篇内容主要是页面的布局,主要涉及到了 Vue 的生命周期以及 Element UI 中的组件,在学习前,先给大家做下简单介绍。

  • Vue 生命周:Vue 对象从创建到销毁的全过程,其中的每个过程都有对应的钩子函数,我们可以通过这些钩子函数指定其在某个过程中要执行的动作。
  • Container 布局容器:用于布局的容器组件,方便快速搭建页面的基本结构。
  • Upload 上传:通过点击或者拖拽上传文件。
  • Dropdown 下拉菜单:将动作或菜单折叠到下拉菜单中。
Vue 生命周期

Vue 对象从创建到销毁经历了以下过程,每个过程都有相应的钩子函数可供调用:

  1. beforeCreate:创建 Vue 对象前,初始化事件,生命周期的开始。
  2. created:Vue 对象创建完成,对语法格式和函数进行校验,创建 Vue 对象。
  3. beforeMount:Vue 对象挂载前,对模板 <template> 进行编译。
  4. mounted:Vue 对象挂载完成,模板、数据、方法均准备完毕,Vue 对象完全挂载到页面上。
  5. boforeDestory:销毁前,解除绑定,销毁子组件以及事件监听器。
  6. 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 事件的参数

流程设计

用户名片的页面操作主要分为创建、展示和修改:

  1. 用户注册成功后,填写昵称、头像等个人信息,点击“完成”按钮后完成设置(接口:2001、2003)
  2. 设置完毕后,进入用户主页,主页里显示用户昵称、头像等信息(接口:2002)
  3. 用户主页里可以修改用户昵称、头像等信息(接口: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 组件有多种不同的展示效果,大家在学习之余可以多多尝试,希望大家收获多多,快乐多多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值