Vue全栈技术重构字节跳动招聘网站总结(下)

前言

全新重构升级的项目vue-bytedanceJob 2.0终于完成了,特此写一篇文章总结一下,也是文章Vue全栈技术重构字节跳动招聘网站(上)
的续篇。本篇文章会重点介绍网站新版本添加的主要功能,并会对有意思的地方详细分析,还有就是对于整个项目的重新概括(技术栈)以及项目中一些典型业务逻辑的实现剖析。同时,2.0版本的项目还增加了几个API类型的自定义组件,比如,进度条弹窗消息通知数据加载loading等组件,这些组件的功能特点和开发过程我也会进行解析。所以下面的介绍是干货满满,看完了别忘记点赞留言额!

新增加的需求

已实现

未实现

  • 邮箱注册账号
  • 手机号登录
  • 简历投递
  • 项目进一步的优化

部分屏幕截图

简历预览页面


image

简历编辑页面


image

除了以上列出来的需求已全部实现之外,针对于一些功能的重构也有很多。包括几个可以使用API方式调用的组件也是通过自己手动开发封装实现的,并且替换了在上一个版本中使用第三方组件库引入的组件。项目最后的展示效果实际测试下来,在业务的整体结合和组件基础功能的定制性上有了很大的改善,不仅是沉余的代码变少了,而且在业务逻辑上也更吻合了。

有了很多改进的地方,也有不足的地方,相比于第三方成熟的类库在测试用例上不够全面,部分地方还需要进一步的测试改进。其次如果你需要引入到自己的项目中使用这些组件是需要进行二次开发的,因为这些都是业务组件而不是通用组件。如果你在使用的过程中有问题或者好的建议,欢迎提issues!

新增加的三个API组件

以下的组件均支持API的方式调用,本项目各组件的调用方法挂载到了Vue实例的原型对象上,根据具体用例你也可以单独引入到特定文件内使用 ,各组件详细介绍如下

数据加载组件Loading

image

Loading组件基本的使用方式同大多数类库是一样的,我也是参考了它们的API设计方式和参数传递方式实现的。图上显示的loading有两种调用状态,一个是局部调用(通过指令的方式),还有就是方法调用,这里以简化版代码做一个演示。

统一说明:代码演示中this均为Vue实例

API方式使用

/*
@params `position`是全屏`loading`具体的定位信息,默认为`0`,可以根据需求适当调整其位置
*/ 

const  loading = this.$loading({ position: { top: 0, left: 0, right: 0, bottom: 0 } });

// 在适当的实际关闭
loading.close()

以指令的方式调用

<template>
  <div v-loading.scrollFixed="true"></div>
</template>

指令的绑定值可以用一个组件状态变量代替,以便灵活控制loading状态,这里以简化版代码代替
scrollFixed是支持传递的指令修饰符,其作用是当被绑定loadingDOM元素滚动到页面视口之外时,loading图标永远居中显示,小伙伴们不用考虑元素滚动带来loading一起滚动并消失在视口内的烦恼了,想想是不是很酸爽呢!

查看组件代码点这里

进度条弹窗组件popup-progress

image

popup-progress组件可以认为是弹出式进度条组件,由于没有想到更好的名字暂且先这样命名吧。使用过一些类库组件的同学很容易能想到他就是结合了弹窗alert和进度条progress设计的。由于属于是全屏组件,这里又引出了js众多设计模式之一的单例模式的概念。这个组件设计的时候也是运用了此模式,跟大多数弹框类的组件一样也算是一个比较经典的实现方式吧。那么它跟其他模态框组件不同的一点是什么呢?

由于弹框中的滚动条是一个不断变化的状态,调用此组件的时候跟别的返回Promise的一些组件就不一样了,比如alert,confirm,prompt这类组件等等。这些组件之所以可以返回promise是组件挂载后需要等待用户操作状态,不经过用户手动操作状态组件自身的状态是固定不变的,这跟js中的promise颇为相像。所以组件调用返回值为promise也就不足为奇了。但是本文中的popup-progress就不一样了,为了符合业务需要,组件在挂载之后,进度条的进度是一个需要变化的值。显然通过向组件传递固定状态值属性的方式就不行了,所以组件创建后返回实例自身更合适。这样的处理在组件被调用的上线文环境中返回了组件实例自身,而不是通过组件初始化的时候传递函数等复杂的数据类型参数以便在组件内部处理。这种设计方式让组件注册监听自定义事件也颇为方便,不仅可以链式的调用API,而且我个人认为这比向组件传递监听器函数的参数的方式更优雅。说了这么多,唯有代码演示才更直观。

