We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
好久没写文章了,标题起的有点膨胀。
我想写一个结对编程小记。最近在和 S (帅气的花名) 利用业余时间,进行了一次结对编程。现在我准备把结对编程的一些思考分享给大家,下面开始吧。
S
PS: 此篇文章,不拘泥于细节,将会聚焦整体上的见解,希望对各位小伙伴有所帮助。
PS:
这里我说明一下原因,请往下看。
百度百科的定义如下:
结对编程(英语:Pair programming)是一种敏捷软件开发的方法,两个程序员在一个计算机上共同工作。一个人输入代码,而另一个人审查他输入的每一行代码。输入代码的人称作驾驶员,审查代码的人称作观察员(或导航员)。两个程序员经常互换角色。 在结对编程中,观察员同时考虑工作的战略性方向,提出改进的意见,或将来可能出现的问题以便处理。这样使得驾驶者可以集中全部注意力在完成当前任务的“战术”方面。观察员当作安全网和指南。结对编程对开发程序有很多好处。比如增加纪律性,写出更好的代码等。结对编程是极端编程的组成部分。
为什么我觉得过时了呢,听我简单(胡)析(诌)下:
两个人共用一台计算机,这可能在 ACM 竞赛或者组队 PK 中常见。但对于业务开发来说,有点不科学,首先效率就不高,如果对方代码太可爱,可能会忍不住打他。当然了,在特殊场景下也会出现,但是 95% 的场景下,是不可能存在下图这种场景的。
ACM
PK
95%
下面这种场景犹如六月飞雪:
不过这种场景倒是很乐意接受的:
当然,别问我为什么,因为:
那什么是我认为的新时代的结对编程呢?
我认为新时代的结对编程,应该是这样一种状态:
两(N)个 coder , 两(N)台电脑,坐在一起(后续也可以不用坐在一起)进行开发。代码可以互相看到。最关键的一点就是,我们可以互相看到并且看懂对方的代码。
N
coder
什么意识呢,这里我举个例子:
我和 S 达成意见,S 负责 node , 也就是后端,我负责前端,前后端分离。然后各自的代码我们都能互相看到,要开发什么功能,我们都知道,我可以 review S 的代码,S 也可以 review 我的代码。当开发的时候,我可以通过 review S 的代码,提前知道 S 的接口逻辑。如果我认为他的逻辑写的有问题,我会和他进行沟通,提前把可能存在的疑问处理掉。我也会提前按照他写的接口来预留好请求这块的逻辑处理。总之,在我理解的结对编程中。应该是能力相同,代码相同,通过互相 review 对方的功能代码,来对比自己的代码。从而告诉对方可能存在的问题,而这种问题的解决会让开发的效率大大增加,更早的解决了潜在的一些问题。
node
review
PS: 当然这种新的方式,需要一定的技术基础,比如你要能看懂后端的代码。嗯,如果是 Java ,你可能会比较艰难。当然,他也会更艰难。所以还是 node 大法好,手动滑稽。总之,这是我认为的新时代下的结对编程,它不具有普适性,当然这种形式的好处是显而易见的。
Java
嗯?按照传统,当然是来一次结对前的庆祝。去了趟 1912 ,吃了个大餐,享受了下日式服务。然后去咖啡馆开始 face to face talking ,愉快的结对编程就要开始了。
1912
face to face talking
怎么玩出花呢?
我分为两个部分去介绍,第一部分是前端,第二部分是后端。
首先,框架的选择这块,在衡量之后,选择的是 Vue 。这里我对用什么框架,其实没什么看法,唯一的看法就是:
Vue
根据实际情况,来选择合适的开发框架,从而提高整体的开发效率。
要不要使用脚手架,这块我也持上面的那句话,根据实际情况做出合适的选择。这里我选择 Vue-cli3 来快速搭建应用。怎么使用,自己去研究一下就知道了。
Vue-cli3
这里可以提供几个路径
第一个路径:去 https://cli.vuejs.org/ 官网研究
第二个路径:去看 vue-cli3 的源码,了解一下内部的一些机制,比如 chainWebpack 的实现,vue.config.js 的默认设置是如何实现的。
vue-cli3
chainWebpack
vue.config.js
第三个路径:去 github 上,找一些用 vue-cli3 搭建的项目,clone 下来,研究一下别人是如何使用的。
github
clone
PS: 我个人认为脚手架是不会存在技术上的难度的,多看看文档,不行的话再去看源码捣鼓捣鼓,就差不多了。
选完技术框架,我们再来看看样式的选择,通用的样式方案,业界的标准基本都是相同的。但是关于组件中的样式该放哪,目前在业界,大概有这么两种。
样式和组件目录分离,这个是目前很多 ui 库采取的方式。 比如 iview elementui ,我来截图展示一下。
ui
iview
elementui
如图所示 iview 的截图:
从上图可以发现,组件的样式全部放在了 style 目录里,并且用的是 less 。
style
less
说到这个,目前具有代表的大概就是 ant-design 了。
ant-design
如图所示 ant-design 的截图:
我们可以看到,在 ant-design 中,组件的样式是放在组件目录里面的,同时也是用的 less 。
至于使用哪种样式风格编写。为了玩出花,我采取的是同时使用三种样式:scss less stylus 。在这个过程中,我更喜欢 stylus,因为其类似 python 的缩进写法,简单快速。一不用写分号,二不用写括号,三也可以不用写冒号。如果你看过 vue-cli3 的源码,你会发现其中的 ui 部分,样式使用的就是 stylus 。
scss
stylus
python
vue-cli3 源码中的的 ui 部分如图所示:
关于样式方案的选择,我想表达的是:
在组件的样式处理方面,业界存在两个标准,不存在好和不好,但是我们需要知道这些标准,通过知晓,来给自己的实践中多提供一些参考和帮助。
我使用的是:
样式和组件目录不分离的方案,同时样式编写采用的是三个样式,主用 stylus 。
业界的状态管理有很多,vuex 、 redux 、 mobx 、 dva 等等。目的都很明确:通过抽象封装掉混乱。
vuex
redux
mobx
dva
对于我来说,会思考一个问题,此项目是否真的需要 vuex ,为了玩出花,我做的处理是:
切了两个分支,一个不使用 vuex ,一个使用 vuex 。
什么时候使用 vuex
当组件中需要共享一些数据的时候,并且数据较多,就可以使用 vuex 。如果数据不需要共享,或者较少,其实也没有必要用 vuex 。
vuex 的两种形式
使用 vuex 时,如果需要管理的状态不是很多,那可以直接写到一个文件中。如果需要处理的状态很多,那就使用 module 的写法。将状态进行分类,分成不同的 module 。
module
对于请求,我这边做的是,将请求部分尽可能的抽离出来, 预留好以后可能会出现的坑。比如,预留请求拦截,预留对请求进行加密,预留公共的参数,预留好模拟数据的坑。
我一般将这部分逻辑分成三个类。一个是 StateService ,一个是 ApiService ,一个是Service 。当然如果服务过多,可以对 Service 进行细分,比如 UploadService 、 MonitorService 等。
StateService
ApiService
Service
UploadService
MonitorService
说到模拟数据,大家第一反应可能是,使用 easy-mock ,使用 rap 等。而在我这边,选择了一种很少人知道的做法,那就是通过装饰器来进行数据模拟。
easy-mock
rap
什么意识呢?我简单介绍下
如图所示:
从上图可以知道,我对 Service 中的 getuserinfo 进行了装饰拦截,通过装饰器来将模拟数据注入进去。再通过环境判断来确保在生产环境上,此装饰器方法失效。
getuserinfo
虽然会有入侵代码的味道,但是在真正尝试了后,你会感受到利用装饰器来解决数据模拟 的魅力,因为你可以随心所欲的控制所有请求逻辑。从而达到完全不依赖后端接口来实现前端全流程的模拟。
对于这个,需要去思考此项目需不需要依赖一些工具库,比如 lodash 、 ramda 。如果不怎么依赖,那就用原生写吧。
lodash
ramda
对于工具方法,我也会进行分类,我会分为内部方法和外部方法。如果只是提供给另一个方法使用,并不会暴露到业务中,那我会把它认为是内部方法。
这个是老生常谈的事情了,我一般把性能这块分为两个方面。
js
css
base64
cdn
gzip
关于图片压缩
虽然 webpack 有图片压缩,但是根据对比,其压缩的质量和效果还是没有 tinypng 优秀,如果有不知道 tinypng 的小伙伴,可以点击 https://tinypng.com/ 进行 TP。
webpack
tinypng
TP
tinypng 的压缩算法没有开源,虽然可以免费使用,但是会存在一些限制,对此 github 上有人专门开发了 tinypng for mac 。 小伙伴可以自行了解一下,工具还是很好用的。可以原位置替换文件,压缩后的图片基本没有损失。
tinypng for mac
https://github.com/godkun/TinyPNG4Mac
代码级别的性能提升
这是脚手架做不了的,我们在写代码的时候,要注意代码方面的性能。比如将数据存到局部变量、优化循环、函数去抖、函数节流、图片懒加载等等吧。性能这块我就不提了,太老生常谈了。
这块我提一下。在项目中,我们究竟要怎么灵活使用 async await 和 promise ,首先明确的一点是,不能为了使用而使用。这里我发表一下个人看法,下面是几种使用两者的场景。
async await
promise
try catch
我简单举个例子,如下代码:
fn(res => { // TODO: })
上图中,fn 是一个异步操作,该函数中会执行回调函数。现在有两个问题:
fn
针对上面的两个问题,现在来依次解决一下。
解决第一个问题:
首先我们把异步操作的 fn 变成 promise 形式,很简单。
大致代码如下:
function wrap() { return new Promise((resolve, reject) => { fn(res => { resolve() }) }) }
解决第二个问题:
如果 fn 的回调函数中,还要进行异步操作,那该如何优雅的解决这个问题呢?这个时候就要使用 async await 了。
function wrap() { return new Promise(async (resolve, reject) => { try { fn( async res => { let result = await fn2() }) }catch(err) { // TODO: } }) }
是不是发现,代码都是同步的,可以使用 try catch 。嗯,就是这么简单自然。
我们知道,交互这块要友好,不能太生硬,跳转等需要保证流畅性。所以在部分页面中,使用了 gsap ,不了解的小伙伴可以去查一下资料。
gsap
简洁代码如下:
// 只用到了 TweenLite 、TimelineLite 两个方法 import { TweenLite, TimelineLite } from 'gsap' let tw = new TimelineLite() tw.add(TweenLite.to(this.style.blocks[0], 0.5, { opacity: 1, delay: 0.5 })) tw.add(TweenLite.to(this.style.blocks[2], 0.5, { opacity: 1 }), '-=0.3')
通过对样式的设置来达到衔接的流畅性。
我们在开发微信 H5 、天猫淘宝 H5 、 开发快应用、开发小程序等的时候。 loading 这块是一个必须要做的事情。比如请求开始时,loading 开始,用户不能进行其他操作,请求结束或者异常时,loading 结束。
H5
loading
那么在面对第三方 ui 库 或者 APP 自带的实现时,我们要怎么去选择呢,是使用现成的,还是写一个最适合自己的呢?
APP
这块我个人的意见是自己手写一个适合自己的 loading 。这样做的原因我高度概括一下,就是:统一和灵活。
PS: 当然,这个不是绝对的。只是提供一个思路,比如微信 H5 , 天猫 H5 , 就不要用自带的 loading ,使用同一的 loading 组件。
开屏特效有很多方式,比如可以使用 vue-touch 来完成向下滑屏的操作。
vue-touch
大致效果如下 gif 图:
gif
在完成以后,感觉不够炫酷。于是进行改良,执行第二种方案,采用序列帧来完成开屏的特效。
什么是序列帧呢?
序列帧就是通过将一段视频分解成一帧一帧的形式。然后通过 canvas 来按照一定的时间间隔画出来,从而让用户感觉到是一连串的特效画面。可以想象成 PPT 的快闪效果。
canvas
PPT
既然需要序列帧,那么就需要加载的进度条。进度条这块可以封装成组件,思路就是通过数据加载的进度来设置百分比,同时设置一些动画的效果。
从上面可以看到,当 godkun: 源码终结者 显示完全的时候,也就是进度条达到 100% 的时候。表明序列帧需要的数据已经加载完成。
godkun: 源码终结者
100%
需要做分享图,如果交给后端去做,由于需要合成的图片很多,后端的压力会变大。商量后,决定在前端合成,通过 canvas 来将10 张图片,合成为一张分享图,这里的注意点不多。需要注意的就是在图片 onload 事件回调中再进行画图。
10
onload
async drawCanvas() { let canvas = this.$refs.myCanvas canvas.width = xxx canvas.height = xxx let bg = await this.drawBg() this.drawImage(bg) // 不变 // TODO: 绘制其他 let data = canvas.toDataURL('image/jpeg') const params = { base64: data } let result = await Server.getImage(params) this.$refs.canvasImg.setAttribute('src', result) }
PS: 这里有个坑,安卓手机下无法保存 src 为 base64 的图片,后面经过采坑,决定通过将 base64 数据发到后端,然后返回 png 的地址来解决这个坑。
src
png
埋点的目的是收集各种信息,比如 PV 、 UV 、点击率、异常。那么埋点该怎么做,一般的前端埋点,我认为,需要遵循两点:
PV
UV
第一点:不要过度入侵代码,也就是俗称的硬编码
第二点:做到复用性,也就是进行统一的封装
比如,将对应的埋点进行重命名,如 b1 b2 b3 。
b1
b2
b3
大致代码如下,简单粗暴:
burryDetail ={ b1: { actionName: 'gotohome' } } export default function burry(key) { let burryObject = burryDetail[key] // TODO: args let argN = burryObject.actionName send(...args, argN) }
这样做的好处是将所有埋点放在一个文件中进行集中处理,不要在业务代码里面直接写,有利于解耦。对于有一些特殊情况,需要在业务代码里面写的,那就特殊对待吧。
说到运行模式,可以想到有开发模式,生产模式,甚至还有分析模式。目前在 vue-cli3 下,按照其规定的方法进行设置就好了。比如新建 .env.dev .env.prd .env.xxx 文件
.env.dev
.env.prd
.env.xxx
如下 .env.dev 代码:
NODE_ENV = "development" VUE_APP_BASE_URL = "xxxxxxxxxxxx"
然后在 scripts 中写入
scripts
"dev": "vue-cli-service serve --mode dev",
就可以通过 npm run dev 来运行开发模式了。
npm run dev
sdk
有时候,你会发现,引入 sdk 后,没有代码提示。然后去网上找,也找不到官方解决方案,这个时候怎么办呢?
显然,只能自己去编写声明文件了,这里是针对 VSCODE 来说的,标准方法就是新建一个类型目录,然后新建 sdk.d.ts 。
VSCODE
sdk.d.ts
代码大致如下:
declare namespace SDK { function fn1(callback: () => void): void function fn2(text: String): void function fn3(): void function fn4( object: { arg1: String arg2: String arg3: String arg4: String }, callback: (res: {}) => void ): void }
这块自己根据具体的 SDK 去编写你需要的提示就好了。
SDK
后端是 S 写的,所以我就以一个 code review 的形式去大致说一下后端的整体情况吧。
code review
大致有如下几点:
API
这里使用的是 egg.js ,其通过约定的哲学,来快速搭建应用,提高开发效率。egg 的学习文档有很多,贴个官网文档地址吧:
egg.js
egg
https://eggjs.org/zh-cn/intro/index.html
这个没啥好说的,通过路由拦截,然后转到对应的逻辑处理,中间可能需要经过相应的中间件进行处理。
如何更好地设计返回,这里的做法是将返回封装成 plugin ,然后扩展到 context 上。这样的话,你就可以通过 ctx.sendresult 来统一处理返回内容了。
plugin
context
ctx.sendresult
中间件也没啥好说的,本质上就是一个导出的函数。用来处理接收到的数据,并进行对应的数据处理。
数据处理基本有两种结局:
game over
举个真实场景:
比如最常见的,鉴权。我们可以在路由中就进行控制:
代码如下:
router.post('/api/xxx', auth(), controller.xxx);
在处理受限接口的请求时,先进行 auth 处理,如果没有成功,就中断后续的逻辑处理,直接返回没有登录或者没有授权之类的响应内容。
auth
MVC
MV*
V
这里我简单提一下,在 node 层,和在前端层,其 V 大家都是能理解的,都是视图的意识,node 层,也要写页面的,比如我们写一个 404 页面,配合处理异常的中间件。如果中间件捕捉到了 404 ,那么直接返回 404 页面给前端。
404
C
C 在前端来说,其实是最富有变化的一个点,所以我加了 * 表示。C 对 node 来说,时候也是最重要的一个部分,它专门去处理接收到的请求,并且分发给各个逻辑处理中心,最后通过一系列的处理,再通过 C 层返回给前端。
*
M
M 对 node 来说很简单,在处理逻辑的时候,需要和数据库进行交互,来实现 CRUD 从而实现数据的增删改查。M 对前端来说,也很简单,就是对 V 层的数据进行 CRUD 。前后端的 M 层还是有点区别的。
CRUD
总结一下,后端的 MVC 看起来,是比前端的 MVC 好理解,前端的 MVC 就好像被强行安排了一波😂。
随着前端工程化的持续完善,前端的配置和后端的配置 ,在思想上,基本是一致的,这里我就不提了。
上面提了,使用 mysql ,当然了,像 egg-sequelize mysql2 这些都要用的。模型定义通常情况下是在 model 目录下,定义好模型,然后挂在到 Application 下,通过 app.model.xxx 来拿到对应模型的上下文。对模型的处理,一般是放在 service 目录下。
mysql
egg-sequelize
mysql2
model
Application
app.model.xxx
service
绝大多数情况下,前端的项目在打包后,会放到 public 目录下,所以看到这,小伙伴应该明白了构建工具中的 publicPath 是什么意识了吧(手动滑稽)。
public
publicPath
看完后端部分,是不是发现也挺简单的,代码都是 js ,前端怎么写业务逻辑,后端就怎么写业务逻辑。
两者的区别主要是前后端需要考虑的点不一样。
后端需要考虑安全、考虑服务器的压力、考虑接口的设计、考虑数据库的设计。当然高层次一点,还要考虑负载均衡,高并发等。而前端则需要考虑页面的美观性、页面的流畅性、用户交互的友好性、页面的打开速度等等。总之,大家都不容易的,唯有执子之手,才能与子偕老。(手动滑稽 +2 )
+2
读完,是不是有点感觉和结对编程没啥关系,我特喵的读完也感觉到了。
写了 6000 字,我图个啥。
6000
开玩笑的,开玩笑的,其实,本文和结对编程是有强联系的,这个过程是我和 S 一起参与完成的。
下图体现在整个过程中。
毕竟不能只说结对编程,还是要说一下其他的东西的。
我认为结对编程的魅力,就在于可以:
互相反馈,及时调 整,共同提高开发效率。当然最重要的是可以 搞(你在说)基(什么?)
掘金系列技术文章汇总如下,觉得不错的话,点个 star 鼓励一下哦。
https://github.com/godkun/blog
我是源码终结者,欢迎技术交流。
也可以进 前端狂想录群 大家一起头脑风暴。有想加的,因为人满了,可以先加我好友,我来邀请你进群。
明天就五一了,祝小伙伴五一快乐,我不管什么安康,我只要你们快乐!
最后:尊重原创,各位首富,转载请注明出处哈😋
The text was updated successfully, but these errors were encountered:
No branches or pull requests
好久没写文章了,标题起的有点膨胀。
你猜我想说什么
我想写一个结对编程小记。最近在和
S
(帅气的花名) 利用业余时间,进行了一次结对编程。现在我准备把结对编程的一些思考分享给大家,下面开始吧。为什么就叫新时代下的结对编程
这里我说明一下原因,请往下看。
传统结对编程
结对编程(英语:Pair programming)是一种敏捷软件开发的方法,两个程序员在一个计算机上共同工作。一个人输入代码,而另一个人审查他输入的每一行代码。输入代码的人称作驾驶员,审查代码的人称作观察员(或导航员)。两个程序员经常互换角色。
在结对编程中,观察员同时考虑工作的战略性方向,提出改进的意见,或将来可能出现的问题以便处理。这样使得驾驶者可以集中全部注意力在完成当前任务的“战术”方面。观察员当作安全网和指南。结对编程对开发程序有很多好处。比如增加纪律性,写出更好的代码等。结对编程是极端编程的组成部分。
两个人共用一台计算机,这可能在
ACM
竞赛或者组队PK
中常见。但对于业务开发来说,有点不科学,首先效率就不高,如果对方代码太可爱,可能会忍不住打他。当然了,在特殊场景下也会出现,但是95%
的场景下,是不可能存在下图这种场景的。下面这种场景犹如六月飞雪:
不过这种场景倒是很乐意接受的:
当然,别问我为什么,因为:
那什么是我认为的新时代的结对编程呢?
新时代的结对编程
两(
N
)个coder
, 两(N
)台电脑,坐在一起(后续也可以不用坐在一起)进行开发。代码可以互相看到。最关键的一点就是,我们可以互相看到并且看懂对方的代码。我和
S
达成意见,S
负责node
, 也就是后端,我负责前端,前后端分离。然后各自的代码我们都能互相看到,要开发什么功能,我们都知道,我可以review
S
的代码,S
也可以review
我的代码。当开发的时候,我可以通过review
S
的代码,提前知道S
的接口逻辑。如果我认为他的逻辑写的有问题,我会和他进行沟通,提前把可能存在的疑问处理掉。我也会提前按照他写的接口来预留好请求这块的逻辑处理。总之,在我理解的结对编程中。应该是能力相同,代码相同,通过互相review
对方的功能代码,来对比自己的代码。从而告诉对方可能存在的问题,而这种问题的解决会让开发的效率大大增加,更早的解决了潜在的一些问题。结对编程之前的狂欢?
嗯?按照传统,当然是来一次结对前的庆祝。去了趟
1912
,吃了个大餐,享受了下日式服务。然后去咖啡馆开始face to face talking
,愉快的结对编程就要开始了。我分为两个部分去介绍,第一部分是前端,第二部分是后端。
前端
技术架构选择
首先,框架的选择这块,在衡量之后,选择的是
Vue
。这里我对用什么框架,其实没什么看法,唯一的看法就是:根据实际情况,来选择合适的开发框架,从而提高整体的开发效率。
要不要使用脚手架,这块我也持上面的那句话,根据实际情况做出合适的选择。这里我选择
Vue-cli3
来快速搭建应用。怎么使用,自己去研究一下就知道了。第一个路径:去 https://cli.vuejs.org/ 官网研究
第二个路径:去看
vue-cli3
的源码,了解一下内部的一些机制,比如chainWebpack
的实现,vue.config.js
的默认设置是如何实现的。第三个路径:去
github
上,找一些用vue-cli3
搭建的项目,clone
下来,研究一下别人是如何使用的。样式方案的选择
选完技术框架,我们再来看看样式的选择,通用的样式方案,业界的标准基本都是相同的。但是关于组件中的样式该放哪,目前在业界,大概有这么两种。
样式和组件目录分离
样式和组件目录分离,这个是目前很多
ui
库采取的方式。比如
iview
elementui
,我来截图展示一下。如图所示
iview
的截图:从上图可以发现,组件的样式全部放在了
style
目录里,并且用的是less
。样式和组件目录不分离
说到这个,目前具有代表的大概就是
ant-design
了。如图所示
ant-design
的截图:我们可以看到,在
ant-design
中,组件的样式是放在组件目录里面的,同时也是用的less
。使用哪种样式进行编写
至于使用哪种样式风格编写。为了玩出花,我采取的是同时使用三种样式:
scss
less
stylus
。在这个过程中,我更喜欢stylus
,因为其类似python
的缩进写法,简单快速。一不用写分号,二不用写括号,三也可以不用写冒号。如果你看过vue-cli3
的源码,你会发现其中的ui
部分,样式使用的就是stylus
。vue-cli3
源码中的的ui
部分如图所示:总结
在组件的样式处理方面,业界存在两个标准,不存在好和不好,但是我们需要知道这些标准,通过知晓,来给自己的实践中多提供一些参考和帮助。
样式和组件目录不分离的方案,同时样式编写采用的是三个样式,主用
stylus
。关于状态管理
业界的状态管理有很多,
vuex
、redux
、mobx
、dva
等等。目的都很明确:通过抽象封装掉混乱。切了两个分支,一个不使用
vuex
,一个使用vuex
。当组件中需要共享一些数据的时候,并且数据较多,就可以使用
vuex
。如果数据不需要共享,或者较少,其实也没有必要用vuex
。使用
vuex
时,如果需要管理的状态不是很多,那可以直接写到一个文件中。如果需要处理的状态很多,那就使用module
的写法。将状态进行分类,分成不同的module
。关于请求的处理
对于请求,我这边做的是,将请求部分尽可能的抽离出来, 预留好以后可能会出现的坑。比如,预留请求拦截,预留对请求进行加密,预留公共的参数,预留好模拟数据的坑。
我一般将这部分逻辑分成三个类。一个是
StateService
,一个是ApiService
,一个是Service
。当然如果服务过多,可以对Service
进行细分,比如UploadService
、MonitorService
等。关于模拟数据
说到模拟数据,大家第一反应可能是,使用
easy-mock
,使用rap
等。而在我这边,选择了一种很少人知道的做法,那就是通过装饰器来进行数据模拟。如图所示:
从上图可以知道,我对
Service
中的getuserinfo
进行了装饰拦截,通过装饰器来将模拟数据注入进去。再通过环境判断来确保在生产环境上,此装饰器方法失效。虽然会有入侵代码的味道,但是在真正尝试了后,你会感受到利用装饰器来解决数据模拟 的魅力,因为你可以随心所欲的控制所有请求逻辑。从而达到完全不依赖后端接口来实现前端全流程的模拟。
关于工具方法
对于这个,需要去思考此项目需不需要依赖一些工具库,比如
lodash
、ramda
。如果不怎么依赖,那就用原生写吧。对于工具方法,我也会进行分类,我会分为内部方法和外部方法。如果只是提供给另一个方法使用,并不会暴露到业务中,那我会把它认为是内部方法。
关于性能
这个是老生常谈的事情了,我一般把性能这块分为两个方面。
脚手架能做到的事情
js
css
等进行压缩,是否对css
进行分离base64
cdn
ui
库进行性能处理,比如后置编译gzip
脚手架做不到的事情
虽然
webpack
有图片压缩,但是根据对比,其压缩的质量和效果还是没有tinypng
优秀,如果有不知道tinypng
的小伙伴,可以点击 https://tinypng.com/ 进行TP
。tinypng
的压缩算法没有开源,虽然可以免费使用,但是会存在一些限制,对此github
上有人专门开发了tinypng for mac
。 小伙伴可以自行了解一下,工具还是很好用的。可以原位置替换文件,压缩后的图片基本没有损失。这是脚手架做不了的,我们在写代码的时候,要注意代码方面的性能。比如将数据存到局部变量、优化循环、函数去抖、函数节流、图片懒加载等等吧。性能这块我就不提了,太老生常谈了。
关于async await 和 promise
这块我提一下。在项目中,我们究竟要怎么灵活使用
async await
和promise
,首先明确的一点是,不能为了使用而使用。这里我发表一下个人看法,下面是几种使用两者的场景。try catch
捕捉异步操作的异常时promise
的时候我简单举个例子,如下代码:
上图中,
fn
是一个异步操作,该函数中会执行回调函数。现在有两个问题:fn
变成promise
呢?针对上面的两个问题,现在来依次解决一下。
首先我们把异步操作的
fn
变成promise
形式,很简单。大致代码如下:
如果
fn
的回调函数中,还要进行异步操作,那该如何优雅的解决这个问题呢?这个时候就要使用async await
了。大致代码如下:
是不是发现,代码都是同步的,可以使用
try catch
。嗯,就是这么简单自然。关于动画衔接
我们知道,交互这块要友好,不能太生硬,跳转等需要保证流畅性。所以在部分页面中,使用了
gsap
,不了解的小伙伴可以去查一下资料。简洁代码如下:
通过对样式的设置来达到衔接的流畅性。
关于 loading 组件
我们在开发微信
H5
、天猫淘宝H5
、 开发快应用、开发小程序等的时候。loading
这块是一个必须要做的事情。比如请求开始时,loading
开始,用户不能进行其他操作,请求结束或者异常时,loading
结束。这块我个人的意见是自己手写一个适合自己的
loading
。这样做的原因我高度概括一下,就是:统一和灵活。PS: 当然,这个不是绝对的。只是提供一个思路,比如微信
H5
, 天猫H5
, 就不要用自带的loading
,使用同一的loading
组件。关于开屏特效
开屏特效有很多方式,比如可以使用
vue-touch
来完成向下滑屏的操作。大致效果如下
gif
图:在完成以后,感觉不够炫酷。于是进行改良,执行第二种方案,采用序列帧来完成开屏的特效。
序列帧就是通过将一段视频分解成一帧一帧的形式。然后通过
canvas
来按照一定的时间间隔画出来,从而让用户感觉到是一连串的特效画面。可以想象成PPT
的快闪效果。既然需要序列帧,那么就需要加载的进度条。进度条这块可以封装成组件,思路就是通过数据加载的进度来设置百分比,同时设置一些动画的效果。
大致效果如下
gif
图:从上面可以看到,当
godkun: 源码终结者
显示完全的时候,也就是进度条达到100%
的时候。表明序列帧需要的数据已经加载完成。关于图片合成
需要做分享图,如果交给后端去做,由于需要合成的图片很多,后端的压力会变大。商量后,决定在前端合成,通过
canvas
来将10
张图片,合成为一张分享图,这里的注意点不多。需要注意的就是在图片onload
事件回调中再进行画图。大致代码如下:
关于埋点
埋点的目的是收集各种信息,比如
PV
、UV
、点击率、异常。那么埋点该怎么做,一般的前端埋点,我认为,需要遵循两点:第一点:不要过度入侵代码,也就是俗称的硬编码
第二点:做到复用性,也就是进行统一的封装
比如,将对应的埋点进行重命名,如
b1
b2
b3
。大致代码如下,简单粗暴:
这样做的好处是将所有埋点放在一个文件中进行集中处理,不要在业务代码里面直接写,有利于解耦。对于有一些特殊情况,需要在业务代码里面写的,那就特殊对待吧。
关于运行模式
说到运行模式,可以想到有开发模式,生产模式,甚至还有分析模式。目前在
vue-cli3
下,按照其规定的方法进行设置就好了。比如新建.env.dev
.env.prd
.env.xxx
文件如下
.env.dev
代码:然后在
scripts
中写入就可以通过
npm run dev
来运行开发模式了。关于第三方
sdk
的代码提示问题有时候,你会发现,引入
sdk
后,没有代码提示。然后去网上找,也找不到官方解决方案,这个时候怎么办呢?代码大致如下:
这块自己根据具体的
SDK
去编写你需要的提示就好了。后端
后端是
S
写的,所以我就以一个code review
的形式去大致说一下后端的整体情况吧。后端要做什么
大致有如下几点:
API
接口后端的框架选择
这里使用的是
egg.js
,其通过约定的哲学,来快速搭建应用,提高开发效率。egg
的学习文档有很多,贴个官网文档地址吧:如何编写接口
这个没啥好说的,通过路由拦截,然后转到对应的逻辑处理,中间可能需要经过相应的中间件进行处理。
如何集中处理响应
如何更好地设计返回,这里的做法是将返回封装成
plugin
,然后扩展到context
上。这样的话,你就可以通过ctx.sendresult
来统一处理返回内容了。中间件的使用
中间件也没啥好说的,本质上就是一个导出的函数。用来处理接收到的数据,并进行对应的数据处理。
game over
比如最常见的,鉴权。我们可以在路由中就进行控制:
代码如下:
在处理受限接口的请求时,先进行
auth
处理,如果没有成功,就中断后续的逻辑处理,直接返回没有登录或者没有授权之类的响应内容。node 的
MVC
和前端的MV*
这里我简单提一下,在
node
层,和在前端层,其V
大家都是能理解的,都是视图的意识,node
层,也要写页面的,比如我们写一个404
页面,配合处理异常的中间件。如果中间件捕捉到了404
,那么直接返回404
页面给前端。C
在前端来说,其实是最富有变化的一个点,所以我加了*
表示。C
对node
来说,时候也是最重要的一个部分,它专门去处理接收到的请求,并且分发给各个逻辑处理中心,最后通过一系列的处理,再通过C
层返回给前端。M
对node
来说很简单,在处理逻辑的时候,需要和数据库进行交互,来实现CRUD
从而实现数据的增删改查。M
对前端来说,也很简单,就是对V
层的数据进行CRUD
。前后端的M
层还是有点区别的。总结一下,后端的
MVC
看起来,是比前端的MVC
好理解,前端的MVC
就好像被强行安排了一波😂。前端的配置和后端的配置
随着前端工程化的持续完善,前端的配置和后端的配置 ,在思想上,基本是一致的,这里我就不提了。
关于数据库
上面提了,使用
mysql
,当然了,像egg-sequelize
mysql2
这些都要用的。模型定义通常情况下是在model
目录下,定义好模型,然后挂在到Application
下,通过app.model.xxx
来拿到对应模型的上下文。对模型的处理,一般是放在service
目录下。关于 publicPath
绝大多数情况下,前端的项目在打包后,会放到
public
目录下,所以看到这,小伙伴应该明白了构建工具中的publicPath
是什么意识了吧(手动滑稽)。总结
看完后端部分,是不是发现也挺简单的,代码都是
js
,前端怎么写业务逻辑,后端就怎么写业务逻辑。后端需要考虑安全、考虑服务器的压力、考虑接口的设计、考虑数据库的设计。当然高层次一点,还要考虑负载均衡,高并发等。而前端则需要考虑页面的美观性、页面的流畅性、用户交互的友好性、页面的打开速度等等。总之,大家都不容易的,唯有执子之手,才能与子偕老。(手动滑稽
+2
)文末总结
读完,是不是有点感觉和结对编程没啥关系,我特喵的读完也感觉到了。
写了
6000
字,我图个啥。开玩笑的,开玩笑的,其实,本文和结对编程是有强联系的,这个过程是我和
S
一起参与完成的。下图体现在整个过程中。
毕竟不能只说结对编程,还是要说一下其他的东西的。
互相反馈,及时调 整,共同提高开发效率。当然最重要的是可以 搞(你在说)基(什么?)
备注
review
后端代码,根据后端代码写前端请求逻辑等等,好像也是有点花的。参考
我的一些其他系列文章
交流
掘金系列技术文章汇总如下,觉得不错的话,点个 star 鼓励一下哦。
我是源码终结者,欢迎技术交流。
也可以进 前端狂想录群 大家一起头脑风暴。有想加的,因为人满了,可以先加我好友,我来邀请你进群。
风之语
明天就五一了,祝小伙伴五一快乐,我不管什么安康,我只要你们快乐!
最后:尊重原创,各位首富,转载请注明出处哈😋
The text was updated successfully, but these errors were encountered: