独立开发的一些体会

快速上线

独立开发完成一个功能就要上线,这是非常重要的。这是因为线上环境涉及到虚机性能、网络带宽这些硬件因素,快速上线可以即使针对这些客观因素即使调整代码。

如在本地加不加分页都不影响使用,但是线上可能就会明显感到时延;本地落库数据库可能没有影响,但是线上可能落库时间较长需要做异步处理等。

渐进式开发

个人能力有限,在每个阶段都要专注于主要的业务或者功能。如一开始项目没上线,可能就不需要日志文件或者配置文件,先完成关注的业务就行。

React 状态机使用感受

Photo by erik cid on Unsplash

上手 react antd 之后,按照官方推荐的套娃框架 umi 和 antd pro 配合搭建了目前的项目。其中 umi 又可以使用 dva 状态管理框架进行数据流管理。

一开始我的认为是这个东西比较麻烦使用起来不太顺手,并且解决不了什么问题。但是现实是在我的项目里有很多组件共用的数据,不用状态管理会让代码显得非常冗余。学习了 dva 之后发现套娃框架非常适合上手,也精简了不少代码。

状态管理的核心是拆分状态。一开始我综合了知乎的一些回答,认为若组件之间有大量的共享数据,那么就可以使用状态机管理数据可以精简非常多的代码。但是实际来说需要针对具体的问题具体解决,不限于组件共享思路。

比如我这边有个分页功能,假如我的数据获取已经放在副作用 effect 去完成,那么数据的分页数据和分页信息都要放到状态去管理,否则就又会涉及到 state 的编码和 dispatch 的回调,会四不像。

哦又是this——浅谈 React 事件绑定

Photo by Jeremy Zero on Unsplash

在使用 React JSX 事件绑定中有个最大的问题是它不会帮你处理 this 的指向问题。我刚刚上手的时候有些疑惑,看了教程之后豁然开朗。

React 事件绑定的需要和显示的修改对应事件处理函数的 this 的值。这主要是因为 Babel 开启了严格模式。若这个函数 this 指向没有改变,直接赋值给 onClick,那么函数体内的 this 仍是 undefined 。为此需要使用 bind 函数来修改函数体内的 this 指向。比如下面这段代码 :

import React, { Component } from "react";

class test extends Component {
  test() {}
  render() {
    return <div onClick="this.test.bind(this)"></div>;
  }
}

export default test;

对于一个类组件,this 指向的是类的实例,this.test 方法会沿着原型链找到类中定义的 test 方法,然后将这个类方法中的 this 替换为当前实例对象。这样一来, test 方法中的 this 就可以当前实例对象的值。

另一种方法是将 test 写出箭头函数的形式。这里有两个含义。首先 test = func 的形式,test 就是一个实例属性,但是这样仍然没有改变这个直接调用时函数内部的 this 的指向。但是假如写成箭头函数的形式,箭头函数中的 this 会使用实例对象的 this,如下所示。

import React, { Component } from "react";

class test extends Component {
  test = () => {};
  render() {
    return <div onClick="this.test.bind(this)"></div>;
  }
}

export default test;

对应视频教程

bind https://www.bilibili.com/video/BV1wy4y1D7JT?p=16

箭头函数 https://www.bilibili.com/video/BV1wy4y1D7JT?p=18

模块化工程杂感

Photo by Michael Scherback on Unsplash

为了更好的分解大规模的代码,包(package)的概念就产生了。包可以隔离命名空间,消除函数变量的命名冲突。一般的做法是,相同包下的文件都会放在在一个文件夹下。针对这个习惯,Python 在文件夹下定义__init__的方法来组织下面的小文件,JavaScript 的模块系统基本也是这个思路。

和这两者不同, Golang 不在单独在文件夹下指定一个导出文件,而是直接使用关键字 package 来指定,同时摒弃了文件导入这个概念,包为导入的最小单位。这样一来,同一个包内的各个文件可以直接使用而无需再次引入。而包外部的代码想要使用包内代码必须是显示的调用。这和它们家 Angular 的模块是一个思路。而导出文件的作用被大小写导出的内容所取代。

Windows Server 设定 eggjs 自启

Windows Server 总是感觉很心虚,有些程序相性不太好,一旦八字不合就要调试半天,若非单位有这使用 Windows Server 的传统,我是绝不用它作为主力系统。这不,今天又碰到一个 eggjs 写的转接口应用需要在 Windows Server 2012 做自启,不出所料又折腾半天。