// 创建进度条弹窗
const popPro = this.$popupProgress();

//在具体的使用用例中更新`popPro`的进度值, 这里用`setInterval`模拟演示

const timer = setInterval(() => {
  //控制进度条的进度的值这里为`value`,值需要是`1-100`之间的数
  popPro.value += 10;
}, 300);

// 监听上传终止事件(点击`取消`按钮后触发)
popPro.$on("abort", () => {
  //终止上传过程后的操作, 关闭弹窗进度条
    popPro.close()
});
//当进度条进度为`100%`的装态时触发`success`事件
popPro.$on("success", () => {
  clearInterval(timer);
  // 关闭弹窗进度条
    popPro.close()
});

上面注册事件的代码可以简写为

this.$popupProgress()
  .$on("abort", () => {
     
  })
  .$on("success", () => {
    
  });

至此有关popup-progress组件的全部分析就到这了,如果您有好的建议或问题欢迎提issue

查看代码点 https://github.com/konglingwen94/vue-bytedanceJob/tree/2.0/src/components/popup-progress

消息通知组件message

image

引言

message组件是日常业务开发中使用比较多的,可能追求快捷开发的同学直接就引入通用的类库了(我之前就是这么做的)。通用类库的组件有一个特点,它之所以通用是因为在功能设计上考虑了很多的业务场景和用例,自然包含的功能就很丰富。但是对于需要长期维护更新的项目来说就会带来很多问题,首先通用组件的UI风格和自身业务的需求并不恰好一致,其次代码量会有沉余,这些都是不可规避的问题。所以当我们在遇到类似的业务需求时,自己动手实现往往是更好的选择,这样不仅会使项目整体的代码更聚合,与此同时我们自身的技术水平也会有很大提高。

基本介绍

message组件有三种消息状态分别为成功失败警告,对于一般复杂度的项目应该够用了。麻雀虽小,五脏俱全,消息通知类组件应该有的功能本组件都有,虽不如通过的轮子可传递的参数多样。仅以本项目的用例说的话足够用了,有兴趣的同学可以基于此二次开发。欢迎提PRissue。组件API的使用方式也保持了通用的设计方式。具体演示如下

// 这里以成功的消息状态举例,其他两种同理
this.$message({message:"成功",type:"success"})

// 支持使用消息类型的别名直接调用
this.$message.success('成功')

// 支持传递消息关闭的时间参数,默认为`3000ms`

this.$message({message:"成功",duration:2000})

message组件和上面介绍的popup-progress组件相反,API底层的设计模式是工厂模式。所有已创建的组件实例在销毁前都存放到一个队列中。像代码中创建组件的方法每调用一次都会在视图上添加一个新消息。显示效果就如图上那样依次排列。所以在使用的时候可以多次的调用。

查看代码点 https://github.com/konglingwen94/vue-bytedanceJob/tree/2.0/src/components/message

递归思想在业务中的运用

image

image

看到这两个典型用例的演示,好像跟标题中要说的递归没有联系,其实这里面的一个函数的实现方式正是用了递归的思想。回到图片中的功能本身,页面在滚动过程中某一部分动态吸底或吸顶并不复杂,这里要说的是其中的一个细节实现。

我们知道DOM元素的一个属性值offsetTop。它代表的是相对最近的定位父级元素顶部的距离偏移,那么这里又印出来了另外一个属性offsetParent,它代表的就是元素最近的父级定位元素。有了这两个属性,我们可以轻松的获取元素各个方向距离父元素的偏移距离。那如果我们要获取元素距离页面最顶部的距离应该怎么拿到?如果元素的offsetParent属性是根元素html的话,直接获取元素的offsetTop属性就行了。对于有多个父级定位元素的话,我们就需要手动逐级的查找元素的offsetParent元素的offsetTop进行累加计算。这种方式最终也可以正确的获取到结果。问题是在页面布局复杂的场景下这个方法就不好使了。如果要计算的元素层级嵌套很深,父级定位元素又多的话计算量是非常大而且容易出错。我把逐级向上查找父级元素的offsetTop值看成是一个手动的递归过程,既然可以用程序解决的问题,最终都将用程序来解决。直接放代码出来吧

