TS学习过程

一、TS文件运行前的准备

1.1、node的安装

你可以到 Node.js 官网去下载 Node 进行安装(https://node.js.org),建议你下载LTS版本,也就是长期支持版本。安装的过程我就不演示了,这个过程就和安装 QQ 一样,没有任何难度。
如果你已经安装了,可以打开命令行工具,然后使用node -v命令查看安装的版本,但是一般还有一个命令需要检测一下,就是npm -v,如果两个命令都可以输出版本号,说明你的 Node 安装已经没有任何问题了。

1.2、TS的安装

npm install typescript -g

注意:mac在执行这段命令的时候报错如下:

npm WARN checkPermissions Missing write access to /usr/local/lib/node_modules
npm ERR! code EACCES
npm ERR! syscall access

使用了sudo cnpm install typescript -g执行就安装成功了

1.3、ts-node 的安装

npm install -g ts-node

报错的话就使用sudo cnpm install -g ts-node安装

以上都安装成功的话就可以开始写代码,运行代码啦~(ts-node demo.ts)

二、基础静态类型和对象类型

2.1、基础静态类型

基础静态类型非常简单,只要在声明变量的后边加一个:号,然后加上对应的类型哦。比如下面的代码,就是声明了一个数字类型的变量,叫做count。

let count: number = 1;
//这是一个number类型的

null,undefinded,symbol,booleanvoid这些都是最常用的基础数据类型

//any任意类型:在定义的时候没有定义类型,则该变量就是any类型
let age:any='12',
age = '我爱你中国'
image.png

2.2、对象类型

  • 对象类型
const xiaoJieJie: {
  name: string,
  age: number,
} = {
  name: "大脚",
  age: 18,
};
console.log(xiaoJieJie.name);
  • 数组类型
const xiaoJieJies: String[] = ["谢大脚", "刘英", "小红"];
  • 类类型
const dajiao: Person = new Person();
  • 函数类型
const jianXiaoJieJie: () => string = () => {
  return "大脚";
};
自定义对象类型
interface XiaoJieJie {
  uname: string;
  age: number;
}

const xiaohong: XiaoJieJie = {
  uname: "小红",
  age: 18,
};

2.3、类型注解和类型推断

  • 类型注解(type annotation)
let count: number;
count = 123;
//这段代码就是类型注解,意思是显示的告诉代码,我们的count变量就是一个数字类型,这就叫做类型注解
  • 类型推断(type inference)
let countInference = 123;
//这时候我并没有显示的告诉你变量countInference是一个数字类型,但是如果你把鼠标放到变量上时,你会发现 TypeScript 自动把变量注释为了number(数字)类型,也就是说它是有某种推断能力的,通过你的代码 TS 会自动的去尝试分析变量的类型。

注意:

  • 如果 TS 能够自动分析变量类型, 我们就什么也不需要做了
  • 如果 TS 无法分析变量类型的话, 我们就需要使用类型注解

三、函数

3.1、函数的参数以及返回值

  • 函数有返回值
//   参数要指定类型、返回值也要指定类型
function getTotal(one: number, two: number): number {
  return one + two;
}

const total = getTotal(1, 2);
  • 函数没有返回值
//没有返回值的函数,我们就可以给他一个类型注解void,代表没有任何返回值。
//如果这样定义后,再加入任何返回值,程序都会报错。
function sayHello(): void {
  console.log("hello world");
}
  • never返回值类型
//如果一个函数是永远也执行不完的,就可以定义返回值为never(执行的时候,抛出了异常,这时候就无法执行完了)
function errorFuntion(): never {
  throw new Error();
  console.log("Hello World");
}


//一直循环,也是我们常说的死循环,这样也运行不完
function forNever(): never {
  while (true) {}
  console.log("Hello JSPang");
}
  • 函数参数为对象(解构)
//如果参数是对象---对象解构
function add({ one, two }: { one: number, two: number }): number {
  return one + two;
}

const three = add({ one: 1, two: 2 });
//如果参数是对象,并且里边只有一个属性
function getNumber({ one }: { one: number }): number {
  return one;
}

const one = getNumber({ one: 1 });

四、数组

4.1、一般数组类型的定义

const numberArr = [1, 2, 3];
//如果你要显示的注解,也非常简单,可以写成下面的形式。
const numberArr: number[] = [1, 2, 3];
//如果你的数组各项是字符串,你就可以写成这样。
const stringArr: string[] = ["a", "b", "c"];
//也就是说你可以定义任意类型的数组,比如是undefined。
const undefinedArr: undefined[] = [undefined, undefined];
//既有数字类型,又有字符串的时候
const arr: (number | string)[] = [1, "string", 2];

4.2、数组中对象类型的定义

const xiaoJieJies: { name: string, age: Number }[] = [
  { name: "刘英", age: 18 },
  { name: "谢大脚", age: 28 },
];

//上面的写法太麻烦,修改后
type Lady = { name: string, age: Number };

const xiaoJieJies: Lady[] = [
  { name: "刘英", age: 18 },
  { name: "谢大脚", age: 28 },
];

//上述写法在对象里再加入一个属性,编译器就会报错,修改为用类来定义
class Madam {
  name: string;
  age: number;
}

const xiaoJieJies: Madam[] = [
  { name: "刘英", age: 18 },
  { name: "谢大脚", age: 28 },
];

4.3、元祖的使用和类型约束

  • 元祖的了解

可以把元组看成数组的一个加强,它可以更好的控制或者说规范里边的类型

const xiaojiejie: (string | number)[] = ["dajiao", 28, "teacher"];
//调换数组中元素的位置,如下,ts不能检测到问题
const xiaojiejie: (string | number)[] = ["dajiao", "teacher", 28];
//这时,需要元祖来加强
const xiaojiejie: [string, string, number] = ["dajiao", "teacher", 28];
//把数组中的每个元素类型的位置给固定住了,这就叫做元组。

五、TypeScript 中的 interface 接口

5.1、interface接口的理解和使用

个人理解: 从js的角度看ts中的interface,就是先声明了一个对象obj,这个对象obj里面有很多的属性name,这个对象obj会在你后面定义的方法fun中当作参数(形参)传进去,这个对象obj中的属性有必传的、非必传的、还有函数类型的。你在方法fun中若要使用某个属性name,那么这个属性name需要在对象obj中定义过,否则会报错。(除非interface中定义了[propname: string]: any;属性)
注意:对象中的每一个属性都需要定义类型,方法定义返回值的类型

// 这是定义的一个obj
interface Girl {
    // 每一个属性都要有类型
    name: string;
    age: number;
    // 必传的属性
    height: number;
    // 非必传的属性
    footer?: number;
    // 允许加入任意值 
    // 在实参中新增了sex属性,interface中并没有定义,此时并没有报错
    [propname: string]: any;
    // 存方法,要定义返回值的类型
    say(): string;
    //非必传方法
    run?(): void;
}
// 后面定义的方法 fun 把上面定义的对象 Girl 当作参数传给方法
const screenResume = (girl: Girl) => {
    girl.age < 24 && girl.height >= 168 && console.log(girl.name + "进入面试");
    girl.age > 24 || (girl.height < 168 && console.log(girl.name + "你被淘汰"));
  };
  
  const getResume = (girl: Girl) => {
    console.log(girl.name + "年龄是:" + girl.age);
    console.log(girl.name + "身高是:" + girl.height + "cm");
    girl.footer  &&  console.log(girl.name + "鞋码是:" + girl.footer + "码");
    girl.sex && console.log(girl.name + "性别是:" + girl.sex);
    console.log(girl.name + "开心说:" + girl.say());
  };
  //实参
  const girl = {
    name: "大脚",
    age: 18,
    height: 174,
    footer: 38,
    // 这里不报错的原因是 interface中增加了 [propname: string]: any;属性
    sex: '女',
    say() {
        return "hello world";
      },    
  };
  //调用方法
  screenResume(girl);
  getResume(girl);

控制台输出的内容:

大脚进入面试
大脚年龄是:18
大脚身高是:174cm
大脚鞋码是:38码
大脚性别是:女
大脚开心说:hello world

5.2 implements --- 接口(interface)的引用(被class引用)

// implements 是指 类 引用了 某个 接口(interface)
//这里是指 XiaoJieJie这个类 引用了 Girl 这个接口,此时定义XiaoJieJie这个类的时候,要给必传属性赋值
class XiaoJieJie implements Girl {
    name = '小花';
    age = 18;
    height = 180;
    say() {
        return "傻子"
    }
}
//new XiaoJieJie() ----实例对象
screenResume(new XiaoJieJie())
getResume(new XiaoJieJie())

控制台输出的结果:

小花进入面试
小花年龄是:18
小花身高是:180cm
小花开心说:傻子

5.3、extends --- 接口的继承

// extends 是指 新的接口 继承了 某个接口
interface Boy extends Girl {
    play(): string;
}
const boy = {
    name: 'wanwan',
    age: 18,
    height: 185,
    say() {
        return "是你呀";
    },
    play() {
        return "打篮球";
    } 
}

const getResume = (girl: Boy) => {
    console.log(girl.name + "年龄是:" + girl.age);
    console.log(girl.name + "身高是:" + girl.height + "cm");
    girl.footer  && console.log(girl.name + "鞋码是:" + girl.footer + "码");
    girl.sex && console.log(girl.name + "性别是:" + girl.sex);
    girl.say() && console.log(girl.name + "开心说:" + girl.say());
    girl.play() && console.log(girl.name + "喜欢的运动是:" + girl.play());
};
getResume(boy);

控制台结果:

wanwan年龄是:18
wanwan身高是:185cm
wanwan开心说:是你呀
wanwan喜欢的运动是:打篮球

5.4、函数型接口

因为对象中仅包含一个函数,这个对象的全部意义也仅在于那个可被外部调用的函数,故而称之为函数型接口。

六、TypeScript 中类的概念和使用

6.1、类的概念

使用关键字 class

// 定义一个类
class Lady {
    content = "Hi,帅哥";
    sayHello() {
        return this.content;
    }
}
// 实例类的对象
const goddess = new Lady();
console.log(goddess.sayHello());

6.2、extends --- 类的继承

// 定义一个类
class Lady {
    content = "Hi,帅哥";
    sayHello() {
        return this.content;
    }
}
// XiaoJieJie类身上既有自己的方法,也有从Lady类继承来的方法
class XiaoJieJie extends Lady {
    sayLove() {
        return "I love you";
    }
}

console.log(new XiaoJieJie().sayHello());//Hi,帅哥
console.log(new XiaoJieJie().sayLove());//I love you

6.3、类(继承的子类)的重写和super关键字

// 定义一个类
class Lady {
    content = "Hi,帅哥";
    sayHello() {
        return this.content;
    }
}
// XiaoJieJie类身上既有自己的方法,也有从Lady类继承来的方法
class XiaoJieJie extends Lady {
    sayLove() {
        return "I love you";
    }
    // 可以对继承来的方法进行重写
    sayHello() {
        return "hi, wan";
    }
    // 继续使用Lady中的方法
    ladySayHello() {
        return super.sayHello() + "。你好!";
    }
}

console.log(new XiaoJieJie().sayHello());//hi, wan
console.log(new XiaoJieJie().sayLove());//I love you
console.log(new XiaoJieJie().ladySayHello());//Hi,帅哥。你好!

6.4、类的访问类型 --- private、protected、public

  • public

public从英文字面的解释就是公共的或者说是公众的,在程序里的意思就是允许在类的内部和外部被调用.

  • private

private 访问属性的意思是,只允许再类的内部被调用,外部不允许调用

  • protected

protected 允许在类内及继承的子类中使用

class Person {
    protected name:string;
    private age: number;
    public sayHello(){
        // 在类中使用 private 和 protected 属性都不会报错
        console.log(this.name + 'say Hello' + ",年龄是:" + this.age)  //此处不报错
    }
}
//-------以下属于类的外部--------
const person = new Person()
//此处报错---属性“name”受保护(protected),只能在类“Person”及其子类中访问。
person.name = 'jspang.com'
//此处报错---属性“age”为私有属性(private),只能在类“Person”中访问。
person.age = 12 
person.sayHello()
//此处报错---属性“name”受保护,只能在类“Person”及其子类中访问。
console.log(person.name)  
image.png

6.5、类的构造函数

  • 1、通过构造函数给类增加属性

类的构造方法只在实例化的时候被调用,并且只调用一次。
类的构造方法在类的外部无法访问。

  • 2、调用构造方法中定义的属性
  • 3、构造函数的访问控制符
class Person{
    // 在构造函数中定义属性,必须给属性添加访问控制符(访问类型)
    constructor(public name: string){
        this.name = name
        console.log(this.name);
    };
    public sayHello(){
        // 这里的name需要通过this.name去获取,直接写name获取不到
        console.log(this.name+':hello world')
    }
}
let girl = new Person("xiaohua");//xiaohua(实例化的时候构造函数被调用)
// 调用构造方法中定义的属性
girl.sayHello();//xiaohua:hello world
console.log(girl.name); //xiaohua

6.5、继承类的构造器写法

子类中使用构造函数需要用super()调用父类的构造函数

// 父类
class Person{
    // 在构造函数中定义属性,必须给属性添加访问控制符(访问类型)
    constructor(public name: string){
        this.name = name
        console.log(this.name);
    };
    public sayHello(){
        // 这里的name需要通过this.name去获取,直接写name获取不到
        console.log(this.name+':hello world')
    }
}
// 子类
class Teacher extends Person{
    constructor(public age: number){
        // 若父类的构造函数有参数则子类在使用super()时也需要传递参数否则会报错(2)
        // 1、未写super时报错---派生类的构造函数必须包含 "super" 调用
        // 2、未写参数时报错---应有 1 个参数,但获得 0 个;未提供 "name" 的自变量。
        super("小花")
        // 若父类的构造函数没有参数则子类在使用super()时不需要传参数
        this.age = age;
        console.log(this.name + "今年" + this.age + "岁")
    }
}
let girl = new Person("xiaohua");//xiaohua(实例化的时候构造函数被调用)
// 调用构造方法中定义的属性
girl.sayHello();//xiaohua:hello world
console.log(girl.name); //xiaohua

let teach = new Teacher(24);//小花今年24岁(实例化的时候构造函数被调用)

6.6、类的 getter 、 setter 、static

  • getter 、 setter

getter和setter都是属性,用get()和set()来设置private类型的属性可修改和获取

// set和get方法---用来修改private属性的值
class Person {
    private _name: string;
    constructor(private _age: number) {
        console.log(this._name + "今年" + this._age + "岁")
    }
    get name() {
        return this._name
    }
    set name(value) {
        this._name = value
    }
    get age() {
        return this._age - 10
    }
    set age(age: number) {
        this._age = age
    }
}
const girl = new Person(18)//undefined今年18岁
girl.name = "小花"
girl.age = 23
console.log(girl.name + "今年" + girl.age + "岁")//小花今年13岁
  • 类中的static

当你不想new出对象,而想直接使用这个方法,用static声明的属性和方法,不需要进行声明对象,就可以直接使用

readonly只读属性

class Person {
    public static logo: String = "huahua";
    // readonly只读属性
    public readonly xingm: string;
    static sayLove() {
        return "I Love you " + this.logo;
    }
}
new Person().xingm = 'www';//报错 --- 无法分配到 "xingm" ,因为它是只读属性。
console.log(Person.sayLove());//I Love you huahua
  • 抽象类---abstract

抽象类--- 用abstract 修饰, 里面可以没有抽象方法。但有抽象方法(abstract method)的类必须声明为抽象类(abstract class)

abstract class Development {
    //抽象方法 ,不包含具体实现,要求子类中必须实现此方法
    abstract skill():any;
    //非抽象方法,无需要求子类实现、重写
    equipment(){
        console.log('非抽象方法,不要子类实现、重写');
    }

}
// 多态:父类定义一个方法不去实现,让继承它的子类去实现 每一个子类有不同的表现
// 注意:使用多态基础是类的继承或者接口实现
class Frontend extends Development {
     //子类中必须实现父类抽象方法,否则ts编译报错
    skill() {
        console.log("我是一个前端")
    }
}
class Backend extends Development {
    skill() {
        console.log("我是一个后端")
    }
}
class UI extends Development {
    skill() {
        console.log("我是一个UI")
    }
}

七、联合类型和类型保护

  • 1、联合类型(Union Types)可以通过管道(|)将变量设置多种类型,赋值时可以根据设置的类型来赋值。
  • 2、类型保护

1、类型断言就是通过断言的方式确定传递过来的准确值(传递过来的值中是否存在某个准确的值)
2、in语法
3、typeof语法
4、instanceof语法(只能用在类上)

个人:这一段理解比较重要,不知道怎么描述

八、枚举

使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。 TypeScript支持数字的和基于字符串的枚举。

// 随机选择一个数字
// function getServe(status: number) {
//     if (status === 0) {
//         return "这是0";
//     } else if (status === 1) {
//         return "这是1";
//     } else if (status === 2) {
//         return "这是2";
//     }else if (status === 3) {
//         return "这是3";
//     }
// }
// const result = getServe(2);
// console.log(`输出:${result}`);


// const Stauts = {
//     ZERO: 0,
//     ONE: 1,
//     TWO: 2,
// };
// function getServe(status: any) {
//     if (status === Stauts.ZERO) {
//         return "这是0";
//     } else if (status === Stauts.ONE) {
//         return "这是1";
//     } else if (status === Stauts.TWO) {
//         return "这是2";
//     }
// }
// const result = getServe(Stauts.ONE);
// console.log(`输出:${result}`);

enum Stauts {
    ZERO,
    ONE,
    TWO,
};
function getServe(status: any) {
    if (status === Stauts.ZERO) {
        return "这是0";
    } else if (status === Stauts.ONE) {
        return "这是1";
    } else if (status === Stauts.TWO) {
        return "这是2";
    }
}
// const result = getServe(Stauts.TWO);//输出:这是2
const result = getServe(2);//输出:这是2
console.log(`输出:${result}`);
console.log(Stauts.TWO, Stauts[2]);//2 TWO

九、泛型

泛型:[generic - 通用、泛指的意思],那最简单的理解,泛型就是泛指的类型。
泛型的本质是参数化类型,通俗的将就是所操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法的创建中,分别成为泛型类,泛型接口、泛型方法。
泛型的定义使用<>(尖角号)进行定义

9.1、泛型的使用

// identity函数。 这个函数会返回任何传入它的值
// function identity(arg: number): number {
//     return arg;
// }
// 这时identity函数就不可以传除number类型以外类型的参数
// console.log(identity(1))

// function identity(arg: any): any {
//     return arg;
// }
// // 使用any类型会导致这个函数可以接收任何类型的arg参数,
// // 这样就丢失了一些信息:传入的类型与返回的类型应该是相同的(要自己typeof才会知道)
// console.log(identity(111))

// 泛型的使用
function identity<T>(arg: T): T {
    return arg;
}
console.log(identity(111))

//STR:两个参数的类型相同
function join<STR>(first: STR, second: STR) {
    return `${first}${second}`;
}
// 参数的类型可以在调用的时候定义
console.log(join<string>("我是", "huahua"))//我是huahua
console.log(join<number>(1,2))//12

9.2、泛型中数组的使用

// 泛型中 数组的使用
// 泛型函数loggingIdentity,接收类型参数T和参数arg,它是个元素类型是T的数组,并返回元素类型是T的数组
// 第一种写法
// function loggingIdentity<T>(agr: T[]){
//     console.log(agr.length)
// }
// loggingIdentity<number>([1,2,3])
// 第二种写法
// function loggingIdentity<T>(agr: Array<T>){
//     console.log(agr.length)
// }
// loggingIdentity<number>([1,2,3])

9.3、多个泛型的定义

// 多个泛型的定义
function joinMore<T, P>(first: T, second: P) {
    return `${first}${second}`;
}
joinMore<number, string>(1, "2");
// 注意:如果函数定义了多个泛型,使用时要对应的定义出具体的类型。

9.4、泛型类

// class Person {
//     constructor(private girls: string[]) {}
//     getGirl(index: number): string {
//         return this.girls[index]
//     }
// }
// const girls = new Person(["huahua", "dahua", "xiaohua"]);
// console.log(girls.getGirl(1));//dahua

//此时若需要传入的数组是number类型的,上述代码则不能正常运行,此时使用泛型

class Person<T> {
    constructor(private girls: T[]) {}
    getGirl(index: number): T {
        return this.girls[index]
    }
}
const girls = new Person<string>(["huahua", "dahua", "xiaohua"]);
const boys = new Person<number>([1,2,3])
console.log(girls.getGirl(1));//dahua
console.log(boys.getGirl(1));//2

泛型类(好理解的方式---类的复用)

class GetMin<T>{
    arr: T[] = [];
    add(ele: T) {
        this.arr.push(ele);
    }
    min(): T {
        var min = this.arr[0];
        this.arr.forEach(function (value) {
            if (value < min) {
                min = value;
            }
        });
        return min;
    }
}
var gm1 = new GetMin<number>();
gm1.add(5);
gm1.add(3);
gm1.add(2);
gm1.add(9);
console.log(gm1.min());
//比较字符在字母表中的索引
var gm2 = new GetMin<string>();
gm2.add("tom");
gm2.add("jerry");
gm2.add("jack");
gm2.add("sunny");
console.log(gm2.min());

9.5、泛型中类的继承

  • 先看泛型中类的写法
class Person<T> {
    constructor(private girls: T[]) {}
    getGirl(index: number): T {
        return this.girls[index]
    }
}
const girls = new Person<string>(["huahua", "dahua", "xiaohua"]);
console.log(girls.getGirl(1));//dahua

上述写法中,getGirl方法只是获取了这个数组的第几项,在实际开发过程中,我们数组的每一项一般都是对象,const girls = new Person([ { name: "huahua" }, { name: "dahua" }, { name: "xiaohua" }, ]);此时需要获取这个对象的属性值(name),此时getGirl()的return就需要是this.girls[index].name,但是此时会报错

image.png
此时,我们可以写一个接口(含有name属性),让类Person继承这个接口

interface Girl {
    name: string
}
class Person<T extends Girl> {
    constructor(private girls: T[]) { }
    getGirl(index: number): string {
        return this.girls[index].name
    }
}
const girls = new Person([
    { name: "huahua" },
    { name: "dahua" },
    { name: "xiaohua" },
]);
console.log(girls.getGirl(1));//dahua

9.6、泛型的约束

可以使用关键字extends来进行约束

class Person<T extends number | string> {
  //.....
}

十、实际开发

自己百度吧,整理太麻烦

以上参考: https://jspang.com/detailed?id=63#toc290

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345