半天时间,我试了很多种方案,比如 pm2-windows-startup,任务计划+node-cmd,无一例外失败了。其中只有 pm2-windows-service 竟然在折腾之下意外成功,这里记录一下关键点。

继续阅读Windows Server 设定 eggjs 自启

走火入魔做产品

在业余时间一直开发一款小程序应用,陆陆续续也有大半年的时间。半年时间来,我的感受是产品和开发不同,开发侧重与实现与做到,产品注重是做好。

做好相对于做到没有一个明确的目标,因此需要反复迭代。半年以来设计了很多 UX/UI,过了一段时间觉得很不好用,又推翻重来。这种自虐的感觉真的很难受。

UX/UI 到组件封装复用其实每个过程都是渐进迭代,过程很曲折,但是想到也算慢慢接近目标,也就宽慰了。放上目前的阶段性成果留作纪念。

继续阅读走火入魔做产品

HTTPS 理解关键问题

Photo by stefan moertl on Unsplash

防止中间人攻击

为了防止中间人拦截攻击,对于采用证书机构来加密服务器端公钥。这样中间人假如拦截了 HTTPS 流量,并且使用自己生成公私钥对,使用自己的私钥加密数据发给客户端,那么客户端无法使用机构提供的服务器公钥对密文进行解密,从而导致协议出错。

防止中间人窥探

由于在握手阶段是协议出一个双方都可以对称密钥,客户端采用机构认证的服务器公钥对协商好的对称密钥进行加密。这样即使中间人劫持到,由于没有服务器私钥所以无法对这段密文进行解密。

证书防篡改

证书颁发机构将服务器公钥等一系列信息首先做摘要算法,然后使用 CA 机构的私钥(非服务器公钥)对服务器公钥信息进行加密,作为数字签名,在客户端需要使用机构的公钥对证书内容进行解密。

继续阅读HTTPS 理解关键问题

z-index 层叠的一些细节

最近要把一个筛选的功能做组件化,涉及到了z-index 和定位的一些细节。z-index 的最大特点是它只有作用于定位的组件之上才有效果,比如 relative,absolute 或者 fixed。

其中 relative 很特殊,它不会脱离文档流,因此一旦 relative 定位的组件被渲染,会把父结点撑开,然后不管你怎么移动 transform 那个坑都会在。

相反 absolute 和 fixed 都脱离了文档流,因此它不会把父组件撑开,也不会留一个空白坑。其中 fixed 和 fixed 的图层处于同一维度。同一维度意味着父组件的范围可以限制子组件的表示范围,假如父组件写了 overflow:hidden,那么子组件也不会显示出来。

absolute 和其最近定位的父结点处于同一维度。同一纬度在上一段落已经得到解释。

最后,微信小程序组件中使用 fixed 定位很奇怪,模拟器可以但是 IOS 端不行。

Throttle 与 Debounce 使用场景

Photo by Cristina Gottardi on Unsplash

不管什么技术概念,都要落到实际使用场景比较容易理解。Throttle 和 Debounce 也是一样,这里我分别解释一下。

单位时间只做一次使用 Throttle

单位时间只做一次使用 Throttle。PC 上有些操作在小程序真机上延迟特别明显,比如点击按钮展开菜单的动画,假如用户点击频率过高就会导致小程序显示异常。为了解决这个问题,需要在单位时间比如 500ms 之内对用户点击只响应一次,这样可以减少动画调用的频率。

等待操作不再发生使用 Debounce

等待操作不再发生使用 Debounce。比如我们搜索根据关键词从实时后台拿到商品名称,我们不知道用户什么时候结束输入。假如每监听一个关键字就去后台拿数据会导致后端压力比较大。那么再前端就可以做一个 Debounce。当用户键入一个关键字后等待 500ms,若这 500ms 之内没有新的输入,当作用户结束输入,然后再去后台请求数据,可以减轻后端压力。

IOS 视频播放黑屏问题解析

IOS 下浏览器播放本网站的视频会出现黑屏。假如在浏览器中直接访问视频文件的地址也出现黑屏,那么你就需要检查一下(通过 POSTMAN 等 HTTP 工具)后端有没有对 Range 请求头做出响应。

产生原因

IOS 下浏览器(Chrome,Safari)在请求视频流时,会默认在 HTTP 请求头中加入 Range 来向服务器请求对应的视频片段。参考这个在线视频链接,IOS 浏览器可以完美播放。使用 Fiddler 在 IOS 下抓包可以看到,在请求这个资源时(单单针对这个视频),手机发出了二次请求。

继续阅读IOS 视频播放黑屏问题解析