五一之后第一周(5.6-5.9)的安排

  • type 和 interface 区别
  • webpack中的externals配置使用
  • https和http协议的区别

ts语法强烈建议浏览官网,英语理解力强的,阔推荐英文官网

ts运行,本地tslint提示的各种报错有时真让人抓狂!!!(持续完善当中)

序列 提示 描述
1 Exceeds maximum line length of 150 单行超150字符
2 expected an assignment or function call expected an assignment or function call
3 comment must start with a space // 注释应以空格开头
4 for (… in …) statements must be filtered with an if statement for in 循环体内应有if判断属性是否存在
5 Declaration of instance field not allowed after declaration of instance method. Instead, this should come at the beginning of the class/interface. class/interface的属性定义应放在方法前
6 Declaration of static method not allowed after declaration of instance method. Instead, this should come after instance fields. class/interface的静态方法定义应放在非静态方法前
7 Shadowed variable 变量名重名
8 Missing radix parameter parseInt缺少转换基数,直接第二个参数为0即可
9 Class name must be in pascal case class类命名必须首字母大写
10 file should end with a newline 文件末尾少个空行
11 Type ‘string’ is not assignable to type ‘number’ 接口规定的是number类型不是字符串类型

参考链接目前 Angular2 项目内的 TSLint 设置

ts中的type和interface区别

interface 和 type interface 和 type 都可以用来定义一些复杂的类型结构,最很多情况下是通用的,最初我一直没能理解它们二者之间区别在哪里,后来发现,二者的区别在于:

  • type 不能像 interface 那样合并,其在作用域内唯一
  • interface创建了一种新的类型,而 type 仅仅是别名,是一种引用;
  • 如果 type 使用了 union operator (|) 操作符,则不能将 type implements 到 class 上;
  • 如果 type 使用了 union(|) 操作符 ,则不能被用以 extends interface

interface阔以,type不行

可选属性

