记录一些在学习过程中get到的新知识点。

e2e

e2e或者端到端(end-to-end)或者UI测试是一种测试方法,它用来测试一个应用从头到尾的流程是否和设计时候所想的一样。简而言之,它从一个用户的角度出发,认为整个系统都是一个黑箱,只有UI会暴露给用户。

具体链接看:http://sentsin.com/web/658.html

angular1.5

指令的transclude选项以及ng-transclude指令

transclude字面意思就是嵌入,也就是说你需不需要将你的指令内部的元素(注意不是指令的模板)嵌入到你的模板中去,默认是false。

Linux

ubuntu

  • 安装python模块:sudo apt-get updatesudo apt-get install python-websocket
  • 安装jdk:sudo apt-get install openjdk-8-jdk

命令行下载 google drive 中的文件

1
wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id=FILEID' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\1\n/p')&id=FILEID" -O FILENAME && rm -rf /tmp/cookies.txt

Note: 其中 FILEID 是 Google Drive 共享文件的ID,可以通过 右键->【获取共享链接】得到, FILENAME 随意

terminal

设置代理:

1
export ALL_PROXY=socks5://127.0.0.1:1080

Git

clone 某个分支:

1
git clone -b b1 https://github.com/...

clone 指定目录:

1
git clone https://github.com/... directory

git stash: 备份当前的工作区的内容,从最近的一次提交中读取相关内容,让工作区保证和上次提交的内容一致。同时,将当前的工作区内容保存到Git栈中。

git stash pop: 从Git栈中读取最近一次保存的内容,恢复工作区的相关内容。由于可能存在多个Stash的内容,所以用栈来管理,pop会从最近的一个stash中读取内容并恢复。

Node

debug:

1
2
3
4
5
6
在chrome中debug:
1. 安装插件node-inspector
npm install -g node-inspector
node-debug main.js

ps:如果不能正常安装node-inspector,把npm回退到5.3.0

单元测试

最简单的示例代码:

1
2
3
4
5
6
7
descript('模块名', function () {
it('期待的正确行为与结果', function () {
...测试代码

assert.equal({期待的结果}, {实际的结果});
})
})

Sinon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 入口:sinon对象(全局对象)
const sandbox = sinon.sandbox.create();

// 方法:stub,替代对象原生的方法,当调用之后直接返回给定的结果
sandbox.stub({对象}, '方法名').returns('直接返回的结果');

// 取消对方法的监视
sandbox.restore();

// 方法:spy,模拟一个函数,记录它被调用的参数以及调用次数
// 1. 创建一个匿名函数
var callback = sinon.spy();
PubSub.subscribe("message", callback);

PubSub.publishSync("message");

assertTrue(callback.called);

// 2. 包装一个已经存在的函数
sinon.spy(jQuery, 'ajax');

jQuery.getJSON("/some/resource");

assert(jQuery.ajax.calledOnce);

Vue

  • 引入css文件:@import './default.css'
  • vue componentkey 可以让页面重新渲染
  • 异步组件:Vue 允许以一个工厂函数的方式定义组件,这个工厂函数会异步解析组件定义'my-component': () => import('./my-async-component')
  • 路由懒加载:结合 Vue 的异步组件和 Webpack 的代码分割功能,轻松实现路由组件的懒加载。

Vue cli3

  • vue 使用了 sockjs-client/sockjs-node 保证我们在改完代码重新编译之后,能够通知浏览器重新加载变更结果。
    如果出现 WebSocket connection to 'ws://192.168.30.104:8080/sockjs-node/292/auzldzcy/websocket' failed: WebSocket is closed before the connection is established. 的警告,则有可能是开了全局代理

Vue 全局错误捕获

在vue项目中,用window.onerror 的方式捕获不到全局错误。
得用官方提供的 Vue.config.errorHandler 来捕获全局错误。

1
2
3
4
5
Vue.config.errorHandler = function (err, vm, info) {
// handle error
// `info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子
// 只在 2.2.0+ 可用
}

Note: 链接

npm

  • nrm: 快速切换npm源

js

  • Array数组排序方法sort的返回必须是两个值相减,不能是大于小于相比。因为排序似乎使用返回值和0,-1,1比较来排序的。
  • 错误跟踪插件:sentry
  • es6中module语法import用于静态文件导入(被 JavaScript 引擎静态分析),符合 ECMAScript 提案import() 语法可以完成动态加载

判断浏览器

1
2
3
4
5
6
7
8
9
10
11
12
const ua = window.navigator.userAgent;
const isIE = window.ActiveXObject !== undefined && ua.includes('MSIE');
const isIE11 = ua.includes('Trident') && ua.includes('rv:11.0');
const isEdge = ua.includes('Edge');
const isFirefox = ua.includes('Firefox');
const isChrome = (ua.includes('Chrome') && window.chrome) || ua.match('CriOS'); // 'CriOS'判断在ipad上是不是chrome
const isSafari = ua.includes('Safari') && ua.includes('Version');
const isQQBrower = ua.includes('QQBrowser');
const is360EE = ua.includes('360EE');
const is360SE = ua.includes('360SE');
const isSouGou = ua.includes('MetaSr');
const hasMine = navigator.mimeTypes['application/vnd.chromium.remoting-viewer']; // 360浏览器判断(ps: 不确定)

webpack

  • 代码分割功能:当涉及到动态代码拆分时,webpack 提供了两个类似的技术。对于动态导入,第一种,也是推荐选择的方式是,使用符合 ECMAScript 提案 的 import() 语法。import('path/to/module') -> Promise

PM2

PM2是node进程管理工具,可以利用它来简化很多node应用管理的繁琐任务,如性能监控、自动重启、负载均衡等,而且使用非常简单。

参考:PM2实用入门指南

npm script

npm 脚本有一个非常强大的功能,就是可以使用 npm 的内部变量。
例如npm_package_version能获取到项目版本信息。

然后,npm 脚本还可以通过npm_config_前缀,拿到 npm 的配置变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// package.json
{
"scripts": {
"build": "node build/build.js",
"build:axios": "npm_config_axios=true npm run build",
}
}

// webpack.config.js
{
resolve: {
alias: {
'~services': process.env.npm_config_axios ? resolve('src/services-axios') : resolve('src/services')
}
},
}

正则

Safari 不支持正则反向匹配((?<=\d))

数据埋点 + 跨域

为什么通常在发送数据埋点请求的时候使用的是 1x1 像素的透明 gif 图片?

利用空白gif或1x1 px的img是互联网广告或网站监测方面常用的手段,简单、安全、相比PNG/JPG体积小,1px 透明图,对网页内容的影响几乎没有影响,这种请求用在很多地方,比如浏览、点击、热点、心跳、ID颁发等等,

  • 避免跨域(img 天然支持跨域);没有跨域问题,一般这种上报数据,代码要写通用的;(排除ajax)
  • 不会阻塞页面加载,影响用户的体验,只要new Image对象就好了;(排除JS/CSS文件资源方式上报)一般情况下也不需要append到DOM中,通过它的onerror和onload事件来检测发送状态。
  • 在所有图片中,体积最小;(比较PNG/JPG)GIF的最低合法体积最小(最小的BMP文件需要74个字节,PNG需要67个字节,而合法的GIF,只需要43个字节)
  • 触发 GET 请求之后不需要获取和处理数据、服务器也不需要发送数据
  • 图片请求不占用 Ajax 请求限额,相比 XMLHttpRequest 对象发送 GET 请求,性能上更好

除了img 天然支持跨域之外,script 标签也是支持跨域的,这也是 jsonp 跨域方案的基础。

注释

变量是个对象,带属性

1
2
3
4
5
6
7
/**
* Assign the project to an employee.
* @param {Object} employee - The employee who is responsible for the project.
* @param {string} employee.name - The name of the employee.
* @param {string} employee.department - The employee's department.
*/
Project.prototype.assign = function(employee) { // ...};

map标签

今天看到一段代码:

1
2
3
4
5
6
7
<img src="planets.jpg" border="0" usemap="#planetmap" alt="Planets" />

<map name="planetmap" id="planetmap">
<area shape="circle" coords="180,139,14" href ="venus.html" alt="Venus" />
<area shape="circle" coords="129,161,10" href ="mercur.html" alt="Mercury" />
<area shape="rect" coords="0,0,110,260" href ="sun.html" alt="Sun" />
</map>

忽然发现自己对map标签不是很熟悉。然后就查了下。发现这是一个挺有意思的标签。

其实这个标签的功能是在图片的区域内切割一部分来实现点击弹出新页面的功能。上面代码中area标签中的shape和coords属性分别用来定义区域的形状和可点击区域(对鼠标敏感的区域)的坐标。而href属性就是用来指定新页面的URL,和a标签的href具有相同的意义。同时,area也具有target属性。

map标签需要结合img标签中的usemap属性来使用。usemap中的#planetmap指定了要使用的map的id。

注意<img> 中的 usemap 属性可引用 <map> 中的 id 或 name 属性(由浏览器决定),所以我们需要同时向 <map> 添加 id 和 name 两个属性。

爬虫协议

如果你希望你的网站所有内容都被百度爬取,那么只要不写 rebots.txt 就行,