监控用户在当前页面的停留时间
我们希望知道一个用户在当前这个页面停留的时间,这中间要考虑到用户通过切换浏览器tab的情况,把所有用户动作都记录下来。
const tracers = [] // 进入 tracers.push({ type: 'enter', time: Date.now(), }) // 切屏 const visibilitychangeFn = () => { if (document.visibilityState === 'hidden') { tracers.push({ type: 'focusout', time: Date.now(), url: window.location.href, requestId: this.getRequestId(), }) } else { tracers.push({ type: 'focusin', time: Date.now(), }) } } document.addEventListener('visibilitychange', visibilitychangeFn) // 离开 const unloadFn = () => { tracers.push({ type: 'leave', time: Date.now(), url: window.location.href, requestId: this.getRequestId(), }) record({ type: 'usertracer', tracers, stay: tracers[tracers.length - 1].time - tracers[0].time, }) } window.addEventListener('beforeunload', unloadFn)
function record(info) {}
通过一个traces数组,记录了用户从进入这个页面,在这个页面停留、切换tab,到最后离开这个页面的时间。
Unsplash
可免费商用的图片素材供应商。
https://unsplash.com/
思源宋体
思源宋体、思源黑体这两款字体都是开源免费(可商用)的高质量字体,由adobe发布,值得收藏。
https://source.typekit.com/source-han-serif/cn/
手机端真机调试
https://segmentfault.com/a/1190000018613578
文件名绝对不能使用驼峰命名方式,原因很简单,不同操作系统对大小写敏感程度不同,导致修改文件名之后无法被识别,git不对这些文件进行任何处理,但是你在代码里面又是使用新的文件名。等你部署的时候,代码报错说找不到这些文件。正确的文件名命名方式是使用-或_连接单词,但是也又一些命名为了省空间不使用连接符,全部小写,这样会导致一些单词连在一起之后,有歧义,而且说实话,工程项目,有的时候为了提升团队协作的整体效率而牺牲小部分性能,也是可以接受的,成熟的现代编程,会平衡代码开发时和运行时的体验,而非一味追求运行时体验。
js数据模型驱动器
在一次表单重构中,我逐渐意识到,在数据和UI分开的前端开发模式中,UI和数据越来越需要解耦,UI要完完全全和数据本身无关,做到无状态,做到完全靠数据驱动,并且提供响应接口(更新UI的接口)。而数据层面,如果考虑到自身将被用于渲染,那么就要配置一个驱动器,将原始的数据结构转化为便于UI使用的数据结构,这就是独立于UI的数据模型驱动器。
拿表单来说,市面上有一些基于jquery的表单框架,虽然说是框架,实际上,还是一套基于js配置的ui组件,并非真正意义上的框架。而我的思考是,我们同一套表单,它背后的业务逻辑、数据提交的验证、编辑时的数据回溯等等问题,也就是脱离了UI层面的其他逻辑问题,都可以抽象出来。现在的开发全部是多端开发,同一个表单,在UI界面上可能不同,使用的UI技术也可能不同,例如在公众号网页和在小程序中,甚至在ReactNative构建的原生app中,他们抛开UI、交互层面的东西,背后的业务逻辑几乎是一摸一样的,为什么不可以共享?而且这三种场景,背后都支持js原生的计算能力和语言特性,所以,很明显是一定可以共享的,所不同的是,在将模型和UI框架进行拼接时,拼接方式不同。
表单模型只是一个例子。这种将模型抽离出UI的方案,适用于大部分带有业务逻辑的中后台应用中,在都使用了web技术的前提下,想多端共享同一套业务逻辑,就应该用这种思路去写。
现在的问题是,有没有一套完整方案(框架),去像React那样,编写模型。我认为还没有,或者说,还没有一个UI框架是基于这种考虑去实现的,因此,也就没有模型框架可以被应用到实际开发中。如果有一种UI框架(特别是React),可以基于“模型-视图”的方式去开发自己,那么就更有利于模型框架的出现。就目前而言,最接近这种形态的是rxjs作为模型框架,react作为UI框架。
第一步,在鼠标setting里面激活secondary click,并选择click on left side。这样就可以左右两个键互换了。接下来就是修改鼠标指针,参考如下步骤。
1. Download Mousecape.zip containing the 0.0.5 pre-release and install.
2. Install the helper tool from the menu bar by clicking Mousecape > Install Helper Tool.
3. From Mousecape preferences (Command-,) select "I am... left handed"
4. From the menu bar click Capes > Dump Cursors.
5. Click the cursor dump to highlight. Command-Enter to apply. Command-R to restore the default cursors.
npm依赖应该放在哪一个字段?
在一个前端项目中,我们把依赖通过特有的pacakge.json,其中的dependencies字段提供给npm来安装依赖。自从npm升级之后,就增加了依赖的控制,例如增加package-lock.json来锁定开发时使用的依赖版本。而我们的项目,很多会上到CI系统去构建,然后通过CD系统来部署到我们的生产环境中。这就会带来一个问题,我们在开发环境中使用的依赖,应不应该在CI系统中安装,因为大部分CI系统都不具备开发环境那么宽松的编译环境。那么到底要怎么来安排我们的开发环境依赖、CI环境依赖和生产环境依赖?
首先理解三种依赖:
dependencies
本包的依赖。即当另外一个包/项目依赖你这个包的时候,你的包必须依赖的其他包。npm在安装一个包的时候,它不单单只安装了这个包本身,同时还安装了dependencies里面指定的依赖。例如:
npm i databaxe
你会发现,不单单databaxe这个包被安装了,databaxe这个包的package.json里面的dependencies字段里面的包也被安装了(devDependencies里面的包没有被安装,optionalDependencies 也会被安装,但是 optionalDependencies 有一点不同,如果里面的包在安装过程中失败了,那么不会影响安装过程,这个包因为安装失败而被忽略,具体阅读这里)。
由于我们大部分前端项目,在现阶段还是需要通过构建工具构建的,因此,对于一个完整的上线项目而言,dependecies里面只需要放置node端的modules即可,例如express等服务器依赖包,而不需要把jquery等前端代码需要的包放在 dependencies 里面,因为,前端代码的依赖包会被webpack等工具打包进去。这些在构建阶段用到的包,可以放在 devDependencies 里面。
但是,对于一个组件,或者一个第三方前端包,你需要考虑的是,你的包被其他项目引用时,会由其他项目去自己实现构建过程。你的代码里面的依赖可以和该项目其他依赖的依赖共用,例如前面提到的jquery,有可能你的包和别人的包都用到了,是一个公用的依赖,因此,你不应该把jquery的代码打包到你自己发布的包代码中,而是作为依赖的形式,添加到dependencies中去。这样,当别人的项目在构建时,会同时使用你的包、别人的包、jquery去进行构建。这样保证了代码的复用和代码量的减少。
devDependencies
本包的开发依赖。当你在开发一个包的时候,你可能需要用到一些用于开发的依赖,例如webpack,babel等。这些依赖只会在开发构建阶段(也包括你上到CI系统进行构建时)用到,而不会在生产环境用到。npm在安装一个包时,这个包pacakge.json里面的devDependencies里面的包不会被同时安装。但你在把这个包的源码克隆到本地,并准备开发时,你在项目目录下执行
npm i
你就会发现,这些包被安装了。而且,这些包里面的package.json里面的规定,也完全和本文所讲的规则一致。也就是说,虽然这些包是放在devDependencies里面,但是,它们被安装时,它们自己package.json里面的devDependencies里面的包不会被安装,因为,这些是它们自己的开发依赖。当它们被安装时,是被当作一个正式的第三方产品来使用。
optionalDependencies
本包的可选依赖。当你在开发一个包的时候,你可能希望有些包是可选的,比如,一个包由AB两位同学在开发。其中A开发时由于自己的习惯,使用到了一个包,但是B同学没有这个习惯,他不希望自己在开发时这个多余的包被下载浪费时间,这个时候,这个包应该被放在optionalDependencies里面。npm在安装一个包的时候,该包的optionalDependencies里面的依赖也不会被安装。但是,在开发时,你执行
npm i
这些包还是会被安装。你可能会问,那它和devDependencies有啥区别?区别在于,你可以使用参数让它们不被安装:
npm i --no-optional
通过这个参数,在执行npm i的时候,optionalDependencies就不会被安装了。
不同的开发环境如何正确选择一个包应该放在哪里?
- 但凡用于构建的、测试的、质量检查的,都放到devDependencies里面
- 但凡仅用于本地开发,例如预览等,都放到optionalDependencies里面
例如,我们经常会在本地开发时,起一个devserver来对开发结果进行预览,但是在上到CI系统时,这个功能根本不会用到,所以,我们把这些依赖放到optionalDependencies里面,而在CI系统构建脚本中,一定要加上--no-optional参数。
所以,最终总结下来,我们大致可以这么认为:dependencies是给生产环境用的,devDependencies是给CI构建用的,optionalDependencies是给本地开发用的。虽然这个理解有偏差,但对于对这个知识点刚刚了解的同学来说,非常有用。
大部分开发肯定都是要考虑兼容性的,
就算是参考,
也是片面的,
唉,
不说了