带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个?符号。

  • 优点一是可以对可能存在的属性进行预定义
  • 优点二是可以捕获引用了不存在的属性时的错误
    1
    2
    3
    4

    interface Chart {
    Num: number;
    Type?: string[];

    只读属性

    初次创建的时候赋值,其他时候不允许再次赋值,在属性前用readonly指定
    1
    2
    3
    4
    interface Point {
    readonly x: number;
    readonly y: number;
    }

    额外属性检查

    当你不确定接口会有哪些其他的属性的时候,阔以用一个字符串索引签名
    1
    2
    3
    4
    5
    interface Point {
    readonly x: number;
    readonly y: number;
    [propName: string]: any
    }

    Declaration merging, type 不能像 interface 那样合并

    接口阔以定义多次,而类型别名则不行
    1
    2
    3
    4
    5
    6
    interface data {
    x: number
    }
    interface data {
    y: number
    }

    函数类型

    1
    2
    3
    interface SearchFunc {
    (source: string, subString: string): boolean;
    }
    这样定义后,我们可以像使用其它接口一样使用这个函数类型的接口。 下例展示了如何创建一个函数类型的变量,并将一个同类型的函数赋值给这个变量。
    1
    2
    3
    4
    5
    let serF: SearchFunc
    serF = function(source: string, subString: string) {
    let result = source.search(subString);
    return result > -1;
    }
    对于函数类型的类型检查来说,函数的参数名不需要与接口里定义的名字相匹配,这样也想
    1
    2
    3
    4
    5
    let serF: SearchFunc
    serF = function(sou: string, sub: string) {
    let result = sou.search(sub);
    return result > -1;
    }

    可索引类型

    索引类型具有一个 索引签名,它描述了对象索引的类型,还有相应的索引返回值类型。
    1
    2
    3
    4
    5
    6
    7
    interface dataArray {
    [index: number]: string
    }
    let arr:dataArray = [
    'chen',
    'peng'
    ]
    上面例子里,我们定义了dataArray接口,它具有索引签名。 这个索引签名表示了当用 number 去索引dataArray时会得到string类型的返回值。

    TypeScript支持两种索引签名:字符串和数字。 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。

    1
    2
    3
    4
    5
    interface NumberDictionary {
    [index: string]: number;
    length: number; // 可以,length是number类型
    name: string // 错误,`name`的类型与索引类型返回值的类型不匹配
    }

类类型

  • 实现接口
    TypeScript也能够用它来明确的强制一个类去符合某种契约,用implements实现接口
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    interface ClockInterface {
    currentTime: Date;
    setTime(d: Date); // 在接口中描述一个方法,在类里实现它,如同下面的setTime方法一样:
    }

    class Clock implements ClockInterface {
    currentTime: Date;
    setTime(d: Date) {
    this.currentTime = d;
    }
    constructor(h: number, m: number) { }
    }
  • 类静态部分与实例部分的区别
    当你操作类和接口的时候,你要知道类是具有两个类型的:静态部分的类型和实例的类型。 你会注意到,当你用构造器签名(new )去定义一个接口并试图定义一个类去实现这个接口时会得到一个错误:

这里因为当一个类实现了一个接口时,只对其实例部分进行类型检查。 constructor存在于类的静态部分,所以不在检查的范围内。

1
2
3
4
5
6
7
8
9
10
// 只对其实例部分进行类型检查
interface ClockConstructor {
new (hour: number, minute: number);
}

class Clock implements ClockConstructor {
currentTime: Date;
// constructor存在于类的静态部分,所以不在检查的范围内
constructor(h: number, m: number) { }
}

因此,我们应该直接操作类的静态部分。 看下面的例子,我们定义了两个接口, ClockConstructor为构造函数所用和ClockInterface为实例方法所用。 为了方便我们定义一个构造函数 createClock,它用传入的类型创建实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 构造函数所用,这里用interface会报错?类的静态部分
type PerConstructor = new (name: string, age: number) => PerInterface;
// 实例部分
interface PerInterface {
sayName(): void;
}
export function createPerson(ctor: PerConstructor, name: string, age: number): PerInterface {
return new ctor(name, age)
}
export class P1Type implements PerInterface {
public name!: string;
public age!: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
public sayName() {
console.log(`call sayName: ${(this as any).name}`)
}
}

因为createPerson的第一个参数是PerConstructo类型,在createPerson(P1Type, 7, 32)里,会检查P1Type是否符合构造函数签名。

访问修饰符:private、public、protected

  • 默认为public,public规定的属性必须在类的顶层
  • 当成员被标记为private时,它就不能在声明它的类的外部访问
  • protected和private类似,但是,protected成员在派生类(子类)中可以访问。这是protected和privat最大的区别
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

interface ClockInter {
setTime(): void;
}
class ClockParent implements ClockInter {
public currentTime!: any;
protected habit = 'shufa'; // 受保护的属性
// 限定于属性 在定义方法
constructor(h: number) {
this.currentTime = h
}
public setTime() {
console.log('d', this);
}
}
// 导出一个Clock 类 继承父类 并通过ClockInter实现接口
export class Clock extends ClockParent implements ClockInter {
public currentTime!: any;
// 限定于属性 在定义方法
constructor(h: number) {
super((new Date()).getTime());
this.currentTime = h
}
public setTime() {
// 能访问受保护的属性 habit
console.log('d', this.habit);
}
}

这个例子展示了最基本的继承:类从基类中继承了属性和方法。 这里,Clock是一个 派生类,它派生自 ClockParent 基类,通过 extends关键字。 派生类通常被称作子类,基类通常被称作超类
派生类包含了一个构造函数,它 必须调用 super(),它会执行基类的构造函数。 而且,在构造函数里访问 this的属性之前,我们 一定要调用 super()。 这个是TypeScript强制执行的一条重要规则。

一个ts文件不能同时定义2个及以上的类?添加tslint.json中的规则即可

1
2
3
4
5
6
"rules": {
"max-classes-per-file": [
true,
2
]
}

继承接口

和类一样,接口也可以相互继承。 这让我们能够从一个接口里复制成员到另一个接口里,可以更灵活地将接口分割到可重用的模块里。主要type类型别名,也阔以继承,语法稍有不同

1
2
3
4
5
6
7
8
9
10
11
12
13
interface Shape {
color: string;
[propName: string]: any;
}

interface Square extends Shape {
sideLength: number;
}

const square = {} as Square;
square.color = 'red';
square.sideLength1 = 10;
square.name = 'cpp'

也阔以继承多个接口

1
2
3
4
5
6
7
8
9
10
11
12
13
interface Shape {
color: string;
}
interface Shape2 {
name: string
}
interface Square extends Shape, Shape2 {
sideLength: number;
}
const square = {} as Square;
square.color = 'red';
square.name = 'cpp';
square.sideLength = 22

关键字implements有什么作用?

一句话即: 约束接口按照某种契约,举例说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// implements的实现
interface ClockInter {
age: number;
setTime(): void;
}
export class Clock implements ClockInter {
// 如果age = '1111' Type 'string' is not assignable to type 'number'.
public age = 1111;
// !非空断言操作符 能确定变量一定不为空时使用
// 非空断言操作符不会防止出现 null 或 undefined
public currentTime!: any;
// 限定于属性 在定义方法
constructor(h: number) {
this.currentTime = h
}
public setTime() {
console.log('d', this);
}
}

接口中ClockInter约束了age必须是数字类型,所以在通过ClockInter实现Clock这个类的时候,age必须按照接口定义的来约束。
如何引用这个Clock这个类呢,在vue文件直接import导入,然后new调用即可,如

1
2
3
4
5
6
7
8
9
10
11
12
13
import { Clock } from '../../utils/implementsd2'

@Component()
export default class HomeDem extends Vue {
private person1: any = ''
private mounted() {
const num = (new Date()).getTime()
// 创造一个实例并传入当前的时间戳
this.person1 = new Clock(num)
console.log('p1', this.person1);
this.person1.setTime(num);
}
}

Type类型别名

type 会给一个类型起个新名字。 type 有时和 interface 很像,但是可以作用于原始值(基本类型),联合类型,元组以及其它任何你需要手写的类型

1
2
3
4
5
6
// 构造函数所用,这里用interface会报错?
type PerConstructor = new (name: string, age: number) => PerInterface;
// 实例所用
interface PerInterface {
sayName(): void;
}

起别名不会新建一个类型 - 它创建了一个新名字来引用那个类型。给基本类型起别名通常没什么用,尽管可以做为文档的一种形式使用。

interface vs type

  • 两者都可以用来描述对象或函数的类型,但是语法不同

    1
    2
    3
    4
    type SetPoint = (x: number, y: number) => void;
    interface SetPoint {
    (x: number, y: number): void;
    }
  • 与接口不同,类型别名还可以用于其他类型,如基本类型(原始值)、联合类型、元组。

    1
    2
    3
    4
    5
    6
    // tuple
    type Data = [number, string];

    // dom
    let div = document.createElement('div');
    type B = typeof div;
  • 继承Extend
    语法有所不同,interface继承用extends,type用 & 继承

    1
    2
    type PartialPointX = { x: number; };
    type Point = PartialPointX & { y: number; };
  • class implements实现接口
    类可以以相同的方式实现接口或类型别名。但是请注意,类和接口被认为是静态的。因此,它们不能实现/扩展命名联合类型的类型别名。

    1
    2
    3
    4
    5
    6
    7
    type PartialPoint = { x: number; } | { y: number; };

    // FIXME: can not implement a union type
    class SomePartialPoint implements PartialPoint {
    x: 1;
    y: 2;
    }
  • declaration mergeing

与类型别名不同,接口可以定义多次,并将被视为单个接口(合并所有声明的成员)

  • 计算属性,生成映射类型
    type 能使用 in 关键字生成映射类型,但 interface 不行。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    type Keys = "firstname" | "surname"

    type DudeType = {
    [key in Keys]: string
    }

    const test: DudeType = {
    firstname: "Pawel",
    surname: "Grzybek"
    }

    // 报错
    //interface DudeType2 {
    // [key in keys]: string
    //}

参考链接

webpack中的externals配置使用

官网解释

webpack 中的 externals 配置提供了不从 bundle 中引用依赖的方式。解决的是,所创建的 bundle 依赖于那些存在于用户环境(consumer environment)中的依赖。

意思是如果需要引用一个库,但是又不想让webpack打包(减少打包的时间),并且又不影响我们在程序中以CMD、AMD或者window/global全局等方式进行使用(一般都以import方式引用使用),那就可以通过配置externals;

Vue项目中如何实践

  • 在vue.config.js中更改
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    module.exports = {
    configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
    config.externals = {
    echarts: 'echarts',
    }
    }
    }
    }
  • index.html中引入vue.js,通过cdn方式或者本地资源引入都行

