作者:Anna 4erepawko Mészáros,UI/UX 设计师。
关注作者: Medium、Twitter
这篇文章是写给无力邀请专业设计师的所有内容创作者的,以及设计师异常忙碌的团队的非设计师们。如果您按照这些简单的步骤进行操作,我保证您的设计会变得更好。
这些 Tips 来源于我对身边非设计朋友的多年观察,家人与同事在日常生活中也需要设计他们的东西。比如简历、作品集,Facebook 和 Instagram 上帖子要使用的图片,YouTube 视频的缩略图等。
所有这些人都向我寻求帮助与建议,希望能让他们的东西看起来更好。我坚信「授人以鱼不如授人以渔」,所以我试图提供更有价值的建议,以便他们在未来也能解决类似的问题。
随着时间的推移,我意识到我一直在给所有人提供相同的建议,虽然每次所使用的措辞不同,但我所有的建议都可以提炼为以下四个原则。
这些 Tips 会帮您创造出美丽动人的设计吗?答案是不会!它们只会帮您创造出色、清晰且易于理解的设计。是每个人都可以轻松理解和互动吗?那当然,所以不多说废话,下面我就向您逐一展示。
对比
确保所有元素之间有足够的对比度。为什么?因为那些略有差异但是又不够不同东西,创造了一种恐怖谷。人类的眼睛会排斥它们,对它们感到厌恶、难以理解。我们不希望它们出现在我们的设计中,难道不是吗?
恐怖谷理论,是一个关于人类对机器人和非人类物体的感觉的假设。如果一个非人类实体不够拟人,那么它身上的人类特征会很容易辨认;而当它足够拟人时,他身上的非人类特征则会变得很容易辨认。因此会在人类观察者眼中产生一种古怪的感觉,想想您看到病患者或者尸体时的感觉。
因此您设计的元素要么完全相同,要么具有显著差异。
您可以从下面四个方面来突出对比:
1、颜色:浅色上使用暗色,反之亦然
示例: 切勿在浅蓝色上使用浅灰色或浅粉红色等灰色组合,它们会造成阅读/互动上的极大困难。
2、大小:相邻元素要么大小完全相同,要么大小区别很大
示例: 不要将 32pt 和 36pt 的文本放在一起;18pt 和 36pt 放在一起会显得更加协调。
3、粗细:与大小一样,相邻元素的粗细要么完全相同,要么有明显的区别
示例: 不要将相同字体的粗体与黑体放在一起,因为它们看起来太相似了;将黑体与细体放在一起会显得很协调。
4、风格:不要将一个斜体类型放在另一个斜体类型旁边,或者在一个衬线字体旁边放置另一个衬线字体。应该组合不同的东西。
示例: 不要将 Times New Roman 与 Georgia 放在一起,它们看起来太相似了,应该组合完全不同的风格。
一致性
确保相似的元素以相似的方式出现。为什么呢?首先,通过确保确保事物一致性,您可以让用户将注意力集中在设计的重要方面,而不是被随时变化的元素分散注意力。
其次,一致性也增加了用户对您的信任,使事物看起来实际上是设计的,而不是简单快速拼凑出来的。
一旦你选择了具体的风格,就要毫不犹豫的坚持下去,这里所说的风格包括字体、颜色、阴影、栅格、对齐、装饰风格等等。
当您处理许多相邻的不同部分时(比如 YouTube 的视频缩略图或是中型文章的封面),您应该为所有部分选择一种整体风格,并坚持使用。
奥卡姆剃刀 减少视觉噪音
在您的设计中,使用的元素越少越好。为什么呢?因为人类的大脑很难在输入过载的情况下处理信息并作出决策。您应该使用尽可能少的装饰元素(字体、颜色、阴影、图标等等)。
将奥卡姆剃刀应用于所有内容。如果只需要两个元素就能满足需求,那么就不要使用 3 个元素;如果 10 个元素实现所需的功能,那么就不要用 20 个元素。
如果您不喜欢古老的英国哲学家风格,更喜欢您在 Netflix(一家美国流媒体提供商)上看到的东西。请将怦然心动的人生整理魔法应用到您的设计中。
《怦然心动的人生整理魔法》是美国流媒体提供商Netflix于2019年1月1日首播的一档真人实境秀节目。节目由日本“整理咨询顾问” 近藤麻理惠主创。她在每集节目中拜访一个家庭,帮助他们整理自己的房间。
近藤麻理惠认为整理房间时应当将物品分为五类:衣物、书籍、纸张文件、杂物和情感纪念品;在整理时拿起每件物品,如果能使自己“怦然心动”则留下,如果不能则要感谢物品的贡献然后与其告别。
间距
元素的位置会发送关于其含义的元级别消息。为什么这很重要?因为了解如何放置元素以及在它们周围预留了多少空间有助于降低设计的复杂性,因此会使人更加愉悦,并且更容易交互。
在您的设计中使用间距来传达下面 3 个方面的信息:
1、接近度 = 相关性
与其它元素相比,彼此更接近的事物被认为它们有更强的相关性。这是最重要的,因为我觉得它常常容易被忽视。
它可以以很多不同的方式应用,比如行与行之间应该有一定的间距,而不是一行中每个单词之间的间距那么小;同样不同段落之间的空间也比段落内的行空间要大。
元素之间的间距应该小于元素与组合边缘之间的间距。
标签和支撑信息应该位于其相关元素附近。
2、留白
结合奥卡姆剃刀,给您的设计尽可能留白,去整理它们,使它们的意义更加明显。
如果把太多元素放在有限的空间里,就像同时听三首不同的哥,很难理解别人在说什么。
3、重要性与顺序
这是一个很普通的常识,但是我还是要在这里提到它。
最重要的事情放在第一位,使它们占据最大的空间,用一系列的事物来传达秩序。
结束语
恭喜您!如果您按照这些 Tips 进行设计,那么按照行业标准,它可能看起来非常好。
For everything else, there is always a designer.
Read More ~
深入理解计算机系统——CPU 是怎样工作的?
参考内容:
处理器是如何工作的
《编码:隐匿在计算机软硬件背后的语言》——[美] Charles Petzold
CPU 大家应该都不会陌生,日常用的手机、电脑中都有 CPU,CPU 作为一个设备的大脑,指挥着其它各种硬件的协同工作,芯片技术也是国内一直没有突破的技术。
我们先来看看怎么让电路去运算呢?比如如何让电路运算1 + 1,直接使用下面这个装置就可以了。
作为一个比较好奇的人,总会想看看那个方框框里面是什么样子的,让我们慢慢解开加法器的外衣。
这个电路你应该不会陌生,它需要两个开关都闭合时灯泡才会发光,也就是说它有两个输入,开关闭合时我们认为输入为 1,未闭合状态视为 0;而灯泡是否发光就是我们的输出,发光为 1,否则为 0。于是就有了下面这张表。
and
0
1
0
0
0
1
0
1
这样的电路我们就把它称之为与(and)门,它接受两个逻辑输入,并会给出我们一个逻辑输出,与它相似的电路还有逻辑或(or)、**异或(xor)**等等,因为太多了,就不一一介绍了,如果感兴趣可以 Google 一下。
为了方便我们把上面的电路做一个简化,抽象成下面这个样子,其它的电路也可以通过 Google 找到它们的样子。
现在直接给出一个可以运算加法的电路,它的样子长下面这样。
我们也可以给它列一个表,显得更清晰,表中之所以有两位是因为加法有可能会产生进位,而我们使用的是二进制表示,所以10表示的是十进制中的2。
+
0
1
0
00
01
1
01
10
有加法就很好办了,减法实际上是加一个负数,除法可以改写成乘法,乘法又可以改写成加法,现在加法一统天下了。
好了,上面说了那么多,还贴了那么多图,只是为了让你相信电路是可以实现我们数学上的运算的,下面就没有那么声情并茂了。
我们可以把一个运算抽象为下面这个模型。
输入数据 --> 运算 --> 输出数据
计算机中把各种像上述加法器一样的运算器放在了同一个小盒子里面,组成成一个运算器集合,我们给它取个名字叫算术逻辑单元(ALU:Arithmetic Logical Unit),它是 CPU 的核心组成部分。
当然我们不可能只进行加法这种简单运算,一个很长很长的算式需要经过多步运算,小学我们就学过梯等式,它实际上有一大推输入,中间那么多梯子,都是临时步骤,临时步骤、数据一类的东西都需要有个东西给它存起来,所以在 CPU 就拿出一个小盒子当做存储器。
# 梯等式
485 - ( 6 × 4 + 32 )
= 485 - ( 24 + 32 )
= 485 - 56
= 429
现在我们有了存储器和运算器两个干事的人,但是没有一个统筹兼顾的领导者,控制器就充当了这个角色,它需要把控制储存器中的数据发送到 ALU 去进行运算,然后再将运算的结果取出来存到储存器中。总的来说,控制器的工作就是完成协调和指挥整个计算机系统的操作。
我们把上面的结构画出来,图中的虚线表示指令流,实线表示数据流,这个结构就是著名的冯 · 诺依曼体系结构,遵循这种结构的计算机都叫做冯诺依曼机,现在所有的机器都是冯诺依曼机。
请注意,我们现在实际上只有硬件,没有软件是什么事情都干不了了,我们这里所说的软件是一堆指令序列,比如加法指令、传送指令等等组成的序列,也就是我们常说的汇编语言。
但是在早期并不是这样的,这台机器上编写的指令序列是无法运行在另一家公司生产的机器上的,即使是同一个公司的机器,如果不是同一代,那也不能运行,所以早期的编程是直接面向硬件的。
这时就有人站出来研究如何实现一次编写多处运行了,IBM 首次在它的 360 系统上引入了ISA的概念,即指令集体系结构。
指令集体系结构将编程所要了解的硬件信息从硬件系统中抽象了出来,这样开发人员就可以直接面向处理器的 ISA 进行编程了。
为什么手机上的软件不能运行在电脑中呢?就是因为个人电脑所使用的 Intel 和 AMD 处理器都是基于 x86 指令集的,而手机大多数都使用的是基于 ARM 指令集的处理器。
现在处理器被分为指令集体系结构、处理器微架构、处理器物理实现三个层次。体系结构相当于需求,微架构好比设计,物理实现则是具体的实现过程。
比如我们规定指令集中必须有加法指令,这个指令你怎么设计、如何实现是你给的事,我只管给出两个加数你能给我输出一个正确的结果,简单来说就是抽象封装。
Read More ~
如何保证快速加载网页?——详解浏览器缓存机制
参考内容:
彻底理解浏览器的缓存机制
彻底弄懂HTTP缓存机制及原理
前端开发人员有大部分时间都在调整页面样式,如果页面没有按照自己预期的样式显示,可能想到的第一个解决方案就是清一下浏览器缓存,HTTP 缓存机制作为 Web 性能优化的重要手段,也应该是 Web 开发人员必备的基础知识。我们常说的浏览器缓存机制也就是 HTTP 缓存机制,它是根据 HTTP 报文的缓存标识运行的,所以首先要对 HTTP 报文有一个简单的了解。
HTTP 报文
HTTP 报文是浏览器和服务器间进行通信时所发的响应数据,所以 HTTP 报文分为请求(Request)报文和响应(Response)报文两种,浏览器向服务器发送的是请求报文,而服务器向浏览器发送的是响应报文。HTTP 请求报文由请求行、请求头、请求体组成,响应报文则由状态行、响应头、响应正文组成,与缓存有关的规则信息则都包含在请求头和响应头中。
缓存概述
浏览器与服务器通过请求响应模式来通信,当浏览器第一次向服务器发送请求并拿到结果后,会根据响应报文中的缓存规则来决定是否缓存结果,其简单的流程如下图:
浏览器每次发起请求都会先在浏览器缓存中查找该请求的结果和缓存标识,而且每次拿到响应数据后都会将该结果和缓存标识存入缓存中。HTTP 缓存的规则有多种,我们可以根据是否需要重新向服务器发起请求这一维度来分类,即有强制缓存和协商缓存两类,也有人把协商缓存叫对比缓存。
强制缓存
我们先自己想一下,使用缓存是不是会有下面几种情况出现。
存在所需缓存并且未失效:直接走本地缓存即可;强制缓存生效;
存在所需缓存但已失效:本地缓存失效,携带着缓存标识发起 HTTP 请求;强制缓存失效,使用协商缓存;
不存在所需缓存:直接向服务器发起 HTTP 请求;强制缓存失效。
控制强制缓存的字段分别是Expires和Cache-Control,并且Cache-Control的优先级高于Expires。
Expires
Expires是 HTTP/1.0 控制网页缓存的字段,其值为服务器返回的该缓存到期时间,即下一次请求时,请求时间小于Expires值,就直接使用缓存数据。到了 HTTP/1.1,Expires已经被Cache-Control替代了。
Expires被替代的原因是因为服务端和客户端的时间可能有误差(比如时区不同或者客户端与服务端有一方时间不准确),这就会导致缓存命中误差,强制缓存就变得毫无意义。
Cache-Control
Cache-Control是 HTTP/1.1 中最重要的规则,主要取值为:
取值
规则
public
所有内容都可以被缓存,包括客户端和代理服务器,纯前端可认为与private一样。
private
所有内容只有客户端可以缓存,Cache-Control的默认值。
no-cache
客户端可以缓存,但是是否缓存需要与服务器协商决定(协商缓存)
no-store
所有内容都不会被缓存,既不是用强制缓存,也不使用协商缓存,为了速度快,实际上缓存越多越好,所以这个慎用
max-age=xxx
缓存内容将在 xxx 秒后失效
我们可以看看下面这个例子,可以从截图中看到Expires是一个绝对值,而Cache-Control是一个相对值,此处为max-age=3600,即 1 小时后失效。在无法确定客户端的时间是否与服务端的时间同步的情况下,Cache-Control相比于Expires是更好的选择,所以同时存在时只有Cache-Control生效。
协商缓存
协商缓存,顾名思义就是需要双方通过协商来判断是否可以使用缓存。强制缓存失效后,浏览器带着缓存标识向服务器发起请求,由服务器根据缓存标识决定是否可以使用缓存,那自然而然就有协商缓存生效和协商缓存不生效两种情况了。
上图是协商缓存生效的流程,如果协商缓存不生效则返回的状态码为 200。协商缓存的标识也是在响应报文的响应头中返回给浏览器的,控制协商缓存的字段有Last-Modified / If-Modified-Since和Etag / If-None-Match,其中Etag / If-None-Match的优先级比Last-Modified / If-Modified-Since高,所以同时存在时只有Etag / If-None-Match生效。
Last-Modified / If-Modified-Since
你可以往上翻一翻,看一下那张响应报文截图,其中有一个Last-Modified字段,它的值是该资源文件在服务器最后被修改的时间。
If-Modified-Since则是客户端再次发起该请求时,携带上次请求返回的Last-Modified值。服务器收到该请求后,发现该请求头有If-Modified-Since字段,则会将If-Modified-Since与该资源在服务器的最后被修改时间做对比,若服务器的资源最后被修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为 200;否则则返回 304,代表资源无更新,可继续使用缓存文件。
Etag / If-None-Match
Etag是服务器响应请求时,返回当前资源文件的一个由服务器生成的唯一标识。
If-None-Match则是客户端再次发起该请求时,携带上次请求返回的唯一标识Etag值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。服务器收到该请求后,发现该请求头中含有If-None-Match,则会根据If-None-Match的字段值与该资源在服务器的Etag值做对比,如果一致则就返回 304,代表资源无更新,可以继续使用缓存文件;否则重新返回资源文件,状态码为200,
disk cache 与 memory cache
我们可以通过浏览器调试工具查看强制缓存是否生效,如下图所示,状态码为灰色的请求就代表使用了强制缓存,请求对应的 size 显示了该缓存存放的位置,那么什么时候用 disk 什么时候用 memory 呢?
猜都能猜出来,肯定是优先使用内存(memory)中的缓存,然后才用硬盘(disk)中的缓存。
内存缓存具有快速读取的特点,它会将编译解析后的文件直接存入该进程的内存中,但是一旦进程关闭了,该进程的内存就会被清空,所以如果你将一个网页关闭后再打开,那么缓存都会走硬盘缓存,而如果你只是刷新网页,那有部分缓存走的就是内存缓存。
浏览器一般会再 js 和图片等文件解析执行后直接存入内存缓存中,当刷新页面时,这部分文件只需要从内存缓存中读取即可,而 css 文件则会存入硬盘中,所以每次渲染页面都需要从硬盘中读取文件。
总结
到这里偷懒一下子了,找到人家画的一张图,看图就行了。
Read More ~
什么是契约测试?
参考文章:
聊一聊契约测试 —— ThoughtWorks洞见
契约测试
前后端分离了,然后呢?
契约测试全称为:消费者驱动契约测试,最早由 Martin Fowler 提出。契约这个词从字面上很容易理解,就是双方(多方)达成的共同协议,那又为什么需要契约测试这个东西呢?
在当前微服务大行其道的行业背景下,越来越多的团队采用了前后端分离和微服务架构,我们知道微服务是由单一程序构成的小服务,与其它服务使用 HTTP API 进行通讯,服务可以采用不同的编程语言与数据库,微服务解决了单体应用团队协作开发成本高、系统高可用性差等等问题。
但是微服务也引入了新的问题,假设 A 团队开发某服务并提供对应的 API,B 团队也在开发另一个服务,但是他们需要调用 A 团队的 API,为了产品的尽快发布,两个团队都争分夺秒,已经进入联调阶段了,然而出现了下面这样的尴尬情况。
随着越来越多的微服务加入,它们的调用关系开始变得越来越复杂,如果每次更改都需要和所有调用该 API 的团队协商,那沟通成本也未免太大了,试想下图的沟通成本。
为了保证 API 调用的准确性,我们会对外部系统的 API 进行测试,如果外部系统稳定性很差,或者请求时间很长的时候,就会导致我们的测试效率很低,当调用 API 失败时,你甚至无法确定是因为 API 被更改而导致的失败还是运行环境不稳定导致的失败。
A 团队提供的 API 不稳定,肯定会导致 B 团队效率低下,为了不影响 B 团队的进度,所以构建了测试替身,通过模拟外部 API 的响应行为来增强测试的稳定性和反应速度。
但是这样做真的就解决问题了吗?当所有内部测试都通过时,能拍着胸脯说真正的外部 API 就一定没有变化?很简单的一个解决方案就是:部分测试使用测试替身,另一部分测试定期使用真实的外部 API,这样既保证了测试的运行效率、调用端的准确性,又能确保当真实外部系统API改变时能得到反馈。
感觉剧情到这里就差不多该结束了,实际上真正的高潮部分开刚刚开始。如果外部 API 的反馈周期很长,那增加真实 API 测试间隔时间就又回到了最初的起点。现在我们回顾一下上面的方案。
在上面的场景中,我们都是已知外部 API 功能来编写相应的功能测试,并且使用直接调用外部 API 的方式来达到测试的目的,如此就不可避免的带来了两个问题:
API 调用者(消费者)对服务提供方(生产者)的更改是通过对 API 的测试来感知的;
直接依赖于真实 API 的测试效果受限于 API 的稳定性和反映速度。
解决方案首先是依赖关系解耦,去掉直接对外部 API 的依赖,而是内部和外部系统都依赖于一个双方共同认可的约定—“契约”,并且约定内容的变化会被及时感知;其次,将系统之间的集成测试,转换为由契约生成的单元测试,例如通过契约描述的内容,构建测试替身。这样,同时契约替代外部 API 成为信息变更的载体。
前后照应一下,我们现在再来看一下消费者驱动契约测试。它有两个不可或缺的角色:消费者是服务使用方;生产者(提供者)是服务提供方。采用需求驱动(消费者驱动)的思想。契约文件(比如 json 文件)由双方共同定义规范,一般由消费者生成,生产者根据这份契约去实现。
契约测试其中一个的典型应用场景是内外部系统之间的测试,另一个典型的例子是前后端分离后的 API 测试。行业内比较成熟的解决方案是 Swagger Specification 和 Pact Specification,这里不做展开讨论。
我们同样可以把契约测试的思想用到代码的编写中,契约测试通过一个契约文件来解耦依赖,那么对于需要用户定义很多规则的场景,我们同样可以将这些规则像契约文件一样抽取出来,这样就降低了代码之间的耦合度。
最后敲敲黑板,契约测试不是替代 E2E 测试的终结者,更不是单元测试的升级换代,它更偏向于服务和服务之间的 API 测试,通过解耦服务依赖关系和单元测试来加快测试的运行效率。
Read More ~
智齿|读研否|家庭小江湖|广告乱象
建议读者大人们,如果自己经常一上火牙就疼,或者自己感觉牙已经有点问题了,可以提早预约医院的口腔科查一下,如果有问题早点预防,总是没有坏处的。抽烟的半年洗一次牙,不抽烟的一年洗一次牙。
因为智齿发炎被狠狠的折磨了近两周,我属于比较能忍得疼痛的人,这不周末才进行了一场春季骑行,唯有美景与美食不可辜负,什么病痛都是浮云,但回想起连续几晚上疼到睡不着觉的滋味,昨天毅然决然斩草除根,给拔掉了,今天就感觉好了很多。
前几天考研成绩出来了,估计现在大部分同学都在准备复试,我没有体验过考研的这个过程,毕业这半年有时候还是会想,我也应该体验一下考研的那个过程,已经很久没有体验过把所有时间都投入到一件事情上的快乐了。
但我还是不太建议读研,我这是无责任建议,毕竟自己没有读过研究生,在研究生实验室待了两年,算是有一半的硕士生经历吧。对于学历我一直以来的观点都是绝大部分人将它的作用放大了,总是认为名校成造就了强能力,而恰恰把因果关系给弄反了,是能力强的人都进了名校(本科)。当然,不否认像医学一类的专业是肯定要考研的,一棒子全打死肯定是不对的。
刘大发起的读书活动告一段落了,跟着小伙伴们泛泛的读了一遍《深入理解计算机系统》,只能用“痛并快乐着”来形容这个过程,每周输出一篇读书笔记,没有按时输出就罚钱的规矩很好,人还是需要自己逼自己才行。
这本书不适合初学者阅读,在豆瓣上的评分接近 10 分,不讲究速成,而是一本内功心法,如果是您是码农的话,读一读绝对会提高一个层级。现在已经开启了另一本书籍的阅读计划,刘大这个活动组织的超好。
春节回家发现了一个巨大的变化,我老家那种贫困县地区的村民们,也在开始讨论保险这一类产品了,我是觉得这个改变太大了,说明农民伯伯的经济水平也有很大的提升了。另外通过朋友圈还发现,我认识的大佬们貌似出身都并不是多好,反倒是大部分普通朋友家里的矿更多。
我们家族每年会组织祭祖活动,在正月初三一大家 50 人左右一同祭拜曾祖曾母,通过这么一个活动把整个大家族的年轻人联系起来,能搭建这样一个平台很棒,我正也在着手将家族信息数字化。
说到这里,想说一句家族群是个小江湖,亲戚之间也是暗暗较劲的,母亲不会抢群里几个特定的人发的红包,家里都是山路,车技不好的人很容易就寸步难行,一表叔就因为不到 10 米的距离,整个春节都在亲戚朋友面前抬不起头。
堂弟现在是民航飞行员在读,而另一个表弟今年正值高考,说要去考炮兵学院,将来好把飞机打下来,这一下可好了,这些话全部伯父被截屏保留了,将来某一天要是这俩兄弟闹矛盾了,估计有的好看。保二爷写的家族群不是群,是江湖...看起来更有趣一点。
在我身上更可悲的事情发生了,所有长辈一致认同应该由我来管理家族群,想想整个群里充斥的都是是那种要露不露、似露非露、就是不露的视频,或者是用粗糙都无法形容的大而泛的鸡汤文,整个头就大了,这可比解决技术问题难多了。
最近愈发觉得“大佬”之间的抄袭严重了,真大佬基本都是原创内容,或者是引用了别人的文字就标注出来,然而总是看到一些“大佬”原封不动发出来,还不表明出处,下面粉丝跟着继续做同样的事,我看到最多的一次是朋友圈连续 10 多条是一样的段子。
最后想无责任乱说一点科技相关的东西,5G 是当下的风口浪尖,各大厂商都希望在 5G 上有一席之地,搞芯片的搞芯片、做基站的做基站、整手机的整手机,5G + IPV6 肯定会带来无法想象的未来,5G 会大幅推动智能硬件的应用,但是手机这个应用场景是不是被夸大了呢?
现在的 4G 手机在线看一部高清电影不会有多卡顿的现象,广大吃瓜群众和各大媒体,一直都拿着 5G 手机来吹嘘,吃瓜群众跟随媒体引导的大流,我总觉得当拿到 5G 手机的那一刻,心里肯定会从喜悦急转失望的,就像目前的苹果产品一样。
Read More ~
Bootstrap-table 如何合并相同单元格
Bootstrap-table 官方提供了合并单元格方法 mergeCells,它根据四个参数可以合并任意个单元格,我们要做的只是告诉它怎么合并。
要合并同一列相同的单元格,无非两种办法,一种是一边遍历一边合并,遍历完了再合并。这里采用第二种办法,这里不需要遍历所有数据,因为用户只能看到当前页的数据,所以只遍历当前页的数据更省时间。
下面是我实现的获取合并信息算法,最终返回的是一个哈希表,比如下面的这个表格,如果要对「性别」这一列进行合并,很明显前面两个“男”需要合并成一个单元格,再去看下 Bootstrap-table 提供的 API,它需要的是从哪个单元格开始,合并多少个单元格,也就是它需要的是两个数值类型的参数。
姓名
性别
年龄
张三
男
23
李四
男
19
王二
女
20
麻子
男
21
所以我把哈希表设置为,键存的是索引,值存的是从这个索引开始后面连续有多少个和它一样的单元格,那么上述表格性别这一列所得到的合并信息哈希表就为:
{
0: 2,
2: 1,
3: 1
}
下面算法很简单,使用两个指针遍历指定的列,如果两个指针所指向的数据相同,那么就将键所对应的值进行加一操作,整个方法只会对该列数据遍历一边,所以时间复杂度为 O(n)。
let getMergeMap = function (data, index: number) {
let preMergeMap = {};
// 第 0 项为表头,索引从 2 开始为了防止数组越界
for (let i = 2; i < data.length; i++) {
let preText = $(data[i-1]).find('td')[index].innerText;
let curText = $(data[i]).find('td')[index].innerText;
let key = i - 2;
preMergeMap[key] = 1;
while ((preText == curText) && (i < data.length-1)) {
preMergeMap[key] = parseInt(preMergeMap[key]) + 1;
i++;
preText = $(data[i - 1]).find('td')[index].innerText;
curText = $(data[i]).find('td')[index].innerText;
}
// while循环跳出后,数组最后一项没有判断
if (preText == curText) {
preMergeMap[key] = parseInt(preMergeMap[key]) + 1;
}
}
return preMergeMap;
}
上述算法得到了单列数据的合并信息,下一步就是按照这个信息进行相同单元格的合并了,因此封装了下面的方法按照指定哈希表进行合并。
let mergeCells = function (preMergeMap: Object, target, fieldName: string) {
for (let prop in preMergeMap) {
let count = preMergeMap[prop];
target.bootstrapTable('mergeCells', { index: parseInt(prop), field: fieldName, rowspan: count });
}
}
到目前为止,我们实现的都只是对单列数据进行合并,要实现对多列数据进行合并,那么只需要对所有列都进行相同的操作即可。
export let mergeCellsByFields = function (data: Object[], target, fields) {
for (let i = 0; i < fields.length; i++) {
let field = fields[i];
// 保证 field 与 i 是相对应的
let preMergeMap = getMergeMap(data, i);
let table = target.bootstrapTable();
mergeCells(preMergeMap, table, field);
}
}
因为我在程序中做了一点处理,保证了fields中每个值得索引与对应表头的索引是一样的,因此不需要额外传入索引信息。简单来说就是我所实现的表格会根据fields的顺序,实现列之间的动态排序。你需要注意的是这一点很可能和你不一样。
到现在已经能够合并所有的列了,查看 Bootstrap-table 的配置信息发现,它有个属性是 onPostBody 它会在 table body 加载完成是触发,所以把这个属性配置成我们的合并单元格方法即可。
// groups 为要合并的哪些列
onPostBody: function () {
mergeCellsByFields($('#table' + ' tr'), $('#table'), groups);
}
再说一点不太相关的,我实现的是让用户可以自己选可以合并多少列,即用了一个可多选的下拉列表框供用户选择,根据用户选择的数量去合并,所以传入了一个groups参数。
最后推荐一个排序插件 thenBy,你可以用它进行多字段排序,比如用在合并相同单元格的场景,在绘制表格前先对数据进行排序,那么最后合并的结果就是把所有相同的数据聚合到一起了,并且还将它们合并到一起了,起到了一个隐形的过滤查询功能。
Read More ~
坟头蹦迪|清理手机上的干扰信息|2018 简短总结
前一周在一席上面看了一场演讲叫「不正经历史研究所所长」,整场演讲都伴随着欢声笑语,讲的是民间文化与经典文化,经典文化实际上是统治阶级强行推动的精致文化,绝大部分老百姓是看不懂这些东西的,反正我自己参观博物馆,如果没有讲解,我是完全看不懂那些玩意的。
能和生活联系在一起的文化最有活力,比如天天发杨超越祈求不挂科,拜拜马云希望有更多的钱等等。有一句老话叫「人活一口气」,民间文化都基于此,我在别人面前要抬得起头,要的是气派、要的是大气,上个世纪的「四大件」应该就是成功的一个标配,老百姓置办这些物件后,在邻居面前也更能昂首挺胸了。
昨天了解到一个朋友家乡的有一个非常奇怪的习俗,那就是「坟头蹦迪」,我最开始的想法是,这是不是最近兴起来的习俗,但是一问才知道,他小时候就是这样的了。基于我们的体系是无法理解坟头蹦迪的,你能说它们对于亲人的去世就不伤心吗?他们要的还是能抬起头,来参加追悼会的人们看到这么豪华的场面,第一反应是故人后代是很有成就的,在某种程度上这算是对故人的颂扬。
花了几个小时时间把微信清理了一下,只留下了 83 个公众号,这其中还包括一信用卡一类的服务号,也就是说只留下了 70 个左右的公众号。留下的都是小而美的公众号,这些大佬作者的更新频率也很低,比如子柳老师最近才更新了一篇文章,而上一篇文章的更新时间是 7 月 25 日。
最近在自己身上认识的一个问题是,关注的公众号太多读不过来,虽然在此之前已经筛选掉了很多号,然而自己还是读不过来,所以索性就做了减法。现在像公众号这些,已经变成了获取信息的一个重要渠道,我也确实比周围小伙伴掌握信息更快,大部分时间也自认为比他们更了解真相。
但是我最近突然有个疑问,我真的比他们更了解真相吗?大部分人是通过垃圾文章获取信息,我虽然没有跟着垃圾文章人云亦云,但是我还是通过网络获取信息的,那么我是不是看到的是另外一种看起来更接近真相的假象呢?
这些信息其实我就算不知道好像也没有什么大碍,顶多是别人谈什么新闻时,我所了解的也就他们知道的那么点而已,更好的方式是让自己的大脑去思考,以时间的维度去追踪事件的发展。
顺便推荐一个应用叫「刷屏」,我发现自己通过「刷屏」、「知识星球」、「微信公众号」、「朋友圈」四个地方,已经掌握大部分信息了,经常同事给我说某某新闻,而我在两三天前已经见过了。
我对国际计量大会修改「1 千克」的定义这件事印象很深,但是这件事我只看到在阮一峰老师的文章中有被提到过;人们更喜欢听自己了解的领域,跟自己同好的很容易产生好感,一些明星结婚、出轨竟然能把微博的服务给搞挂了,说明绝大部分人还是更喜欢撩自己 G 点的信息。
另外第二个问题是自己现在比在学校时更喜欢玩手机了,在学校时还能做到不带手机去自习,现在是隔一会儿就看看手机,把本来就碎片化的时间变得更加碎片化了,这种效率导致工作、学习效率低下,所以把微信和 TIM 的通知全部关掉了。
写到这里发现有点点像总结,索性就给自己简单总结总结吧。2018 我从校园走向了社会,完成了从学生到职场的转变。最大的改变是思维的提升,知道去投资自己,在学生时代,愿意花几百块钱去买课程,这对我来说是很大的突破,和现在愿意花几百的概念完全不一样,想想那时候一个月生活费总共也没有多少,而我去看了下自己在毕业前花在这方面的钱居然有一千多,如果加上毕业后的开销,那就是两千多了,真感谢那时候的自己。
这其中的收获是巨大的,后面我偶尔会向朋友推荐一些好的付费课程,但是他们都和大部分人一样,吃一顿饭花几百块钱,而如果花点钱买一堂课提升一下自己,就好像要他命一样,所以后面就不和他们讲了。
2018 开始用文字记录技术、生活、感悟,这其中的收获也是不小的,认识了此前只能仰望的大佬,结交了志同道合的朋友,而且也让自己更愿意去思考了。收到电子工业出版社的约稿合同,但是现在书都没写完,明年还写不完的话,那就不写了,主要是懒。
自负的缺点已经在渐渐改变了,更加懂得了谦虚。眼界不再局限于技术,很多东西我都会去了解,也结交了很多有趣的人,初入职场,好好学习与不同的人沟通。以后如果有能力,希望能给山区带去一点点教育资源。
2019 依旧坚持每周和同事或者校友打一次羽毛球,常去爬爬山,和有趣的朋友一起疯一疯;多读书,用豆瓣等工具去筛选好书,加大阅读量;常输出,输出是更高层次的输入;尝试去了解金融的逻辑;学习新的技术领域。
Read More ~
2018 年个人总结
这个总结写的还算认真,回头看,我真的运气很好,遇到了很多大佬,在我还未毕业时并没有嫌弃我傻,教我的不仅仅是技术,还有理财、为人处世,下面是我这一年的成长经历。
有一段时间因为华为 34 岁以上员工被裁、中兴程序员跳楼等事件的发生,各种蹭热点讨论“中年危机”的文章漫天飞,那时我正忙于找工作。
当时一个微信群里面大家各种讨论中年危机,都在给自己制造焦虑,刚好群里有个大神可能看大家过于焦虑,就在群里发了几条消息,教大家如何避免中年危机,并且推荐了两本书。
还是学生的我下意识的就发了一个添加好友请求,庆幸的是他同意了我的好友请求,当然我们没有什么交流,我的问题过于浅显,我明白自己这个水平问问题,会浪费人家时间,当时的想法是看看大神的朋友圈,他平时都接触什么,自己学习一段时间。
大神推荐的书是李笑来写的《把时间当做朋友》、《财富自由之路》,两本书在学校图书馆都没有,我就给学校图书馆荐购系统提交了这两本书,图书馆效率也挺高,不到一周就把书给买回来了,我立马就借回来阅读。
书中的内容刷新了我以前狭隘的认知,自己从来没有像书中那样考虑问题,除了对作者的佩服之外,更多的是思考自己这种学生思维局限性太大了,要慢慢的将它摒弃。
有个定律是你关心什么就会来什么,后面陆续碰到几位像大神一样的人士,并加了他们的微信,但是都仅仅是通过他们朋友圈的蛛丝马迹去找知识,通过他们朋友圈的分享内容,我知道了“简七理财”、“码农翻身”公众号,然后知道了《富爸爸穷爸爸》、《小狗钱钱》,于是我通过微信读书,读完了这两本书,逐渐培养了理财理念。
后来没隔多久,简七出书了,我第一时间就买了她写的《好好赚钱》(同期还有刘大也出了《码农翻身》一书,我也第一时间买了),简七写的内容通俗易懂,很容易理解。
刘大在群里开了几次公开课,作为计算机专业的我,被刘大对技术的理解之深给折服了,正是业界浮躁的时候,成千上万人想着人工智能、大数据、区块链,而刘大一直能沉下心来去了解技术的原理,这给了我一个很好的榜样,我也逐渐沉下心来,开始去补最基础的知识,像《深入理解计算机系统》一类书也能尽下心来慢慢去啃(当时没啃完,最近又在啃),这种不浮躁的特质对我的技术成长是很有帮助的。
此后有一天,另一个大神在朋友圈分享了曹大写的《从校园到职场系列文章》,喜欢深入挖掘信息的我,以曹大公众号为源头,又找到了冯大、池大、二爷等人的公众号。
作为自由的大四学生,因为不用担心第二天起不来,我那段时间经常熬夜阅读他们的文章,再阅读的过程中我也开始思考自己此前哪些想法狭隘,哪些品质又是值得继续保持的。
也是那时开始接受知识付费的,那时候已经有小密圈(现在叫知识星球)了,出于对几位大佬的信任,我第一次大胆的花了几百块钱加入了刘大、曹大、冯大、程序员小灰的小密圈,其中的内容比网上蹭热点的文章好不知多少倍,一贯爱捕捉蛛丝马迹的我,又通过评论信息发现了 angela zhu、子柳老师、陈利人老师等,然后去找他们的文章,他们输出的内容要比水军写的文章好太多。
自己也是从那时候开始坚持写文章记录自己的心得的,通过写文章,我认识了很多优秀的人,比如吴小龙同学、了不起的杰克、java 小咖秀等公众号的作者,和他们交流的很少,但是却很受用,他们的积极向上也影响着我一直保持着乐观豁达的心态。
自己写的文章也被几个资深程序员赞同,同时还收到了两个出版社发来的出书邀请,让我体会到了无心插柳柳成荫的收获。
让我坚持一直写文章的动力不是赚钱,而是我切切实实体会到了它给我个人带来的成长,为了自己日后再看时能立刻就找到清晰的逻辑,我把都尽可能把文章写得有理有据,掌握自己的节奏,尽量提高文章质量。此前写的谈一下写作的重要性一文有说写作可以带来的好处。
现在已经不把自己当新人了,而且有同龄人甚至比我年龄还大的人向我咨询问题时,我也能给出合理建议,都得到了他们的肯定。最近发现和周围伙伴最明显的一个区别就是,对于同一个新闻,我经常早于他们半天甚至一两天知道,而且掌握的信息比他们还准确,我认为这就是整体认知水平的提升。
想说的是,执行力与信息素养很重要,执行力强的人会与你拉开越来越大的距离,信息素养也是一个关键品质,现在网络上充斥着大量的虚假信息,如何去分别这些信息的真假,在相同条件下如何获得更多的有效信息,是必备的能力。
当前年龄 23,刚大学毕业几个月,没读研。按十年为期给自己定了几个小小的目标:
父母是地地道道的农民,智能手机都不会用,十年之类给自己和父母把重疾险、意外险之类的保险配置齐全,虽然父辈一直反对买保险。
提高获取信息的能力,虽然现在对信息的掌握都比周边伙伴要早半天至几天,但是都不是自己的分析结果,学习以时间的纬度跟踪事件的发展。
学习理财知识,现在只对信用卡、基金有一点点的了解,不管炒不炒股,金融知识都还是要学的,这方面通过看书、阅读、小额实操学习。
提升自己的技术实力,职业是程序员,前后端都做,但是自己对技术的热情不是多么高涨(至少比身边一半人要高涨),以我对自己的了解,我在技术的道路上成长为小公司一个的架构师应该不成问题,再高层级怕是不行。
慢慢做到不止一份收入来源,这方面不是多清晰,现在每个月平均会有 200 左右的非工资收入(帮助别人时发的红包等),十年后做到其它收入基本和工资持平。不至于因为钱的问题而忍受心中的不快,至少得有能指着老板的鼻子说“老子不干了”的底气。
世界那么大,应该去看看,国内除了西北地区,中国很多地方已经留下了我的足迹,旅游不仅仅是玩耍,更是提升见识、获得灵感的有效途径,十年至少得把自己的脚印印到 5 个国家的土地上吧。
十年之后应该已经结婚了,房子是现在最遥不可及的目标,但是心里莫名有一股自信,这个后面会实现的,虽然不知道哪里来的这股自信。
最后一个,趁年轻,多学习,做一个终身学习的人,时刻保持学习的态度,多做有利于他人的事,现在水平不高,我能帮助到的大部分都是硕士及以下。努力提高自己,帮助更多的人。更大的目标是能给山区学校带去一些更好的教育资源。
Read More ~
匆匆的岁月——成都七中网校远端学生的高中生活
周三刷星球时看到一条关于成都七中网校的信息,没想到周四就被成都七中网校给刷屏了,看到文章里面的描写,感悟颇多,网校陪伴了自己三年,一个诗意的女孩——西凉忆就是因为网校结识的。
我是 12 年入学高中,那一年学校也刚和成都七中开通网校,因此我属于学校第一届全程使用网校资源的学生。记得刚入学时,对这种教学方式并不适应。不止学生不适应,老师也不适应,政治课老师就不使用直播课程,而是选择自己给我们讲。不过后来年级组出了硬性规定,特优班必须使用直播课程。
就像教育的水平线中描述的一样,我们被称为远端学生,大家都是第一次使用这样的系统,七中老师估计也很好奇,都在第一节课或者第二节课上抽了远端同学回答问题,后来就很少有抽远端同学回答问题了,估计是因为远程视频效果不好还浪费时间。
成都七中本部的学生上课很有激情,一到讨论等环节,虽然很吵但是却很有秩序,而我们这边基本是大家都盯着屏幕,等待对方讨论结束。
对方学生的基础我们是没办法比的,大部分能够完全以纯英文交流,而我们远端学生大部分都只能说出“My name is ..., I'm from ..., I like ...”,英语的差距是最大的。我自己是主动找了英语老师谈话,和她做了一个约定,每周我写一篇作文交给她,她帮我批改,这样坚持了两年。
让我感受到最大差距的是,一个中学有自己的电视台,经常会有像《汉语桥》冠军一类的人物前来演讲,美国第一夫人米歇尔也到七中演讲(那是总统还是奥巴马),作为远端学生有幸蹭了一场名人演讲;七中学生的寒暑假是参加联合国模拟大会、到哈佛做了简短的交流、到华盛顿旅行......
而大部分远端的学生,要么是参加学校组织的补课,要么是在家干农活,基本连县城都没有走出去过,和七中相比,完全是天壤之别。
现在我依旧还清晰的记得七中的几个老师,做 PPT 从来没有背景图的数学老师,语速超快但又吐字清晰的化学老师,说着一口标准川普的物理老师,有着一头蓬松金黄卷发的历史老师(男)......去看这些老师的背景,也都是名校出身,武汉大学、华中师大等等。
有一个细节记得很清楚,在一堂数学课中有个题目,题目具体内容忘了,只记得是要求算新华中学的一本录取率,最后的答案是在 74% 左右,这个数字在我眼里很高了,但是那一刻并没有觉得有什么,毕竟这是书上的学校嘛!!
想不到的是,下一秒那个做 PPT 从来没有背景图的数学老师说了句:“这个就比较低了啊,我们学校考的很差的时候才是百分之七十多的录取率”。一下让我震惊了,因为我在心里算过自己学校的一本录取率,在此之前不到 10%,而且我所在高中在所有远端学校中还是比较靠前的。
让我意外的是,七中的老师原来也会骂人、打人,即使打的很轻;学生没完成作业,也会被罚拿个小凳子到教室外面补作业;在全国禁止补课的规定之下,七中也会给高三的学生补课,当然我们也同步补课了。
我无法构想如果三年没有使用网校资源会是神马结果,如果仅仅是看数据的话,一本率是按倍数翻的,12 年开始使用网校资源后,学校有了第一个清华,13 年又添了一个清华。我属于 14 届,这届没有清华,最好的是浙大,我进了个普普通通的哈尔滨工程大学。据说 15 届又出了清华。
我所在的高中也被央视作为典型案例探讨农村高考。无疑能上央视,那这个学校在当地乃至全国同等水平的学校中是很成功的。
无疑这种生活给每个同学都留下了难忘的记忆,如果哪位同学加了七中本部直播班级某位同学的 QQ(那时没有人用微信),那能吹好几天牛逼,七中人在我们眼里就像明星一样。
我们当地 14 届县状元高考分数是 635 分,七中本部平均分是 616 分,这差距至今都让我目瞪口呆。前段时间曹大在星球发起了一个作业:十年后的期望目标。我所提交的作业中写了句,如果有能力,希望能给乡村学校带去一点教育资源。
我并不认为穷是光荣的事情,但在很多农村人眼里穷是一种资本,一种获取国家福利的资本,如果某次补助没有评到自己头上,那得记恨村长一辈子。我认为这才是造成农村孩子和城里孩子有巨大差距的原因,如果孩子没有从这种思维走出来,那一辈子也不可能有什么大的成就。
没想到自己都大学毕业了,却看到成都七中的网校被刷屏了。毫无疑问,这是一件极为有意义的事情,这种内容就应该被刷屏,愿七中和远端学校都越办越好。
文中照片取自于同学 QQ 空间,记得我原来还有英语老师 Spring 的 QQ,高中时向他请教过自己的英语问题,太久没联系后来 Spring 把我删了 =_=,反正是没了。
Read More ~
记录在南京大学半天
因为工作需要,到南京出差了半个月,中间利用周末和最好的朋友疯了一天,之后自己又一个人到南京大学鼓楼校区逛了逛。
不会勾搭妹子的我总是能勾搭到老爷爷,到南大就勾搭了一个 86 岁高龄的老教授,他毕业于中山大学,年轻时候是做地质工作的。
我就像个熊孩子一样要爷爷给我讲有趣的故事,要听他讲我们这一代人或者是大部分人都不知道的历史。
爷爷虽然已经是快到耄耋之年的人了,但是对年轻时候的事记得很清楚,只是对最近的事记不起来。这篇文章仅仅是记录一下爷爷所讲的趣事。
爷爷年轻时候接到中科院的任务,前往内蒙古考察。在考察期间他们用汽车压死过一只狼,而且当时吃了狼肉,一行 30 多个人都吃过那匹狼的心,但是没有吃过狗肺。
据爷爷说,狼是很狡猾的动物,他们用汽车去追狼,狼就在原地不跑,等到你离它只有 10 来米的时候,突然拐弯跑了,这样的情况他们一共遇到了 6 次。这和《狼图腾》一书中的描写基本一致,狼有先进的军事文化。
爷爷告诉我,南大起源于金陵大学,南京大学的标志性建筑「北大楼」是个教堂的样子,金陵大学本来是个教会大学,现在的「北大楼」就是原来的「钟楼」。
南大的地下有隧道,是当年毛主席提倡「深挖洞、广积粮、不称霸」时挖的,目的是为了防空。后来被南京食品公司用来存放香蕉,就是那种没有熟的香蕉,在隧道里面放熟了,再拿出来卖。不过现在隧道所有的口都没堵上了,完全废弃了。
在南大,有一些楼中间有 5 层,然后到两遍就只有 3 层了,整体看来像是个三角形。实际上这些楼当年都是要修 8 层的,因为那时候没钱,建着建着发现没资金了,所以就封顶了。
但是南大计算中心那栋楼只有 3 层却不是因为没钱,而是因为它旁边是消防大队,本来也是要建 8 层的,消防队说建高了挡住了他们视线,不能及时发现火情。爷爷笑着对我说:“但是也没见他们在上面拿个望远镜望啊!”。
我们都知道「五四运动」,但是却很少有人知道「四五运动」,这个运动的起源就在南大,当时 300 多学生(我回来查资料说是 400)发起了这个运动,后来演变为全国性的运动,直接带动了半年后四人帮被粉碎。
那是爷爷是个老师,他说他们教职工是很支持这些学生的,但是不敢公开性的支持。学生们很聪明,把标语刷到火车上,但是所有出南京的火车都被四人帮用水把标语给冲刷掉了,学生们就用沥青往火车上面写,才通过火车把这项运动的信息带到了全国各地。
我回来后查了一点资料,「四五运动」的起源是因为周恩来总理的去世,四人帮居然压制人民群众悼念周恩来,诬陷邓小平,而那时的毛主席也已经病到无法行动。
人们把花圈都放到人民英雄纪念碑前悼念周总理,却被四人帮给清理了,北京广大人民群众在“还我花圈,还我战友”的口号下行成了天安门广场大规模的群众抗议运动。
那也是一个诗意的年代,人们通过写诗来表达自己心中的愤怒,把小瓶子挂在树上,蕴意着期待邓小平的归来。那段时间四人帮应该是很难过的,从姚文元的日记就可以看出来。
爷爷还给我讲了一点他们的研究,他们研究行政规划的很多人认为,中国现在的行政划分有很多缺点的,中国应该划分 50~80 个省级单位。现在中国的行政级别也有问题,宪法规定行政层级只有三级(这一点我没查),而现在很多地方县下面是镇,镇下面还有乡,严格讲这是违宪的。
快到午饭时间时,爷爷还教我写了一会儿字,有的简体字很难看,比如「龍飛鳳舞」用繁体字写出来很好看,但是用简体字写出来就特难看。要想练好毛笔字,把三个字写好了就行了,然而我现在只记得一个“飛”字了,这可能就是老师们常说的「你又还给我了」。
Read More ~