Skip to content

Latest commit

 

History

History
4157 lines (3439 loc) · 250 KB

随笔.md

File metadata and controls

4157 lines (3439 loc) · 250 KB

理解能力的增强也会提升记忆力,因为记忆的基础就是大脑根据信息组织意义的能力。 请不要忘记自己最初的梦想。十年后的你,一定会感激现在拼命努力学习的自己。

真正的知识不分文理,对知识的渴望也不是简单的文理所能区分

我觉得所谓的 判断神学是错误的,并不影响 其本身的存在。哲学定义存在就是不依赖人的意志不以人的意志为转移客观世界,是其价值在宇宙中的自我体现,人类只是发现了他。可能存在喜欢和不喜欢认可与不认可。和又有什么关系呢?

这是最好的时代,这是最坏的时代。我们永远在享受人类最新的文明,我们也在承受进步带来的恶果。因为,当下的我们存在于世,我们就是此时的最新。(2018年4月27日 11:04:52)

几年前刚上大学的时候,我就看过这篇文章,但是那时的我看不懂,我没有敢写出什么评论。如今我觉得我依旧懵懂,看着这一句句,一字字,我的眼眶湿润了。我不知道该如何描述我现在的心情,但是我从心底里是快乐的。我觉得 神学 就像是 对人类的一种保护,对于大大超出我们理解和认知范围的一个自我保护机制。如果对于我们接受不了,理解不到的事物,放任不管,也就没有后人不断去质疑、打破,提出新的观点和证实。我想可能我们的文明是不会像现在这样灿烂、辉煌。致以我最崇高的敬意,向这些 宝贵的 论述 以及提出他们的人~

说话七误区

1.流言蜚语。背后说坏话 2.评判。自己的活法,对自己的选择负责,站在自己的立场评判他人,有时候并不够格。 3.消极。演讲者举了一个例子:有一天他对自己的妈妈说:“今天是十月一号”,没想到妈妈回应到:“我知道 但这不可怕吗?” 4.抱怨。抱怨是病毒性悲催,它像流感病毒一样在人与人之间不断传播,但它并不会传播光明,只会毁坏人们的好心情。 5.借口。把错误推卸到别人的身上,只会让自己显得不可靠不可信。 6.浮夸和说谎。浮夸到了一定程度就变成了说谎,说谎的人没人会喜欢。 7.固执己见。当人们把事实和意见混淆,用自己的意见来强迫对方时,听者一定会产生抵触情绪。

“良言一句三冬暖”的道理谁都懂,但能做到的却少之又少。 情商高绝不是世故圆滑阳奉阴违