externals和libraryTarget的关系

  • libraryTarget配置如何暴露 library。如果不设置library,那这个library就不暴露。就相当于一个自执行函数
  • externals是决定的是以哪种模式去加载所引入的额外的包
  • libraryTarget决定了你的library运行在哪个环境,哪个环境也就决定了你哪种模式去加载所引入的额外的包。也就是说,externals应该和libraryTarget保持一致。library运行在浏览器中的,你设置externals的模式为commonjs,那代码肯定就运行不了了。
  • 如果是应用程序开发,一般是运行在浏览器环境libraryTarget可以不设置,externals默认的模式是global,也就是以全局变量的模式加载所引入外部的库。

参考链接

https和http协议的区别

HTTP和HTTPS的基本概念

HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。

HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,是http协议身披一层SSL(Secure Socket Layer,安全套阶 层)协议,SSL这层协议存在于应用层(http层)到TCP层之间:

应用层(http) => ssl => TCP => IP

HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。

HTTP缺点

  • 明文传输,私密信息已被窃取
  • 无法验证通信者身份,可能存储伪装者(客户端和服务器)
  • http协议无法判断通信报文的完整性,通信报文在TCP/IP协议通信中可能会被篡改
    http协议的缺点,只能是ssl协议来完成

HTTPS使用SSL(Secure Scocket Layer ,安全套阶层)和TLS(Transport Layer Secure,安全层传输协议)这两种协议。