function getOffsetTop(node, targetOffsetParentNode, offsetTopSum = 0) {
  offsetTopSum += node.offsetTop;

  if (node.offsetParent !== targetOffsetParentNode) {
    return getOffsetTop(node.offsetParent, targetOffsetParentNode, offsetTopSum);
  }
  return offsetTopSum;
}

//用例:获取元素`$0`距离根元素顶部的距离`offsetTop`

const offsetTop = getOffsetTop($0,document.documentElement)

有了这个相对于根元素的顶部距离跟实现图中的效果有什么关联?通过比较这个值和滚动容器的滚动坐标就可以实现滚动切换定位元素的功能了,这里就不具体分析了。

功能实现源代码

职位搜索栏滚动吸顶 这里

简历编辑操作栏动态吸底 https://github.com/konglingwen94/vue-bytedanceJob/blob/2.0/src/views/ResumeEditor.vue#L974

查看本项目更多工具函数点 这里

服务端接口抓取

关于服务端接口是如何抓取的,这里我也简单谈一下项目整个后端接口代理的整个过程。从最开始在浏览器开发者工具提供的Network面板里面逐个查找,接着就是用Postman一个一个的实际调试。说到这我想说一下自己爬数据接口的一点心得,用工具调试接口和用代码模拟调试真的是两回事。由于运行环境的不一致,往往会出现一些意料之外的问题。这里我就拿登录类强依赖接口状态的接口请求举例子,这类的接口由于需要身份验证需要很多私密字段携带到请求头里面发送到服务端,有一些请求头字段是浏览器默认不允许携带的,比如referer,origin等字段,所以需要携带这类信息发送请求的接口在浏览器是无法实现的,所以我们往往需要一个代理服务器去转发这些接口,其实本项目也是这么做的,而且代理转发请求的方式是用一个第三方中间件实现的,有兴趣的同学可以点这里查看具体实现方式。

除了上面说的这些,让我采坑比较深的就是token验证类型的请求接口了,且本项目就是靠验证token的方式实现的,有兴趣查看具体实现过程的同学在这里

持续集成

对于一个完整上线的项目是离不开持续集成这道步骤的。本项目使用的是一个简化版的持续集成配置,首先上线的服务器是购买某电商的,项目自身用到持续部署插件借鉴了知名开源项目Vue的使用方式yorkiepackage.json文件的配置为

{
  "gitHooks": {
    "pre-push": "sh deploy.sh"
  }
}

前提是需要编写一个部署脚本deploy.sh,当项目每次提交到远程仓库的时候就会触发gitHooks配置好的脚本命令,然后就静静等待程序自动部署就ok了。

脚本部署文件内容可以按如下配置,需要添加更多步骤的话直接编写即可。

!/usr/

npm run build  # 需要构建到`server`目录

scp -r server user@192.168.1.1:/var/www/projectname

项目构建发布后,还需要登录云服务器开启服务,本项目使用的是pm2,在终端运行以下命令开启服务


cd /var/www/projectname 

pm2 start app.js

总结

通过全新重构升级的基于Vue的单页面应用,自己除了对Vue的理解和认识提高了一个层次之外,对于项目重构,升级这一系列要做的工作又熟练了一遍。从开始的API接口分析爬取,接着是对需求的整理分析,再到代码的最终编写完成,最后就是一遍又一遍的测试和持续集成。从而我对项目的开发步骤流程也有了更好的梳理和把握,同时自己也有很多不足的地方需要持续的补充和学习。

另外也希望对看过本篇文章的你在学习上有所帮助,共勉一下,一起加油哇!

支持

如果您读完文章感觉还不错的话欢迎点赞,谢谢!

如果您有好的想法和建议欢迎在评论区留言!

文章中有错误的地方欢迎指出,谢谢!

查看

项目仓库地址:https://github.com/konglingwen94/vue-bytedanceJob

项目线上预览:http://123.56.124.33:3000

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容