Articles
Articles copied to clipboard
经验文章
**Hook** 是 React 16.8 的新增特性,可以让你在不编写 class 的情况使用 state 以及其他的 React 特性。 **React Hooks出现,组件可尽量写成纯函数,如需要外部功能和副作用,就用钩子把外部代码"钩"进来。** React Hooks 就是那些钩子。 使用 React Hooks 好处: - **Hook 将组件中相互关联的部分拆分成更小的函数方便复用** - **Class 组件通过 Hook 拆分复用状态逻辑方便理解** React 默认提供了一些常用钩子,也可以封装自己的钩子,以下常用的几个钩子:...
# HSTS详解 ## 1. 缘起:启用HTTPS也不够安全 有不少网站只通过HTTPS对外提供服务,但用户在访问某个网站的时候,在浏览器里却往往直接输入网站域名(例如 `www.example.com`),而不是输入完整的URL(例如 `https://www.example.com`),不过浏览器依然能正确的使用HTTPS发起请求。这背后多亏了服务器和浏览器的协作,如下图所示。  图1:服务器和浏览器在背后帮用户做了很多工作 简单来讲就是,浏览器向网站发起一次HTTP请求,在得到一个重定向响应后(服务器发起301、302),发起一次HTTPS请求并得到最终的响应内容。所有的这一切对用户而言是完全透明的,所以在用户眼里看来,在浏览器里直接输入域名却依然可以用HTTPS协议和网站进行安全的通信,是个不错的用户体验。 一切看上去都是那么的完美,但其实不然,由于在建立起HTTPS连接之前存在一次明文的HTTP请求和重定向(上图中的第1、2步),使得攻击者可以以中间人的方式劫持这次请求,从而进行后续的攻击,例如窃听数据,篡改请求和响应,跳转到钓鱼网站等。 以劫持请求并跳转到钓鱼网站为例,其大致做法如下图所示:  图2:劫持HTTP请求,阻止HTTPS连接,并进行钓鱼攻击 - 第1步:浏览器发起一次明文HTTP请求,但实际上会被攻击者拦截下来 - 第2步:攻击者作为代理,把当前请求转发给钓鱼网站 - 第3步:钓鱼网站返回假冒的网页内容 - 第4步:攻击者把假冒的网页内容返回给浏览器 这个攻击的精妙之处在于,攻击者直接劫持了HTTP请求,并返回了内容给浏览器,根本不给浏览器同真实网站建立HTTPS连接的机会,因此浏览器会误以为真实网站通过HTTP对外提供服务,自然也就不会向用户报告当前的连接不安全。于是乎攻击者几乎可以神不知鬼不觉的对请求和响应动手脚。 ## 2. 解决之道:使用HSTS 既然建立HTTPS连接之前的这一次HTTP明文请求和重定向有可能被攻击者劫持,那么解决这一问题的思路自然就变成了如何避免出现这样的HTTP请求。我们期望的浏览器行为是,当用户让浏览器发起HTTP请求的时候,浏览器将其转换为HTTPS请求,直接略过上述的HTTP请求和重定向,从而使得中间人攻击失效,规避风险。其大致流程如下:  图3:略过HTTP请求和重定向,直接发送HTTPS请求...
在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表格数据、上传影音文件等。如果文件体积比较大,或者网络条件不好时,上传的时间会比较长(要传输更多的报文,丢包重传的概率也更大),用户不能刷新页面,只能耐心等待请求完成。 下面从文件上传方式入手,整理大文件上传的思路,并给出了相关实例代码,由于PHP内置了比较方便的文件拆分和拼接方法,因此服务端代码使用PHP进行示例编写。 本文相关示例代码位于[github](https://github.com/tangxiangmin/JSMagic/tree/master/Upload)上,主要参考 - [聊聊大文件上传](https://blog.kazaff.me/2014/11/14/聊聊大文件上传/) - [大文件切割上传](https://blog.csdn.net/baochao95/article/details/52812876) ## 文件上传的几种方式 首先我们来看看文件上传的几种方式。 ### 普通表单上传 使用PHP来展示常规的表单上传是一个不错的选择。首先构建文件上传的表单,并指定表单的提交内容类型为`enctype="multipart/form-data"`,表明表单需要上传二进制数据。 ``` 复制代码 ``` 然后编写`index.php`上传文件接收代码,使用`move_uploaded_file`方法即可(php大法好...) ``` $imgName = 'IMG'.time().'.'.str_replace('image/','',$_FILES["myfile"]['type']); $fileName = 'upload/'.$imgName; // 移动上传文件至指定upload文件夹下,并根据返回值判断操作是否成功 if (move_uploaded_file($_FILES['myfile']['tmp_name'], $fileName)){ echo...
 ## 常见 MVC 框架双向绑定方案 实现数据绑定的做法有大致如下几种: - 发布者-订阅者模式(backbone.js) - 脏值检查(angular.js) - 数据劫持(vue.js) **发布者-订阅者模式:** 一般通过 sub, pub 的方式实现数据和视图的绑定监听,更新数据方式通常做法是 `vm.set('property', value)`,可能我们更希望通过 `vm.property = value `这种方式更新数据。 **脏值检查:** angular.js 是通过脏值检测的方式比对数据是否有变更,来决定是否更新视图,最简单的方式就是通过 `setInterval()` 定时轮询检测数据变动,angular 只有在指定的事件触发时进入脏值检测,大致如下: -...
## 什么是事件轮询 事件循环是 Node.js 处理非阻塞 I/O 操作的机制——尽管 JavaScript 是单线程处理的——当有可能的时候,它们会把操作转移到系统内核中去。 既然目前大多数内核都是多线程的,它们可在后台处理多种操作。当其中的一个操作完成的时候,内核通知 Node.js 将适合的回调函数添加到 *轮询* 队列中等待时机执行。我们在本文后面会进行详细介绍。 ## 事件轮询机制解析 当 Node.js 启动后,它会初始化事件轮询;处理已提供的输入脚本(或丢入 REPL,本文不涉及到),它可能会调用一些异步的 API、调度定时器,或者调用 `process.nextTick()`,然后开始处理事件循环。 下面的图表展示了事件循环操作顺序的简化概览。 ``` ┌───────────────────────────┐ ┌─>│ timers │ │ └─────────────┬─────────────┘...
一个应用程序通常会被划分为几个相互独立又彼此配合的模块, 浏览器也是如此。其实开发一个浏览器,它可以是单进程多线程的应用,也可以是使用 IPC 通信的多进程应用。 不同浏览器采用了不同的架构模式,这里研究以 **Chrome** 为代表的浏览器,它由多个进程组成,每个进程都有自己核心的职责,它们相互配合完成浏览器的整体功能,每个进程中又包含多个线程,一个进程内的多个线程也会协同工作,配合完成所在进程的职责。  ## 进程和线程 进程和线程都是操作系统的概念。 #### 进程(process) **进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,即进程是操作系统进行资源分配和独立运行的最小单元。** **当我们启动一个应用,计算机会至少创建一个进程,cpu会为进程分配一部分内存,应用的所有状态都会保存在这块内存中,应用也许还会创建多个线程来辅助工作,这些线程可以共享这部分内存中的数据。如果应用关闭,进程会被终结,操作系统会释放相关内存。** Mac 电脑可以在活动监视器中查看启动的进程数:  #### 线程(thread) - 进程内部的一个执行单元,是被系统独立调度和分派的基本单位。系统创建好进程后,实际上就启动执行了该进程的主执行线程 - 进程就像是一个有边界的生产厂间,而线程就像是厂间内的一个个员工,可以自己做自己的事情,也可以相互配合做同一件事情,所以**一个进程可以创建多个线程。** - 线程自己不需要系统重新分配资源,它与同属一个进程的其它线程共享当前进程所拥有的全部资源。 **PS:** **进程之间是不共享资源和地址空间的,所以不会存在太多的安全问题,而由于多个线程共享着相同的地址空间和资源,所以会存在线程之间有可能会恶意修改或者获取非授权数据等复杂的安全问题。** 而现在通用叫法**单线程与多线程,都是指在一个进程内的单和多。** >...
由于 `Python` 拥有众多的版本,以及不同模块也有不同的版本。同一模块不同版本有时需要的 `Python` 版本是不相同的,所以 `Python` 的版本控制显得尤为重要。 目前,常用的有以下三种工具进行 `Python` 版本管理: - [virtualenv](https://github.com/pypa/virtualenv) - [pyenv](https://github.com/pyenv/pyenv) - [anaconda](https://www.anaconda.com/) ## virtualenv `virtualenv` 用来为一个应用创建一套“隔离”的 `Python` 运行环境。 ### Install ```python pip3 install virtualenv ``` ###...
# 防抖动(Debounce)和节流阀(Throttle) 函数节流和函数防抖,两者都是优化高频率执行js代码的一种手段。常用于优化DOM 上有些事件是会频繁触发,比如mouseover、scroll、resize...。把 js 代码的执行次数控制在合理的范围,既能节省浏览器CPU资源,又能让页面浏览更加顺畅,不会因为js的执行而发生卡顿,这就是函数节流和函数防抖要做的事。 `函数节流`是指一定时间内js方法只跑一次。比如人的眨眼睛,就是一定时间内眨一次。这是函数节流最形象的解释。 `函数防抖`是指频繁触发的情况下,只有足够的空闲时间,才执行代码一次。比如生活中的坐公交,就是一定时间内,如果有人陆续刷卡上车,司机就不会开车。只有别人没刷卡了,司机才开车。 ## 函数节流 函数节流应用的实际场景,多数在监听页面元素滚动事件的时候会用到。因为滚动事件,是一个高频触发的事件。以下是监听页面元素滚动的示例代码: ``` var timer , canRun = true; function throttle(delay){ if(!canRun)return; canRun = false; clearTimeout(timer) timer = setTimeout(function(){ console.log(222) canRun...
先定义一份初始化,设置一个User类,其初始数据如下: ```js { arr: [ 1, 2 ], _id: 5ac5ee12a79131259413c40f, name: 'scy', __v: 0 } ``` 随后以初始数据为基,进行操作。 **1、向内嵌数组添加数据** 使用操作符 *$push*,向数组末尾添加数据 ,可重复 ```js //第一个参数是匹配条件 第二个参数是具体操作向user里面的arr末尾追加元素3 User.update({name:"scy"},{$push:{"arr":3}}); ``` `执行结果`: ```js { arr:...
## 什么是 GraphQL? [GraphQL](http://graphql.org/) 是 Fackbook 的一个开源项目,它是一种 API 查询语言,它其实是一种语言的规范,跟具体的实现是没有关系的。而且它是一层非常薄的数据抽象层,它既不会负责存储数据,也不会负责渲染数据;简单说就是一层 Proxy(代理),它把后端的数据做一些聚合、校验、判断,再返回给前端。对于前端来说,它是一种结构化的查询语言,类似于 JSON。相比 `RESTful API` 主要有以下特点: - 根据需要返回数据 - 一个请求获取多个资源 - 提供内省系统 ## GraphQL 与 RESTful 有什么区别? REST 与 GraphQL 都是服务端所承载的系统对外的服务接口,因此两者肯定是可以共存的,甚至可以共用一套 Authorization...