而是以真诚待人,用恰到好处的行为,为他人着`,也对自己负责,为人谦和好相处,但也不失自己的原则

Fundebug

(https://www.fundebug.com/project/integrate) 接入插件

  1. fundebug.js插入您网页的<head>标签 参考文档 复制
<script src="https://js.fundebug.cn/fundebug.0.3.6.min.js" apikey="70a045c01dc0e4fe4de20634e58cb4bed2d62b0f3e49c60d7b0200328f0f7be7"></script>

此代码已经包含了您的apikey, 可直接复制到您的代码中

宇宙银河、星河灿烂

你看时间对于我们何其珍贵,从幼稚的孩童到步入婚姻殿堂仿佛也只转瞬之间。每个人在尘世都有那么一段注定的姻缘,我们反复确认,耐心寻找,只为了不负这一世光阴。经历了重重波澜,两个可心的人儿,终于手牵手,信誓旦旦的站在这里。 虽然我们每个人在这天地间不过沧海一粟,但是你看那宇宙中的银河,浩淼、璀璨.我要把对你的爱赋予意义,洒进星河灿烂。不管经历千世万世,只要天地不灭、星辰恒久,我的爱亦不悔!

关于男女所处社会地位的思考(2018年3月8日 14:31:55)

(https://mp.weixin.qq.com/s/cTYgLH3TGpDK5vlweVTTSg) 因为畸形的计划生育政策,导致男女比例严重失调。又因为 男女平等,女人又可以接受和男人一样的教育,女孩子们珍惜这几千年以来的从未有过的大好时机,在太平盛世,她们努力、刻苦,不敢有一丝懈怠自己,几乎所有的培训班里都有认真听讲,奋笔疾书的女孩子的身影,她们渴望知识胜过对男人的渴望!她们左手纸笔书本,右手香水口红,高跟与红唇是她们自信的体现。这使得她们慢慢蜕变,优雅、强大起来。

在这个不需要战争与蛮力的和平年代,在这个崇拜智慧与美的多元时代,在这个需要素质与耐心的包容时代,在这个强调细节与认真的进步时代。女人的优点被一点一点的放大,像一朵朵散发着不同芬芳的瑰丽花朵,在这个时代与男人们博弈。

虽然过去的男女不平等确实很严重,但太过激烈的社会发展转型,也让很多永远活在上个世纪的一些人无法接受延续了几千年的传统文化。90后的不婚主义,社会矛盾 这使得本来在

我要在晚上进入她的作用域,PUSH and POP,并留下封装过的继承了自己遗传基因多态的代码

(2018年2月2日 10:46:22) #

博客部署远程仓库

  • github新建仓库
  • 进入博客修改URL
  • 编写blog 。。。省略
  • 部署

</>

Promise的用法简单入门(掘金文章分享)

(2018年3月13日 10:38:36)(https://juejin.im/post/5aa1fce051882555677e21aa)

JS知识点

-Array对象属性 -类数组对象

Array对象属性

方法:
concat() // 连接两个或更多的数组,并返回结果。
copyWithin() // 从数组的指定位置拷贝元素到数组的另一个指定位置中。

什么叫做类数组对象

JavaScript中,数组是一个特殊的对象,其property名为正整数,且其length属性会随着数组成员的增减而发生变化,同时又从Array构造函数中继承了一些用于进行数组操作的方法。

关于javascript中apply()和call()方法的区别

(http://www.cnblogs.com/fighting_cp/archive/2010/09/20/1831844.html) (http://www.cnblogs.com/afrog/p/4279066.html)

object-assign

(https://www.npmjs.com/package/object.assign) This package implements the es shim API interface. It works in an ES3-supported environment and complies with the spec. In an ES6 environment, it will also work properly with Symbols. 译:这个包实现了es shim API接口。它在一个es3支持的环境中工作,并符合规范。在ES6环境中,它也能正确地使用符号。

Takes a minimum of 2 arguments: target and source. Takes a variable sized list of source arguments - at least 1, as many as you want. Throws a TypeError if thetargetargument isnullorundefined. 译:至少需要两个参数:target、source。获取一个可变大小的源参数列表——至少1个,如您想要的那样多。如果目标对象是无定义的,则抛出一个类型错误。

Most common usage(常见用法): <script> var assign = require('object.assign').getPolyfill(); //returns native method if compliant /or/ var assign = require('object.assign/polyfill')(); //returns native method if compliant

  ~ function () {
    var assert = require('assert');
    //Multiple sources!
    var target = {
      a: true
    };
    var source1 = {
      b: true
    };
    var source2 = {
      c: true
    };
    var sourceN = {
      n: true
    };
    var expected = {
      a: true,
      b: true,
      c: true,
      n: true
    };
    assign(target, source1, source2, sourceN);
    assert.deepEqual(target, expected); //AWESOME!
  }

  ~ function () {
    var target = {
      a: true,
      b: true,
      c: true
    };
    var source1 = {
      c: false,
      d: false
    };
    var sourceN = {
      e: false
    };
    var assigned = assign(target, source1, sourceN);

    assert.equal(target, assigned); //returns the target object
    assert.deepEqual(assigned, {
      a: true,
      b: true,
      c: false,
      d: false,
      e: false
    });
  }

  ~ function () {
    /* when Object.assign is not present */
    delete Object.assign;
    var shimmedAssign = require('object.assign').shim();
    /*or*/
    var shimmedAssign = require('object.assign/shim')();
    assert.equal(shimmedAssign, assign);
    var target = {
      a: true,
      b: true,
      c: true
    };
    var source = {
      c: false,
      d: false,
      e: false
    };
    var assigned = assign(target, source);
    assert.deepEqual(Object.assign(target, source), assign(target, source));
  }

  ~ function () {
    /*when Object.assign is present*/
    var shimmedAssign = require('object.assign').shim();
    assert.equal(shimmedAssign, Object.assign);
    var target = {
      a: true,
      b: true,
      c: true
    };
    var source = {
      c: false,
      d: false,
      e: false
    };
    assert.deepEqual(Object.assign(target, source), assign(target, source));
  }
`</script>`

ES5和ES6数组遍历方法详解

(https://segmentfault.com/a/1190000010203337)(2018年2月2日 10:17:51)

在ES5中常用的10种数组遍历方法:

  • 1、原始的for循环语句
  • 2、Array.prototype.forEach数组对象内置方法
  • 3、Array.prototype.map数组对象内置方法
  • 4、Array.prototype.filter数组对象内置方法
  • 5、Array.prototype.reduce数组对象内置方法
  • 6、Array.prototype.some数组对象内置方法
  • 7、Array.prototype.every数组对象内置方法
  • 8、Array.prototype.indexOf数组对象内置方法
  • 9、Array.prototype.lastIndexOf数组对象内置方法
  • 10、for...in循环语句

ES6中新增加了一种:

  • 1.for...of循环语句

数组内置方法Array.prototype.forEach 代码解读forEach方法最大的好处就是便于使用,而且不用定义额外的参数变量,但是从效率以及性能角度来说它是劣于原始for循环的,而且也不能强制return结束循环,原因如下: forEach循环一看就是通过回调函数来提供参数的,而回调函数在JS中是闭包的一种,闭包的作用是用来生成私有作用域的,所以,每一个回调函数都是一个独立的作用域,都拥有自己独立的存储空间,互不影响,而且内部变量不及时释放,这也就是为什么在能不用闭包的情况下就不要用闭包的原因,而在闭包中return的话,也只是在当前回调函数中返回了,可是forEach中的其他的回调函数(闭包)仍然存在,所以,导致return没办法结束循环的。下面写一个forEach循环实现例子供大家参考理解:

数组内置方法Array.prototype.map 代码解读mapforEach不同,在forEachreturn语句是没有任何效果的,而map可以改变当前循环的值,并且最终会返回一个新的被改变过值之后的数组(map如果不用return就和forEach一样了),由于这个特性,map一般用来处理需要修改某一个数组的值mapforEach在其他的方面都是一样的,也不能return结束循环等特性,下面写一个map循环实现的例子供大家参考理解:

数组内置方法Array.prototype.filter 代码解读filtermap不同,map目的是为了改变值,而filter目的是为了去掉不要的值,在循环的时候如果返回的是false那么就表示本次循环的不添加该值,返回true则相反是表示要添加到新建的数组中,下面写一个filter循环实现例子供大家参考:

数组内置方法Array.prototype.reduce 代码解读reduce的不同之处在于累加,和其他几个内置方法不同的地方,它的第二个参数不是this对象,而是初始累加值(如果不设置的话数组会乱掉),而且回调函数的个数也不同,比其他的多了一个,而且还在开始时多加了一个参数,第一个参数记录的是上一次循环的累加值,下面写一个reduce循环实现例子供大家参考:

小结:对于以上8个数组的内置方法,forEach方法仅仅只是为了循环,并不可以帮你做额外的事情;map方法相当于在循环的时候你告诉数组当前遍历的这个值需要改成什么样,那么它就会最后给什么样的数组;filter方法相当于在循环的时候数组遍历一个个对象,并问你这个是不是你要找的值,如果你说是,他就会给你返回一个到新的数组中,不是他就会剔除;reduce方法相当于循环遍历对象做统计(累加或者累减之类的);some和every方法相当于在遍历的时候拿着一个个对象问你这个是不是你找的,只要你说了一遍是,那么他就会给你分别返回的是true和false;indexOf和lastIndexOf方法相当于你告诉它你要找什么值,找到之后立马返回给你它的门牌号。

JS DateFormat

(http://blog.csdn.net/vbangle/article/details/5643091)

JSON用法(stringify parse)

JSON.stringify 把一个对象转换成json字符串, JSON.parse 把一个json字符串解析成对象。

异步加载

AMD提前执行,CMD延迟执行 || CMD推崇依赖就近,AMD推崇依赖前置 AMD异步加载,所有加载请求提前执行,推崇依赖前置 || CMD同步加载,所有加载请求延迟执行,推崇依赖就近; AMD:{ 优:速度快, 劣:浪费资源, 特点:预加载所有模块,直到使用时才执行 } CMD:{ 优:按需加载, 劣:性能较差, 特点:直到使用时才定义,并加载模块 } YUI3模块机制,上线前压制,把互相依赖模块压缩在一个文件 RequireJS AMD(异步模块定义) SeaJS CMD(通用模块定义?同步模块定义)

import

import语句用于导入由另一个模块导出的绑定。

语法

import defaultExport from "module-name"; import * as name from "module-name"; import { export } from "module-name"; import { export as alias } from "module-name"; import { export1 , export2 } from "module-name"; import { export1 , export2 as alias2 , [...] } from "module-name"; import defaultExport, { export [ , [...] ] } from "module-name"; import defaultExport, * as name from "module-name"; import "module-name";

defaultExport 将引用模块默认导出的名称。 module-name 要导入的模块。这通常是包含模块的.js文件的相对或绝对路径名,不包括.js扩展名。某些打包工具可以允许或要求使用该扩展;检查你的环境。只允许单引号和双引号的字符串。 name 引用时将用作一种命名空间的模块对象的名称。 export, exportN 要导入的导出名称。

描述

name参数是“模块对象”的名称,它将用一种名称空间来引用导出。导出参数指定单个命名导出,而import * as name语法导入所有导出。以下示例阐明该语法。 导入整个模块的内容 这将myModule插入当前作用域,其中包含来自位于/modules/my-module.js文件中导出的所有模块。

import * as myModule from '/modules/my-module.js'; 在这里,访问导出意味着使用模块名称(在这种情况下为“myModule”)作为命名空间。例如,如果上面导入的模块包含一个doAllTheAmazingThings(),你可以这样调用: myModule.doAllTheAmazingThings();

导入单个导出 给定一个名为myExport的对象或值,它已经从模块my-module导出(因为整个模块被导出)或显式地导出(使用export语句),将myExport插入当前作用域。

import {myExport} from '/modules/my-module.js';

导入多个导出 这将foo和bar插入当前作用域。

import {foo, bar} from '/modules/my-module.js';

导入带有别名的导出(导入时重命名导出的模块作用域名) 导入时可以重命名导出。例如,将shortName插入当前作用域。

import {reallyReallyLongModuleExportName as shortName} from '/modules/my-module.js';

导入时重命名多个导出 使用别名导入模块的多个导出。

import { reallyReallyLongModuleMemberName as shortName, anotherLongModuleName as short } from "my-module";

导入默认值 可以使用默认export(无论是对象,函数,类等)。然后可以使用import语句来导入这样的默认值。

最简单版本,直接导入默认值:

import myDefault from "my-module";

也可以使用默认语法与上述(命名空间导入或命名导入)。在这种情况下,默认导入将必须首先声明。 例如:

import myDefault, * as myModule from "my-module"; // myModule used as a namespace

TypeScript(手册指南)

基础类型

  • 布尔(boolean)
  • 数字(number)
  • 字符串(string/模板字符串)
  • 数组(array)
  • 元组(Tuple) 元组类型 允许 表示一个已知元素数量类型数组 ,各元素的类型不必相同。 比如,你可以定义一对值分别为stringnumber类型的元组。 引入联合类型概念
  • 枚举(enum)
  • Any
  • Void
  • NullUndefined
  • Never
  • 类型断言

变量声明

  • 作用域规则
  • 变量捕获
  • 块作用域
  • 暂时性死区
  • 重定义及屏蔽
  • 块级作用域变量的获取
  • 解构
    • 解构数组
    • 对象解构
    • 属性重命名
    • 默认值
    • 函数声明
    • 展开

接口(interface)

  • 介绍
  • 接口初探
  • 可选属性(?)
  • 只读属性(readonly x: number;)
    • readonly vs const 变量使用const; 属性使用readonly
  • 额外 属性 检查 不符合 接口定义 的 参数名 报错提示
    • 绕开这些检查方法1 使用 (类型断言:(as))

    let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);

    • 方法2:(字符串索引签名 [propName: string]: any;)
  • 函数类型
  • 可索引的类型

class类型

  • 实现接口(implements)
  • 类 静态部分 与 实例部分 区别
  • 继承接口(extends) 一个接口 可 继承 多个接口, 创建 多个接口 的 合成接口.
  • 混合类型
  • 接口继承类

  • 介绍
  • 继承(extends)
  • 公共/私有/受保护的 修饰符(默认为public/私有private/受保护的protected) private: 当成员被标记成 private,它就不能在 声明它的类 的 外部访问。

TypeScript(慕课视频学习笔记)

(慕课网视频)(https://www.imooc.com/learn/763)

  • 课程须知 1、对javascript基础知识已经掌握。 PS: 对ES6的掌握程度越深越好

  • 老师告诉你能学到什么? 1、TypeScript语言中的字符串新特性 2、TypeScript语言中的变量和参数新特性 3、TypeScript语言中的函数新特性 4、TypeScript语言中的匿名函数(箭头函数表达式) 5、TypeScript语言中的for of循环 6、TypeScript语言中的面向对象特性

1-1 TS介绍

1-2 TS课程内容介绍

  • 学TS好处
  • 安装TS开发环境
  • TS概念、语法和特性介绍

前置知识

  • 理解ES5、ES6、JS、TS之间的概念关系
  • 基础JS知识

2-1 TS优势

  • ES6规范
  • IDE支持(集成开发环境 integrated development environment)
  • 类型检查
  • 语法提示(类、变量、方法、关键字)
  • 代码重构(所有 变量、方法、文件 名的调用和引用自动修改)
  • Angular2的开发语言

3-1 搭建TS开发环境--在线compiler(编译器)

  • 什么是compiler?为什么需要compiler?
  • 在线compiler开发

3-2 搭建TS开发环境--本地compiler(编译器)

  • 本地compiler开发
  • 安装TSC(TypeScript Compiler)
  • IDE配置自动编译(视频中介绍WebStorm,在Chrome浏览器书签有VSCode for TSC)

4-1 TS字符串新特性(ES6涉及模板字符串)

  • 多行字符串
  • 模板字符串(``)
  • 自动拆分字符串(使用字符串模板调用方法,自动拆分字符串模板表达式里面的值,并赋值给被调用方法的参数) Method(function)string ${variable}, string ${functionName()} // 英文半角 圆括号"()" 用"``"代替 PS:概述就是 Method接受`参数`视`模板字符串`而定,`第一个参数`默认是以`模板字符串`里的`变量`为分隔符的`数组`形式的`字符串`,后面的参数依次是`模板字符串`里的`变量`, 有几个`变量`就可写多少接受`参数`.

5-1 TS参数新特性-参数类型

  • 参数类型 在参数名称后面使用冒号来指定参数类型。可声明的类型有变量函数函数形参(函数变量) 类型值包括但不限于: any(代表所有类型的variable)、string、number、boolean、void(只用来声明方法返回值) 视频讲解: ①如何声明类型; ②TS类型推荐机制; ③五种基本类型; ④可声明类型的位置; ⑤自定义类型interface class生成自定义类型.

  • PS:可自行拓展其他声明类型

5-2 TS参数新特性-参数默认值(ES6涉及)

  • 默认参数 在参数声明后面用等号来指定参数的默认值

5-3 TS参数新特性-可选参数

  • 可选参数 在方法参数声明后面用问号标明此参数为可选参数

6-1 TS函数新特性-TypeScript-Rest and Spread操作符(ES6拓展运算符)

  • 传参时(...[] || ...{})

6-2 TS函数新特性-TypeScript-generator函数(ES6规范部分yield)

  • 控制函数执行过程,手工暂停和恢复代码执行,类似断点. function* somefun(){ console.log("start"); yield; console.log("finish") }
  • PS: ①方法需要变量引用; (var 关键字=function; 需要注意function后加*)(var xxx = somefun();\xxx.next()) ②下一次调用需要.next()其包含两个字段value:any,done:boolean

6-3 TS函数新特性-destructuring析构表达式(解构赋值)

  • destructuring析构表达式 通过表达式将对象或数组拆解成任意数量的变量
  • 解构赋值拓展运算符混合使用

7-1 TS表达式与循环-箭头表达式(ES6涉及)

  • 箭头表达式 用来声明匿名函数,消除传统匿名函数this指针问题

7-2 TS表达式与循环-for of循环(ES6涉及)

  • forEach(),for infor of forEach(): 自动跳过/忽略属性值、不识别break关键字; for in: 打印 数组index和 对象key, 遍历数组时会把属性也遍历出来; for of: 类似forEach()遍历对象、数组的值, 支持break关键字, 另:其忽略数组的 属性值key.

8-1 面向对象特性-TS-类

  • 类(Class) 类是TypeScript核心,使用TS开发,大部分代码都写在类里面。 介绍:
  • 类的定义 (构造函数)(访问控制符 公共public 私有provate 受保护的protected) class Person { property key: value; method (){ console.log('string') }; } 实例化new关键字
  • 构造函数(类的特殊方法,实例化的时候只被调用一次) constructor(public声明变量)
  • 类的继承(extendssuper) extends继承之前 类 的 属性 和 方法; super用法: ①子类调用父类构造函数;super(传参) ②子类调用父类其他方法;super.父类方法() 属性方法(视频作者引入了private访问控制符的作用)

PS:类里面就是属性方法

8-2 面向对象特性-TS-泛型(generic)

  • 泛型(generic) 参数化的类型,一般用来限制集合的内容

    var workers: Array<Person(泛型)> = [];

8-3 面向对象特性-TS-接口(interface/implements)

  • 声明接口(interface:声明接口/) 用来建立某种代码约定,使得其它开发者在调用某个方法创建新类时必须遵循接口所定义的代码约定。 用法①: 函数方法 参数 的类型声明(检查传参是否满足接口定义的所有属性); 用法②: 接口声明方法(类 实现 接口,必须包含接口里的方法); class Xxx implements interfaceName {}
  • 类的实现(implements:声明class实现接口)

8-4 面向对象特性-TS-模块(export/import)

  • 模块(Module) 模块 帮助开发者将 代码 分割为 可重用 的单元。开发者可自行决定将模块中的哪些资源(类、方法、变量)暴露出去供外部使用,哪些资源只在模块内使用。 模块在TS中概念:一个文件就是一个模块。 a模块抛出(export)在b模块引入(import)

8-5 面向对象特性-TS-注解(annotation)

  • 注解(annotation) 为程序的元素(类、方法、变量)加上更直观明了的说明,这些说明信息与程序业务逻辑无关,而是提供指定工具或框架使用的。

8-5 面向对象特性-TS-类型定义文件(*.d.ts)

  • 类型定义文件 用来帮助开发者在TS中使用已有的JS库、工具包。如:JQuery

9 TS-总结

  • 介绍了TS基本概念优势
  • 介绍了如何搭建TS开发环境
  • 介绍了TS语法特性

名词解释(UI GUI CLI API)

UI:user interface GUI:graphical user interface CLI:command line interface API:application interface

前端知识点总结(框架和库的区别 Vue概述)

(https://mp.weixin.qq.com/s/6Mo5csEDVKMq4-v6Yi8ZPQ)(作者:楷楷 https://www.hazyzh.com/b/180211145458) -1.框架和库的区别 -2.Vue概述

1.框架和库的区别

框架(framework):有着自己的语法特点、都有对应的各个模块。 (library):专注于一点。

框架的好处:

  • 提高代码的质量,开发速度
  • 提高代码的复用率
  • 降低模块之间的耦合度(高内聚低耦合)

思维模式的转换:从操作DOM的思维模式 切换到以数据为主。

2.Vue概述

1、what 是一个渐进式的构建用户界面的js框架 2、where 小到的简单的表单处理,大到复杂的数据操作比较频繁的单页面应用程序 3、why 中文文档 上手容易 体积小 组件开发 可读性、可维护性 4、how 工作方式:可以通过丰富的指令扩展模板,可以通过各种各样的插件来增强功能

搭建环境 方式1:vue-cli 方式2:cdn引入

3.Vue基础知识

1、双大括号(插值表达式) // 指令 2、循环指令(v-for) 3、选择指令(v-if/v-else-if/v-else) 4、事件绑定(v-on/@) 5、属性绑定(v-bind/:) 6、双向数据绑定(v-model 必须为表单元素)

4.组件化

组件:组件就是可被反复使用的,带有特定功能的视图。

Vue响应式原理

(https://juejin.im/post/5adf0085518825673123da9a)

如何在 Vue.js 中使用第三方库

(https://juejin.im/entry/58febbcba0bb9f0065cee1d9) 2018年1月20日 13:49:41

Vue复习笔记#

http://blog.csdn.net/sinat_17775997/article/details/52536010 安装 # 全局安装 cnpm淘宝镜像 $ npm install -g cnpm --registry=https://registry.npm.taobao.org

# 全局安装 vue-cli
$ cnpm install -g vue-cli

# 创建一个基于 "webpack" 模板的新项目
$ vue init webpack my-project

# 安装依赖,走你
$ cd my-project
$ cnpm install
$ npm run dev

#父向子组件传参#

例子:App.vue为父,引入componetA组件之后,则可以在template中使用标签(注意驼峰写法要改成componet-a写法,因为html对大小写不敏感,componenta与componentA对于它来说是一样的,不好区分,所以使用小写-小写这种写法)。而子组件componetA中,声明props参数’msgfromfa’之后,就可以收到父向子组件传的参数了。例子中将msgfromfa显示在<p>标签中。

<!-- App.vue中 -->
<component-a msgfromfa="(Just Say U Love Me)"></component-a>
import componentA from './components/componentA'
export default {
  new Vue({
      components: {
        componentA
      }
  })
}

#子组件向父传参(.$emit)# 用法:vm.$emit( event, […args] ),触发当前实例上的事件。附加参数都会传给监听器回调。 例子:App.vue中component-a绑定了自定义事件”child-say”。子组件componentA中,单击按钮后触发”child-say”事件,并传参msg给父组件。父组件中listenToMyBoy方法把msg赋值给childWords,显示在<p>标签中。

<!-- App.vue中 -->

<p>Do you like me? {{childWords}}</p>
<component-a msgfromfa="(Just Say U Love Me)" v-on:child-say="listenToMyBoy"></component-a>

`import componentA from './components/componentA'
export default {
  new Vue({
    data: function () {
        return {
          childWords: ""
        }
    },
    components: {
      componentA
    },
    methods: {
      listenToMyBoy: function (msg){
        this.childWords = msg
      }
    }
  })
}`

<!-- componentA.vue中 -->

<button v-on:click="onClickMe">like!</button>
`import componentA from './components/componentA'
export default {
  data: function () {
      return {
        msg: 'I like you!'
      }
  },
  methods: {
    onClickMe: function(){
      this.$emit('child-say',this.msg);
    }
  }
}`

#子组件向父传参(.$dispatch)# 用法:vm.$dispatch( event, […args] ),派发事件,首先在实例上触发它,然后沿着父链向上冒泡在触发一个监听器后停止。 例子:App.vue中events中注册”child-say”事件。子组件componentA中,单击按钮后触发”child-say”事件,并传参msg给父组件。父组件中”child-say”方法把msg赋值给childWords,显示在<p>标签中。

<!-- App.vue中 -->

iview 中 render函数内的on事件

(https://segmentfault.com/q/1010000009764136) 阻止冒泡: i-switch组件的on-change事件处理器里面,有一个默认的变量event: event.stopPropagation();

Vue2.x中的Render函数详解

(http://www.jb51.net/article/115009.htm) Vue2.x版本中VNode属性: tag:当前节点标签名, data:当前节点数据对象, children:子节点数组, text:当前节点文本, elm:当前虚拟节点对应的真实dom节点, ns:节点的namespace( 名称空间), content:编译作用域, functionalContext:函数化组件的作用域,即全局上下文, key:节点标识,有利于patch优化, componentOptions:创建组件实例时的options, child:当前节点对应的组件实例, parent:组件的占位节点, raw:原始html, isStatic:是否是静态节点, isRootInsert:是否作为跟节点插入,若被包裹的节点,该属性值为false, isComment:是否为注释节点, isCloned:是否为克隆节点, isOnce:是否只改变(渲染)一次,或是否有v-once指令;

Angular CLI(慕课视频)

(https://www.imooc.com/video/15152)

1-1课程简介

  • 学习目标
    • Angular CLI 主要命令 参数配置
    • 使用Angular CLI进行项目构建
      • 项目构建
        • 开发
          • 项目(整体项目解构)
          • 组件(每个功能模块)
        • 打包(提速/安全)
        • 测试
  • 学习重点
    • 理解开发解构运行解构联系与区别(映射、编译拷贝)
    • 能够使用 Angular CLI 进行项目构建
  • 课程tips

1-2 Angular CLI 简介

  • 功能简介
    • 快速创建ng (new generate)
    • CLI开发同步(serve)
    • 测试/打包(test/build)

2-1 Angular CLI 安装

  • 淘宝镜像
  • cnpm install -g @angular/cli

2-2 Hello Angular CLI

  • 学习目标
    • 使用Angular CLI 创建项目并运行
      • ng new my-app(--skip-install)
      • cd my-app
      • (cnpm install 使用淘宝镜像)
      • ng serve
    • 分析项目目录结构

3-1 Ng new 主要功能和使用方法

  • 开发辅助(--dry-run)
    • --dry-run显示创建项目的所有文件但不进行硬盘操作
    • -si(--skip-install)
    • --routing()
  • 修改项目默认值(--perfix)

3-2 Ng serve 主要功能和使用方法

  • 修改端口 ng serve --port 4201(修改运行端口)
  • 代码同步过程

3-3 Ng generate 主要功能和使用方法

  • component生成器
    • ng g c name : 创建新的组件 ng g component test(默认注册) 已在app.module进行了update 在组件引用即可
  • service 生成注册
    • ng g s name -m xx.ts :在某个组件注册服务 ng g service test -m(默认不注册 -m注册 ) 进入生成的service文件,定义构造函数方法 在app.component.ts引入该ts文件

3-4 Ng test 主要功能和使用方法

3-5 Ng build 主要功能和使用方法

  • ng build 编译到dist文件夹
  • UNIX CLI命令行
    • ls -alh [dist/(文件夹名)]
    • du -h dist/ (显示文件夹大小)
  • aot 预编译技术
    • ng build --aot
  • prod
    • ng build --prod

4-1 Angular-cli 总结

  • 课程回顾
    • 创建项目快速上手
    • 学习常用命令进行开发

Angular2(快速入门)

1-1 起源

  • 内容纲要
    • 历史 2009年MiskoAdam业余时间创造
    • 核心概念
    • 快速上手

1-2 痛点

  • 12年6月发布 1.0.0 正式版推出
    • 双向绑定
    • 依赖注入
    • 指令
  • 1.3.x版本放弃IE8支持
    • 推出单词绑定语法
  • 1.5.x增加类似组件式书写体验
    • 主要为过渡Angular2做铺垫
    • 学习曲线陡峭/曲折,似懂非懂,懵懵懂懂
  • 1.x困境
    • 性能问题 脏检查数据更新(数据量增加,导致卡顿严重)
    • 落后当前web发展理念(组件开发方式)
    • 对手机端支持不够友好(性能问题/笨重耗资源)

1-3 ng2萌生

  • 14年3月,官方博客提及新Ng开发计划
  • 14年9月下旬NG-Europe大会亮相
  • 由AngularJS更名为Angular
  • Ng2新特性
    • 移除controller+$scope设计,改用组件式开发
    • 性能(渲染,变化监测效率更高)
    • 优先移动应用(Angular Mobile Toolkit)
    • 贴合未来标准(ES6/7、WebComponent)
  • 无缝升级方案-UpgradeAdapter

总结

历史起源、推出背景、简单介绍重要特性

2 核心概念

  • ★组件(Components)(核心,其他概念为延伸,都为组件提供服务)
  • 元数据(Metadata)
  • 模板(Templates)
  • 数据绑定(Data binding)
  • 服务(Services)
  • 指令(Directives)
  • 依赖注入(Dependency Injection)
  • 模块(Modules)

2-1 核心概念-组件(Components)及组建树(装饰器、元数据)

  • 组件
    • JS
    • HTML
    • CSS
  • 组件通讯机制
    • 父组件 输入接口
      • 子组件 输出接口
      • 子组件
  • 生命周期
    • Constructor 构造器初始化
    • OnChanges 第一次触发数据变化钩子
    • OnInit 组件初始化
    • OnChanges 运行期间触发数据变化钩子
    • OnDestroy 组件销毁前
      • 事件解绑、清除定时器、取消数据订阅

元数据示例(在TS中,我们用 装饰器(decorator) 来附加元数据)

  • @Component(装饰器为TypeScript提供语法特性,用来修饰 类)
    • 元数据(里面的对象参数称为元数据)
      • selectorC3选择器
      • template(定义组件内联模板)
      • templateUrl:"path/to/xx.html"(外联模板)(二者择其一)

装饰器作用是赋予一个类更丰富的信息(元数据) 更多见 reflect-metadata数据流向 数据流向.png

  • 父组件 @Input属性绑定=> 子组件 { 组件类 } 属性绑定 => < 模板 > < 模板 > 事件绑定 => { 组件类 }
  • 子组件 @Output事件绑定=> 父组件 { 组件类 } 属性绑定 => < 模板 > < 模板 > 事件绑定 => { 组件类 }

数据绑定(直接使用组件类里面的成员变量) + 属性绑定 - {{}}插值(interpolation) + 事件绑定 + 双向绑定

  • class (组件类)

2-2 指令(Directives)@Directive装饰器

Angular模板动态的 。当 Angular 渲染它们时,它会根据指令对 DOM 进行修改。 指令是一个带有"指令元数据"的。在 TypeScript 中,要通过@Directive装饰器把元数据附加到类上。 包含以下三种类型指令:

  • 组件(自身带有模板的指令) 继承=> 指令 // 作为指令的一个重要子类,组件本质上可以看作是一个带有模板的指令。

  • 属性指令改变组件模板外观或者行为/样式等 // 以元素的属性形式来使用的指令。

  • 结构指令改变组件模板DOM解构 [ngIf] // 用来改变DOM树的结构

  • 自定义指令 @Directive selector: '[highlight]'(中括号表示指令使用在元素属性上) ElementRef获取模板元素引用/Renderer辅助渲染 DOM解耦,适应服务器渲染

  • *ngFor 告诉 Angular 为 sites 列表中的每个项生成一个

  • 标签。 *ngIf 表示只有在选择的项存在时,才会包含 SiteDetail 组件。

    2-3 服务(Services)与依赖注入

    Ng2中的服务是封装了某一特定功能,并可通过注入方式供他人使用的独立模块。 服务分为很多种,包括:函数,以及应用所需的特性。 例如,多个组件中出现了重复代码时,把重复代码提取到服务中实现代码复用。

    以下是几种常见的服务:

    • 日志服务

    • 数据服务

    • 消息总线

    • 税款计算器

    • 应用程序配置

    • 服务是实现专一目的的逻辑单元,如日志服务

      • 通俗说就是一个类,定义了一些方法。
      • 模块使用需要依赖注入 依赖注入 控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫依赖查找(Dependency Lookup)。 通过控制反转,对象在被创建的时候,由一个 调控系统内所有对象外界实体,将其所依赖对象引用传递给它。也可以说,依赖被注入到对象中。 在传统的开发模式中,调用者负责管理所有对象的依赖,循环依赖一直是梦魇,而在依赖注入模式中,这个管理权交给了注入器(Injector),它在软件运行时负责依赖对象的替换,而不是在编译时。这种控制反转,运行注入的特点即是依赖注入的精华所在。

    Angular 能通过查看构造函数的参数类型,来得知组件需要哪些服务。 例如, SiteListComponent 组件的构造函数需要一个 SiteService:

    constructor(private service: HeroService) { }

    当 Angular 创建组件时,会首先为组件所需的服务找一个`注入器`( Injector ) 。
    
    注入器是一个维护服务实例的容器,存放着以前创建的实例。
    
    如果容器中还没有所请求的服务实例,注入器就会创建一个服务实例,并且添加到容器中,然后把这个服务返回给 Angular 。
    
    当所有的服务都被解析完并返回时, Angular 会以这些服务为参数去调用组件的构造函数。 这就是依赖注入 。
    
    • 依赖注入组件引入外部构建(服务)的一种机制(最常用的是引入服务)
      • 组件引入服务是这个服务类实例,被引入之前会有实例化过程,缓存以备其他组件使用
      • LogService 实例化=> 依赖注入 => 组件(管理实例化以及实例缓存的过程,通过依赖注入机制实现)(服务的实例存储在依赖机制建立的注入器对象里)
    • 例子@Component下的providers: [,,]依赖注入配置
    • 分层注入(hierarchical dependency injection)(适当的位置重新创建新的实例)
      • 先了解依赖注入组建树关系 某一组件注入服务后,组件本身所有子组件(保持单例形态, 所有组件使用同一实例, 在何处修改都影响同一实例)

    2-4 模块

    • 模块含义
      • 框架代码以模块形式组织(文件模块)(关注代码层面) @angular/core(核心模块) import { Component } from '@angular/core' import { Directive } from '@angular/core' import { ElementRef, Renderer } from '@angular/core' @angular/common(通用模块) @angular/forms(表单模块) @angular/http(网络模块) import { Http } from '@angular/http' 更多
      • 功能单元以模块形式组织(应用模块)(关注功能层面)
        • 把有关联的模块构建到一起,形成独立单元
        • @NgModule应用模块
          • declarations: 包装组件或指令等
          • providers: 依赖注入(注入模块可全局,注入组件只能此组件及子组件使用)
          • imports: 导入其他模块
          • bootstrap: 设置根组件(只在跟模块使用)
          • exports: 到处组件或指令等
        • 服务的注入是全局的
        • 启动服务
          • 根模块
            • 核心模块(维护登录信息,header、footer模块)
            • 特性模块
            • 特性模块(支持懒加载)
            • 共享模块
    • 核心概念

    3-1 TS简述(装饰器)

    • 简单介绍
    • 类型声明
    • 类与接口
    • 装饰器(TS独有特性)
      • 一种特殊类型的声明
      • 能被附加到方法访问符属性参数上 列: 装饰器逻辑须自定义 装饰器本质是一个函数,返回一个匿名函数,匿名函数接收的参数指向被修饰类的引用 匿名函数体内对类添加额外信息 约束类能否派生子类 回顾

    3-2 开发环境准备

    • Node.js
    • webpack
    • IDE(VSCode)

    3-3 项目启动

    五个功能点

    项目目录树(骨架)文件介绍

    • package.json文件
    • tsconfig.json(TS项目必须保留,TSCompiler配置文件)

    3-4 内置指令使用(*ngif)

    • 实现方式 <el *ngif="variable">

    用户输入($event #var key.enter blur)

    通过 $event 对象取得用户输入 我们可以绑定到所有类型的事件。 从一个模板引用变量中获得用户输入 模板引用变量通过在标识符前加上井号 (#)来实现。 按键事件过滤(通过key.enter) (keyup)事件处理语句会听到每一次按键, 我们可以过滤按键, 比如每一个$event.keyCode, 只有在按下回车键才更新values属性。 blur(失去焦点)事件

    Ng2表单()

    创建Site模型 创建一个表单组件

    Angular官网学习

    (https://angular.cn/tutorial/toh-pt6) -教程 -8.HTTP

    8.HTTP

    HTTP 服务 借助 Angular 的 HttpClient 来添加一些数据持久化特性。

    • HeroService 通过 HTTP 请求获取英雄数据。
    • 用户可以添加、编辑和删除英雄,并通过 HTTP 来保存这些更改。
    • 用户可以根据名字搜索英雄。

    启用 HTTP 服务 HttpClient 是 Angular 通过 HTTP 与 远程服务器通讯的机制。 要让 HttpClient 在应用中随处可用,请

    • 打开根模块 AppModule,
    • 从 @angular/common/http 中导入 HttpClientModule 符号,
    • 把它加入 @NgModule.imports 数组。

    模拟数据服务器 教学例子会与一个使用 内存 Web API(In-memory Web API) 模拟出的远程数据服务器通讯。

    Linux命令大全

    pwd: 打印当前路径
    dirs: 打印当前路径
    

    自定义命令npm.shell

    Root权限(sudo su)

    输入密码 退出: exit

    • 正常模式下的 变量名 消失 需要重新添加

    安装Python

    sudo su获取root权限 apt install python

    #《Linux就该这么学》学习笔记

    -第2章新手必须掌握的Linux命令 -2.1 强大好用的SHELL

    第2章新手必须掌握的Linux命令

    2.1强大好用的SHELL

    计算机硬件是由运算器控制器存储器输入/输出设备等共同组成的,而让 各种硬件设备 各司其职 且 又能 协同运行的东西就是系统内核Linux系统内核负责完成对硬件资源的分配调度管理任务系统内核对计算机的正常运行来讲是太重要了,因此一般不建议直接去编辑内核中的参数,而是让用户通过基于系统 调用接口 开发出的程序或服务来管理计算机,以满足日常工作的需要,如图2-1所示(https://www.linuxprobe.com/chapter-02.html)。 Linux系统中有些 图形化工具(比如 逻辑卷管理器[Logical Volume Manager,LVM])确实非常好用,极大地降低了运维人员操作出错的概率,值得称赞。但是,很多 图形化工具 其实是 调用了脚本 来完成相应的工作,往往只是为了完成某种工作而设计的,缺乏Linux命令原有的 灵活性 及 可控性。再者图形化工具 相较于 Linux命令行界面 会更加消耗系统资源因此经验丰富的运维人员 甚至都不会给Linux系统安装图形界面,需要开始运维工作时 直接通过 命令行模式 远程连接 过去,不得不说这样做确实挺高效的。 Shell就是这样的一个 命令行工具。Shell(也称为终端)充当的是 人与内核(硬件)之间的翻译官,. 现在包括红帽系统在内的许多主流Linux系统默认使用的终端是Bash(Bourne-Again SHell)解释器。 主流Linux系统选择Bash解释器作为 命令行终端 主要有以下4项优势: + 1:通过上下方向键来调取过往执行过的Linux命令; + 2:命令或参数仅需输入前几位就可以用Tab键补全; + 3:具有强大的批处理脚本; + 4:具有实用的环境变量功能。

    Windows安装Ubuntu虚拟机

    说明: Ubuntu on Windows allows one to use Ubuntu Terminal and run Ubuntu command line utilities bash, ssh, git ,apt and many more. 在Windows上的Ubuntu允许一个人使用Ubuntu终端,运行Ubuntu命令行实用程序bash、ssh、git、apt等等。

    To launch, use "ubuntu" on the command-line prompt(cmd.exe), or click on the Ubuntu tile in the Start Menu. 要启动,在命令行提示符(cmd.exe)上使用“ubuntu”,或者在“开始”菜单中单击“ubuntu”。

    To use this feature, one first needs to use "Turn Windows features on or off" and select "Windows Subsystem for Linux", click OK, reboot, and use this app. 要使用这个功能,首先需要使用“打开或关闭Windows功能”,并选择“Linux的Windows子系统”,单击OK,重新启动,并使用这个应用程序。

    The above step can also be performed using Administrator PowerShell prompt: 上面的步骤也可以使用管理员PowerShell提示执行:

    Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux 启用- windowsoptionalfeature - online - featurename微软-Windows -子系统- linux。

    linux shell 永久环境变量临时环境变量普通变量 之完全解读

    添加变量

    • export X=[path]

    一. 永久环境变量(~/.bashrc)(添加source [~/.bashrc] 完成注册)

    (实际上属于文件, 而不属于shell, 每打开一个shell, 都会加载/导入到shell中, 形成当前shell的临时环境变量)

    export在shell脚本中设置环境变量失效(source)

    shell脚本中 设定的 路径和环境变量 只对改shell和其子shell有效。 对其父shell和其它shell无效。 解决方法: source

    Vim操作的四种模式

    • 命令模式(command-mode) 多用于操作文本文件(而不是操作文本文件的内容),例如 保存文件; 或用来改变编辑器本身状态,例如 设定多栏窗口标签或者退出编辑器……

    • 插入模式(insert-mode)(用来向文本中添加内容的) i在光标所在字符前开始输入文字并进入插入模式; I行首开始输入文字并进入插入模式。此 行首 指第一个非空白字符处。如果行首有空格,则在空格之后输入文字并进入插入模式;

      a在光标所在字符后开始输入文字并进入插入模式; A行尾开始输入文字并进入插入模式。这个好用,您不必管光标在此行的什麽地方,只要按A就会在行尾等着您输入文字;

      o(字母o) 在光标所在下面单独开一新行来输入文字并进入插入模式; O(大写字母O) 在光标所在上面单独开一新行来输入文字并进入插入模式;

      s``删除光标所在字符并进入插入模式; S``删除光标所在并进入插入模式

    • 可视模式(visual-mode)(相当于高亮选取文本后的普通模式) 可视模式具有子模式:

      • 为单位 进行选取 的可视行模式,使用V键进入(也就是Shift+v
      • 为单位 进行选取 的可视块模式,使用Ctrl+v键进入
    • 正常模式(normal-mode) 正常模式主要用来浏览和修改文本内容的 一般 打开Vim都是正常模式。在任何模式下,只要按下Esc键就可以返回正常模式

    Vim操作模式的转换

    • ① 其它模式 => 正常模式 按Esc
    • ② 正常模式 => 插入模式 按 i 在光标前插入 按 I 在行首插入 按 a 在光标后插入 按 s 删除光标所在的字符再插入 按 A 在行末插入
      按 o 在当前行之下新建行
      按 O 在当前行之上新建行 按 S 删除光标所在行再插入
    • ③ 正常模式 => 命令模式
      按 : (shift 加 分号)
    • ④ 正常模式 => 可视模式
      按 v 可视模式
      按 V 可视块模式

    Vim--linux系统中如何进入退出vim编辑器,方法及区别

    (https://www.cnblogs.com/crazylqy/p/5649860.html)

    进入VIM编辑器(新建/修改)

    1 新建文件 也可 修改文件,命令为:vim /usr/local/con.cfg 2 如这个文件,以前没有,则为新建 下方有提示为新文件,如图。(图略) 如果文件已存在,则没有提示。 3 进入编辑器后,按I,即切换到“插入”状态。就可通过 上下左右 移动光标,或空格、退格及回车等进行编辑内容了,和WINDOWS一样。

    退出vim编辑器的方法及区别( 保存退出/正常退出/不保存退出/强制退出 )

    文本编辑结束,需退出编辑器。退出编辑器分4种情况:保存退出正常退出不保存退出强制退出

    退出按键盘左上角的ESC, 左下角的插入状态不见了,如图(略)。 1 保存退出输入“冒号”,即:(不需反引号),在下方出现 冒号,等待输入命令,输入WQ,功能如下:

    • W:write,写入
    • Q:quit,退出
    • X: WQ。 再回车,就保存退出了
    • 最快捷的方法:按ESC后,直接按shift+zz,或者切换到大写模式ZZ,就可以保存退出了,即是按2下大写的Z。 2 正常退出前提条件: 打开的文本文件在内容上没有改动
    • ESC后输入:, 直接输入q 3 不保存退出
    • ESC后输入:, 直接输入q! 4 强制退出(实在是不应该做的操作,因为很操蛋!)
    • ESC后输入:, 直接输入! - 退出后,会有提示! 查看命令(cat) cat查看其内容:cat /usr/local/con.cfg

    注意事项(linux命令要小写!!!)

    Shell脚本-ksh简介

    (http://blog.csdn.net/shangboerds/article/details/48623567)

    什么是 Shell

    如果把 Linux 比作一个蛋,那么 Shell 就是蛋壳,我们需 通过 Shell 使用 系统。

    Shell 的种类(Bourne Shell(sh) csh tcsh ksh tksh dtksh pdksh bash zsh)

    最早的 ShellBourne Shell(sh), 随着 Linux 的发展, 又出现好多 Shell,如: csh, tcsh, ksh, tksh, dtksh, pdksh, bash, zsh. 有这么多 Shell,每个 Shell 都有自己的特点,使用起来肯定不方便,所以 IEEE 制订了 POSIX 标准。

    什么是 ksh

    ksh 的全称是 Korn shell, 是一个 Linux/Unix shell,用来访问 Linux/Unix 系统。它完全向上兼容 Bourne shell 并包含了 C shell 的很多特性。

    ksh 能够用来干什么?

    ksh 提供了许多 强大的功能 方便 我们 编写脚本 管理 Linux/Unix 系统。

    ksh 的运行环境

    几乎所有的 Linux/Unix 系统都安装了 ksh,如果没有,运行下面的命令安装。

    sudo yum install ksh

    开发 ksh 的工具

    任何一款文本编辑器或 Eclipse, 有专门编辑 shell 的插件。

    一个示例程序

    #!/bin/ksh
    print "Hello World.";

    • 第一行代码称为沙邦(sh-bang),表示由什么程序运行此脚本。
    • 第二行的 print 是一个命令,用来打印输出。

    arp -a

    后台新项目配置 注意事项

    下载依赖,工具的变量路径 数据库 地址

    深入理解node中require的原理及执行过程

    (https://www.jianshu.com/p/609489e8c929)(2018年3月17日 16:12:55)

    Node.js点滴(工作总结)

    path模块的认识

    { resolve: [Function: resolve], normalize: [Function: normalize], isAbsolute: [Function: isAbsolute], join: [Function: join], relative: [Function: relative], _makeLong: [Function: _makeLong], dirname: [Function: dirname], basename: [Function: basename], extname: [Function: extname], format: [Function: format], parse: [Function: parse], sep: '/', delimiter: ':', win32: { resolve: [Function: resolve], normalize: [Function: normalize], isAbsolute: [Function: isAbsolute], join: [Function: join], relative: [Function: relative], _makeLong: [Function: _makeLong], dirname: [Function: dirname], basename: [Function: basename], extname: [Function: extname], format: [Function: format], parse: [Function: parse], sep: '\', delimiter: ';', win32: [Circular], posix: [Circular] }, posix: [Circular] }

    path.dirname(__dirname) // 当前文件在 系统 硬盘 绝对路径 path.join(path1, path2, path3...) // 以/为分隔符加入path2/path3

    Node.js基础(一)

    (慕课网视频)

    Node.js文件系统(FS模块)

    (https://www.jianshu.com/p/5683c8a93511)(http://www.runoob.com/nodejs/nodejs-fs.html) Node.js 文件系统Api

    //公共引用 var fs = require('fs'), path = require('path');

    1、读取文件(readFile)

    //readFile(filename,[options],callback); /**

    • filename, 必选参数,文件名
    • [options],可选参数,可指定flag(文件操作选项,如r+ 读写;w+ 读写,文件不存在则创建)及encoding属性
    • callback 读取文件后的回调函数,参数默认第一个err,第二个data 数据 */

    fs.readFile(__dirname + '/test.txt', {flag: 'r+', encoding: 'utf8'}, function (err, data) { > if(err) { > console.error(err); > return; > } > console.log(data); });

    2、写入文件(writeFile)

    // fs.writeFile(filename,data,[options],callback);

    var w_data = '这是一段通过fs.writeFile函数写入的内容;\r\n'; var w_data = new Buffer(w_data); // 关于Buffer实例还需要了解 /**

    • filename, 必选参数,文件名
    • data, 写入的数据,可以字符或一个Buffer对象
    • [options],flag,mode(权限),encoding
    • callback 读取文件后的回调函数,参数默认第一个err,第二个data 数据 */

    fs.writeFile(__dirname + '/test.txt', w_data, {flag: 'a'}, function (err) { > if(err) { > console.error(err); > } else { > console.log('写入成功'); > } });

    3、追加方式写文件(appendFile)

    // fs.appendFile(filename,data,[options],callback);

    fs.appendFile(__dirname + '/test.txt', '使用fs.appendFile追加文件内容', function () { > console.log('追加内容完成'); });

    4、打开文件(open)

    // fs.open(filename, flags, [mode], callback); /**

    • filename, 必选参数,文件名
    • flags, 操作标识,如"r",只读方式打开
    • [mode],权限,如777,表示任何用户读写可执行
    • callback 打开文件后回调函数,参数默认第一个err,第二个fd为一个整数,表示打开文件返回的文件描述符,window中又称文件句柄 */

    fs.open(__dirname + '/test.txt', 'r', '0666', function (err, fd) { > console.log(fd); });

    5、读文件(read) 读取打开(open)的文件内容到缓冲区中

    //fs.read(fd, buffer, offset, length, position, callback); /**

    • fd, 使用fs.open打开成功后返回的文件描述符
    • buffer, 一个Buffer对象,v8引擎分配的一段内存
    • offset, 整数,向缓存区中写入时的初始位置,以字节为单位
    • length, 整数,读取文件的长度
    • position, 整数,读取文件初始位置;文件大小以字节为单位
    • callback(err, bytesRead, buffer), 读取执行完成后回调函数,bytesRead实际读取字节数,被读取的缓存区对象 */

    fs.open(__dirname + '/test.txt', 'r', function (err, fd) { > if(err) { > console.error(err); > return; > } else { > var buffer = new Buffer(255); > console.log(buffer.length); > //每一个汉字utf8编码是3个字节,英文是1个字节 > fs.read(fd, buffer, 0, 9, 3, function (err, bytesRead, buffer) { > if(err) { > throw err; > } else { > console.log(bytesRead); > console.log(buffer.slice(0, bytesRead).toString()); > //读取完后,再使用fd读取时,基点是基于上次读取位置计算; > fs.read(fd, buffer, 0, 9, null, function (err, bytesRead, buffer) { > console.log(bytesRead); > console.log(buffer.slice(0, bytesRead).toString()); > }); > } > }); > } });

    6、写文件(write),将缓冲区内数据写入使用(fs.open)打开的文件

    //fs.write(fd, buffer, offset, length, position, callback); /**

    • fd, 使用fs.open打开成功后返回的文件描述符
    • buffer, 一个Buffer对象,v8引擎分配的一段内存
    • offset, 整数,从缓存区中读取时的初始位置,以字节为单位
    • length, 整数,从缓存区中读取数据的字节数
    • position, 整数,写入文件初始位置;
    • callback(err, written, buffer), 写入操作执行完成后回调函数,written实际写入字节数,buffer被读取的缓存区对象 */

    fs.open(__dirname + '/test.txt', 'a', function (err, fd) { > if(err) { > console.error(err); > return; > } else { > var buffer = new Buffer('写入文件数据内容'); > //写入'入文件'三个字 > fs.write(fd, buffer, 3, 9, 12, function (err, written, buffer) { > if(err) { > console.log('写入文件失败'); > console.error(err); > return; > } else { > console.log(buffer.toString()); > //写入'数据内'三个字 > fs.write(fd, buffer, 12, 9, null, function (err, written, buffer) { > console.log(buffer.toString()); > }) > } > }); > } });

    7、刷新缓存区

    // 使用fs.write写入文件时,操作系统是将数据读到内存,再把数据写入到文件中,当数据读完时并不代表数据已经写完,因为有一部分还可能在内在缓冲区内。 // 因此可以使用fs.fsync方法将内存中数据写入文件;--刷新内存缓冲区; //fs.fsync(fd, [callback]) /**

    • fd, 使用fs.open打开成功后返回的文件描述符
    • [callback(err, written, buffer)], 写入操作执行完成后回调函数,written实际写入字节数,buffer被读取的缓存区对象 */

    fs.open(__dirname + '/test.txt', 'a', function (err, fd) { > if(err) > throw err; > var buffer = new Buffer('我爱nodejs编程'); > fs.write(fd, buffer, 0, 9, 0, function (err, written, buffer) { > console.log(written.toString()); > fs.write(fd, buffer, 9, buffer.length - 9, null, function (err, written) { > console.log(written.toString()); > fs.fsync(fd); > fs.close(fd); > }) > }); });

    Express学习笔记

    (https://segmentfault.com/a/1190000002812451)

    路由基础

    路由指确定程序如何针对特定请求进行反应,这个请求是一个URI和它的HTTP请求方法。每一个路由有一个处理函数,当路由匹配的时候执行。 路由定义格式为:app.VERB(PATH, HANDLER),其中app是一个express实例,VERB是一个HTTP请求方法,PATH服务器上的一个路径,HANDLER是用于处理请求的函数

    以下代码展示app的基本路由: 略……

    NodeJs搭建WebSocket

    (2018年2月1日 17:53:00)(慕课网https://www.imooc.com/learn/861)

    第2章 WebSocket初体验之实现简单聊天功能

    2-1WebSocket初体验

    它是伴随HTML5出现的新技术,与HTTP不同 浏览器发起,服务器接受,返回数据 断开连接。区别建立长连接/本质是TCP连接

    NodeJs使用MongoDB(文档翻译)

    (http://www.expressjs.com.cn/guide/database-integration.html#mongo) 模块: mongoskin 安装: $ npm install mongoskin 示例:

    var db = require('mongoskin').db('localhost:27017/animals'); db.collection('mamals').find().toArray(function(err, result) { if (err) throw err; console.log(result); });

    If you want a object model driver for MongoDB, checkout Mongoose.

    Mongoose Mongoose是用于在异步环境中工作的MongoDB对象建模工具。

    文档 (http://mongoosejs.com/)

    支持

    • 堆栈溢出(Stack Overflow)
    • 错误报告(Bug Reports)
    • 猫鼬冗余通道(Mongoose Slack Channel)
    • 支援论坛(Help Forum)
    • MongoDB支持(MongoDB Support)

    Importing(导入) // Using Node.js require()

    const mongoose = require('mongoose');

    // Using ES6 imports

    import mongoose from 'mongoose';

    插件

    Installation(安装) 首先安装node.js和mongodb。然后:

    $ npm install mongoose

    Overview(简介) 连接到MongoDB 首先,我们需要定义一个连接。如果你的应用程序只使用一个数据库,你应该使用mongoose.connect。如果你需要创建其他额外的连接,使用mongoose.createConnection

    Both connect and createConnection take a mongodb:// URI, or the parameters host, database, port, options. (connectcreateConnection都采用mongodb:// URI,或参数主机数据库端口选项。)

    const mongoose = require('mongoose');

    mongoose.connect('mongodb://localhost/my_database');

    Once connected, the open event is fired on the Connection instance. If you're using mongoose.connect, the Connection is mongoose.connection. Otherwise, mongoose.createConnection return value is a Connection. 译: 一旦连接,open事件将在Connection实例上触发。如果你正在使用mongoose.connect,那Connection就是mongoose.connection。否则,mongoose.createConnection返回值是一个Connection

    Note: If the local connection fails then try using 127.0.0.1 instead of localhost. Sometimes issues may arise when the local hostname has been changed. 注意: 如果本地连接失败,请尝试使用127.0.0.1而不是(替代)localhost。当本地主机名已被更改时,有时可能会出现问题。

    Important! Mongoose buffers all the commands until it's connected to the database. This means that you don't have to wait until it connects to MongoDB in order to define models, run queries, etc. 重要!Mongoose缓存所有的命令,直到它连接到数据库。这意味着您不必等到它连接到MongoDB才能定义模型,运行查询等。

    Defining a Model(定义一个模型) Models are defined through the Schema interface.(模型通过Schema界面进行定义。)

    const Schema = mongoose.Schema; const ObjectId = Schema.ObjectId;

    const BlogPost = new Schema({ > author: ObjectId, > title: String, > body: String, > date: Date });

    Aside from defining the structure of your documents and the types of data you're storing, a Schema handles the definition of: 除了定义文档的结构和要存储的数据类型外,Schema还处理以下定义:

    • Validators (async and sync) // 验证器(异步和同步)
    • Defaults // 默认
    • Getters
    • Setters
    • Indexes // 索引
    • Middleware // 中间件
    • Methods definition // 方法定义
    • Statics definition // 静力学定义
    • Plugins // 插件
    • pseudo-JOINs

    下面的示例展示了这些特性:

    const Comment = new Schema({ > name: { type: String, default: 'hahaha' }, > age: { type: Number, min: 18, index: true }, > bio: { type: String, match: /[a-z]/ }, > date: { type: Date, default: Date.now }, > buff: Buffer });

    // a setter

    Comment.path('name').set(function (v) { return capitalize(v); });

    // middleware

    Comment.pre('save', function (next) { notify(this.get('email')); next(); });

    Take a look at the example in examples/schema.js for an end-to-end example of a typical setup. 看看examples/schema.js中的例子。一个典型设置的端到端示例的js。

    Accessing a Model(访问模型) Once we define a model through mongoose.model('ModelName', mySchema), we can access it through the same function 一旦我们定义了一个模型mongoose.model('ModelName', mySchema),我们可以通过相同的函数来访问它 > const myModel = mongoose.model('ModelName');

    Or just do it all at once(或者只做一次。)
    > const MyModel = mongoose.model('ModelName', mySchema);
    
    The first argument is the singular name of the collection your model is for. Mongoose automatically looks for the plural version of your model name. For example, if you use
    第一个参数是您的模型的所用集合的唯一名称。Mongoose自动查找您的模型名称的复数版本。例如,如果你使用。
    
    > const MyModel = mongoose.model('Ticket', mySchema);
    
    Then Mongoose will create the model for your tickets collection, not your ticket collection.
    然后,`Mongoose`将为你的`tickets`集合 创建模型,而不是你的`ticket`集合。
    
    Once we have our model, we can then instantiate it, and save it:
    一旦我们有了模型,我们就可以实例化它,并保存它:
    > const instance = new MyModel();
    > instance.my.key = 'hello';
    > instance.save(function (err) {
    >   //
    > });
    
    Or we can find documents from the same collection
    或者我们可以从同一个集合中找到文档
    > MyModel.find({}, function (err, docs) {
    >   // docs.forEach
    > });
    
    您还可以`findOne`,`findById`,`update`,等有关详细信息请查看的文档。
    
    **重要!**如果你打开一个单独的连接,`mongoose.createConnection()`但试图通过访问模型,`mongoose.model('ModelName')`它不会按预期工作,因为它没有连接到活动的数据库连接。在这种情况下,通过您创建的连接访问您的模型:
    

    Embedded Documents(嵌入式文档)

    Middleware(中间件)

    简书-Mongoose (https://www.jianshu.com/p/ff6bb4b290bc)

    • 安装
    • 开始
    • 客户端 Mongodb不像mysql等数据库 有可视化 管理器,

    MongoDB在Node.js中的使用

    (https://www.jianshu.com/p/a4c096899502)

    Node.js 中使用MongoDB(几乎是标配)

    • mac中安装MongoDB brew install mongodb
    • node.js 中使用mongoose第三方库来管理MongoDB npm install mongoose --save - 为什么使用mongoose:官方的驱动都是 回调方式的API, 而mongoose封装成promise, 可使用await/async
    • 配置连接DB信息,并导出连接的对象 > import mongoose from 'mongoose' // 引入 > const options = { user: 'admin', pwd: '123456', host: 'localhost', port: '27017', database: 'hollywood', authSource: 'admin', > }
    > const uri = `mongodb://${options.user}:${options.pwd}@${options.host}:${options.port}/${options.database}?authSource=${options.authSource}`
    
    mongoose.Promise = global.Promise //需要
    mongoose.connect(uri)
    
    export default mongoose
    
    • 定义一个模型的概要,类似于关系型数据库中的定义表结构 > import db from '../db.js' > import logger from '../logger'
    > const Schema = db.Schema
    
    //account对应的字段
    > const accountSchema = new Schema(
        {
            name: { type: String, maxlength: 15 },
            password: { type: String, maxlength: 20 },
            gender: { type: String, enum: ['male', 'female'] },
            email: { type: String, maxlength: 25 },
            avatar: { type: String },
            age: { type: Number },
            create_date: { type: Date },
            update_date: { type: Date },
        },
        {
            versionKey: false,
        },
    > )
    
    //当account执行save()前,执行该代码片段,有点类似于中间件(这个方法内容仅仅是介绍pre()的使用方法)
    > accountSchema.pre('save', function(next) {
        const currentDate = new Date()
        if (!this.create_date) {
            this.create_date = currentDate
        } else {
            this.update_date = currentDate
        }
        next()
    > })
    
    //当account执行save()后
    > ...
    
    //定义模型的方法
    > accountSchema.methods.sayHi = () => (console.log('sayHi()!!!!!'))
    > const Account = db.model('Account', accountSchema)
    > export default Account
    
    • 保存到数据库, 并返回一个保存到数据库的对象 > import Account from './model'
    > export default class AccountService {
        static async save(json) {
          const accountModel = new Account(json)
          const account = await accountModel.save()
          return account
        }
    > }
    

    MongoDB日常()

    备份(mongodump)与恢复(mongorestore)

    (http://www.runoob.com/mongodb/mongodb-mongodump-mongorestore.html) 数据备份(mongodump) Mongodb中 使用mongodump命令来备份MongoDB数据。该命令可以导出所有数据到指定目录中。 mongodump命令可以通过参数指定导出的数据量级转存的服务器。 语法

    mongodump -h dbhost -d dbname -o dbdirectory -h:MongDB所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017 -d:需要备份的数据库实例,例如:test -o:备份的数据存放位置,例如:c:\data\dump,当然该目录需要提前建立,在备份完成后,系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。

    MongoDB之compact操作详解

    (https://juejin.im/post/5ae27e17518825670d72d2b7)

    MongdDB官方文档

    mongo shell -本页内容 -介绍 -开始 mongo Shell -使用mongo Shell -Tab命令补全和其他键盘快捷键 -退出Shell

    介绍

    mongo shellMongoDB的交互式JS接口。您可以使用mongo shell查询更新数据以及执行管理操作mongo shellMongoDB发行版的一个组件。安装并启动MongoDB后,将mongo shell连接到运行的MongoDB实例。 MongoDB手册中的大多数 示例 使用mongo shell;然而,许多驱动程序MongoDB提供了类似接口开始 mongo Shell > 重要 > 在尝试启动 mongo shell前请确保MongoDB实例正在运行。

    Reference > mongo Shell Methods > Collection Methods > db.collection.findAndModify() db.collection.findAndModify() -On this page(在此页) -Definition(定义) -Return Data(返回 数据) -Behavior(行为 反映 表现) -Examples(例子)

    Definition

    db.collection.findAndModify(document) Modifies and returns a single document. / By default, the returned document does not include the modifications made on the update. / To return the document with the modifications made on the update, use the new option. The findAndModify() method is a shell helper around the findAndModify command. 译:修改并返回单个文档。/ 默认情况下,返回的文档不包括更新所做的修改。/ 要在对文档进行修改时并显示更新,请使用new选项。findAndModify()方法是在findAndModify命令周围的一个shell助手。 The findAndModify() method has the following form:(方法有如下形式) db.collection.findAndModify({ query: , // 查询 sort: , // 排序 remove: , // 删除(true/false) update: , // 更新 new: , // 对文档进行修改时并显示更新(true/false) fields: , // 字段、域 upsert: , // 不存在的值是否添加字段(默认:false) bypassDocumentValidation: // 文档验证,(true/false) writeConcern: , // 关注 collation: // 校对、排序规则、整理 });

    The db.collection.findAndModify() method takes a document parameter with the following embedded document fields:
    译:db.collection.findAndModify()方法接受一个文档参数与嵌入的文档字段如下:
    
    -Parameter------Type------Description-
    Parameter(参数):{
      query:{
        `Type`: "document";
        `Description`: "Optional. The selection criteria for the modification. The query field employs the same query selectors as used in the db.collection.find() method. Although the query may match multiple documents, findAndModify() will only select one document to modify.";
        `Description译`:可选的。修改的选择标准。查询字段使用与db.collection.find()方法中使用的相同的查询选择器。虽然查询可能匹配多个文档,但findAndModify()只会选择要修改的一个文档。
      },
      sort:{
        `Type`: "document";
        `Description`: "Optional. Determines which document the operation modifies if the query selects multiple documents. findAndModify() modifies the first document in the sort order specified by this argument.";
        `Description译`: "可选的。确定如果查询选择多个文档,操作将修改哪个文档。findAndModify()根据该参数指定的排序顺序修改第一个文档。"
      },
      remove:{
        Type: "boolean";
        Description: Must specify either the remove or the update field. Removes the document specified in the query field. Set this to true to remove the selected document . The default is false.;
        `Description译`: 必须指定删除或更新字段。删除查询字段中指定的文档。将此设置为true,以删除选定的文档。默认的是假的。
      },
      update:{
        `Type`: "document";
        `Description`: "Must specify either the remove or the update field. Performs an update of the selected document. The update field employs the same update operators or field: value specifications to modify the selected document.";
        `Description译`: "必须指定删除或更新字段。执行所选文档的更新。更新字段使用相同的更新操作符或字段:值规范来修改所选文档。"; 
      }
      new:{
        `Type`: "boolean";
        `Description`: "Optional. When true, returns the modified document rather than the original. The findAndModify() method ignores the new option for remove operations. The default is false.";
        `Description译`: "可选的。当操作正确时,返回修改后的文档,而不是原始文档。findAndModify()方法忽略了`remove`操作的`new`选项。默认是`false`。"; 
      }
      fields:{
        `Type`: "document";
        `Description`: "Optional. A subset of fields to return. The fields document specifies an inclusion of a field with 1, as in: fields: { <field1>: 1, <field2>: 1, ... }. See projection.";
        `Description译`: "可选的。字段的子集返回。字段文档指定包含一个字段,其中包含1个字段,如:{<field1>: 1, <field2>: 1,…}。 See "projection"。"; 
      }
      upsert:{
        `Type`: "boolean";
        `Description`: 
          "Optional. Used in conjuction with the update field.
           When true, findAndModify() either:
            Creates a new document if no documents match the query. For more details see upsert behavior.
            Updates a single document that matches the query.
            To avoid multiple upserts, ensure that the query fields are uniquely indexed."
            Defaults to false.";
        `Description译`:
          "可选的。与更新字段一起使用。
           当返回值为`true`,findAndModify() either(任一,两方,随便哪一个;两者中的一个或另一个):
            如果没有文档匹配查询,则创建一个新文档。有关更多细节,请参见upsert行为。
            更新与查询匹配的单个文档。
            为了避免多个upserts,确保查询字段是惟一的索引。默认值为false";
      },
      bypassDocumentValidation:{
        `Type`: "boolean";
        `Description`: "Optional. Enables db.collection.findAndModify to bypass document validation during the operation. This lets you update documents that do not meet the validation requirements.";
        `Description译`: "可选的。使`db.collection.findAndModify`在操作过程中绕过文档验证。这允许您更新不符合验证要求的文档。";
        `Tip`: "3.2 新版功能";
      },
      writeConcern:{
        `Type`: "document";
        `Description`: "Optional. A document expressing the write concern. Omit to use the default write concern.";
        `Description译`: "可选的。表示关注的文档。忽略将使用默认 写关注/问题。";
        `Tip`: "3.2 新版功能";
      },
      maxTimeMS:{
        `Type`: "integer";
        `Description`: "Optional. Specifies a time limit in milliseconds for processing the operation.";
        `Description译`: "可选的。指定处理操作的毫秒数。";
      },
      collation:{
        `Type`: "document";
        `Description`: 
          "Optional.
           Specifies the collation to use for the operation.
           Collation allows users to specify language-specific rules for string comparison, such as rules for  lettercase and accent marks.
           The collation option has the following syntax:
    
           collation: {
             locale: <string>,
             caseLevel: <boolean>,
             caseFirst: <string>,
             strength: <int>,
             numericOrdering: <boolean>,
             alternate: <string>,
             maxVariable: <string>,
             backwards: <boolean>
           }
           When specifying collation, the locale field is mandatory; all other collation fields are optional. For  descriptions of the fields, see Collation Document.
    
           If the collation is unspecified but the collection has a default collation (see db.createCollection()),  the operation uses the collation specified for the collection.
    
           If no collation is specified for the collection or for the operations, MongoDB uses the simple binary  comparison used in prior versions for string comparisons.";
        `Description译`:
          "可选的。
           指定用于操作的排序规则。
           `Collation`允许用户为字符串比较 指定特定语言的规则,比如字母大小写和重音符号的规则。
           `collation`选项有以下语法:
              collation: {
                locale: <string>,
                caseLevel: <boolean>,
                caseFirst: <string>,
                strength: <int>,
                numericOrdering: <boolean>,
                alternate: <string>,
                maxVariable: <string>,
                backwards: <boolean>
              };
           在指定collation时,`locale`字段是强制的;所有其他排序字段都是可选的。有关字段的描述,请参见Collation文档。
           如果排序未指定,但是集合有默认的排序规则(请参阅db.createCollection()),该操作将使用指定的排序集。
           如果没有为集合或操作指定排序,MongoDB将使用以前版本中用于字符串比较的简单二进制比较。";
      }
    }
    

    Return Data

    删除操作 For remove operations, if the query matches a document, findAndModify() returns the removed document. If the query does not match a document to remove, findAndModify() returns null. 译:对于删除操作,如果查询数据库集合 有匹配项,findAndModify()将返回已删除的文档。如果查询 无匹配项 要删除的文档,findAndModify()返回null。(笔记:对于这句话的理解就是,删除操作,如果有匹配值,返回被操作的那条数据;没有匹配值,则返回null.)

    更新操作 For update operations, findAndModify() returns one of the following: 译:对于更新操作,findAndModify()返回以下内容之一: If the new parameter is not set or is false:(如果新参数没有设置或为false:) - the pre-modification document if the query matches a document; 译:如果查询匹配文档,则预修改文档; - otherwise, null.(否则,空.) If new is true:(如果newtrue) - the modified document if the query returns a match; 译:如果查询 返回匹配,修改后的文档(符合查询条件 则修改文档); - the inserted document if upsert: true and no document matches the query; 译:插入的文档如果upsert: true和no文档匹配查询; - otherwise, null.(否则,空.) 在 3.0 版更改: In previous versions, if for the update, sort is specified, and upsert: true, and the new option is not set or new: false, db.collection.findAndModify() returns an empty document {} instead of null. 译:在以前的版本中,如果更新指定排序,插入:为true,没有设置newnew:false,db.collection.findAndModify()返回一个空文档{ },而不是null。

    Behavior

    Upsert and Unique Index(插入和惟一索引) When findAndModify() includes the upsert: true option and the query field(s) is not uniquely indexed, the method could insert a document multiple times in certain circumstances. 译:当findAndModify()包含upsert: true选项 和查询字段不是惟一的索引时,该方法可以在特定情况下多次插入文档。 db.people.findAndModify({ query: { name: "Andy" }, sort: { rating: 1 }, update: { $inc: { score: 1 } }, upsert: true }) Then, if these clients’ findAndModify() methods finish the query phase before any command starts the modify phase, and there is no unique index on the name field, the commands may all perform an upsert, creating multiple duplicate documents. 译:然后,如果这些客户机的findAndModify()方法在任何命令启动修改阶段之前完成查询阶段,并且在name字段上没有唯一的索引,那么这些命令可能都执行一个upsert,创建多个重复的文档。

    Sharded Collections(分片集合)

    Document Validation(文档验证)

    Comparisons with the update Method(与更新方法进行比较)

    Examples

    Update and Return(更新并返回) Upsert() Return New Document(返回新文档) Sort and Remove(排序和删除) Specify Collation(指定排序)

    mongoose入门

    (http://www.nodeclass.com/api/mongoose.html)

    $ npm install mongoose // 安装

    // getting-started.js

    var mongoose = require('mongoose'); // 引入 mongoose.connect('mongodb://localhost/test'); // 连接

    var db = mongoose.connection; db.on('error', console.error.bind(console, 'connection error:')); db.once('open', function (callback) { // yay! }); 一旦连接打开,回调将被调用。为简洁起见,假设所有以下代码都在此回调中。 使用Mongoose,所有内容都来自Schema。参考它并定义mongoose。 var kittySchema = mongoose.Schema({ name: String })

    7分的人如何找到9分的工作?

    (https://mp.weixin.qq.com/s?__biz=MjM5OTE1NDQwMA==&mid=2653349129&idx=1&sn=d61108bd89d42a90aec66fc233728247&chksm=bced82868b9a0b90430fdfb69d816f7584d266bb3e6ba931e080cac89747040cefb465edcbf3#rd)

    你没钱,真的真的不是因为不努力

    ( http://www.bslxx.com/a/zixun/zhichang/2018/0115/1611.html )

    今天,我们不鸡汤、不鸡血、不厚黑地来聊聊——关于“钱”的方法论。 肉分五花三层,人是否有三六九等? 所有的人都会发现,同样学校同样专业的同学,毕业几年之后,薪资差距会变得很大。

    鸡汤君说:别在乎一时的薪酬,应该继续坚持梦想。 鸡血君说:你还不够努力,还没看到过魔都帝都凌晨四点的太阳。 厚黑君说:你别傻干了,得学会搞关系、找资源。

    好吧,我真是烦透这些东西了……

    所以今天,我们不鸡汤、不鸡血、不厚黑地来聊聊——关于“钱”的方法论。

    我们都知道,产品会有不同的价值定位:产品领先、价格低廉、服务一流。 举例来说,你买苹果是因为产品好,去沃尔玛是冲着价格低,住万豪是服务差异化。 人也一样,讲白了,大家都是出来卖的。要让别人出钱买你,得看你的价值在什么方面。

    那么,用分析产品的思路来分析人,人都有哪些价值定位、各种定位从物质回报的角度有无高低之分呢?

    决定你价值的,其实就只有六个因素

    首先,我们都必须承认,这个世界并不完美,所以你的收入不完全是你能创造的价值,这其中,是存在一个差值的。用公式表示就是: (文章中并没有公式。。。)

    那么,你的实际价值又取决于什么呢? 我们在做人才测评的时候,有个基础模型,称为冰山模型,可以回答这个问题。根据这个模型,你个人能够创造出多大的价值,离不开三大要素: **第一个要素,知识和技能。**比如我现在写这篇文章,冰山模型是知识,电脑打字是技能。一个人的知识和技能是可以后天习得的,也是非常显性,容易展示出来的。所以,我们称为冰山上的部分。 **第二个要素,是能力,比如学习和思考能力、人际交往能力等等。**相对知识和技能来说,能力的培养周期长,并且,相对隐性,能力高低不是一眼就能看出来的,往往要通过仔细的行为观察。所以,能力是在冰山中间的部分。 第三个要素,天赋,包括价值观、性格特质、动机。比如,你的人际敏感度天生很强,那么在做一些服务类的工作,就会比人际敏感度弱的人要来得轻松。再比如,你是成就感动机的人,那你做咨询工作,就会比权力动机的人感受到更多快乐,也容易做得好。 但是,这些天赋对成人来说,几乎不可改变的。同时,也很难观察到,即便是自己,也常常意识不到你的天赋在什么地方。(个人理解:小孩子的天赋可以慢慢发现和培养么?个人认为是可行的)

    说完了内部因素,我们再来看外部因素。 外部因素也包括三个方面:出身、选择、运气。 出身是你拥有的原始资本; 选择是给你重新获得资本的机会; 而运气 则是你选择之后能否如愿的随机因素。

    这些因素,将你的价值定位分成五种类型

    所以,我们再回顾一下这个模型,一个人的账面价值(薪酬)最终取决于六大因素。 你会发现,这六个因素里面,有些是无法改变的,比如出身和运气,而另一些是可以人为改变的,比如知识、技能、能力

    复杂一点的是天赋和选择。 天赋本身并不能改变,但是你可以通过发掘自己的天赋、选择与之匹配的工作,从而最大化利用它。所以,我们暂且也认为它是部分可变的。 另外,选择大于努力这句话我完全同意,可问题是,当你选择的时候,并不知道哪个选择是对的。我们都知道,早十年有100万的话,买房比炒股的选择更明智,但在当时,谁也不肯定。 有研究表明,股评家们的选择并不比随机更加靠谱。所以,把时间投入于选择,更像是投机

    刨除不可变因素,我们可以把*个人所选择的定位(也可以称之为增值方式)*分成五种不同的类型:投机型、知识型、技能型、能力型、天赋型。 需要注意的是,在识别你的价值类型时,并非看你有没有知识、能力,因为所有的人都不可能只有单一价值,而是要看你的差异化因素在哪里。 这跟产品的道理是一样的,沃尔玛东西多,可别的超市也不少。你会用excel,可所有人都会,你的可替代性很强,那就不会有人愿意购买。 所以,差异化因素才是你的价值所在。

    你选择的价值定位,已经决定了你的天花板

    **实际上,你的定位类型,早就已经决定你的薪酬天花板在哪里了,不管多努力,基本很难突破。**我们不妨来分析一下。
    
    1. **投机型:**追求的账面价值最大化。人才市场,还不是一个完全信息对称的市场。所以,同等能力,可能A企业支付1万,B企 支付1.2万,C企业支付1.5万。投机型的人竭尽全力,通过各种渠道,找到愿意支付更高价格的地方,不惜频繁跳槽。这类人,天 板很明显,就是企业愿意为他们所支付的最高价格。

    2. **知识型:**或许你觉得知识很值钱?讲真,我见过不少知识装X、知识泡妞、知识唬人的,但没怎么见过单纯用知识赚钱的。 为什么知识的价值不高呢? 其一,当今社会,你想知道什么,网上搜索就可以了,可替代性太高。你就算把百科全书背下来,最后还得靠卖记忆力课程赚钱。 其二,知识跟思维,是有差别的。现代社会,随便一个人,知识储备都超过孔子、老子、亚里士多德……但你为什么还在学他们的 想? 所以,不能内化为能力的知识,是很难为你增加财富的。 另外,你可能会想,罗辑思维难道不是贩卖知识吗?是的,可罗振宇能贩卖知识,靠的是他的商业运作能力。

    3. **技能型:**技能型跟知识型其实有点类似,你能想到的最典型的技能型应该是操作工,熟练地修理仪器、操作机器。 我曾为一家企业设计过职业发展体系,对方问我:我们的工人,十年二十年不离开公司,可生产管理岗位毕竟很少,能否像研发 样,除了管理通道之外,再给建立一个专业通道,让他们也可以在企业内部长久发展? 我的回答是:可以,只要你们愿意支付他们每次升职的加薪。 所有高管都沉默了,因为再熟练的操作工,能为企业创造的价值是有限的,所以他们不愿意付出那么高的成本。 你可能没意识到的是,很多初级白领,其实也是技能型,数年如一日地写报告、做表格、走流程,Office软件用得贼溜。 所以,技能型的人,天花板是:企业愿意为技能付的钱,而这个,取决于该技能在市场上的稀缺性。

    4. **能力型:**比如一些做专业服务类以及管理类工作的人,其定位基本是能力型。比如咨询顾问,每天用PPT,但不会有谁,是 为PPT用得好而成为一个好顾问的,恰恰相反,PPT用得一般,但能力很强,也没有太影响职业生涯。 技能不行,能力可以弥补,但能力不行,技能无法代替。能力型的人,天花板往往是他们自己,而不是外在的限制。 我曾经问过为企业做人才测评十多年的顾问一个问题:你掌握那么多人才数据,到底是什么因素,让同样起点的人,在多年之 差距那么大? 她给出的答案是:韧性、沟通合作能力、结果导向。一半是能力,一半是天赋

    5. **天赋型:**比如搞艺术、做设计的,同等努力的情况下,最终能够做得比一般人好的,个人价值定位常常在这个类型。 Gillian Lynne是音乐剧《Cat》和《The Phantom of the Opera》的编舞,是位舞蹈家。她小时候注意力一直不集中。后来,母亲带她去看专科医生,听完讲述之后,医生打开了桌上的收音机,然后医生和母亲走出房间,在门外观察她。他们一离开,Laynne就伴着音乐开始舞动,医生跟她母亲说:她没有病,她是个天生的舞者,送她去舞蹈学校吧。后来的故事,我们都知道了。

    我们之前提到的冰山模型,有很多研究都表明,冰山下面的天赋部分,60%以上的程度决定了一个人能够创造的价值。

    五种价值定位类型,回报有高低,但大多数人的选择都不是最优

    windows自动关机(2018年3月26日 09:07:13)

    • shutdown /?显示帮助
    • shutdown -s -t 7200 【1小时=3600秒, 这里设置7200就等于两个小时之后电脑自动关机】
    • 命令注意空格不要打错! 成功之后电脑右下角会有提示什么时候自动关机!!
    • 取消 自动关机命令,在命令窗输入 shutdown -a 按下回车即可
    • 同样, 电脑右下角也会有相关提示!!

    关于京典一线的后台页面的感想(2018年1月20日)

    组件库主要用到了iview。着重接触了里面的render函数渲染,列表表头 通过脚本定义,再渲染内容,以及筛选功能。 间接 接触了ES6的一些新语法(Object.assign)。必须得在项目中用到的语法,印象才能深刻。没有实际利用,书本的知识点还是没那么深刻的印象。

    Ubuntu

    GraphQL

    面试题

    -Heyper Text Markup Language -Cascading Style Sheets -Java Script

    HTML

    块级元素: div/p/dl/dt/dd/h1-6/ul/ol/li/header/footer/form/table/tr/th/ block(块)元素的特点: ①总是在新行上开始; ②高度,行高以及外边距和内边距都可控制; ③宽度缺省是它的容器的100%,除非设定一个宽度。 ④它可以容纳内联元素和其他块元素

    行内元素: a/abbr/br/code/input/label/small/u/span/img/i/b/em/s/sup/sub/strong/select/ inline元素的特点: ①和其他元素都在一行上; ②高,行高及外边距和内边距不可改变; ③宽度就是它的文字或图片的宽度,不可改变 ④内联元素只能容纳文本或者其他内联元素 (中文叫法有多种内联元素、内嵌元素、行内元素、直进式元素。)

    块元素(block element)和内联元素(inline element)都是html规范中的概念。块元素和内联元素的基本差异是块元素一般都从新行开始。而当加入了css控制以后,块元素和内联元素的这种属性差异就不成为差异了。比如,我们完全可以把内联元素加上display:block这样的属性,让他也有每次都从新行开始的属性即成为块元素,同样我们可以把块元素加上display:inline这样的属性,让他也在一行上排列
    

    可变元素: 是基于以上两者随环境而变化的,它的基本概念就是他需要根据上下文关系确定该元素是块元素或者内联元素。可变元素还是属于上述两种元素类别,一旦上下文关系确定了他的类别,他就要遵循块元素或者内联元素的规则限制

    CSS

    水平垂直同时居中 .dad { position: relative; } .son { position: absolute; margin: auto; top: 0; right: 0; bottom: 0; left: 0; }

    .dad {
    position: relative;
    }.son {
        width: 100px;
        height: 100px;
        position: absolute;
        top: 50%;
        left: 50%;
        margin-top: -50px;
        margin-left: -50px;
    }
    

    盒模型 margin/border/padding/content

    引入方式 行内样式: 优先级最高 内联(嵌入方式)/外联(链接方式): 后被读取的覆盖前面的 导入方式: 一般是内联嵌入方式,在内容部分写 "@import url(../path/xxx.css)" 权重: !important > inline > id > class > element

    比较链接方式和导入方式1 链接方式(下面用 link 代替)和导入方式(下面用 @import 代替)都是引入外部的 CSS 文件的方式,下面我们来比较这两种方式,并且说明为什么不推荐使用 @import。

    • link 属于 HTML,通过 <link> 标签中的 href 属性来引入外部文件,除了引入css还有其他用处; 而 @import 属于 CSS,所以导入语句应写在 CSS 中, 要注意的是导入语句应写在样式表的开头,否则无法正确导入外部文件,只能引入css文件;

    • link 无兼容问题; @import 是 CSS2.1 才出现的概念,所以如果浏览器版本较低,无法正确导入外部样式文件;

    • 当 HTML 文件被加载时,link 引用的文件会同时被加载,而 @import 引用的文件则会等页面全部下载完毕再被加载;

    • link 支持使用 Javascript 控制 DOM 去改变样式, @import 则不支持

    区别2 两者都是外部引用CSS的方式,但是存在一定的区别: 区别1:link是XHTML标签,除了加载CSS外,还可以定义RSS等其他事务;@import属于CSS范畴,只能加载CSS。 区别2:link引用CSS时,在页面载入时同时加载;@import需要页面网页完全载入以后加载。 区别3:link是XHTML标签,无兼容问题;@import是在CSS2.1提出的,低版本的浏览器不支持。 区别4:link支持使用Javascript控制DOM去改变样式;而@import不支持。

    CSS hack技巧 什么是CSS hack? 由于不同厂商的流览器或某浏览器的不同版本(如IE6-IE11,Firefox/Safari/Opera/Chrome等),对CSS的支持、 解析不一样,导致在不同浏览器的环境中呈现出不一致的页面展现效果。这时,我们为了获得统一的页面效果,就需要针对不同的浏览器或不同版本写特定的 CSS 样式,我们把这个针对不同的浏览器/不同版本写相应的CSS code的过程,叫做CSS hack!

    CSS hack的原理:
      不同的浏览器 浏览器各版本 对CSS的支持及解析不一样,CSS优先级对 浏览器展现效果 影响,据此针对不同浏览器情景 应用不同 CSS。
    
    CSS hack分类:
      CSS Hack大致 3种 表现形式
      1️⃣CSS属性前缀法
      2️⃣选择器前缀法
      3️⃣IE条件注释法(即HTML头部引用if IE)
      实际项目中CSS Hack大部分是针对IE浏览器不同版本之间的表现差异而引入。
      属性前缀法(即类内部Hack):例如 IE6能识别下划线"_"和星号" * ",IE7能识别星号" * ",但不能识别下划线"_",IE6~IE10都认识"\9",但firefox前述三个都不能认识。
    

    JS

    (2018年1月5日 16:18:52)
    

    JavaScript继承详解

    (http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html)
    
    *面向对象与基于对象*
    
    几乎每个开发人员都有面向对象语言(比如C++、C#、Java)的开发经验。 在传统面向对象的语言中,有两个非常重要的概念 ——"类"和"实例"。 类 定义了一类事物公共的行为和方法; 实例 则是类的一个具体实现。 我们还知道,面向对象编程有三个重要的概念—— 封装、继承和多态。
    
    但是在JavaScript的世界中,所有的这一切特性似乎都不存在。 因为JavaScript本身不是面向对象的语言,而是基于对象的语言。 这里面就有一些有趣的特性,比如JavaScript中所有事物都是对象, 包括字符串、数组、日期、数字,甚至是函数,比如下面这个例子:
    
    // 定义一个函数 - add
    function add(a, b) {
        add.invokeTimes++; // 每次调用 自增
        return a + b;
    }
    // 因为函数本身也是对象,这里为函数add定义一个属性,用来记录此函数被调用的次数
    add.invokeTimes = 0; // 初始化
    add(1 + 1); // 第一次调用
    add(2 + 3); // 第二次调用
    console.log(add.invokeTimes); // 2
    
    ### 模拟JavaScript中类和继承
    在面向对象的语言中,我们使用类来创建一个自定义对象。然而JavaScript中所有事物都是对象,那么用什么办法来创建自定义对象呢?
    这就需要引入另外一个概念 - 原型(prototype),我们可以简单的把prototype看做是一个模版,新创建的自定义对象都是这个模版(prototype)的一个拷贝 (实际上不是拷贝而是链接,只不过这种链接是不可见,给人们的感觉好像是拷贝)。
    
    通过prototype创建自定义对象的一个例子:
    
    // 构造函数
    function Person(name, sex) {
        this.name = name;
        this.sex = sex;
    }
    // 定义Person的原型,原型中的属性可以被自定义对象引用
    Person.prototype = {
        getName: function() {
            return this.name;
        },
        getSex: function() {
            return this.sex;
        }
    }
    

    JavaScript继承方式详解

    (https://segmentfault.com/a/1190000002440502)
    

    JS继承

    (http://www.cnblogs.com/xieex/archive/2008/01/25/1053342.html)
    JavaScript中要实现继承,其实就是实现三层含义:
      1、子类的实例可以共享父类的方法;
    
      2、子类可以覆盖父类的方法或者扩展新的方法;
    
      3、子类和父类都是子类实例的“类型”。
    
    JavaScript中,并不直接从语法上支持继承,但是可以通过模拟的方法来实现继承,以下是关于实现继承的几种方法的总结:
      1、构造继承法
        
      2、原型继承法
      3、实例继承法
      4、拷贝继承法
    
    
    (2018年1月4日 13:35:24)
    
    `
    

    console.log(typeof null); // object console.log(typeof NaN); // number console.log(typeof NaN == undefined); // false console.log(typeof NaN == NaN); // false `

    ()=>{
      function create(obj) {
        console.log(111,obj,this); // 111, {}, Window
        obj.name = '粉粉';
        console.log(222,obj,this); // 222, {name: "粉粉"}, Window 
        obj = new Object()
        console.log(333,obj,this); // 333, {}, Window
        obj.name = '娇娇';
        console.log(444,obj,this); // 444, {name: "娇娇"}, Window
      };
    
      var person = new Object()
      create(person)
      console.log(person.name); // 粉粉
    }
    
    var a = "小旭";
    (function () {
      console.log(window/this); // window
      console.log(typeof a); // undefined // 变量提升 var a = "旭旭"
      console.log(typeof fun1); // function
      console.log(typeof fun2); // undefined
    
      var a = "旭旭"
      function fun1() {}
      var fun2 = function () {}
    
      console.log(typeof a); // string
      console.log(typeof fun1); // function
      console.log(typeof fun2); // function
    })(window)
    
    var foo = {
      bar: function () {
        return this.baz
      },
      baz: 1
    };
    
    (function () {
      console.log(arguments[0]()); // undefined
      console.log(arguments[0].call(foo)); // 1
    })(foo.bar)
    
    function Foo(){
      getName=function(){
        console.log(1);
      };
      return this;
    }
    
    Foo.getName=function(){console.log(2);}
    Foo.prototype.getName=function(){console.log(3);}
    var getName=function(){console.log(4);}
    function getName(){console.log(5);}
    
    Foo.getName(); // 2
    getName(); // 4
    Foo().getName(); // 1
    getName(); // 1
    new Foo.getName(); // 2
    new Foo().getName(); // 3
    
    js是单线程 你用setTimeout 或者setInterval模拟一下多线程
    (http://www.jb51.net/article/26464.htm)
    
    var jobData = []; //假设是一个数组。里面有1000万个数据。
    function sliceJob() {
      //把任务数据划分为100份。
      var num = ( jobData.length/100 ) + 1;
    
      var portion = 100000; //每份有10万个数字。
    
      var addition = 0; //这里用来保存最后的结果。一开始是0;
    
      var intv = setInterval(function () {
        if (num--) { //然后每一份结果。
          additoin += every;
        } else {
          // 计算最后一份, 然后输出结果。 alert('最终结果是:', addition);
          window.clearInterval(intv);
        }
      }, 50);
    }
    var jobData  = []; //假设是一个数组。里面有1000万个数据。
    function sliceJob() {
      var  num  =   (jobData.length  /  100)  +  1; //把任务数据划分为100份。
    
      var  portion  =  100000; //每份有10万个数字。
    
      var  addition  =  0; //这里用来保存最后的结果。一开始是0;
    
      var  intv  =  setInterval(function () {
        if (num--) { //然后每一份结果。
          additoin  +=  every;
        } else {
          // 计算最后一份,然后输出结果。
          alert('最终结果是:',  addition);
          window.clearInterval(intv);
        }
      },  50);
    }
    
    如果页面上有很多js特效,但是加载很慢,影响用户体验,怎么处理?
      除了异步加载,他问我还有没有其他方法
    
      如果循环类型与性能无关,可以从以下两个可选因素来提高整体性能
        1.每次迭代处理的事务
        2.迭代的次数
    
        减少迭代的工作量
        很明显,如果一次循环迭代要花很长时间去执行,那么多次循环需要花更多的时间。一个提升循环整体速度的好方法就是限制循环中耗时的操作数量。
        一个典型的数组处理循环可以采用三种循环中的任何一种。最常见的写法如下:
        Javascript代码:
          for(vari=0;i<items.length;i++){
            process(items[i]);
          }
    
          var j=0;
          while(j<items.length){
            process(items[j]);
          }
    
          var k=0;
          do{process(items[k]);}while(k<items.length);
    
           上面的每个循环中,每次进行循环体时都会产生如下操作:
           1. 一次控制条件中的属性查找(items.length)
           2. 一次控制条件中的数值大小的比较(i<items.length)
           3. 一次控制条件结果是否为true的比较(i<items.length == true)
           4. 一次自增操作(i++)
           5. 一次数组查找(items[i])
           6. 一次函数调用(process(items[j]);)
    
           这些简单循环中,尽管代码不多,但每次迭代都要进行许多操作。代码运行速度很大晨读上取决于函数process()对每个数组项的操作,尽管如此,减少每次迭代中的操作能大幅提高循环的整体性能。
           优化循环的第一步就是减少对象成员及数组项的查找次数。前面例子中每次循环都要查找items.length,这样做很耗时,由于该值在循环运行过程中从未变过,因此产生了不必要的性能损失,提高整个循环的性能很简单,只查找一次属性,并把值存储到一个局部变量中,然后在控制条件中使用整个变量
          Javascript代码
    

    后端技术栈

    (2018年1月4日 13:28:33) 1.熟悉一门后台语言,包括但不限于(php, python, java, scala, go, ruby) 之一, C/C++作为基础中的基础,仍然是后端程序员需要掌握的技能之一

    2.Unix/Linux系统:后端必须掌握的操作系统

    3.数据库:知道常见 的数据库的优化以及运维,能够分析sql并且调优使之满足性能

    4.网络编程(必备技能):了解linux的网络模型epoll, 熟练掌握http, tcp/ip协议,并且能够通过抓包方式debug. 熟练掌握linux, 能够在高并发场景下通过优化内核解决问题

    5.网络安全:知道各种安全攻击方式(xss, csrf, sql注入)代码实现能够规避常见的安全漏洞,处理各种网络攻击事件

    6.算法和数据结构:知道常规的算法和数据结构,通过分析代码能了解架构的计算复杂度和性能,并针对性做出优化

    7.会写文档,注意编码规范.

    脏技术解读

    const 男朋友 = '服务器'; (http://www.cocoachina.com/special/20171218/21571.html)

    冷备份

    假设你是个妹子,你有一位男朋友,于此同时你和另外一位男生暧昧不清,比朋友好,又不是恋人。你随时可以甩了现任男友,另外一位马上就能补上。这是冷备份补充:备份不能用

    热备份

    假设你是个妹子,同时和两位男性在交往,两位都是你男朋友。并且他们还互不干涉,独立运行。这就是双机热备份补充:

    异地容灾备份

    假设你是个妹子,不安于男朋友给你的安全感。在遥远的男友未知的地方,和一位男生保持着联系,你告诉他你没有男朋友,你现在处于纠结期,一旦你和你男朋友分开了,你马上可以把自己感情转移到异地男人那里去。这是异地容灾备份补充:

    云备份

    假设你是个妹子,有一位男朋友,你又付了钱给一家婚姻介绍所,让他帮你留意好的资源,一旦你和你这位男朋友分开,婚姻介绍所马上给你安排资源,你感情不间断运行,这是云备份补充:

    灾难演练

    假设你是个妹子,你怀疑男朋友对你的忠诚,在某宝购买了一个测试忠诚度的服务。这是灾难演练

    友情提醒,在没有备份的情况下,切忌进行灾难演练,说不好会让你数据血本无归。

    Ping(网络延迟)

    假设你是个妹子,你和男友异地恋,你每天晚上都打电话查岗,问他还爱不爱你了,这叫ping

    TraceRoute(路由追踪/路由跟踪)

    假设你是个妹子,你的男友经常玩失踪,所以你希望时刻掌握他的行踪,你先打电话给他的好基友A,A说好基友B知道,B说好基友C知道,C说好基友D知道,D说你男朋友正在网吧打游戏,你终于知道了男友在哪儿,这叫TraceRoute

    心跳监测

    假设你是个妹子,你的男友沉迷游戏经常不接电话无故宕机,所以当你们约好下午逛街以后你要时不时的打个电话询问,看看他是不是还能正常提供服务,这叫心跳监测

    故障切换

    假设你是个妹子,你想去逛街而你的男友A在打游戏不接电话,于是乎你把逛街的请求发给了替补男友B,从而保障服务不间断运行,这叫故障切换

    master-slave(主从式)

    假设你是个妹子,你有很多需要男朋友完成的事情,于是乎你跟A逛街旅游吃饭不可描述,而B只能陪你逛街,不能拥有全部男朋友的权利,这叫主从配置 master-slave

    负载均衡

    假设你是个妹子,你败家太厉害,以至于你的男友根本吃不消,于是呼你找了两个男朋友,一三五单号,二四六双号限行,从而减少一个男朋友所面临的压力,这叫负载均衡

    集群LVS

    假设你是个妹子并且有多个男朋友,配合心跳检测与故障切换和负载均衡将会达到极致的体验,这叫集群LVS。

    注意,当需求单机可以处理的情况下不建议启用集群,会造成大量资源闲置,提高维护成本。

    multi-cluster grid(多集群横向扩容)

    假设你是个妹子,你的需求越来越高导致一个男朋友集群已经处理不了了,于是乎你又新增了另外几个,这叫多集群横向扩容,简称multi-cluster grid

    Scale up(纵向扩容)

    假设你是个妹子,你的男朋友身体瘦弱从而无法满足需求,于是乎你买了很多大补产品帮你男朋友升级,从而提高单机容量,这叫纵向扩容,Scale up

    切记,纵向扩容的成本会越来越高而效果越来越不明显。

    CDN

    假设你是个妹子,你跟男友经常出去游玩,情到深处想做点什么的时候却苦于没有tt,要去超市购买,于是乎你在你们经常去的地方都放置了tt,从而大幅度降低等待时间,这叫CDN加速

    DOS(拒绝服务攻击)

    假设你是个妹子,你的男朋友英俊潇洒风流倜傥财大气粗对你唯一,于是乎你遭到了女性B的敌视,B会以朋友名义在周末请求你男朋友修电脑,修冰箱,占用男朋友大量时间,造成男朋友无法为你服务,这叫拒绝服务攻击,简称DOS

    DDOS(分布式拒绝服务攻击)

    假设你是个妹子,你因男朋友被一位女性敌视,但是你男朋友的处理能力十分强大,处理速度已经高于她的请求速度,于是她雇佣了一票女性来轮流麻烦你的男朋友,这叫分布式拒绝服务攻击,简称DDOS

    访问控制

    假设你是个妹子,你发现男朋友总是在处理一些无关紧要的其它请求,于是乎你给男朋友了一个白名单,要求他只处理白名单内的请求,而拒绝其它身份不明的人的要求,这叫访问控制

    入侵检测系统(IDS)

    假设你是个妹子,你男朋友风流倜傥,你总担心他出轨,于是你在他身上安装了一个窃听器,里面内置了一些可疑女生勾搭行为的特征库,只要出现疑似被勾搭的情况,就会立刻向你报警,这叫入侵检测系统(IDS)

    入侵防御系统(IPS)

    假设你是个妹子,你改良了上面的窃听器,当可疑女性对你男朋友做出勾搭行为的时候,立刻释放1万伏电压,把可疑人击昏,终止这次勾搭。这叫入侵防御系统(IPS)

    SIEM/SOC

    假设你是个妹子,虽然你装了各种窃听器、报警器,可是你蓝朋友处处留情,报警器响个不停,让你应接不暇,疲于奔命,于是你搞了个装置集中收集这些出轨告警,进行综合分析,生成你男朋友的出轨报告。这叫SIEM或者SOC

    等级保护

    假设你是个妹子,你把男朋友的出轨报告提交给他父母,得到了他们的大力支持,男友父母开始对他严加管教、限期整改,为你们的爱情保驾护航,做到合情合理、合法合规,这叫等级保护

    自建专线/租用专线/SDWAN

    假设你是个妹子,你离男朋友家有点远,你开车去,这叫自建专线,你打车过去,这叫租用专线,你骑摩拜单车过去,这叫SDWAN

    VPN

    假设你是个妹子,你和男朋友的恋爱遭到了双方家长的反对,不准双方往来,你们偷偷挖了一条隧道,便于进行幽会,这叫VPN

    逆向工程

    假设你是个妹子,你的男朋友太优秀而遭人窥视,于是乎它们研究了一下你的男朋友,稍微修改了一点点生产出一个男朋友B,与你的男朋友百分制99相似,这不叫剽窃,这叫逆向工程,比如男朋友外挂

    压力测试

    假设你是个妹子,你要求你的男朋友坚持十分钟,然后十五分钟继而二十分钟,以测试你男朋友的极限在哪里,这叫压力测试

    数据分析

    假设你是个妹子,为了保证你男朋友的正常运行,于是乎你每天查看他的微信微博等社交资料来寻找可能产生问题的线索,这叫数据分析

    并行计算

    假设你是个妹子,你的男朋友属于社交活跃选手,每天的微博知乎微信生产了大量信息,你发现自己的分析速度远远低于他生的速度,于是乎你找来你的闺蜜一起分析,这叫并行计算

    云计算

    假设你是个妹子,你的男朋友太能折腾处处留情产生了天量的待处理信息,你和你的闺蜜们已经累趴也没赶上他创造的速度,于是你付费在知乎上找了20个小伙伴帮你一起分析,这叫云计算

    数据挖掘

    假设你是个妹子,你在得到男朋友经常出没的地点后,根据酒店,敏感时间段等信息确定男朋友因该是出轨了,这叫数据挖掘

    精准推送

    假设你是个妹子,在分析男友的数据后,得知他下午又要出去开房,于是乎你在他准备出门前给他发了个短信,问他有没有带tt,没有的话可以在我这里买,这叫精准推送,需要配合数据挖掘

    容器

    假如你是个妹子,你的男朋友总出去浪而各种出问题,于是乎你租了间屋子并准备好了所有需要的东西并告诉他,以后不用找酒店了,直接来我这屋子吧,什么都准备好了,这叫容器

    collection

    假如你是个妹子,你每天都要和男朋友打通一次接口,采集数据。你一天24小时不停地采,这叫实时数据采集。你决定开发新的接口来和男朋友交流,这叫虚拟化。你决定从不同的男友身上采集数据,你就是大数据中心。有一天你决定生一个宝宝,这叫大数据应用。宝宝生下来不知道是谁的,这叫大数据脱敏。但是从宝宝外观来看,黑色皮肤金色头发,这叫数据融合跨域建模。你决定把这个宝宝拿来展览收点门票,这叫大数据变现

    Git使用笔记

    warning: LF will be replaced by CRLF in source/tags/index.md. 警告:LF将被替换为CRLF在 source/tags/index.md。 The file will have its original line endings in your working directory. 该文件将在您的工作目录中 有其原始的 行结束。 warning: adding embedded git repository: themes/shana 警告:添加嵌入式git存储库:主题/shana。 hint: You've added another git repository inside your current repository. 提示:您已经在当前存储库中添加了另一个git存储库。 hint: Clones of the outer repository will not contain the contents of 提示:外部存储库的克隆将不包含内容。 hint: the embedded repository and will not know how to obtain it. 提示:嵌入式存储库,不知道如何获取它。

    hint: If you meant to add a submodule, use: 提示:如果您打算添加一个子模块,请使用: hint: git submodule add <url> themes/shana

    hint: If you added this path by mistake, you can remove it from the 提示:如果您错误地添加了这条路径,您可以从该路径中删除它。 hint: index with:

    hint: git rm --cached themes/shana

    hint: See "git help submodule" for more information.

    GitHub学习

    (https://guides.github.com/activities/hello-world/)

    创建一个新的存储库

    1.在右上角,在你的头像或身份证旁边,点击然后选择新的存储库。(New repository)
    2.命名您的存储库(hello-world)。
    3.写一个简短的描述。
    4.选择使用README初始化此存储库。
    

    创建一个分支

    分枝是一次处理不同版本的存储库的方式。
    默认情况下,你的仓库有一个名为master这被认为是最终的分支(主支)。在提交之前,我们使用分支进行实验和编辑master。
    当你创建一个分支,你正在复制或快照master。如果其他人更改master,你可以在你的分支上引入这些更新。
    分支机构在GitHub仓库中完成类似的目标。
    在GitHub,开发人员、作者和设计人员,使用 分支机构 来保持错误修复和功能工作。与master(生产)分开。当一个版本变化准备就绪时,他们将分支合并到master。
    
    1.转到您的新存储库hello-world。
    2.点击文件列表顶部的下拉菜单分支:master。
    3.输入分支名称,"readme-edits",进入新的分支文本框。
    4.选择蓝色创建分支或在键盘上按“Enter”键。
    

    进行并提交更改

    现在,你正在分支,这是副本master。我们来做一些编辑。
    *制定和提交更改*
      1.点击readme.md文件
      2.点击铅笔图标的文件视图右上角的编辑。
      3.在编辑器中,写一点关于你自己的。
      4.写一个信息,描述你的变化提交。
      5.点击提交更改按钮
    这些变化将只是分支上的,所以现在这个分支包含的内容是不同于Master的。
    

    拉取请求

    1.点击Pull requests选项卡,然后从Pull requests页面,点击绿色的新拉的要求按钮
    2.示例比较框
    3.比较差异
    4.如果满意这些要提交的更改,请点击大绿色创建合并请求按钮。
    5.给你的拉取请求一个标题,并写下你的变化的简要说明。
    当你完成你的消息,点击创建拉取请求!
    Tips: 您可以使用表情符号和拖放图像和GIF到评论和拉取请求。
    

    合并请求

    在这最后一步,把你的改变 合并你的 分支 入master。
    1.点击绿色合并请求按钮将更改合并到master。
    2.点击确认合并。
    3.继续并删除分支,因为它的变化已被合并,与删除分支紫色框中的按钮。
    

    庆祝! 通过完成本教程中,你已经学会了创建一个项目,并在GitHub上拉请求!

    +以下是您在本教程中完成的任务:
      1.创建了一个开源库
      2.开始并管理一个新的分支
      3.更改了一个文件,并将这些更改提交给GitHub
      4.完成了一个合并请求
    

    can i use

    (兼容性测试 网站)

    Weex笔记

    -[手册] -通用特性 -手势 -斯德哥尔摩 - - -

    通用特性

    # 手势
      ● Touch // 事件信息详细、精准 监听缓慢
        ○ touchstart
        ○ touchmove
        ○ touchend
      ● Pan
        ○ panstart // 采样部分事件信息 不精准 快速、
    

    Weex学习笔记

    -01Weex简介 -02Weex环境搭建 -04Weex常用命令和热更新

    01Weex简介

    三大环节 1.搭建 2.组件和命令 3.答疑

    02Weex环境搭建

    node 简介:单双版本号(版本选择) java环境 git weex-toolkit 脚手架 webpack android-studio 安装步骤讲解,sdk问题

    04Weex常用命令和热更新

    package.json 'scripts' 'dev' -w:'watch'; 'serve' 'build' : 添加 "--watch"(刷新更新); 路由添加 "webpack-dev-server"(生效热更新), 例如:192.168.0.111:8080/webpack-dev-server/...; 'build-plugin' : 且听下回分解;

    前端性能优化之桌面浏览器优化策略#

    (https://juejin.im/post/5a43343bf265da432f316441)

    网络加载类

    1.减少 HTTP 资源请求次数
      尽可能合并资源图片、Javascript、CSS 代码,减少页面请求数和资源请求消耗,缩短页面首次访问的用户等待时间。
      构建工具合并雪碧图、代码压缩、避免重复的资源,防止增加多余请求。
    
    2.减小 HTTP 请求大小
      尽量减小每个 HTTP 请求的大小,没必要的图片、JavaScript、CSS 及HTML 代码,对文件进行#压缩#优化,或者使用 gzip 压缩传输内容,缩短网络传输等待延时。
      前面我们使用构建工具来压缩静态图片资源以及移除代码中的注释并压缩,目的都是为了减小 HTTP 请求的大小。
    
    3.将CSS 或 JavaScript 放到外部文件中,避免使用 <style> 和 <script> 标签直接引入
      在 HTML 文件中引用外部资源可以有效利用浏览器的 *静态资源缓存*,但有时候在移动端页面 CSS 或 JavaScript 比较简单的情况下为了减少请求,也会将 CSS 或 JavaScript 直接写到 HTML 里面,具体 要根据 CSS 或 JavaScript 文件的大小和业务的场景来分析。如果 CSS 或 JavaScript 文件内容较多,业务逻辑较复杂,建议放到外部文件引入。
    
    4.避免页面中空的 href 和 src
      当 <link>标签的 href 属性为空,或<script>、<img>、<iframe>标签的 src 属性为空时,浏览器在渲染的过程中仍会将 href 属性或 src 属性中的空内容进行加载,直到加载失败,这样就阻塞了页面中其他资源的下载进程,而且最终加载到的内容是无效的,因此要尽量避免。
    
    5.为 HTML 指定 Cache-Control 或 Expires
      为 HTML内容设置 Cache-Control 或 Expires 可以将 HTML内容缓存起来,避免频繁向服务器端发送请求。在页面Cache-Control 或 Expires 头部有效时,浏览器将从缓存中读取内容,不向服务器发送请求。
      > <meta http-equiv="Cache-Control" content="max-age=7200" />
      > <meta http-equiv="Expires" content="Mon, 20 Jul 2017 23:00:00 GMT" />
    
    6.合理设置 Etag 和 Last-Modified
      合理设置 Etag 和 Last-Modified 使用浏览器缓存,对于未修改的文件,静态资源服务器会向浏览器端返回 304 ,让浏览器从缓存中读取文件,减少 Web 资源下载的带宽消耗并降低服务器负载。
      > <meta http-equiv="Last-Modified" content="Mon, 03 Oct 2017 17:45:57 GMT" />
    
    7.减少页面重定向
      页面每次重定向都会延长页面内容返回的等待延时,一次重定向大约需要 \600\ 毫秒的时间开销,为了保证用户尽快看到页面的内容,要尽量避免页面重定向。
    
    8.使用静态资源分域存放来增加下载并行数
      浏览器在同一时刻向同一个域名请求文件的并行下载数是有限的,因此可以利用多个域名的主机来存放不同的静态资源,增大页面加载时资源的并行下载数,缩短页面资源加载的时间。通常根据多个域名来分别存储 JavaScript、CSS 和图片文件。
    
    9.使用静态资源 CDN 来存储文件
      如果条件允许,可以利用 CDN 网络加快同一个地理区域内重复静态资源文件的响应下载速度,缩短资源请求时间。
    
    10.使用 CDN Combo 下载传输内容
      CDN Combo 是在 CDN 服务器端将多个文件请求打包成一个文件的形式来返回的技术,这样可以实现 HTTP 连接传输的一次复用,减少浏览器的 HTTP 请求数,加快资源下载速度。例如同一个域名 CDN 服务器上的 a.js,b.js,c.js 就可以按如下方式在一个请求中下载。
      > <script src="//cdn.domain.com/path/a.js,b.js,c.js"></script>
    
    11.使用可缓存的 AJAX
      对于返回内容相同的请求,没必要每次都直接从服务端拉取,合理使用 AJAX 缓存能加快 AJAX 响应速度并减轻服务器压力。
      $.ajax({
        url:url,
        type: 'get',
        cache: true,  // 推荐使用缓存
        data: {}
        success(){
            //...
        },
        error(){
            //...
        }
      });
    
    12.使用 GET 来完成 AJAX 请求
      使用 XMLHttpRequest 时,浏览器中的 POST 方法发送请求首先发送文件头,然后发送 HTTP 正文数据。而使用 GET 时只发送头部,所以在拉取服务端数据时使用 GET 请求效率更高。
    
    13.减少 Cookie 的大小并进行 Cookie 隔离
      HTTP 请求通常默认带上浏览器端的 Cookie 一起发送给服务器,所以在非必要的情况下,要尽量减少 Cookie 来减小 HTTP 请求的大小。对于静态资源,尽量使用不同的域名来存放,因为 Cookie 默认是不能跨域的,这样就做到了不同域名下静态资源请求的 Cookie 隔离。
    
    14. 缩小 favicon.ico 并缓存
      有利于 favicon.ico 的重复加载,因为一般一个 Web 应用的 favicon.ico 是很少改变的。
    
    15.推荐使用异步 JavaScript 资源
      异步的 JavaScript 资源不会阻塞文档解析,所以允许在浏览器中优先渲染页面,延后加载脚本执行。例如 JavaScript 的引用可以如下设置,也可以使用模块化加载机制来实现。
      > <script src="//main.js" defer></script> //使用defer时,加载后续文档元素的过程和main.js的加载是并行的,但main.js的执行要在页面所有元素解析完成之后才开始执行
      > <script src="//main.js" async></script> //使用async时,加载后续文档元素的过程和main.js的加载是并行的
    
    16.消除阻塞渲染的 CSS 及 JavaScript
      对于页面中加载时间过长的 CSS 或 JavaScript 文件,需要进行合理拆分或延后加载,保证关键路径的资源能快速加载完成。
    
    17.避免使用 CSS import 引用加载 CSS
      CSS 中的 @import 可以从另一个文件中引入样式,但应该避免这种用法,因为这样会增加 CSS 资源加载的关键路径长度,带有 @import 的 CSS 样式需要在 CSS 文件串行解析到 @import 时才会加载另外的 CSS 文件,大大延后 CSS 渲染完成的时间。
    
      <!--不推荐-->
      <style>
        @import "path/main.css";
      </style>
    
      <!--推荐-->
      <link rel="stylesheet" href="//cdn1.domain.com/path/main.css">
    

    页面渲染类

    1. 把 CSS 资源引用放到 HTML 文件顶部
      一般推荐将所有 CSS 资源尽早指定在 HTML 文档 <head> 中,这样浏览器可以优先加载 CSS 并尽早完成页面渲染。
     总结:CSS顶部引入
    
    2.JavaScript 资源引用放到 HTML 文件底部
      JavaScript 资源放到 HTML 文档底部可以防止 JavaScript 的加载和解析执行对页面渲染造成阻塞。由于 JavaScript 资源默认是解析阻塞的,除非被标记为异步或者通过其他的异步方式加载,否则会阻塞 HTML DOM 解析和 CSS 渲染的过程。
     总结:JS底部引入
    
    3.不要在 HTML 中直接缩放图片
      在 HTML 中直接缩放图片会导致页面内容的重排重绘,此时可能会使页面中的其他操作产生卡顿,因此要尽量减少在页面中直接进行图片缩放。
     总结:HTML避免直接缩放图片等DOM操作
    
    4.减少 DOM 元素数量和深度
      HTML 中标签元素越多,标签的层级越深,浏览器解析 # DOM # 并绘制到浏览器中所花的时间就越长,所以应尽可能保持 DOM 元素简洁和层级较少。
     总结:减少DOM元素数量和深度
    
    5.尽量避免使用 <table>、<iframe>等慢元素
      <table>内容的渲染是将 table 的 DOM 渲染树全部生成完并一次性绘制到页面上的,所以在长表格渲染时很耗性能,应该尽量避免使用它,可以考虑使用列表元素 <ul> 代替。尽量使用异步的方式动态添加 iframe 内资源的下载进程会阻塞父页面静态资源的下载与 CSS 及 HTML DOM的解析。
      
    6.避免运行耗时的 Javascript
      长时间运行的 JavaScript 会阻塞浏览器构建 DOM 树、DOM 渲染树、渲染页面。所以,任何与页面初次渲染无关的逻辑功能都应该延迟加载执行,这和 JavaScript 资源的异步加载思路是一致的。
    
    7.避免使用 CSS 表达式或 CSS 滤镜
      CSS 表达式或 CSS 滤镜的解析渲染速度是比较慢的,在有其他解决方案的情况下应该尽量避免使用。
      //不推荐
      //.opacity{
      //    filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);
      //}
    

    前端性能优化不是一件简简单单的事情,其涉及的内容很多。 根据实际情况将这些方法应用到自己的项目当中,要想全部做到几乎是不可能的,但做到用户可接受的原则还是很容易实现的。 技术来自于交流。

    实现div毛玻璃背景#

    (https://juejin.im/post/5a45a89051882574d23ca7d6)

    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>毛玻璃效果</title>
    </head>
    <style>
      *{
        margin: 0;
        padding: 0;
      }
      .bg{
        background:url(1.jpg) no-repeat center center fixed;/* 与下面的blur_box:before中的background设置一样 */
        width:100%;
        height:100%;
      }
      .blur_box{
        z-index: 0;/* 为不影响内容显示必须为最高层 */
        position: relative;
        overflow: hidden;
      }
      .blur_box:before{
        content: "";/* 必须包括 */
        position: absolute;/* 固定模糊层位置 */
        width:300%;
        height:300%;
        left: -100%;/* 回调模糊层位置 */
        top: -100%;/* 回调模糊层位置 */
        background:url(1.jpg) no-repeat center center fixed;/* 与上面的bg中的background设置一样 */
        filter: blur(20px);/* 值越大越模糊 */
        z-index: -2;/* 模糊层在最下面 */
      }
      .rgba{
        background-color: rgba(0, 0, 0, 0.2);/* 为文字更好显示,将背景颜色加深 */
        position: absolute;/* 固定半透明色层位置 */
        width:100%;
        height:100%;
        z-index: -1;/* 中间是rgba半透明色层 */
      }
      .content_text{
        text-align: center;
        color: rgba(255, 255, 255, 0.8);
        padding: 50px 30px;
        line-height: 28px;
      }
      article{
        width:40%;
        height:300px;
        margin:120px auto;
      }
    </style>
    <body>
      <div class="bg">
        <article class="blur_box">
          <div class="rgba"></div><!-- 写在这其实和blur_box:before效果相同,但已经设置过blur_box:before了 -->
          <div class="content_text">
            <h1>haha</h1>
            <p>texttexttexttexttexttexttexttexttext</p>
            <p>texttexttexttexttexttexttexttexttext</p>
            <p>texttexttexttexttexttexttexttexttext</p>
            <p>texttexttexttexttexttexttexttexttext</p>
            <p>texttexttexttexttexttexttexttexttext</p>
            <p>texttexttexttexttexttexttexttexttext</p>
          </div>
        </article>
      </div>
    </body>
    </html>
    

    注释已经写的很详细了,但有一点还是得单独说一下。因为blur()产生的模糊效果当值越大时,就会有越宽的边缘渐变过渡,为了消除(实际上只是让它看不见),我将模糊层的宽度和高度都变大,再通过top和left负值调整位置。

    .blur_box:before{ content: ""; position: absolute; width:300%; /* 模糊层的宽度和高度都变大 / height:300%; left: -100%; / 回调模糊层位置 */ top: -100%; background:url(1.jpg) no-repeat center center fixed; filter: blur(20px); z-index: -2; } 其中.rgba也可改为白色半透明background-color: rgba(255,255,255,0.2);,完全取决于自己,然后相应改变内容的字色。blur()的参数也可以根据自己爱好试着改变出想要的效果。

    很全很全的前端本地存储讲解#

    (https://segmentfault.com/a/1190000012578794)

    JSONP的原理与实现以及XSS,CSRF的相亲相爱#

    (https://www.jianshu.com/p/81efb4d188d7)

    1.JSONP的原理与实现

    1.1 同源策略
      前端跨域是每个前端人绕不过的坎,也是必须了解的一个知识点。我记得第一次遇到前端跨域这个坑的时候,真是无语到极点,对于一个移动端出身的人来说,觉得这个玩意无可理喻。但是后来慢慢了解,觉得前端的同源策略是非常有必要的。同源策略就是浏览器默认让www.baidu.com不能加载来自www.google.com的数据。对于现在来说,所有数据都是同源的可能性基本上很小,比如我们公司静态资源www.image.com和前端资源www.htmlcss.com的CDN路径都不一样,前端获取后台数据www.apidata.com又是另一个地址。如何解决这个坑呢?我们公司通过两种方式来避开。具体就是通过设置Access-Control-Allow-Origin来做POST请求,用JSONP来实现GET请求,因为JSONP只能实现GET请求。
    1.1.1 通过Access-Control-Allow-Origin支持跨域
      有些人肯定就纳闷了,我就喜欢跨域,我就不关注安全,难道就没有办法了吗?当然是否定的。你需要做的,只是让服务器在返回的header里面加上Access-Control-Allow-Origin这个域就可以了。这样浏览器在接收到服务器返回的数据,就不会因为违反同源策略限制你拿到数据了。下面就用抓包来具体看一下:
    

    健康体质

    人体健康有五大决定因素:父母遗传占15%,社会环境占10%,自然环境占7%,医疗条件占8%,而生活方式占60%,几乎起了决定作用。 做到以下几点,早看更健康! 1、生活作息 不熬夜,晚上11:00之前睡觉。早上7:00起床。中午小睡半小时。 2、饮食规律 皇帝的早餐,大臣的中餐,叫花子的晚餐。 按照很多健康专家的倡导,应该是:早餐吃饱、午饭吃好、晚饭吃少。但现实中,很多白领、上班一族却恰恰是早饭不吃,午饭凑合,晚饭撑个饱。 长期不吃早餐容易得胆囊炎,午饭不按时吃容易得胃病。每餐一定多吃蔬菜。 3、全世界最不好的习惯是抽烟 抽烟的人,气管炎,肺气肿或者肺心病,最后肺癌,这是死亡三部曲。 4、喝醉一次,等于得一次急性肝炎 最不健康的生活方式:第一是吸烟,第二是酗酒。 5、轻伤就要治 每一个人都要珍惜自己的健康,早防早治。 6、人是气死的 健康的一半是心理健康,疾病的一半是心理疾病,所以,一定不要当情绪的俘虏,而要做情绪的主人;一定要去驾驭情绪,不要让情绪驾驭你。记住,情绪是人们健康的指挥棒,至关重要。 生活中的三种“快乐”,我们要时刻牢记:知足常乐、自得其乐、助人为乐。 7、家庭不和睦,人就易生病 有的家庭小吵天天有,大吵三六九。家庭不和睦,人就易生病。 8、走路是非常好的锻炼方式 人很容易“死在嘴上,懒在腿上”。要坚持每天锻炼半个小时到一个小时,锻炼内容可以采取最简单的办法——走,这是最简单、最经济、最有效的办法。 体质上升期(0-28岁):要参加体育锻炼,羽毛球、乒乓球、马拉松、游泳等活动。 体质下降期(28-49岁):这时就不要参加竞技运动了,要进行体质锻炼。 老年体质衰退期(49岁后):要进行功能锻炼,保持功能正常。最推荐的运动是快速步行(>120步/分)、游泳。年长者适合练太极。 9、请大家记住一个原则 吃植物性的东西,一定要占80%,动物性的东西只能占20%。我们现在相反了,所以很多病都来了,肥胖也来了,糖尿病也来了,痛风也来了。 10、男人要做到12个“一” 男人是家里的顶梁柱,承受着更大的工作和生活压力,在健康方面却更加“粗枝大叶”,因此需要注意更多! 男同胞们每天要尽量做到下面几个一: 每周吃一次,每天一个西红柿 常喝一杯绿茶,每天一把核桃 少抽一支烟,每天几杯白开水 每天一个苹果,白酒不超一两 常喝一杯酸奶,每天一根香蕉 多一些微笑,多一点运动

    长寿健康生活6要点 一定要吃好3顿饭 一定要睡好8小时觉 每天坚持运动半个小时 每天要笑,身心健康 一定要家庭和睦 不吸烟,不酗酒,每天健走

    刷题阶段

    =============================

    文档历史修改记录表

    | 创建人 | 创建时间 | 当前版本 | 备注 | | 李仕臣 | 2017-10-27 | 0.1 | |

    -每日补充 -前端开发面试题收集 -总结 -css部分 -总结 -清除浮动的方法 -webpack -一.webpack基础 -二.webpack配置文件常用配置项介绍 -三.webpack-dev-server -四.例子 -跨域 -JSONP跨域 -js部分 -算法 -JS10个难点 -阿里电话面试 -模拟面试总结 -浅谈HTTP -jQuery 面试问题及答案 -requery.js用法 -OSI七层传输协议 -超文本传输协议 -前端优化点 -webpack优化资源 -前/后端交互

    每日补充

    2017年11月12日 21:39:27 补充: 1、MNV* 开发模式 https://www.sohu.com/a/102942166_364497 校导张成文 | mnv*框架开发时代 2016-07-09 15:09

      当下框架设计显然已经在方式上又发展了一步,virtual 提出不久,使用前端代码来调用native的思路就开始被实践。相信大家也知道是什么东西。到了今天,我们不得不承认,mnv* 框架开发时代已经到来。
      mnv是什么,具体可以这么理解,model-Native-View-*,而后面的则可以认为是 virtual dom 或mvvm 中的 ,或者我们也可以自己使用来实现的调用方式。想想这样定义是非常合适的。相比之前的不同,就是用nativeView 代替了 View。那么我们再看下从dom api 到mnv*,我们为什么会看到这样的变化。
      1.dom交互
      在此之前不得不提下之前的dom交互框架,就是直接选择找到特定的dom进行操作,思路十分直接也很实用,通过dom交互框架,相比原生API,我们可以比较高效地处理dom的改变和事件绑定了,这种高效的方式给我们带来了效率上的提高,但是页面复杂了就不好处理了。
      随着技术的盛行,应用开始被广泛运用。SPA的引入将整个应用的内容都在一个页面中进行异步交互。这样,原有的dom交互方式开发就显得不好管理,例如某SPA页面上交互和异步加载的内容很多,我们的做法是每一次请求渲染后做事件绑定,异步请求后再做另一部分事件绑定,后面以此类推。当所有异步页面全部调用完成,页面上的绑定将变得十分混乱,各种元素绑定,渲染后的视图内容逻辑不清,又不得不声明各种变量保存每次异步加载时返回的数据,因为页面交互需要对这些数据做操作,最后写完,项目代码就成了一锅粥。
      2.前端
      为了更方便地统一管理页面上的事件、数据和视图内容,就有了早期mvc的框架设计。mvc可以认为是一种,其基本思路是将dom交互的过程分为调用事件、获取数据、管理视图。即将之前所有的事件、数据、视图分别统一管理。用model来存放数据请求和数据操作,视图来存放对视图的操作和改变,controller用来管理各种事件绑定。
      例如,SPA中的每个异步页面可以看成是一个组件,之前的做法是每个组件独立完成自己的数据请求操作、渲染和数据绑定,但是组件多了,每个组件自己去做就比较混乱,逻辑比较混乱。到了mvc里面,所有的组件数据请求、渲染、数据绑定都到一个统一的model、view、controller注册管理。后面的操作我们就不再管你有多少个组件了,你要调用必须要通过统一的model、view、controller来调。通俗来说就像是组件交出了自己控制权到一个统一的地方注册调用,这样就方便了很多,相信大家都已经了解过,这里就省篇幅不举例了。
      3.前端mvp
      mvp可以跟mvc对照起来看,而且我们也很少专门去关注它。和mvc一样,mvc的M就是Model, V就是View,而P,则代表Presenter,它与Controller有点相似。不同的是,在mvc中V会直接展现M,而在mvp中V会把所有的任务都委托给P。V和P会互相持有reference,因此可以互相调用。
      例如我们可以在mvc代码上做一点改变,写成这样:
    
      几个好处,这样将view和Controller的引用关联了起来,而mvc一般是通过事件监听或观察者的异步方式来实现的,我们可以在任意地方定义注册监听事件都不会有问题,这样监听的事件和触发这个事件的html元素脱离了引用,当应用复杂起来后要维护dom的交互逻辑就比较麻烦了。而mvp提供了一个简单的引用,将元素对应的操作与对应的presenter关联起来。我们要查询元素对应的controller时只要通过Controller.vp就可以直接调用了,其实这个时候就和mvvm的定义方式有点类似了,不是吗?
      4.前端mvvm
      mvvm概念可以认为是一个自动化的presenter,也在这个时候进一步弱化了C层,任何操作都通过viewModel来驱动。Controller最终在页面上的行为通过s的形式体现,通过对directives的识别来注册事件,这样管理起来就更清晰了。
      看一个定义的例子:
      和mvp的定义比较,有点类似,mvvm设计一个很大的好处是将mvc中controller中的controller注册到相对应的元素中,让我们后期维护时很快定位,免去了查看controller中event列表的工作,而且初始化后自动做数据绑定,能将页面中所有同类操作复用,大大节省了我们自己写代码做绑定的时间。这段代码中初始化时自动帮我们就做了数值填充、数据双向绑定、事件绑定的事情。
      那么框架怎样帮我做的呢。我们来看下VM做了哪些事情:这里传入了元素、数据、方法列表、自定义directive列表,首先程序找到这个元素,开始对这个元素的属性节点进行遍历,一旦遍历到属性名称含有q-开头的属性是,认为是mvvm框架自定义的属性,然后会对属性的指进行特殊处理;例如遍历到q-html=""时,将data中的值赋给这个元素的innerHTML;如果遍历到q-on="click: submit"时,将这这个元素上绑定click事件,事件回调函数为submit;也可以自定义q-mydo的指令,遍历到该节点属性是,调用directive中的mydo方法,输入参数为data中的getValue方法返回的值,getValue输入参数为number值,这里的getValue被称为过滤器。
      这里要知道的是q-开头的属性指令是框架约定的,不同的框架约定的不一样,例如ng-、v-、ms-,这些大家也都见过或用过。这里viewModel创建进行绑定的原理就这么简单,按照这个思路去扩充,就可以自己写一个。当然完整的框架涉及东西多的多,含有丰富的directive、filter、表达式、vm完善的api和甚至一些兼容性处理等。
      总结来说从到mvp,然后到mvvm,前端仍然是向着易实现、易维护、易扩展的基本方向发展的。但目前前端各类框架也已经成熟并开始版本迭代。但是,这还没有结束,我们依然没有脱离dom编程的基本套路,一次次框架的改进只是提高了我们的开发效率,但是dom元素的效率仍没有得到本质的提升。
      5.前端virtual dom
      为了改进dom交互的效率,或者说是尽量减少dom交互的次数,virtual dom的概念当下十分盛行,目前圈内各种大小团队纷纷投入项目使用。因为viewModel的改变最终还是要实时操作dom来刷新view层,而dom对象的操作相对于Java对象的操作仍然是要慢些。原因很简单,dom节点对象的内置属性很多,就创建一个dom对象而言,dom的创建需要处理各种内置属性的初始化,而如果使用Java对象来描述就简单了。
      使用virtual dom,页面的渲染过程不再是数据直接通过前端模板渲染到页面,也不是初始化viewModel进行页面模板填充和事件绑定,而是通过dom衍生描述语法(这为什么称为DOM衍生描述语法,通常我们通过html来描述,但是目前一些框架是通过非标准的html的方式描述的,定义的一套迎合自己框架的方式,其实使用html也是可以的)解析生成virtual dom,页面交互变成了是修改virtual dom,然后将virtual dom的改变反映到htmlView层上。
    
      可以使用如下java来表示:
    
      如果java对象children属性第三个元素要被移除,同时,添加一个class为ui-list-item2的li节点,则首先需要对java对象进行修改记录所有的操作,最后将修改的vitual dom变化反映到页面上:
    
      这里的对象就相当于virtual dom,用户的某个交互操作可能导致dom的多个地方,如果没有vitual dom,那可能就要进行多次dom操作,virtual dom则可以将多个用户交互操作反映在virtual dom上,最后做的virtual dom DIFF然后再ditch到页面view层上。相对于mvvm,在页面初始化渲染阶段,也避免了扫面节点,解析s,要知道这些操作都是dom操作,使用virtual dom显然能将页面渲染速度提高不少。
      6.前端mnv*
      如果说vitual dom减少了dom的交互次数,那么mnv*想要做的一件事情就是完全抛弃使用dom,那样就只能在view层做改进了,使用nativeView来代替目前html的view,而交互逻辑依然可以使用viewModel、virtual Dom或者来实现,具体就看实现的方式了。
      要做到NativeView的操作,这里与之前不同之处就是调用时通过衍生HTML语法通过解释器执行nativeView的渲染,这时就需要在native和衍生HTML语法之间添加一层解释器来解析现有的view描述语法了。比如我们看一个渲染Native的例子:
    
      这里和vitual 框架类似的地方都是都使用衍生的html描述语法来表示view层,而不同的是mnv模式是调用的nativeView来实现的衍生的view展示。其实这里和上节中的实现唯一不同的地方是这里的view是native view。当然这只是一种实现,目前mnv的实现方案已经不止一种了,有人已经实践了通过的编程方式来将渲染转化为native view的方案。
      7.总结
      总结下来,前端框架一次次进化,先从效率的方向上提升,然后在性能上完善,这里只是想提出mnv*的一个概念来描述前端native开发的这个阶段。目前mnv的开发模式开始进入视线,也在快速地形成和建立生态。但尽管如此,我们如果需要选择技术栈方案,当然还是以最适合我们的作为最高原则。切忌过度设计。
      作者简介:,英文名Ouven,校导前端开发工程师,前前端工程师,对前端领域的技术知识具有较高的职业能力和探究精神。对前端响应式页面设计、工程构建组件化、mv*设计实现、前端优化、ES6开发体系、知识体系等有深入的研究和项目实践。
    

    2017年11月19日 11:53:51 今日学习: vue官网,了解pug(jede)语法、单文件组件、理解关注点分离、

    前端开发面试题收集

    总结

    面试时最重要是 随机应变。问到一个不会的知识点应该,最起码说出一个大体思路与方向。
    真诚,把眼睛睁开。
    

    css部分

    http://www.cnblogs.com/wj204/p/5813736.html
    
    1.问: CSS属性是否区分大小写?
    答:不区分。(HTML, CSS都不区分,但为了更好的可读性和团队协作,一般都小写,而在XHTML 中元素名称和属性是必须小写的。)
    
    2.问:对行内元素设置margin-top 和margin-bottom是否起作用?
    答:不起作用。(需要注意行内元素的替换元素img、input,他们是行内元素,但是可以为其设置宽高,并且margin属性也是对其起作用的,有着类似于Inline-block的行为)。看具体效果:
        <style> 
            div {
              width: 500px;
              height: 500px;
              margin-top: 100px;
              margin-left: 100px;
              background: lightblue;
            }
            span {
              margin: 100px;
            }
            img {
              margin: 100px;
            }
        </style>
        <body class="claro"> 
          <div class="test_wrap">
            <span>
              我是行内元素,设置margin看是否对我起作用
            </span>
            <img src="" alt="我是行内替换元素,margin-top,margin-bottom对我起作用">
          </div>
        </body>
    
    3.问:对内联元素设置padding-top和padding-bottom是否会增加它的高度
    答:不会。同上题,要注意行内元素的替换元素,img设置padding-top/bottom是会起作用的。
    
    4.问:如果设置'\<p>'的font-size: 10rem;那么当用户重置或拖拽浏览器窗口时,它的文本会不会受到影响?
    答:不会。(rem是css3新增的一个相对单位(root em,根em),这个单位引起了广泛关注。这个单位与em有什么区别呢?区别在于使用rem为元素设定字体大小时,仍然是相对大小,但相对的只是HTML根元素。)
    
    5.问: 伪类选择器:checked将作用与input类型为radio或者checkbox, 不会作用于option?
    答:不对。(可以作用于option,试了下感觉并没有什么用,虽然能选中,但是这个不能改变其中的属性。)
        <style>
            option:checked {
              color: red;
            }
            input:checked {
              background: red;
            }
        </style>
        <div>
          <select>
            <option>Volvo</option>
            <option selected="selected">Saab</option>
            <option>Mercedes</option>
            <option>Audi</option>
          </select>
          <br>
          <br>
          <input type="radio" name="sex" value="male" checked>Male
          <br>
          <input type="radio" name="sex" value="female">Female
        </div>
    
    6.问: 在HTML文本中,伪类:root总是指向html元素?
    答:是。
    
    7.问:translate()方法能移动一个元素在z轴上的位置?
    答:不能。它只能移动x,y轴的位置。translate3d可以。
    
    8-14.这六个题都是在考css选择器的优先级,看下14题:
    问:如下代码中文本“Sausage”的颜色是?
        <ul class="shopping-list" id="awesome">
          <li><span>Milk</span></li>
          <li class="favorite" id="must-buy"><span class="highlight">Sausage</span></li>
        </ul>
        <style>
          #awesome .favorite:not(#awesome) .highlight {color: red;}
          #awesome .highlight:nth-of-type(1):nth-last-of-type(1) {color: blue;}
        </style>
    答:red
    :nth-of-type(n) 选择器匹配属于父元素的特定类型的第 n 个子元素的每个元素.
    :nth-last-of-type(n) 选择器匹配属于父元素的特定类型的第 n 个子元素的每个元素,从最后一个子元素开始计数。
    
    15.
    html:
      <p id="example">Hello</p>
    css:
      #example {margin-bottom: -5px;}
    
    问:#example的位置会发什么什么?
    答:所有带id为example的元素的位置都会向上移动5px.(一般id不取重复,如果真的这样设置了就和class效果一样)
    
    16.省略。。。
    
    17-21.公用一个例子:
    <div id="test1">
        <span id="test2"></span>
    </div>
    
    17.问:#i-am-useless 会被浏览器加载吗?
    
    #i-am-useless {background-image: url('mypic.jpg');}
    答:不会。
    
    18.问:mypic.jpg 会被浏览器加载吗?
    
    #test2 {
        background-image: url('mypic.jpg');
        display: none;
    }
    答:会。
    
    19.问:mypic.jpg 会被浏览器加载吗?
    
    #test2 {
        background-image: url('mypic.jpg');
        visibility: hidden;
    }
    答:会。
    
    20.问:mypic.jpg 会被浏览器加载吗?
    
    #test1 {
        display: none;
    }
    #test2 {
        background-image: url('mypic.jpg');
        visibility: hidden;
    }
    答:不会。
    
    21.问:mypic.jpg 会被浏览器加载吗?
    
    #test1 {
        visibility: hidden;
    }
    #test2 {
        background-image: url('mypic.jpg');
        display: none;
    }
    答:会.
    
    22-23.
    css:
    @media only screen and (max-width: 1024px) {margin: 0;}
    
    22.问:only选择器的作用是?
    答:停止旧版本浏览器解析选择器的其余部分。(only 用来定某种特定的媒体类型,可以用来排除不支持媒体查询的浏览器。其实only很多时候是用来对那些不支持Media Query 但却支持Media Type 的设备隐藏样式表的。其主要有:支持媒体特性(Media Queries)的设备,正常调用样式,此时就当only 不存在;对于不支持媒体特性(Media Queries)但又支持媒体类型(Media Type)的设备,这样就会不读了样式,因为其先读only 而不是screen;另外不支持Media Qqueries 的浏览器,不论是否支持only,样式都不会被采用。)
    
    23.问:screen关键词是指设备的物理屏幕大小还是指浏览器的视窗。
    答:浏览器的视窗。
    
    24.问:overflow:hidden 是否形成新的块级格式化上下文?
    答:会。
    [会触发BFC的条件有:
    1.float的值不为none。
    2.overflow的值不为visible。
    3.display的值为table-cell, table-caption, inline-block 中的任何一个。
    4.position的值不为relative 和static。
    5.根元素。]
    

    总结

      ###一.css选择器,优先级知识点考的挺多。如何计算优先级,参考http://www.cnblogs.com/wangfupeng1988/p/4285251.html 这篇文章引入的一个概念:特指度。特指度表示一个css选择器表达式的重要程度,可以通过一个公式来计算出一个数值,数越大,越重要。
    
      这个计算叫做“I-C-E”计算公式:
      I——Id;
      C——Class;
      E——Element;
    
      注意:!important优先级最高,高于上面一切。* 选择器最低,低于一切。
    
      浏览器CSS匹配顺序:
    
      浏览器CSS匹配不是从左到右进行查找,而是从右到左进行查找。比如#divBox p span.red{color:red;},浏览器的查找顺序如下:先查找html中所有class='red'的span元素,找到后,再查找其父辈元素中是否有p元素,再判断p的父元素中是否有id为divBox的div元素,如果都存在则匹配上。浏览器从右到左进行查找的好处是为了尽早过滤掉一些无关的样式规则和元素。
    
      二:display:none 和visibilty:hidden的区别。
      两者都是将某个元素隐藏起来,区别是:display:none会使对象彻底消失,不占据空间;但是visibility:hidden所占的空间还在,留了一块空白区域。(不过上述例子,关于img加载的,还有些不是很懂 第18问,为什么display:none还是要加载图片,第20问,却没有加载图片)
    
      三:浏览器渲染,这个自己要着重学习下:
      浏览器的渲染原理简介
      专题:浏览器:渲染重绘、重排两三事
      浏览器加载和渲染HTML的顺序以及Gzip的问题
      从FE的角度上再看输入url后都发生了什么
    
      四:BFC 块级格式化上下文
      深入理解BFC和Margin Collapse
      CSS布局中一个简单的应用BFC的例子
      理解BFC(Block Formatting Context)
      我对BFC的理解
    

    清除浮动的方法

      <!-- 清除浮动的方法一:给父级元素设置高度 -->
      <!-- 清除浮动的方法二:结尾处加空div标签clear:both -->
        <!-- 原理:添加一个空div,利用css提高的clear:both清除浮动,让父级div能自动获取到高度
          优点:简单,代码少,浏览器支持好,不容易出现怪问题
          缺点:不少初学者不理解原理;如果页面浮动布局多,就要增加很多空div,让人感觉很不爽
          建议:不推荐使用,但此方法是以前主要使用的一种清除浮动方法
          评分:★★★☆☆ -->
      <!-- 清除浮动的方法三:父级div定义伪类:after和zoom -->
    
      <!-- 清除浮动的方法四:父级div定义overflow:hidden -->
    
      <!-- 清除浮动的方法五:父级div定义overflow:auto -->
    
      <!-- 清除浮动的方法六:父级div也一起浮动 -->
    
      <!-- 清除浮动的方法七:父级div定义display:table -->
        <!-- 原理:将div属性变成表格
        优点:没有优点
        缺点:会产生新的未知问题
        建议:不推荐使用,只作了解
        评分:★☆☆☆☆ -->
      <!-- 清除浮动的方法八:结尾处加br标签clear:both -->
    

    webpack

    (http://www.cnblogs.com/QxQstar/p/5961387.html)
    

    一.webpack基础

    1.在项目中生成package.json:在项目根目录中输入npm init,根据提示输入相应信息。(也可以不生成package.json文件,但是package.json是很有用的,所有建议生成)
    2.安装webpaack
      a.在全局中安装webpack:npm install webpack -g
      b.将webpack安装到项目并将webpack写入package.json的devDependencies中:进入项目根目录,然后在命令行中输入npm install webpack --save-dev。
    3.打包模块
      webpack <entry> <output>。<entry>用于指定打包的文件,<output>用于指定打包后的文件。如webpack app/index.js build/build.js表示将app文件夹中的index.js打包到build文件夹中的build.js中。
    

    二.webpack配置文件常用配置项介绍

    1.webpack有一个默认的配置文件webpack.config.js,这个文件需要手动的创建,位于项目根目录中。可以为一个项目设置多个配置文件,已达到不同的配置文件完成不同的功能。怎么设置后面介绍。
    2.webpack的配置文件会暴露出一个对象,格式如下:
      module.exports = {
        //配置项
      }
    3.常用配置项将要说明
      entry:打包的入口文件,一个字符串或者一个对象
      output:配置打包的结果,一个对象;
      fileName:定义输出文件名,一个字符串;
      path:定义输出文件路径,一个字符串;
      module:定义对模块的处理逻辑,一个对象;
      loaders:定义一系列的加载器,一个数组;
      [
        {
          test:正则表达式,用于匹配到的文件,
          loader/loaders:字符串或者数组,处理匹配到的文件。如果只需要用到一个模块加载器则使用,
          loader:string,如果要使用多个模块加载器,则使用loaders:array,
          include:字符串或者数组,指包含的文件夹,
          exclude:字符串或者数组,指排除的文件夹,
        }
      ]
      resolve:影响对模块的解析,一个对象;
      extensions:自动补全识别后缀,是一个数组;
      plugins:定义插件,一个数组;
    4.entry详细说明
      (1)当entry是一个字符串时,这个字符串表示需要打包的模块的路径,如果只有一个要打包的模块,可以使用这种形式
      (2)当entry是一个对象
        a.是数组时,当需要将多个模块打包成一个模块,可以使用这个方式.如果这些模块之间不存在依赖,数组中值的顺序没有要求,如果存在依赖,则要将依赖性最高的模块放在最后面.
          例如:entry:["./app/one.js",".app/two.js"]
        b.是键值对形式的对象是,当需要分别打包成多个模块时,可以使用这种方式,
        例如:
          entry:{
            module1:"./app/one.js",
            module2:["./app/two.js","./app/three.js"]
          }
      注:当entry是一个键值对形式的对象时,包名就是键名,output的filename不能是一个固定的值,因为每个包的名字不能一样
    5.output详细说明
      (1)output是一个对象
      (2)output.filename:指定输出文件名,一个字符串。当输出一个文件,output.filename为一个确定的字符串
        如:
          output:{
            filename:"build.js"
          }
        当输出多个文件,output.filename不能为一个确定的字符串。为了让每个文件有一个唯一的名字,需要用到下面的变量
        [name] is replaced by the name of the chunk.对应entry的键名
        [hash] is replaced by the hash of the compilation.
        [chunkhash] is replaced by the hash of the chunk.
        如:
          output:{
            path:'./build/',
            fialname:'[name].js'
          }
      (3)output.path:指定输出文件的路径,相对路径,一个字符串;
      (4)output中还有其他的一些值,不在这里说明,可以在webpack的官方网站中获得更多的详细信息
    6.module.loaders详细说明
      (1)module是一个对象,定义对模块的处理逻辑
      (2)module.loaders是一个数组,定义一系列加载器,这个数组中的每一项都是一个对象
      (3)module.loaders:[
        {
          test:正则,用于匹配要处理的文件
          loader/loaders: 字符串或者数组, 如果只需要用到一个模块加载器 ,则使用loader:string,
          如果要使用多个模块加载器,则使用loaders:array
          include:字符串或者数组,指包含的文件夹
          exclude:字符串或者数组,指排除的文件夹
        }
      ]
      (4)module除了可以配置loaders以外还能配置其他的值,在webpack的官网中获得更多的信息
    7.resolve.extensions详细说明
      (1)resolve.extensions并不是必须配置的,当不配置时,会使用默认值["", ".webpack.js", ".web.js", ".js"],当手动为resolve.extensions设置值,它的默认值会被覆盖
      (2)如果你想要每个模块都能够按照它们自己扩展名正确的被解析,要在数组中添加一个空字符串。
      (3)如果你想请求一个js文件但是在请求时不带扩展(如:require('somecode')),那么就需要将'.js'添加到数组中。其他文件一样
      (4)resolve还有其他的配置项,在webpack的官网获得更多信息
    8.补充
      (1)当设置了配置文件后,在命令行中输入webpack就可按照默认配置文件中的配置项打包模块了。
      (2)设置多个webpack配置文件。webpack默认的配置文件是webpack.config.js,当在命令行中输入webpack时默认找的是webpack.config.js。通过在package.json的scripts中添加例如
      "start-html":"webpack --config webpack.html.config.js"
      在命令行中输入npm run start-html查找的就是webpack.html.config.js,通过这种方式可以实现不同的配置文件有不同的用处,这样就不用反复修改同一个配置文件
    9. 下面是一个简单的配置文件
      module.exports = {
        entry: {
          one: "./app/one.js",
          two: "./app/two.js"
        },
        output: {
          path: "./build/",
          filename: "[name].js"
        },
        module: {
          loaders: [{
            test: /.*\.css$/,
            loaders: ["style", "css"],
            exclude: './node_modules/'
          }]
        },
        resolve: {
          extensions: ['', '.css', '.js', 'jsx']
        }
      };
    

    三.webpack-dev-server

    1.webpack-dev-server是一个轻量级的服务器,修改文件源码后,自动刷新页面将修改同步到页面上
    2.安装webpack-dev-server:
      全局安装:npm install webpack-dev-server -g
      在项目中安装并将依赖写在package.json文件中:npm install webpack-dev-server --save-dev
    3.使用命令webpack-dev-server --hot --inline完成自动刷新
    4.默认的端口号是8080,如果需要8080端口被占用,就需要改端口,webpack-dev-server --port 3000(将端口号改为3000)
    5.安装webpack-dev-server后就可以在命令行中输入webpack-dev-server开启服务,然后在浏览器地址栏中输入localhost:端口号,就可以在浏览器中打开项目根目录的index.html文件,如果项目根目录中没有index.html文件,就会在浏览器中列出项目根目录中的所有的文件夹。
    6.第五条只是启动服务并不能自动刷新,要自动刷新需要用到webpack-dev-server --hot --inline
    7.当使用webpack-dev-server --hot --inline命令时,在每次修改文件,是将文件打包保存在内存中并没有写在磁盘里(默认是根据webpack.config.js打包文件,通过--config xxxx.js修改),这种打包得到的文件和项目根目录中的index.html位于同一级(但是你看不到,因为它在内存中并没有在磁盘里)。
    使用webpack命令将打包后的文件保存在磁盘中例如在index.html文件中引入通过webpack-dev-server --hot --inline打包的build.js
    <script src="build.js"></script>
    在index.html文件中引入通过webpack命令打包的build.js
    <script src="./build/build.js"></script>
    8.每一次都敲一长串命令太麻烦,在项目根目录的package.json文件的scripts配置中添加配置,如"build":"webpack-dev-server --hot --inline",然后在命令行中输入 npm run build就能代替输入一长串命令(webpack-dev-server --hot --inline),运行webpack-dev-server --hot --inline默认是找webpack.config.js,通过--config命令可以修改为另一个配置文件。例如:webpack-dev-server --hot --inline --config  'webpack.es6.config.js'
    9.配置根目录
      (1)当在命令行中输入webpack-dev-server --hot --inline,再在浏览器中输入localhost:端口号,浏览器会在项目的根目录中去查找内容,通过--content-base可以配置根目录。
      如webpack-dev-server --hot --inline --content-base './build/',在build文件夹中去加载index.html,如果没有index.html文件,将会在浏览器中显示所有build目录下的文件和文件夹
    

    四.例子

    一个设置了两个webpack的配置文件分别是webpack.config.js和webpack.react.config.js。 package.json文件中scripts对象的内容如下:
      "scripts":{
        "test":"echo \"Error:no test specified\" && exit 1",
        "react":"webpack --config webpack.react.config.js",
        "build":"webpack-dev-server --hot --inline --content-base ./build/",
        "build-react":"webpack-dev-server --hot --inline --content-base ./react-build/ --config webpack.react.config.js"
      }
    

    跨域

    JSONP跨域

    1、很简单,就是利用 < script > 标签没有跨域限制的“漏洞”(历史遗迹啊)来达到与第三方通讯的目的。当需要通讯时,本站脚本创建一个< script >元素,地址指向第三方的API网址,形如:< script src="http://www.example.net/api?param1=1&param2=2" >< /script >并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。第三方产生的响应为json数据的包装(故称之为jsonp,即json padding),形如: callback({"name":"hax","gender":"Male"})这样浏览器会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理所传入的数据。 **`补充`**:“历史遗迹”的意思就是,如果在今天重新设计的话,也许就不会允许这样简单的跨域了嘿,比如可能像XHR一样按照CORS规范要求服务器发送特定的http头。 2、JSONP是一种非正式传输协议,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。 3、json 是一种数据格式 jsonp 是一种数据调用的方式。 你可以简单的理解为 带callback的json就是jsonp. 4、利用< script >标签可以跨域,让服务器端返回可执行的Javascript函数,参数为要回发的数据
    

    js部分

    算法

    // 方法一:
      在Array数组原型上自定义一个方法, var一个空数组和空对象;
      for循环后if判断原数组里的每一项在不在空对象, 如果不在就push进新数组res, 并且把这一项存进空对象.
      第一步:定义原型
      Array.prototype.quChong = function () {
        var res = [], json = {};
        for (let i = 0; i < this.length; i++){
          if(!json[this[i]]){
            res.push(this[i]);
            json[this[i]] = 'any';
          }
        }
        return res;
      }
    
      第二步:写一个数组并调用
      var oneArr = ['一组随机数']; //调用原型上方法
      oneArr.quChong();
    
    //方法二:去重+排序
      var toObject = function (arr) {
        let obj = new Object() || {},
          j = arr.length;
        for(let i = 0; i<j; i++) {
          obj[arr[i]] = 'any';
        }
        return obj;
      }
    
      var keys = function (obj) {
        var newArr = [];
        for (let atr in obj) {
          if(obj.hasOwnProperty(atr)){
            arr.push(atr);
          }
        }
        return newArr;
      }
    
      var quchong2 = function (arr) {
        return keys(toObject(arr));
      }
    
      var ars = [];
      quchong2(ars);
    

    JS10个难点

    (https://mp.weixin.qq.com/s?__biz=MzA3MjEyNTE4MQ==&mid=2652732429&idx=1&sn=eeac9221a5a9652d082072d88d37cab4&chksm=84cac39fb3bd4a89250348f975106e44051bb0d9cef389e989748d1bae980b952d7ac7b2b4e1&mpshare=1&scene=1&srcid=1028COpbGB6Q7MnhJoklY193#rd)
    1. 立即执行函数;
    2. 闭包;
    3. 使用闭包定义私有变量;
    4. prototype;
    5. 模块化;
    6. 变量提升;
      (JavaScript 将 所有 `变量` 和 `函数声明` 移动到 其 作用域 最前面,这就是所谓的 变量提升 (Hoisting)。也就是说,无论你在什么地方 声明变量和函数,解释器都会将它们移动到作用域的最前面。因此我们可以先使用变量和函数,而后声明它们。
      但是,仅仅是变量声明被提升了,而变量赋值不会被提升。如果你不明白这一点,有时则会出错:
      为了避免 Bug,开发者应该在每个作用域开始时声明变量和函数。)
    7. 柯里化;
      (柯里化,即 Currying ,可以是函数变得更加灵活。我们可以一次性传入多个参数调用它;也可以只传入一部分参数来调用它,让它返回一个函数去处理剩下的参数。)
    8. apply, call 与 bind 方法
      (JavaScript 开发者有必要理解 apply 、call 与 bind 方法的不同点。它们的共同点是第一个参数都是 this ,即函数运行时依赖的上下文。
      三者之中,call 方法是最简单的,它等价于指定 this  值调用函数:
      apply 方法与 call 方法类似。两者唯一的不同点在于,apply 方法使用数组指定参数,而 call 方法每个参数单独需要指定:)
    9. Memoization
      Memoization 用于优化比较耗时的计算,通过将计算结果缓存到内存中,这样对于同样的输入值,下次只需要中内存中读取结果。
    10. 函数重载
      所谓函数重载(method overloading) ,就是函数名称一样,但是输入输出不一样。或者说,允许某个函数有各种不同输入,根据不同的输入,返回不同的结果。凭直觉,函数重载 可以通过 if…else 或者 switch 实现,这就不去管它了。jQuery 之父 John Resig 提出了一个非常巧( bian )妙( tai )的方法,利用了闭包。
    

    阿里电话面试

    # 说一下熟悉的技术栈
      
    # 平常js和css哪个用的多
    
    # css中的bfc是什么
    
    bfc有什么属性可以触发
    
    flex有了解么?弹性布局了解么?常用的属性?
    
    伪类和伪元素的区别?
    
    rem和em,平时用rem怎么用?
    
    jquery源码实现有哪几大块
    
    js性能优化
    
    前端性能优化
    
    淘宝首页整个页面怎样加载能更快
    
    列表里面有十条元素,我现在要加一万条,操作dom效率比较低,如何提高
    
    js某个方法比较耗时,影响后面执行,怎么解决这个问题
    
    用过的ES6新方法
    
    原生方法去重
    

    模拟面试总结

    (2017年10月31日 14:55:16) 自我介绍: 我叫李仕臣,今年24岁,毕业于河北工程技术学院。大学毕业后在上一家公司从事前端开发的岗位,主要用到的技术栈有HTML/CSS/Jquery/Bootstrap等。今天很荣幸能来到咱们公司参加这次前端工程师的面试。

    离职原因:
      主要是上一家公司用到的技术都比较陈旧,而且前端是一个日新月异,发展很快的一个行业。我自己也不想安于现状,被技术淘汰。为了能不断的磨练自己,接触到最新、最高效的技术。所以今天来到了咱们公司参加面试,希望能得到更多的锻炼和提升。
    
    第一个项目是 乐手网
      是一个乐手交流以及乐谱分享的平台,提供音乐圈的新闻咨询。主要用到的技术有Bootstrap、Jquery、AJAX。
    
    第二个项目 丽人计划 
      是一款便于美容院推广产品与客户保持联系的手机端应用。所用技术有Bootstrap、zepto、swiper、node.js、express。
    
    第三个是公司官网
      为公司制作一个门户网站用于宣传展示公司的项目、咨询、愿景等。用到的技术有HTML、CSS、Jquery。
    
    
    技术栈:
      HTML/CSS,移动端适配/Bootstrap快速搭建响应式布局;
      JS的BOM/DOM操作,AJAX数据请求;
      接触到的框架有Vue.js/React;
      使用的工具有webpack、gulp等;
      对node.js有一定了解,可以使用express快速搭建后台程序。
    
    能干啥:
      前端自动化工具的使用;
      页面的实现,浏览器兼容;
      数据交互,模块封装;
      性能优化,服务器减压;
    
    自己的优势:
      首先比较年轻,其次在以往的工作当中积累了一定的经验,习惯各种加班;有一定的沟通表达能力,能够和谐处理人际关系;并且我是带着梦想来的,主要为提升自己,老话说‘人往高处走,水往低处流’,我觉得一家有前途、有发展的优秀企业肯定会选择一个有朝气、积极阳光、并且有追求的人。
    
    会的技术栈:(2017年10月31日 14:09:59 总结)
      HTML布局/CSS3,移动端适配,BootStrap快速搭建响应式布局。
      JS的DOM/BOM操作、AJAX数据请求。
      接触到的框架有vue.js、Reacte。
      使用的工具有webpack、gulp等。对Node.js有一定了解,使用express框架快速搭建后台。
    能做什么:
      前端自动化工具的使用;
      页面的实现;
      浏览器兼容;
      数据交互;
      模块封装;
      性能优化;
      服务器减压;
    

    浅谈HTTP

    1.首先http(超文本传输协议)其处于OSI7层模型中的应用层,OSI7层模型分别为应用层-》表示层-》会话层-》传输层-》网络层-》数据链路层-》物理层,对于这7层模型,我们应该大致的了解每一层是干嘛的,是必须的,在此就不一一说明。
    
    2.http事物是指从客户端(IE)向服务器端发送http请求,再由服务器将响应的内容返发回给客户端的一个过程。
    
    3.http链接是通过tcp链接,首先客户端会打开一条连向服务器端的链接,然后开始发送http请求,接着由服务器返发响应的内容,当客户端接受后就断开此链接,这样一次客户端与服务器端的通信就结束了。
    
    4.http报文:由客户端向服务器端发送的http请求和从服务器端发送到客户端响应的内容都是http报文,其格式为:起始行、头部(HEAD)、主体(BODY)
    
    对于报文的理解,在这里向大家推荐一个工具叫:fiddler。通过它可以详细的看到http报文的组成结构和具体的内容。
    
    5.http中的方法分为5种:增(PUT)、删(DELETE)、改(POST)、查(GET)、HEAD
    
    6.MIME(多用途网络邮箱扩展)类型:对象类型/特定子类型,如:image/png,通过fiddler可在http请求的起始行中看到。
    
    7.发送http请求的目的是为了请求某一资源,然后由服务器返回客户端需要的资源,客户端(IE)通过解析将其显示出来,这里的资源是如何标识的呢?其实是通过URI(Uniform Resource Identifier)统一资源标识符,其主要有2中形式:URL(统一资源定位符)和URN(统一资源名称),目前最常用的是URL。那如何通过URL我们就可以找到某一资源了呢?
    
    举例说明如下:
      当我们在客户端输入如下地址:
      http://www.cnblogs.com/***/****.html
      客户端首先会解析www.cnblogs.com所对应的IP地址为42.121.252.58(即DNS域名服务),而http默认的端口号为80,即向IP地址为42.121.252.58的服务器端口号为80请求***/****.html这样一个资源。
    
    8.在客户端与服务器端还存在着代理,这个代理类似于一个中间人的作用,在2者之间传递http报文,使用代理的好处有很多就不详细介绍了。
    
    9.除此之外还有就是在代理服务器上使用缓存,通过使用缓存可以大大提高访问速度,缓存是将服务器发送给客户端的报文进行了一次COPY而保留在了代理服务器上,当客户端再次请求时,代理就会判断文件的新鲜度来判断是否返回给客户端当前的缓存文件,否则从服务器端下载返回给客户端。
    
    那么代理是如何判断文件的新鲜度呢?主要是通过缓存文件最后修改的时间与服务器端文件最后修改时间是否一致,但这种还存在瑕疵,所以有时候还得通过E-TAG来判断,可以通过fiddler去仔细观察。
    

    jQuery面试问题及答案

    原文链接 www.oschina.net
    
    毫无疑问,jQuery给了JavaScript急需的提振,这是一门如此有用,但同时总是常常被低估的语言. 在 jQuery 粉墨登场之前,我们曾经会写出冗长的JavaScript代码,不仅仅为更大型的应用程序,有时即使是更小的应用程序也要如此. 那种代码常常是既难以阅读又难以维护的.
    
    在使用这个优秀的库之前写过原生的JavaScript,仅仅在用过它的一个月之后,我就能意识到jQuery的真正力量. 鉴于它的巨大人气,有关jQuery的面试问题,以及有关HTML和JavaScript的数量在任何web开发者面试中有所增加. 因为 jQuery 相对较新,大多数面试所涉及的问题都是围绕核心的 jQuery 库的,包括选择器, DOM 操作 以及 jQuery 基础.
    
    在本篇文章中,我要向 HTML 和 JavaScript 开发人员分享 20 个在不同面试遇到的 jQuery 问题。这里面的一些问题也许同样会在那些要求同时进行服务端(Spring,Servlet 和 JSP)和客户端(HTML,CSS,JavaScript 和 jQuery)的开发 Java Web 开发面试中涉及。
    
    如果你正要去面试一个职位,它需要你拥有多项技能,比如:Java、jQuery,它并不是希望你明白jQuery每一个细微的细节,或对其有全面的了解,但是如果你是要面试一个真正的客户端开发职位,你就需要积累更多高级的有技巧性的jQuery问题,而不限于本文列举的这些问题。不过,你可以通过本文来快速的温习那些jQuery面试中经常被提到的问题,而且它们大多也适用于有2到5年经验的web开发人员,特别是Java领域。
    
    jQuery 面试问题和答案
    
    JavaScript 是客户端脚本的标准语言,而 jQuery 使得编写 JavaScript 更加简单。你可以只用写几行的jQuery 代码就能实现更多的东西. 它是最常被用到的 JavaScript 库之一,并且现在已经很少有不用jQuery 而使用原生 JavaScript 的新项目了。这对于作为一个 Java web 开发者的你而言意味着你会在一场Java web开发面试中发现许多jQuery的面试问题.
    
    早些时候,绝大部分都是 HTTP, HTML, CSS 以及 JavaScript,但最近开始,除了 JavaScript 基础之外,人们也希望知道你是否熟悉 jQuery。这16个jQuery的问题是为web开发者准备的,且也能够非常方便你在参加一次电话或者视频一轮的面试之前纠正一些关键的概念。如果你是  jQuery 新手,那么它也能够帮助你更加好的理解基础知识,并激励你去发现更多东西。
    
    1. jQuery 库中的 $() 是什么?(答案如下)
    
    $() 函数是 jQuery() 函数的别称,乍一看这很怪异,还使 jQuery 代码晦涩难懂。一旦你适应了,你会爱上它的简洁。$() 函数用于将任何对象包裹成 jQuery 对象,接着你就被允许调用定义在 jQuery 对象上的多个不同方法。你甚至可以将一个选择器字符串传入 $() 函数,它会返回一个包含所有匹配的 DOM 元素数组的 jQuery 对象。这个问题我已经见过好几次被提及,尽管它非常基础,它经常被用来区分一个开发人员是否了解 jQuery。
    
    2. 网页上有 5 个元素,如何使用 jQuery来选择它们?(答案)
    
    另一个重要的 jQuery 问题是基于选择器的。jQuery 支持不同类型的选择器,例如 ID 选择器、class 选择器、标签选择器。鉴于这个问题没提到 ID 和 class,你可以用标签选择器来选择所有的 div 元素。jQuery 代码:$("div"),这样会返回一个包含所有 5 个 div 标签的 jQuery 对象。更详细的解答参见上面链接的文章。
    
    3. jQuery 里的 ID 选择器和 class 选择器有何不同?(答案)
    
    如果你用过 CSS,你也许就知道 ID 选择器和 class 选择器之间的差异,jQuery 也同样如此。ID 选择器使用 ID 来选择元素,比如 #element1,而 class 选择器使用 CSS class 来选择元素。当你只需要选择一个元素时,使用 ID 选择器,而如果你想要选择一组具有相同 CSS class 的元素,就要用 class 选择器。在面试过程中,你有很大几率会被要求使用 ID 选择器和 class 选择器来写代码。下面的 jQuery 代码使用了 ID 选择器和 class 选择器:
    
    $('#LoginTextBox')  // Returns element wrapped as jQuery object with id='LoginTextBox' $('.active') // Returns all elements with CSS class active.
    
    正如你所见,从语法角度来说,ID 选择器和 class 选择器的另一个不同之处是,前者用字符”#”而后者用字符”.”。更详细的分析和讨论参见上面的答案链接。
    
    4. 如何在点击一个按钮时使用 jQuery 隐藏一个图片?
    
    这是一个事件处理问题。jQuery为按钮点击之类的事件提供了很好的支持。你可以通过以下代码去隐藏一个通过ID或class定位到的图片。你需要知道如何为按钮设置事件并执行hide() 方法,代码如下所示:
    
    $('#ButtonToClick').click(function(){     $('#ImageToHide').hide(); });
    
    我喜欢这个问题,因为很贴近实际使用,代码也不复杂。
    
    5.  $(document).ready() 是个什么函数?为什么要用它?(answer)
    
    这个问题很重要,并且常常被问到。 ready() 函数用于在文档进入ready状态时执行代码。当DOM 完全加载(例如HTML被完全解析DOM树构建完成时),jQuery允许你执行代码。使用$(document).ready()的最大好处在于它适用于所有浏览器,jQuery帮你解决了跨浏览器的难题。需要进一步了解的用户可以点击 answer链接查看详细讨论。
    
    6. JavaScript window.onload 事件和 jQuery ready 函数有何不同?(答案)
    
    这个问答是紧接着上一个的。JavaScript window.onload 事件和 jQuery ready 函数之间的主要区别是,前者除了要等待 DOM 被创建还要等到包括大型图片、音频、视频在内的所有外部资源都完全加载。如果加载图片和媒体内容花费了大量时间,用户就会感受到定义在 window.onload 事件上的代码在执行时有明显的延迟。
    
    另一方面,jQuery ready() 函数只需对 DOM 树的等待,而无需对图像或外部资源加载的等待,从而执行起来更快。使用 jQuery $(document).ready() 的另一个优势是你可以在网页里多次使用它,浏览器会按它们在 HTML 页面里出现的顺序执行它们,相反对于 onload 技术而言,只能在单一函数里使用。鉴于这个好处,用 jQuery ready() 函数比用 JavaScript window.onload 事件要更好些。
    
    7. 如何找到所有 HTML select 标签的选中项?(答案如下)
    
    这是面试里比较棘手的 jQuery 问题之一。这是个基础的问题,但是别期望每个 jQuery 初学者都知道它。你能用下面的 jQuery 选择器获取所有具备 multiple=true 的 select 标签的选中项:
    
    $('[name=NameOfSelectedTag] :selected')
    
    这段代码结合使用了属性选择器和 :selected 选择器,结果只返回被选中的选项。你可按需修改它,比如用 id 属性而不是 name 属性来获取select标签。
    
    8. jQuery 里的 each() 是什么函数?你是如何使用它的?(答案如下)
    
    each() 函数就像是 Java 里的一个 Iterator,它允许你遍历一个元素集合。你可以传一个函数给 each() 方法,被调用的 jQuery 对象会在其每个元素上执行传入的函数。有时这个问题会紧接着上面一个问题,举个例子,如何在 alert 框里显示所有选中项。我们可以用上面的选择器代码找出所有选中项,然后我们在 alert 框中用 each() 方法来一个个打印它们,代码如下:
    
    $('[name=NameOfSelectedTag] :selected').each(function(selected) {     alert($(selected).text()); });
    
    其中 text() 方法返回选项的文本。
    
    9. 你是如何将一个 HTML 元素添加到 DOM 树中的?(答案如下)
    
    你可以用 jQuery 方法 appendTo() 将一个 HTML 元素添加到 DOM 树中。这是 jQuery 提供的众多操控 DOM 的方法中的一个。你可以通过 appendTo() 方法在指定的 DOM 元素末尾添加一个现存的元素或者一个新的 HTML 元素。
    
    10. 你能用 jQuery 代码选择所有在段落内部的超链接吗?(答案略)
    
    这是另一个关于选择器的 jQuery 面试题。就像其他问题那样,只需一行 jQuery 代码就能搞定。你可以使用下面这个 jQuery 代码片段来选择所有嵌套在段落
    
    (标签)内部的超链接(a标签)……
    
    11. $(this) 和 this 关键字在 jQuery 中有何不同?(答案如下)
    
    这对于很多 jQuery 初学者来说是一个棘手的问题,其实是个简单的问题。$(this) 返回一个 jQuery 对象,你可以对它调用多个 jQuery 方法,比如用 text() 获取文本,用val() 获取值等等。而 this 代表当前元素,它是 JavaScript 关键词中的一个,表示上下文中的当前 DOM 元素。你不能对它调用 jQuery 方法,直到它被 $() 函数包裹,例如 $(this)。
    
    12. 你如何使用jQuery来提取一个HTML 标记的属性 例如. 链接的href? (答案)
    
    attr() 方法被用来提取任意一个HTML元素的一个属性的值. 你首先需要利用jQuery选择及选取到所有的链接或者一个特定的链接,然后你可以应用attr()方法来获得他们的href属性的值。下面的代码会找到页面中所有的链接并返回href值:
    
    $('a').each(function(){    alert($(this).attr('href')); });
    
    13. 你如何使用jQuery设置一个属性值? (答案)
    
    前面这个问题之后额外的一个后续问题是,attr()方法和jQuery中的其它方法一样,能力不止一样. 如果你在调用attr()的同时带上一个值 例如. attr(name, value), 这里name是属
    
    14. jQuery中 detach() 和 remove() 方法的区别是什么? (答案)
    
    尽管 detach() 和 remove() 方法都被用来移除一个DOM元素, 两者之间的主要不同在于 detach() 会保持对过去被解除元素的跟踪, 因此它可以被取消解除, 而 remove() 方法则会保持过去被移除对象的引用. 你也还可以看看 用来向DOM中添加元素的 appendTo() 方法.
    
    15. 你如何利用jQuery来向一个元素中添加和移除CSS类? (答案)
    
    通过利用 addClass() 和 removeClass() 这两个 jQuery 方法。动态的改变元素的class属性可以很简单例如. 使用类“.active"来标记它们的未激活和激活状态,等等.
    
    16. 使用 CDN 加载 jQuery 库的主要优势是什么 ? (答案)
    
    这是一个稍微高级点儿的jQuery问题。好吧,除了报错节省服务器带宽以及更快的下载速度这许多的好处之外, 最重要的是,如果浏览器已经从同一个CDN下载类相同的 jQuery 版本, 那么它就不会再去下载它一次. 因此今时今日,许多公共的网站都将jQuery用于用户交互和动画, 如果浏览器已经有了下载好的jQuery库,网站就能有非常好的展示机会。
    
    17.  jQuery.get() 和 jQuery.ajax() 方法之间的区别是什么?
    
    ajax() 方法更强大,更具可配置性, 让你可以指定等待多久,以及如何处理错误。get() 方法是一个只获取一些数据的专门化方法。
    
    18. jQuery 中的方法链是什么?使用方法链有什么好处?
    
    方法链是对一个方法返回的结果调用另一个方法,这使得代码简洁明了,同时由于只对 DOM 进行了一轮查找,性能方面更加出色。
    
    19. 你要是在一个 jQuery 事件处理程序里返回了 false 会怎样?
    
    这通常用于阻止事件向上冒泡。
    
    20. 哪种方式更高效:document.getElementbyId("myId") 还是 $("#myId")?
    
    第一种,因为它直接调用了 JavaScript 引擎。
    

    requery.js用法

    转载网址:http://www.jb51.net/article/73626.htm
    原文网址:http://www.ruanyifeng.com/blog/2012/11/require_js.html
    一、为什么要用require.js?
      依次加载多个js文件,加载 的时候,浏览器会 停止 网页渲染,加载文件越多,网页 失去响应 的时间就会越长;其次,由于js文件之间存在依赖关系,因此必须严格保证加载顺序,依赖性最大的模块一定要放最后加载,当依赖关系很复杂的时候,代码的 编写 和 维护 都会变得 困难。
      require.js的诞生是为了解决两大问题:第一实现js文件的异步加载,避免网页失去响应; 第二管理模块之间的依赖性,便于代码的编写和维护.
    
    二、require.js的加载
      使用require.js的第一步,是先去官方网站下载最新版本。
      下载后,假定把它放在js子目录下面,就可以加载了。
      <script src="js/require.js"></script>
      有人可能会想到,加载这个文件,也可能造成网页失去响应。解决办法有两个,一个是把它放在网页底部加载,另一个是写成下面这样:
      <script src="js/require.js" defer async="true" ></script>
      async属性表明这个文件需要异步加载,避免网页失去响应。IE不支持这个属性,只支持defer,所以把defer也写上。
      加载require.js以后,下一步就要加载我们自己的代码了。假定我们自己的代码文件是main.js,也放在js目录下面。那么,只需要写成下面这样就行了:
     <script src="js/require.js" data-main="js/main"></script>
      data-main属性的作用是,指定网页程序的主模块。在上例中,就是js目录下面的main.js,这个文件会第一个被require.js加载。由于require.js默认的文件后缀名是js,所以可以把main.js简写成main。
    
    三、主模块的写法
      上一节的main.js,我把它称为"主模块",意思是整个网页的入口代码。它有点像C语言的main()函数,所有代码都从这儿开始运行。
      下面就来看,怎么写main.js?
      如果我们的代码不依赖任何其他模块,那么可以直接写入javascript代码。
      <!-- main.js -->
      <!-- alert("加载成功!"); -->
      但这样的话,就没必要使用require.js了。真正常见的情况是,主模块依赖于其他模块,这时就要使用AMD规范定义的的require()函数。
      // main.js
      <!-- require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
        <!-- // some code here //主模块代码 -->
      <!-- }); -->
      require()函数接受两个参数。第一个参数是一个数组,表示所依赖的模块,上例就是['moduleA', 'moduleB', 'moduleC'],即主模块依赖这三个模块;第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块。
      require()异步加载moduleA,moduleB和moduleC,浏览器不会失去响应;它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。
    
      下面,我们看一个实际的例子。
    
      假定主模块依赖jquery、underscore和backbone这三个模块,main.js就可以这样写:
        require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone){
          // some code here //主模块代码
        });
      require.js会先加载jQuery、underscore和backbone,然后再运行回调函数。主模块的代码就写在回调函数中。
    
    四、模块的加载
      上一节最后的示例中,主模块的依赖模块是['jquery', 'underscore', 'backbone']。默认情况下,require.js假定这三个模块与main.js在同一个目录,文件名分别为 jquery.js,underscore.js和backbone.js,然后自动加载。
      使用require.config()方法,我们可以对模块的加载行为进行自定义。require.config()就写在主模块(main.js)的头部。参数就是一个对象,这个对象的paths属性指定各个模块的加载路径。
    
      require.config({
        paths: {
          "jquery": "jquery.min",
          "underscore": "underscore.min",
          "backbone": "backbone.min"
        }
      });
    
      上面的代码给出了三个模块的文件名,路径默认与main.js在同一个目录(js子目录)。如果这些模块在其他目录,比如js/lib目录,则有两种写法。一种是逐一指定路径。
    
      require.config({
        paths: {
          "jquery": "lib/jquery.min",
          "underscore": "lib/underscore.min",
          "backbone": "lib/backbone.min"
        }
      });
    
      另一种则是直接改变基目录(baseUrl)。
      require.config({
        baseUrl: "js/lib", //改变基目录
        paths: {
          "jquery": "jquery.min",
          "underscore": "underscore.min",
          "backbone": "backbone.min"
        }
      });
    
      如果某个模块在另一台主机上,也可以直接指定它的网址,比如:
      require.config({
        paths: {
          "jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min"
        }
      });
    
      require.js要求,每个模块是一个单独的js文件。这样的话,如果加载多个模块,就会发出多次HTTP请求,会影响网页的加载速度。因此,require.js提供了一个优化工具(http://requirejs.org/docs/optimization.html),当模块部署完毕以后,可以用这个工具将多个模块合并在一个文件中,减少HTTP请求数。
    
    五、AMD模块的写法
      require.js加载的模块,采用AMD规范。也就是说,模块必须按照AMD的规定来写。
      具体来说,就是模块必须采用特定的define()函数来定义。 ** 如果一个模块不依赖其他模块 ** ,那么可以直接定义在define()函数之中。
      假定现在有一个math.js文件,它定义了一个math模块。那么,math.js就要这样写:
    

    OSI七层传输协议

    超文本传输协议

    超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。  HTTP的发展是万维网协会(World Wide Web Consortium)和Internet工作小组(Internet Engineering Task Force)合作的结果,(他们)最终发布了一系列的RFC,其中最著名的就是RFC 2616。RFC 2616定义了HTTP协议的我们今天普遍使用的一个版本——HTTP 1.1。  HTTP是一个客户端和服务器端请求和应答的标准(TCP)。客户端是终端用户,服务器端是网站。通过使用Web浏览器、网络爬虫或者其它的工具,客户端发起一个到服务器上指定端口(默认端口为80)的HTTP请求。(我们称这个客户端)叫用户代理(user agent)。应答的服务器上存储着(一些)资源,比如HTML文件和图像。(我们称)这个应答服务器为源服务器(origin server)。在用户代理和源服务器中间可能存在  多个中间层,比如代理,网关,或者隧道(tunnels)。尽管TCP/IP协议是互联网上最流行的应用,HTTP协议并没有规定必须使用它和(基于)它支持的层。 事实上,HTTP可以在任何其他互联网协议上,或者在其他网络上实现。HTTP只假定(其下层协议提供)可靠的传输,任何能够提供这种保证的协议都可以被其使用。  通常,由HTTP客户端发起一个请求,建立一个到服务器指定端口(默认是80端口)的TCP连接。HTTP服务器则在那个端口监听客户端发送过来的请求。一旦收到请求,服务器(向客户端)发回一个状态行,比如"HTTP/1.1 200 OK",和(响应的)消息,消息的消息体可能是请求的文件、错误消息、或者其它一些信息。  HTTP使用TCP而不是UDP的原因在于(打开一个)一个网页必须传送很多数据,而TCP协议提供传输控制,按顺序组织数据,和错误纠正。  通过HTTP或者HTTPS协议请求的资源由统一资源标示符(Uniform Resource Identifiers)(或者,更准确一些,URLs)来标识。 

    协议功能 HTTP是超文本传输协议,是客户端浏览器或其他程序与Web服务器之间的应用层通信协议。在Internet上的Web服务器上存放的都是超文本信息,客户机需要通过HTTP协议传输所要访问的超文本信息。HTTP包含命令和传输信息,不仅可用于Web访问,也可以用于其他因特网/内联网应用系统之间的通信,从而实现各类应用资源超媒体访问的集成。 我们在浏览器的地址栏里输入的网站地址叫做URL (Uniform Resource Locator,统一资源定位符)。就像每家每户都有一个门牌地址一样,每个网页也都有一个Internet地址。当你在浏览器的地址框中输入一个URL或是单击一个超级链接时,URL就确定了要浏览的地址。浏览器通过超文本转移协议(HTTP),将Web服务器上站点的网页代码提取出来,并翻译成漂亮的网页。因此,在我们认识HTTP之前,有必要先弄清楚URL的组成,例如:http://www.******.com/china/index.htm。它的含义如下:  1. http://:代表超文本转移协议,通知****.com服务器显示Web页,通常不用输入;  2. www:代表一个Web(万维网)服务器; 3. ****.com/:这是装有网页的服务器的域名,或站点服务器的名称;  4. China/:为该服务器上的子目录,就好像我们的文件夹;  5. Index.htm:index.htm是文件夹中的一个HTML文件(网页)。 

    我们知道,Internet的基本协议是TCP/IP协议,然而在TCP/IP模型最上层的是应用层(Application layer),它包含所有高层的协议。高层协议有:文件传输协议FTP、电子邮件传输协议SMTP、域名系统服务DNS、网络新闻传输协议NNTP和HTTP协议等。 HTTP协议(HyperText Transfer Protocol,超文本转移协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。这就是你为什么在浏览器中看到的网页地址都是以http://开头的原因。 
    
    自WWW诞生以来,一个多姿多彩的资讯和虚拟的世界便出现在我们眼前,可是我们怎么能够更加容易地找到我们需要的资讯呢?当决定使用超文本作为WWW文档的标准格式后,于是在1990年,科学家们立即制定了能够快速查找这些超文本文档的协议,即HTTP协议。经过几年的使用与发展,得到不断的完善和扩展,目前在WWW中使用的是HTTP/1.0的第六版。 
    

    协议基础 HTTP(HyperText Transfer Protocol)是超文本转移协议的缩写,它用于传送WWW方式的数据,关于HTTP协议的详细内容请参考RFC2616。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求,请求头包含请求的方法、URL、协议版本、以及包含请求修饰符、客户信息和内容的类似于MIME的消息结构。服务器以一个状态行作为响应,相应的内容包括消息协议的版本,成功或者错误编码加上包含服务器信息、实体元信息以及可能的实体内容。 

    通常HTTP消息包括客户机向服务器的请求消息和服务器向客户机的响应消息。这两种类型的消息由一个起始行,一个或者多个头域,一个指示头域结束的空行和可选的消息体组成。HTTP的头域包括通用头,请求头,响应头和实体头四个部分。每个头域由一个域名,冒号(:)和域值三部分组成。域名是大小写无关的,域值前可以添加任何数量的空格符,头域可以被扩展为多行,在每行开始处,使用至少一个空格或制表符。 
    

    HTTP-运作方式 HTTP协议是基于请求/响应范式的。一个客户机与服务器建立连接后,发送一个请求给服务器,请求方式的格式为,统一资源标识符、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可能的内容。服务器接到请求后,给予相应的响应信息,其格式为一个状态行包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。 

    许多HTTP通讯是由一个用户代理初始化的并且包括一个申请在源服务器上资源的请求。最简单的情况可能是在用户代理(UA)和源服务器(O)之间通过一个单独的连接来完成。
    
    
    当一个或多个中介出现在请求/响应链中时,情况就变得复杂一些。中介由三种:代理(Proxy)、网关(Gateway)和通道(Tunnel)。一个代理根据URI的绝对格式来接受请求,重写全部或部分消息,通过URI的标识把已格式化过的请求发送到服务器。网关是一个接收代理,作为一些其它服务器的上层,并且如果必须的话,可以把请求翻译给下层的服务器协议。一个通道作为不改变消息的两个连接之间的中继点。当通讯需要通过一个中介(例如:防火墙等)或者是中介不能识别消息的内容时,通道经常被使用. 
    

    实体 请求消息和响应消息都可以包含实体信息,实体信息一般由实体头域和实体组成。实体头域包含关于实体的原信息,实体头包括Allow、Content-Base、Content-Encoding、Content-Language、Content-Length、Content-Location、Content-MD5、Content-Range、Content-Type、Etag、Expires、Last-Modified、extension-header。extension-header允许客户端定义新的实体头,但是这些域可能无法被接受方识别。实体可以是一个经过编码的字节流,它的编码方式由Content-Encoding或Content-Type定义,它的长度由Content-Length或Content-Range定义。 

    Content-Type实体头 Content-Type实体头用于向接收方指示实体的介质类型,指定HEAD方法送到接收方的实体介质类型,或GET方法发送的请求介质类型Content-Range实体头  Content-Range实体头用于指定整个实体中的一部分的插入位置,他也指示了整个实体的长度。在服务器向客户返回一个部分响应,它必须描述响应覆盖的范围和整个实体长度。一般格式:  Content-Range:bytes-unitSPfirst-byte-pos-last-byte-pos/entity-legth  例如,传送头500个字节次字段的形式:Content-Range:bytes0-499/1234如果一个http消息包含此节(例如,对范围请求的响应或对一系列范围的重叠请求),Content-Range表示传送的范围,Content-Length表示实际传送的字节数。

    Last-modified实体头 Last-modified实体头指定服务器上保存内容的最后修订时间。  例如,传送头500个字节次字段的形式:Content-Range:bytes0-499/1234如果一个http消息包含此节(例如,对范围请求的响应或对一系列范围的重叠请求),Content-Range表示传送的范围,Content-Length表示实际传送的字节数。 Last-modified实体头.

    协议结构 HTTP报文由从客户机到服务器的请求和从服务器到客户机的响应构成。请求报文格式如下: 

    请求行 - 通用信息头 - 请求头 - 实体头 - 报文主体 
    
    请求行以方法字段开始,后面分别是 URL 字段和 HTTP 协议版本字段,并以 CRLF 结尾。SP 是分隔符。除了在最后的 CRLF 序列中 CF 和 LF 是必需的之外,其他都可以不要。有关通用信息头,请求头和实体头方面的具体内容可以参照相关文件。 应答报文格式如下: 
      状态行 - 通用信息头 - 响应头 - 实体头 - 报文主体 
      状态码元由3位数字组成,表示请求是否被理解或被满足。原因分析是对原文的状态码作简短的描述,状态码用来支持自动操作,而原因分析用来供用户使用。客户机无需用来检查或显示语法。有关通用信息头,响应头和实体头方面的具体内容可以参照相关文件。 
    

    工作原理 既然我们明白了URL的构成,那么HTTP是怎么工作呢?我们接下来就要讨论这个问题。  一次HTTP操作称为一个事务,其工作过程可分为四步:  首先客户机与服务器需要建立连接。只要单击某个超级链接,HTTP的工作就开始了。 建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可能的内容。 服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。 客户端接收服务器所返回的信息通过浏览器显示在用户的显示屏上,然后客 户机与服务器断开连接。  如果在以上过程中的某一步出现错误,那么产生错误的信息将返回到客户端,由显示屏输出。对于用户来说,这些过程是由HTTP自己完成的,用户只要用鼠标点击,等待信息显示就可以了。  许多HTTP通讯是由一个用户代理初始化的并且包括一个申请在源服务器上资源的请求。最简单的情况可能是在用户代理和服务器之间通过一个单独的连接来完成。在Internet上,HTTP通讯通常发生在TCP/IP连接之上。缺省端口是TCP 80,但其它的端口也是可用的。但这并不预示着HTTP协议在Internet或其它网络的其它协议之上才能完成。HTTP只预示着一个可靠的传输。  这个过程就好像我们打电话订货一样,我们可以打电话给商家,告诉他我们需要什么规格的商品,然后商家再告诉我们什么商品有货,什么商品缺货。这些,我们是通过电话线用电话联系(HTTP是通过TCP/IP),当然我们也可以通过传真,只要商家那边也有传真。 以上简要介绍了HTTP协议的宏观运作方式,下面介绍一下HTTP协议的内部操作过程。  在WWW中,“客户”与“服务器”是一个相对的概念,只存在于一个特定的连接期间,即在某个连接中的客户在另一个连接中可能作为服务器。基于HTTP协议的客户/服务器模式的信息交换过程,它分四个过程:建立连接、发送请求信息、发送响应信息、关闭连接。这就好像上面的例子,我们电话订货的全过程。

    其实简单说就是任何服务器除了包括HTML文件以外,还有一个HTTP驻留程序,用于响应用户请求。你的浏览器是HTTP客户,向服务器发送请求,当浏览器中输入了一个开始文件或点击了一个超级链接时,浏览器就向服务器发送了HTTP请求,此请求被送往由IP地址指定的URL。驻留程序接收到请求,在进行必要的操作后回送所要求的文件。在这一过程中,在网络上发送和接收的数据已经被分成一个或多个数据包(packet),每个数据包包括:要传送的数据;控制信息,即告诉网络怎样处理数据包。TCP/IP决定了每个数据包的格式。如果事先不告诉你,你可能不会知道信息被分成用于传输和再重新组合起来的许多小块。
    也就是说商家除了拥有商品之外,它也有一个职员在接听你的电话,当你打电话的时候,你的声音转换成各种复杂的数据,通过电话线传输到对方的电话机,对方的电话机又把各种复杂的数据转换成声音,使得对方商家的职员能够明白你的请求。这个过程你不需要明白声音是怎么转换成复杂的数据的。
    

    前端优化点

    (2017年11月12日 20:46:45) https://mp.weixin.qq.com/s/WnS9j184yZId6gtruLQM8w

    一、PC浏览器前端优化策略 PC端优化的策略很多,如 YSlow(YSlow 是 Yahoo 发布的一款 Firefox 插件,现 Chrome 也可安装,可以对网站的页面性能进行分析,提出对该页面性能优化的建议)原则,或者 Chrome 自带的 Audits 等,总结起来主要包括网络加载类、页面渲染类、CSS 优化类、JavaScript 执行类、缓存类、图片类、架构协议类等几类,下面逐一介绍。

    网络加载类 1.减少 HTTP 资源请求次数 在前端页面中,通常建议尽可能合并静态资源图片、JavaScript 或 CSS 代码,减少页面请求数和资源请求消耗,这样可以缩短页面首次访问的用户等待时间。通过构建工具合并雪碧图、CSS、JavaScript 文件等都是为了减少 HTTP 资源请求次数。另外也要尽量避免重复的资源,防止增加多余请求。 2.减小 HTTP 请求大小 除减少 HTTP 资源请求次数,也要尽量减小每个 HTTP 请求的大小。减少没必要 图片、JS、CSS 及 HTML 代码,对文件压缩优化,或使用 gzip 压缩传输内容 等都可以用来减小文件大小,缩短网络传输等待时延。前面我们使用构建工具来压缩静态图片资源以及移除代码中的注释并压缩,目的都是为了减小 HTTP 请求的大小。 3.将 CSS 或 JavaScript 放到外部文件中,避免使用 <style>或 <script> 标签直接引入 在 HTML 文件中引用外部资源可以有效利用浏览器的静态资源缓存,但有时候在移动端页面 CSS 或 JavaScript 比较简单的情况下为了减少请求,也会将 CSS 或 JavaScript 直接写到 HTML 里面,具体要根据 CSS 或 JavaScript 文件的大小和业务的场景来分析。如果 CSS 或 JavaScript 文件内容较多,业务逻辑较复杂,建议放到外部文件引入。 4.避免页面中空的 href 和 src 当 标签的 href 属性为空,或 <script>、 、 <iframe>标签的 src 属性为空时,浏览器在渲染的过程中仍会将 href 属性或 src 属性中的空内容进行加载,直至加载失败,这样就阻塞了页面中其他资源的下载进程,而且最终加载到的内容是无效的,因此要尽量避免。 5.为 HTML 指定 Cache-Control 或 Expires(设置HTTP缓存) 为 HTML 内容设置 Cache-Control 或 Expires 可以将 HTML 内容缓存起来,避免频繁向服务器端发送请求。前面讲到,在页面 Cache-Control 或 Expires 头部有效时,浏览器将直接从缓存中读取内容,不向服务器端发送请求。 6.合理设置 Etag 和 Last-Modified 合理设置 Etag 和 Last-Modified 使用浏览器缓存,对于未修改的文件,静态资源服务器会向浏览器端返回304,让浏览器从缓存中读取文件,减少 Web 资源下载的带宽消耗并降低服务器负载。 7.减少页面重定向 页面每次重定向都会延长页面内容返回的等待延时,一次重定向大约需要200毫秒不等的时间开销(无缓存),为了保证用户尽快看到页面内容,要尽量避免页面重定向。 8.使用静态资源分域存放来增加下载并行数 浏览器在同一时刻向同一个域名请求文件的并行下载数是有限的,因此可以利用多个域名的主机来存放不同的静态资源,增大页面加载时资源的并行下载数,缩短页面资源加载的时间。通常根据多个域名来分别存储 JavaScript、CSS 和图片文件。 9.使用静态资源 CDN 来存储文件 如果条件允许,可以利用 CDN 网络加快同一个地理区域内重复静态资源文件的响应下载速度,缩短资源请求时间。 10.使用 CDN Combo 下载传输内容 CDN Combo 是在 CDN 服务器端将多个文件请求打包成一个文件的形式来返回的技术,这样可以实现 HTTP 连接传输的一次性复用,减少浏览器的 HTTP 请求数,加快资源下载速度。例如同一个域名 CDN 服务器上的 a.js,b.js,c.js 就可以按如下方式在一个请求中下载。 11.使用可缓存的 AJAX 对于返回内容相同的请求,没必要每次都直接从服务端拉取,合理使用 AJAX 缓存能加快 AJAX 响应速度并减轻服务器压力。 12.使用 GET 来完成 AJAX 请求 使用 XMLHttpRequest 时,浏览器中的 POST 方法会发起两次 TCP 数据包传输,首先发送文件头,然后发送 HTTP 正文数据。而使用 GET 时只发送头部,所以在拉取服务端数据时使用 GET 请求效率更高。 13.减少 Cookie 的大小并进行 Cookie 隔离 HTTP 请求通常默认带上浏览器端的 Cookie 一起发送给服务器,所以在非必要的情况下,要尽量减少 Cookie 来减小 HTTP 请求的大小。对于静态资源,尽量使用不同的域名来存放,因为 Cookie 默认是不能跨域的,这样就做到了不同域名下静态资源请求的 Cookie 隔离。 14.缩小 favicon.ico 并缓存 有利于 favicon.ico 的重复加载,因为一般一个 Web 应用的 favicon.ico 是很少改变的。 15.推荐使用异步 JavaScript 资源 异步的 JavaScript 资源不会阻塞文档解析,所以允许在浏览器中优先渲染页面,延后加载脚本执行。例如 JavaScript 的引用可以如下设置,也可以使用模块化加载机制来实现。

      使用 async 时,加载和渲染后续文档元素的过程和 main.js 的加载与执行是并行的。使用 defer 时,加载后续文档元素的过程和 main.js 的加载是并行的,但是 main.js 的执行要在页面所有元素解析完成之后才开始执行。
    16.消除阻塞渲染的 CSS 及 JavaScript
      对于页面中加载时间过长的 CSS 或 JavaScript 文件,需要进行合理拆分或延后加载,保证关键路径的资源能快速加载完成。
    17.避免使用 CSS import 引用加载 CSS
      CSS 中的 @import 可以从另一个样式文件中引入样式,但应该避免这种用法,因为这样会增加 CSS 资源加载的关键路径长度,带有 @import 的 CSS 样式需要在 CSS 文件串行解析到 @import 时才会加载另外的 CSS 文件,大大延后 CSS 渲染完成的时间。
    

    页面渲染类 1.把 CSS 资源引用放到 HTML 文件顶部 一般推荐将所有 CSS 资源尽早指定在 HTML 文档 中,这样浏览器可以优先下载 CSS 并尽早完成页面渲染。 2.JavaScript 资源引用放到 HTML 文件底部 JavaScript 资源放到 HTML 文档底部可以防止 JavaScript 的加载和解析执行对页面渲染造成阻塞。由于 JavaScript 资源默认是解析阻塞的,除非被标记为异步或者通过其他的异步方式加载,否则会阻塞 HTML DOM 解析和 CSS 渲染的过程。 3.尽量预先设定图片等大小 在加载大量的图片元素时,尽量预先限定图片的尺寸大小,否则在图片加载过程中会更新图片的排版信息,产生大量的重排 4.不要在 HTML 中直接缩放图片 在 HTML 中直接缩放图片会导致页面内容的重排重绘,此时可能会使页面中的其他操作产生卡顿,因此要尽量减少在页面中直接进行图片缩放。 5.减少 DOM 元素数量和深度 HTML 中标签元素越多,标签的层级越深,浏览器解析 DOM 并绘制到浏览器中所花的时间就越长,所以应尽可能保持 DOM 元素简洁和层级较少。 6.尽量避免在选择器末尾添加通配符 CSS 解析匹配到 渲染树的过程是从右到左的逆向匹配,在选择器末尾添加通配符至少会增加一倍多计算量。 7.减少使用关系型样式表的写法 直接使用唯一的类名即可最大限度的提升渲染引擎绘制渲染树等效率 8.尽量减少使用JS动画 JS 直接操作 DOM 极容易引起页面的重排 9.CSS 动画使用 translate、scale 代替 top、height 尽量使用 CSS3 的 translate、scale 属性代替 top、left 和 height、width,避免大量的重排计算 10.尽量避免使用

    、 <iframe>
    内容的渲染是将 table 的 DOM 渲染树全部生成完并一次性绘制到页面上的,所以在长表格渲染时很耗性能,应该尽量避免使用它,可以考虑使用列表元素
      代替。尽量使用异步的方式动态添加 iframe,因为 iframe 内资源的下载进程会阻塞父页面静态资源的下载与 CSS 及 HTML DOM 的解析。 11.避免运行耗时的 JavaScript 长时间运行的 JavaScript 会阻塞浏览器构建 DOM 树、DOM 渲染树、渲染页面。所以,任何与页面初次渲染无关的逻辑功能都应该延迟加载执行,这和 JavaScript 资源的异步加载思路是一致的。 12.避免使用 CSS 表达式或 CSS 滤镜 CSS 表达式或 CSS 滤镜的解析渲染速度是比较慢的,在有其他解决方案的情况下应该尽量避免使用。

      二、移动端浏览器前端优化策略 相对于桌面端浏览器,移动端 Web 浏览器上有一些较为明显的特点:设备屏幕较小、新特性兼容性较好、支持一些较新的 HTML5 和 CSS3 特性、需要与 Native 应用交互等。但移动端浏览器可用的 CPU 计算资源和网络资源极为有限,因此要做好移动端 Web 上的优化往往需要做更多的事情。首先,在移动端 Web 的前端页面渲染中,桌面浏览器端上的优化规则同样适用,此外针对移动端也要做一些极致的优化来达到更好的效果。需要注意的是,并不是移动端的优化原则在桌面浏览器端就不适用,而是由于兼容性和差异性的原因,一些优化原则在移动端更具代表性

      网络加载类 1.首屏数据请求提前,避免 JavaScript 文件加载后才请求数据 为了进一步提升页面加载速度,可以考虑将页面的数据请求尽可能提前,避免在 JavaScript 加载完成后才去请求数据。通常数据请求是页面内容渲染中关键路径最长的部分,而且不能并行,所以如果能将数据请求提前,可以极大程度上缩短页面内容的渲染完成时间。 2.首屏加载和按需加载,非首屏内容滚屏加载,保证首屏内容最小化 由于移动端网络速度相对较慢,网络资源有限,因此为了尽快完成页面内容的加载,需要保证首屏加载资源最小化,非首屏内容使用滚动的方式异步加载。一般推荐移动端页面首屏数据展示延时最长不超过3秒。目前中国联通 3G 的网络速度为 338KB/s(2.71Mb/s),所以推荐首屏所有资源大小不超过 1014KB,即大约不超过 1MB。 3.模块化资源并行下载 在移动端资源加载中,尽量保证 JavaScript 资源并行加载,主要指的是模块化 JavaScript 资源的异步加载,例如AMD的异步模块,使用并行的加载方式能够缩短多个文件资源的加载时间。 4.inline 首屏必备的 CSS 和 JavaScript 通常为了在 HTML 加载完成时能使浏览器中有基本的样式,需要将页面渲染时必备的 CSS 和 JavaScript 通过 <script> 或 <style> 内联到页面中,避免页面 HTML 载入完成到页面内容展示这段过程中页面出现空白。 5.meta dns prefetch 设置 DNS 预解析 设置文件资源的 DNS 预解析,让浏览器提前解析获取静态资源的主机 IP,避免等到请求时才发起 DNS 解析请求。通常在移动端 HTML 中可以采用如下方式完成。 6.资源预加载 对于移动端首屏加载后可能会被使用的资源,需要在首屏完成加载后尽快进行加载,保证在用户需要浏览时已经加载完成,这时候如果再去异步请求就显得很慢。 7.合理利用MTU策略 通常情况下,我们认为 TCP 网络传输的最大传输单元(Maximum Transmission Unit,MTU)为 1500B,即一个RTT(Round-Trip Time,网络请求往返时间)内可以传输的数据量最大为 1500 字节。因此,在前后端分离的开发模式中,尽量保证页面的 HTML 内容在 1KB 以内,这样整个 HTML 的内容请求就可以在一个 RTT 内请求完成,最大限度地提高 HTML 载入速度。

      缓存类 1.合理利用浏览器缓存 除了上面说到的使用 Cache-Control、Expires、Etag 和 Last-Modified 来设置 HTTP 缓存外,在移动端还可以使用 localStorage 等来保存 AJAX 返回的数据,或者使用 localStorage 保存 CSS 或 JavaScript 静态资源内容,实现移动端的离线应用,尽可能减少网络请求,保证静态资源内容的快速加载。 2.静态资源离线方案 对于移动端或 Hybrid 应用,可以设置离线文件或离线包机制让静态资源请求从本地读取,加快资源载入速度,并实现离线更新。关于这块内容,我们会在后面的章节中重点讲解。 3.尝试使用 AMP HTML(现代前端技术解析3.1.4(90页)) AMP HTML 可以作为优化前端页面性能的一个解决方案,使用 AMP Component 中的元素来代替原始的页面元素进行直接渲染。 4.尝试使用 PWA 模式 PWA(Progressive Web Apps)是 Google 提出的用前沿的 Web 技术为网页提供 App 般使用体验的一系列方案。

      图片类 1.图片压缩处理 在移动端,通常要保证页面中一切用到的图片都是经过压缩优化处理的,而不是以原图的形式直接使用的,因为那样很消耗流量,而且加载时间更长。 2.使用较小的图片,合理使用 base64 内嵌图片 在页面使用的背景图片不多且较小的情况下,可以将图片转化成 base64 编码嵌入到 HTML 页面或 CSS 文件中,这样可以减少页面的 HTTP 请求数。需要注意的是,要保证图片较小,一般图片大小超过 2KB 就不推荐使用 base64 嵌入显示了。 3.使用更高压缩比格式的图片 使用具有较高压缩比格式的图片,如 webp(需要设计降级兼容方案)等。在同等图片画质的情况下,高压缩比格式的图片体积更小,能够更快完成文件传输,节省网络流量。 4.图片懒加载 为了保证页面内容的最小化,加速页面的渲染,尽可能节省移动端网络流量,页面中的图片资源推荐使用懒加载实现,在页面滚动时动态载入图片。 5.使用 MediaQuery 或 srcset 根据不同屏幕加载不同大小图片 在介绍响应式的章节中我们了解到,针对不同的移动端屏幕尺寸和分辨率,输出不同大小的图片或背景图能保证在用户体验不降低的前提下节省网络流量,加快部分机型的图片加载速度,这在移动端非常值得推荐。 6.使用 iconfont 代替图片图标 在页面中尽可能使用 iconfont 来代替图片图标,这样做的好处有以下几个: 使用 iconfont 体积较小,而且是矢量图,因此缩放时不会失真; 可以方便地修改图片大小尺寸和呈现颜色。

        但是需要注意的是,iconfont 引用不同 webfont 格式时的兼容性写法,根据经验推荐尽量按照以下顺序书写,否则不容易兼容到所有的浏览器上。
      7.定义图片大小限制
        加载的单张图片一般建议不超过 30KB,避免大图片加载时间长而阻塞页面其他资源的下载,因此推荐在 10KB 以内。如果用户上传的图片过大,建议设置告警系统,帮助我们观察了解整个网站的图片流量情况,做出进一步的改善。
      8.强缓存策略
        对于一些「永远」不会变的图片可以使用强缓存的方式缓存在用户的浏览器上。
      

      脚本类 1.尽量使用 id 选择器选择页面 DOM 元素时尽量使用 id 选择器,因为 id 选择器速度最快。 2.合理缓存 DOM 对象 对于需要重复使用的 DOM 对象,要优先设置缓存变量,避免每次使用时都要从整个DOM树中重新查找。 3.页面元素尽量使用事件代理,避免直接事件绑定 使用事件代理可以避免对每个元素都进行绑定,并且可以避免出现内存泄露及需要动态添加元素的事件绑定问题,所以尽量不要直接使用事件绑定。 4.使用 touchstart 代替 click 由于移动端屏幕的设计, touchstart 事件和 click 事件触发时间之间存在 300 毫秒的延时,所以在页面中没有实现 touchmove 滚动处理的情况下,可以使用 touchstart 事件来代替元素的 click 事件,加快页面点击的响应速度,提高用户体验。但同时我们也要注意页面重叠元素 touch 动作的点击穿透问题。 5.避免 touchmove、scroll 连续事件处理 需要对 touchmove、scroll 这类可能连续触发回调的事件设置事件节流,例如设置每隔 16ms(60 帧的帧间隔为 16.7ms,因此可以合理地设置为 16ms )才进行一次事件处理,避免频繁的事件调用导致移动端页面卡顿。 6.避免使用 eval、with,使用 join 代替连接符+,推荐使用 ECMAScript6 的字符串模板 这些都是一些基础的安全脚本编写问题,尽可能使用较高效率的特性来完成这些操作,避免不规范或不安全的写法。 7.尽量使用 ECMAScript6+的特性来编程 ECMAScript6+ 一定程度上更加安全高效,而且部分特性执行速度更快,也是未来规范的需要,所以推荐使用 ECMAScript6+ 的新特性来完成后面的开发。

      渲染类 1.使用 Viewport 固定屏幕渲染,可以加速页面渲染内容 一般认为,在移动端设置 Viewport 可以加速页面的渲染,同时可以避免缩放导致页面重排重绘。在移动端固定 Viewport 设置的方法如下。 2.避免各种形式重排重绘 页面的重排重绘很耗性能,所以一定要尽可能减少页面的重排重绘,例如页面图片大小变化、元素位置变化等这些情况都会导致重排重绘。 3.使用 CSS3 动画,开启GPU加速 使用 CSS3 动画时可以设置 transform:translateZ(0) 来开启移动设备浏览器的GPU图形处理加速,让动画过程更加流畅,但需要注意的是,在 Native WebView 下 GPU 加速有几率产生 App Crash。 4.合理使用 Canvas 和 requestAnimationFrame 选择 Canvas 或 requestAnimationFrame 等更高效的动画实现方式,尽量避免使用 setTimeout、setInterval 等方式来直接处理连续动画。 5.SVG 代替图片 部分情况下可以考虑使用 SVG 代替图片实现动画,因为使用 SVG 格式内容更小,而且 SVG DOM 结构方便调整。 6.不滥用 float 在 DOM 渲染树生成后的布局渲染阶段,使用 float 的元素布局计算比较耗性能,所以尽量减少 float 的使用,推荐使用固定布局或 flex-box 弹性布局的方式来实现页面元素布局。 7.不滥用 web 字体或过多 font-size 声明 过多的 font-size 声明会增加字体的大小计算,而且也没有必要的。 8.做好脚本容错 脚本容错可以避免「非正常环境」的执行错误影响页面的加载和不相关功能的使用

      架构协议类 1.尝试使用 SPDY 和 HTTP2 在条件允许的情况下可以考虑使用 SPDY 协议来进行文件资源传输,利用连接复用加快传输过程,缩短资源加载时间。HTTP2 在未来也是可以考虑尝试的。 2.使用后端数据渲染 使用后端数据渲染的方式可以加快页面内容的渲染展示,避免空白页面的出现,同时可以解决移动端页面SEO的问题。如果条件允许,后端数据渲染是一个很不错的实践思路。后面的章节会详细介绍后端数据渲染的相关内容。 3.使用 NativeView 代替 DOM 的性能劣势 可以尝试使用 NativeView 的 MNV* 开发模式来避免 HTML DOM 性能慢的问题,目前使用 MNV* 的开发模式已经可以将页面内容渲染体验做到接近客户端 Native 应用的体验了。但需要避免 js Framework 和 native Framework 的频繁交互。

      总结 关于页面优化的常用技术手段和思路主要包括以上这些,尽管列举出很多,但仍可能有少数遗漏,可见前端性能优化不是一件简简单单的事情,其涉及的内容很多。大家可以根据实际情况将这些方法应用到自己的项目当中,要想全部做到几乎是不可能的,但做到用户可接受的原则还是很容易实现的。

      webpack优化资源

      (2017年11月12日 20:51:25)
      https://mp.weixin.qq.com/s?__biz=MjM5NTEwMTAwNg==&mid=2650212679&idx=2&sn=b8c3dd944ca9673e179e18fdf3f9643c&chksm=befe096689898070e5d5c5a8505deb710cdcb0220fc59b2dcdd9aa3130a2c6107363f2c994a4&scene=21#wechat_redirect
      

      前言: 在前端应用的优化中,对加载资源的大小控制极其的重要,大多数时候我们能做的是在打包编译的过程对资源进行大小控制、拆分与复用。 本文主要基于 webpack 打包,以 React、vue 等生态(frame work)开发的 单页面应用,来举例说明如何从 webpack 打包的层面去处理资源以及缓存,其中主要我们需要做的是对 webpack 进行配置的优化,同时涉及少量的业务代码的更改。

      前/后端交互