IETF 以 SSL3.0 为基准,后又制定了 TLS1.0、TLS1.1 和TLS1.2。TSL 是以 SSL 为原型开发的协议,有时会统一称该协议 为 SSL。当前主流的版本是 SSL3.0 和 TLS1.0。由于 SSL1.0 协议在设计之初被发现出了问题,就没有实际投入 使用。SSL2.0 也被发现存在问题,所以很多浏览器直接废除了 该协议版本。

HTTP + 认证 + 加密 + 完整性保护 = HTTPS

HTTPS和HTTP的区别主要如下:

1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl(Secure Scocket Layer 安全套阶层)加密传输协议。

3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者默认是80,后者默认是443。

4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

HTTPS优点

  • seo方面
    采用https的网站在搜索结果的排名中较高
  • 安全性

1.使用HTTPS协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;
2.TTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。
3.HTTPS是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。

HTTPS缺点

  • seo方面
    使用HTTPS协议会使页面的加载时间延长近50%,增加10%到20%的耗电,此外,HTTPS协议还会影响缓存,增加数据开销和功耗,甚至已有安全措施也会受到影响也会因此而受到影响

  • 经济方面

1.ca证书需要费用
2.ssl证书需要绑定ip,不能在同一个IP上绑定多个域名
3.https连接缓存不如http高效,大流量网站不一定非要https
4.HTTPS连接服务器端资源占用高很多,支持访客稍多的网站需要投入更大的成本

  • 使用ssl协议,处理速度会变得很慢
    一种是指通信慢。另一种是指由于大量消耗CPU 及内存等资源,导致处理速度变慢。
    由于https还需要做服务器/客户端加密以及解密处理,因此肯定会消耗CPU和内存等硬件资源。

参考链接