typescript筆記

一、ts介紹

是javascript的超集,遵循最新的ES5 ES6規范。ts擴展了js的語法。

二、安裝與編譯

Npm install -g typescript cnpm install -g typescript yarn global add typescript
查看安裝成功與否 新打開終端 輸入:tsc -v
運行: tsc helloword.ts

vscode編譯:因為瀏覽器不認識ts代碼需要我們編譯, 在終端輸入tsc + 文件名.后綴 會在同級生成一個以js結尾的文件
為了節省開發時間,每次寫好ts代碼后能夠自動編譯

1.創建ts.config.json的文件 tsc --init 生成配置文件 修改配置文件中outDir可配置編譯后的Js存放位置
2.vscode點擊:任務->運行任務-> tsc:監視-tsconfig.json(老版本vscode)
終端-> 運行任務-> typescript -> 監視tsconfig.json 即可

三、數據類型

ts中為了使編碼更規范,更有利于維護,增加了類型校驗:
布爾類型(bollean)
數字類型(number)
字符串類型(string)
數組類型(array)
元組類型(tuple)
枚舉類型(enum)
任意類型(any)
null和undefined
void類型
never類型

1.布爾類型
eg. var flag:boolean=true 如果寫falg = “str”,編譯不通過會報錯
2.數字類型(整數、浮點數都ok)
Var a:number = 123
3.字符串類型
4.數組類型 OK 有兩種方式
方式一:let arr:nuber[] = [1, 2, 3, 4]
方式二:let arr:Array<number>=[11, 23, 353, 34]
5.
元組類型
(屬于數組的一種,可以指定數組中每一項的多種類型)
Let arr:[string, number, boolean] = [“ts”, 1, true]
6.**枚舉類型 ** (用于標識狀態和固定值)
隨著計算機的不斷普及,程序不僅只用于數值計算,還更廣泛用于處理非數值的 數據。例如:性別、月份、顏色、單位、學歷等,都不是數值數據。
事先考慮到某一變量可能去的值,盡量用自然語言中含義清楚的單詞來表示他的每一個值,這種方法稱為枚舉方法

enum 枚舉名{
  標識符[=整型常數],
  標識符[=整型常數],
  ...
  標識符[=整型常數]
}
Enum flag {
  Success=1,
  Error=-1
}
Let f:flag = flag.success   /   flag.error就代表一個值

若枚舉中沒有賦值的話,會輸出占位的索引

如果是:

Enum color {red, blue=5, orange} 
Let c:color=color.red    輸出c為其索引 0
Let c:color = color.blue  輸出c為其值 5
Let c:color = color.orange  輸出c為 6   自動跟隨前一個進行累加 

7.任意類型 any

Let num:any=123
Num=”str”  

用于獲取節點之后操作dom可以使用any類型

8.**null undefined **(其他never類型的子類型)
如果定義了變量未賦值,輸出個該變量為undefined 但是會報錯
所以要聲明變量的時候,在變量后加undefined
如果是該變量可能是number 也可能是undefined 就 let num:number | undefined

null也是如此

一個元素是多種類型,any類型可以囊括這些內容,還有一個其他形式:
Let num:number | null | undefiend

9.void類型 :表示沒有任何類型,一般用于定義方法的時候方法沒有返回值

Function run():void {
  Console.log(‘run’)
}
run();

10.never類型 是其他類型,(null undefined的子類型)代表不會出現的值。意味著聲明never的變量只能被never類型所賦值

Let a:undefined;
a = undefined

Let b:null;
b = null;

Let a :never;
a=132;  //錯誤寫法
a =(() => { 
  Throw new Error(‘錯誤”)
})()    //正確寫法

四、函數

函數也是需要指明類型的

//函數聲明類
function run():string {
  return 'run'
}
fun2();

//匿名函數
var fun2=function():number {
  return 123
}
fun2();

ts中定義方法傳參

//函數聲明
function getInfo(name: string, age:number):string {
  return `${name} --- ${number}`
}

console.log(getInfo('zhangsan', 20));

//匿名函數
let getInfo2 = function(name: string, age:number):string {
  return `${name} --- ${number}`
}
console.log(getInfo('zhangsan', 20));

沒有返回值得函數

function run():void {
  console.log('run')
}
run();

方法的可選參數
es5方法的實參和形參可以不一樣,但是ts不可以,此時需要配置可選參數
即在可能不會傳遞的參數后面添加 ?

function getInfo(name: string, age?:number):string {
  if (age) {
    return `${name} --- ${number}`
  } else {
     return `${name} --- 就不告訴你 `
  }
}

//alert(getInfo('張三', 123))   都可輸出
//alert(getInfo('張三'))  都可輸出

注意:可選參數必須配置到參數的最后面

默認參數
es5里面沒法設置默認參數,es6和ts都可以設置默認參數

function getInfo(name: string, age:number=12):string {
  if (age) {
    return `${name} --- ${number}`
  } else {
     return `${name} --- 就不告訴你 `
  }
}

//alert(getInfo('張三'))  都可輸出,且age是默認的
//alert(getInfo('張三', 123))   都可輸出

剩余參數

function sum(a: number, b:number, c:number, d:number):number {
    return a + b+c+d
}

sum(1, 2, 3, 4)

//三點運算符(剩余參數)  接受形參傳來的值
function sum(...result:number[]):number {
    let sum = 0;
    for(var i = 0; i < result.length; i ++) {
      sum += result[i];
    }
  return sum
}

sum(1, 2, 3, 4, 5, 6)

//剩余參數三點運算另一種形式
function sum(a:number, ...result:number[]):number {
    let sum = a;
    for(var i = 0; i < result.length; i ++) {
      sum += result[i];
    }
  return sum
}

sum(1, 2, 3, 4, 5, 6)

函數重載
java中方法的重載,重載的是兩個或兩個以上同名函數,但他們的參數不一樣,這時會出現函數重載的情況
ts中的重載,通過為同一個函數提供多個函數類型定義來試下多種功能的目的
ts為了見佛那個es5和es6 重載的寫法 和java有區別

//es5中 出現同名方法,后面的會替換上面的方法
function css(config:any):any {
  ...
}

function css(config:any, value:any):any {
  ...
}


//ts中的重載
function getInfo(name: string):string;
function getInfo(age: number):number;
function getInfo(str: any):any {
  if(typeof str === 'string') {
    return '我是,’+ str;
  } else {
    return ‘我的年齡是,’ + str
  }
}

alert(getInfo('張三'))  //正確
alert(getInfo(12))  //正確
alert(getInfo(true))  //錯誤


//----------------------------------------------
//參數一樣
function getInfo(name: string):string;
function getInfo(name: string, age: number):string;
function getInfo(name: string, age?:any):any {
  if (age) {
    return '我叫,' + name + '我的年齡是' + age;
  } else {
    return '我叫, ' + name
  }
}
alert (getInfo('張三'))    //正確
alert (getInfo(123))    //錯誤
alert (getInfo('張三', true))    //錯誤

箭頭函數

this指向的問題, 箭頭函數的this指向上下文

//es5
setTimeout(function() {
  alert('run')
}, 1000)

//箭頭函數     
setTimeout(() => {
  alert('run')
}, 1000)

五、ts中的類

  1. 通過class類來定義
class Person {
  name:string;    //屬性   前面省略了public關鍵詞
  constructor(n:string) {   //構造函數  實例化類的時候觸發的方法
    this.name = n;
  }

  run():void {
    alert(this.name);
  }
}

let p = new Person('張三');
p.run();
class Person {
  name: string;   
  constructor(name: string) {   
    this.name = name;
  }

  getName():string {
    return this.name;
  }

  setName():void {
    this.name = name;
  }
}

let  p = new Person('張三')
alert(p.getName());
p.setName('李四')
alert(p.getName());
  1. ts中實現繼承 extends / super
class Person {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  run():void {
    return `${this.name}在運動`
  }
}

//繼承
class Web extends Person {
  constructir(name: string) {
    super(name);    /*初始化父類的構造函數*/
  }

let w = new Web('李四');
alert(w.run());
  1. ts中繼承 父類的方法和子類的方法一致
    如果父類和子類都有同樣的方法 調用子類的就會執行子類方法,先去找子類再找父類

  2. 類里的修飾符
    提供了三種修飾符

  • public : 表示共有。 在當前類里面、子類、類外部都可以訪問
  • protected: 表示保護類型。 在當前類里面、子類里面可以訪問, 類外部無法訪問 //控制臺會報錯,但是會輸出,
  • private: 表示私有。 在當前類里面可以訪問,子類和類外部都無法訪問
    屬性如果不加修飾符 默認為共有public
class Person {
  public  name: string;      //公有屬性
  constructor(name: string) {   
    this.name = name;
  }

  run():string {
    return `${this.name}在運動`
  }
}

class Web extends Person {
  constructir(name: string) {
    super(name);    /*初始化父類的構造函數*/
  }

let w = new Web('李四');
alert(w.run());

  1. 靜態屬性 靜態方法
class Person {
  public name: string
  public age: number=12
  
  //靜態屬性才能在靜態方法中調用
 static sex = "男"

  constructor(name:string) {
    this.name = name
  }

  run() {
    alert(`${this.name}在運動`)                //實例方法
  }

  work() {
    alert(`${this.name}在工作`)                //實例方法
  }

  //靜態方法   沒法直接調用類里的屬性  
  static print() {
    alert('方法' + this.age)      //會報錯
  }

static print() {
    alert('方法' + Person.sex)      //調用成功
  }
}

let p = new Pweson('張三');
p.run();
p.work();

//調用靜態方法
Person.print();

//使用靜態屬性
alert(Person.sex)
  1. 多態:父類定義一個方法不實現,讓繼承他的子類去實現 每一個子類有不同的表現
    //多態也是一種繼承的表現,屬于繼承
class Animal {
    name:string;
    constructor(name: string) {
        this.name = name
    }
    
    eat() {
        console.log('吃的方法')
    }
}

class Dog extends Animal {

    construactor(name: string) {
        super(name)
    }

    eat() {
        return this.name + '吃狗糧'
    }
}


class Cat extends Anmal  {

    construactor(name: string) {
        super(name)
    }

    eat() {
        return this.name + '吃貓糧'
    }
}
  1. 抽象類:它是提供其他類繼承的基類,不能直接被實例化
    abstract關鍵字定義抽象類和抽象方法,抽象類中的抽象方法不包含其具體實現并且必須在派生類中實現 abstract抽象方法只能放在抽象類里面 抽象類和抽象方法用來定義標準
//抽象類和抽象方法用來定義標準  標準:Animal這個類要求他的子類必須包含eat方法
abstract class Animal {

   abstract eat():any;
}

let a = new Animal()   //錯誤的寫法   不能直接被實例化

image.png

image.png

正確寫法

//抽象類和抽象方法用來定義標準  標準:Animal這個類要求他的子類必須包含eat方法
abstract class Animal {
  public name:string;
  constructor(name:string) {
      this.name = name;
  }
   abstract eat():any;   //該方法必須實現

    run() {
      console.log('其他方法可以不實現')
    }
}

let a = new Animal()   //錯誤的寫法

class Dog extends Animal {

    constructor(name:any) {
       super (name);
  }

    //抽象類的子類必須實現抽象類里面的抽象方法
    eat()  {
        console.log(this.name + '吃糧食')
     }
}

let d = new Dog('小花花');
d.eat();

六、ts中的接口

接口的作用:在面向對象的編程中,接口是一種規范的定義,它定義了行為和動作的規范,在程序設計里面,接口起到一種限制和規范作用,接口起到一種限制和規范的作用,接口定義了某一批類所需要遵守的規范,接口不關心這些類的內部狀態數據,也不關心這些類里方法的實現細節,它之規定這批類里必須提供某些方法,提供這些方法的類就可以滿足實際需要。ts中的接口類似于java,同時還增加了更靈活的接口類型,包括屬性、函數、可索引和類等。 相當于定義標準。

通過interface進行定義

  1. 屬性類接口
  • 對傳入對象參數進行約束
//就是傳入對象的約束   是屬性接口
interface FullName {

    firstNmae: string;       //注意  以分號結束
    secondName: string; 

}
function printName(name:FullName) {
    
    //必須傳入對象   firstName  secondName
    console.log(name.firstName + '--' + name.secondName)

}

printName('123')  //錯誤的寫法
printName({firstName: '張', secondName: '三'})    //正確
printName({ age: 20, firstName: '張', secondName: '三'})    //錯誤寫法  因為多了age,內容必須只有firstName和secondName
let obj = {
  age: 20,     //但是當調用的時候就會報錯
  firstName: '張',
  secondName: '三'
}
printName(obj);     //正確寫法  且推薦此使用   外層定義只要有firstName和secondName就行
  • 對批量方法進行約束
interface FullName {

    firstNmae: string;       //注意  以分號結束
    secondName: string; 

}
function printName(name:FullName) {
    
    //必須傳入對象   firstName  secondName
    console.log(name.firstName + '--' + name.secondName)

}

function printInfo(name:FullName) {
    
    //必須傳入對象   firstName  secondName
    console.log(name.firstName + name.secondName )

}

let obj = {
  age: 20,     
  firstName: '張',
  secondName: '三'
}
printName(obj); 

printInfo({firstName: '李', secondName: '四'})

  1. 可選屬性
interface FullName {
    firstName: string;
    secondName?: string;     //可傳可不傳
}

function getName(name: FullName)  {
    console.log(name)
}

getName({firstName: 'xixixi', secondName: '啦啦'})
getName({firstName: 'xixixi'})   //也可編譯成功
  1. 函數類型接口: 對方法傳入的參數 以及返回值進行約束 可以做批量約束
//實現加密的函數類型接口
interface encrypt {
  (key: string, value: string): string;    //參數是key和value   返回值是string類型
}

let md5:encrypt = function(key: string, value: string):string {
    //模擬操作
    return key + value
}

md5('name', 'zhangsan')
  1. 可索引接口,數組、對象的約束(不常用)
//定義數組的方式
let arr:number[] = [123, 34555]
let arr1:Array<string>=['23g', 'err4']

//可索引接口 對數組的約束 1
interface UserArr {
  [index: number]:string
}
let arr:UserArr=['aaaa', 'bbbb'];
console.log(arr[0])

//對對象的約束
interface UserObj{
  [index:string]:string
}
let arr:UserObj = {name: '20'}
  1. 類類型接口:對類的約束 和 抽象類相似
    implements不是繼承,是實現接口
interface Animal {

    name: string;

    eat(str: string):void;

}

class Dog implements Animal {
    name: string;
    constructor(name: string) {
        this.name = name;
    }

  eat() {
    console.log(this.name + '吃狗糧')
  }
}

let d = new Dog('小黑')
d.eat();


class Cat implements Animal {
    name: string;
    constructor(name: string) {
        this.name = name;
    }

  eat(food:string) {
    console.log(this.name + food)
  }
}

let c = new Cat('小花')
d.eat('老鼠')
  1. 接口擴展,接口可以繼承接口
interface Animal {
  eat(): void;
}
interface Person extends Animal {     //person繼承animal
  work();
}

class Web implements Person {
    public name:string;
    constructor(name: string) {
        this.name = name
    }

    eat() {
        console.log(this.name + '喜歡吃饅頭')
    }

    work() {
      console.log(this.name + '喜歡工作')
    }
}

let w = new Web('小李')
w.eat()
interface Animal {
  eat(): void;
}
interface Person extends Animal {     //person繼承animal
  work();
}

class Programmer {
    public name:string;
    constructor(name: string) {
        this.name = name
    }
    coding(code:string) {
      console.log(this.name + code)
    }
}

class Web extends Programmer  implements Person {   //既繼承又實現接口

    constructor(name: string) {
        super(name)
    }

    eat() {
        console.log(this.name + '喜歡吃饅頭')
    }

    work() {
      console.log(this.name + '喜歡工作')
    }
}

let w = new Web('小李')
w.eat()
w.coding('寫ts代碼')

七、ts中的泛型

  1. 泛型的定義
    泛型:軟件工程中,我們不僅要創建一致的定義好的API,同時也要考慮重用性。 組件不僅能夠支持當前的數據類型,同時也能支持未來的數據類型,這在創建大型系統時為你提供了十分靈活的功能。

在像C#和java這樣的語言中,可以使用泛型來創建可重用的組件,一個組件可以支持多種類型的數據。這樣用戶就可以以自己的數據類型來使用組件。

通俗理解:泛型就是解決 類、接口、方法的復用性、以及對不特定數據類型的支持

  1. 泛型函數
//例如同時返回兩個不同類型的函數  容易代碼冗余
function getData1(value: string):string {
  return value;
}

function getData2(value: number): number {
  return value
}

//可以使用any類型來進行同時輸出,但是使用any放棄了類型檢查,傳入什么,返回什么
//泛型就出現了

泛型可以支持不特定的數據類型 要求,傳入的參數和返回的參數一致。
T或者是任意大寫字母。(建議使用T)表示泛型,具體什么類型是調用這個方法的時候決定的

function getData<T>(value: T):T {
  return value;
}

getData<number>(123);
function getData<T>(value: T): any {
  return 'sfdsfgfdgdfg'
}
getData<number>(123);     //參數必須是number
getData<string>('dfdsfdsfg');
  1. 泛型類
//泛型類: 比如有個最小堆算法,需要同時支持返回數字和字符串兩種類型   通過類的泛型來實現
class MinClass {

    piblic list:number[] = [];

    add(num: number) {
        
       this.list.push(num)
    }

    min() {

      let minNum = this.list[0];
    }

}

  1. 泛型接口

//函數類型接口
interface ConfigFn{
    (value1: string, value2: string): string;
}

let setData:ConfigFn = function(value1: string, value2: string):string {
    retirn value1+value2;
}

setData('name': '張三')


//第一種泛型接口

interface ConfigFn{
    <T>(value: T): T;
}

let getData: ConfigFn = function<T>(value: T):T {
    return value;
}
 
getData<string>('張三')     //正確
getData<string>(1234)   //錯誤


//第二種泛型接口
interface ConfigFn<T>{
    (value: T): T;
}

function getData<T>(value: T):T {
    return value;
}

let myGetData:ConfigFn<string>=getData;

myGetData('20');    //正確
myGetData(20);    //錯誤
  1. 泛型類--延伸
    1.定義個User類 作用:隱射數據庫字段
    2.定義個MysqlDb的類 用于操作數據庫
    3.然后把User類作為參數傳入到MysqlDb中
//把類作為參數來約束數據傳入的類型
class User {
    username: string | undefined;
    password: string | undefined;
}

class MysqlDb {
    add(user: User): boolean {
      // console.log(user);
      return true;
    }
}

let u = new User();
u.username = '張三';
u.password = '123456';

let Db = new MysqlDb();
Db.add(u);
//把類作為參數來約束數據傳入的類型
class ArticleCate {
    title: string | undefined;
    desc: string | undefined;
    status: number | undefined;
}

class MysqlDb {
    add(info: ArticleCate): boolean {
      // console.log(info);
      return true;
    }

    updated(info: T, id: number): boolean {
        console.log(info)
        console.log(id)
        return true
    }
}

let a= new ArticleCate();
a.title = "國內";
a.desc = "國內新聞";
a.status = 1
let Db = new MysqlDb();
Db.add(a);

發現以上兩種寫法在每操作一次數據庫表的時候 都需要重新指定值得類型,所以使用泛型動態的定義類型,避免代碼重復封裝

//操作數據庫的泛型類
class MysqlDb<T> {
    add(info: T): boolean {
      // console.log(info);
      return true;
    }
}

//給User表增加數據
//1.定義一個user類 和數據庫進行映射
class User {
    username: string | undefined;
    password: string | undefined;
}
let u = new User();
u.username = '張三';
u.password = '123456';


let Db = new MysqlDb<User>();    //可以對傳入的數據進行校驗
Db.add(u);   


//賦值方式2    使用構造函數將值提前賦進去
class User {
    username: string | undefined;
    password: string | undefined;
    constructor(params: {
       username: string | undefined,
       password: string | undefined,
      //或者是可選參數 記得加?
    }) {
        this.username = params.username;
        this.password = params.password;
    }
}

let u = new User({
    username: '張三',
    password: '123456'
});

let Db = new MysqlDb<User>();    //可以將類作為參數傳入到泛型類中進行數據的約束及驗證
Db.add(u);   
  1. ts類型、接口、類、泛型綜合使用--ts封裝統一操作Mysql Mongodb Mssql的底層庫
    定義一個操作數據庫的庫 支持Mysql Mongodb Mssql
    要求1 Mysql Mongodb Mssql功能一樣 都有add update delete get方法
    注意:約束統一的規范,以及代碼重用
    解決方案:需要約束規范所以要定義接口,需要代碼重用所以用到泛型
    1.接口:在面向對象的編程中,接口是一種規范性的定義,它定義了行為和動作的規范
    2.泛型 通俗理解:泛型就是解決 類 接口 方法的復用性
interface DBI<T> {
    add(info: T): boolean;
    update(info: T, id: number): boolean;
    delete(id: number): boolean;
    get(id: number): any[];
}

//定義一個操作mysqul數據庫的類  注意:要實現泛型接口  這個類也應該是一個泛型類
class MysqlDb<T> implements DBI<T> {

    constructor() {
        console.log('數據庫建立連接')
    }

    add(info: T): boolean {
       console.log(info)
        return true
    }

    update(info: T, id: number): boolean {
        throw new Error('Method not implemented')
    }

    delete(id: number): boolean {
        throw new Error('Method not implemented')
    }
    
    get(id: number): any[] {
        let list = [
          {
              title: ‘xxx’,
              desc: 'xxxxx'
          },
           {
              title: ‘xxx’,
              desc: 'xxxxx'
          },
        ]
      return list;
    }
}

//定義一個操作mssqul數據庫類型的類
class MsSqlDb<T> implements DBI<T> {

    constructor() {
        console.log('數據庫建立連接')
    }
    add(info: T): boolean {
        throw new Error('Method not implemented')
    }

    update(info: T, id: number): boolean {
        throw new Error('Method not implemented')
    }

    delete(id: number): boolean {
        throw new Error('Method not implemented')
    }
    
    get(id: number): any[] {
        throw new Error('Method not implemented')
    }
}

//操作用戶表 定義一個類和數據表做映射
class User {
    username: string | undefined;
    password:  string | undefined;
}

let u = new User();
u.username = '戰三';
u.password = "123456";

let oMysql = new MysqlDb<User>();
oMysql.add(u)

八、ts中的模塊

模塊的概念(官方)
關于屬于的一點說明:ts1.5里的術語名已經發生了變化。 “內部模塊”現在稱作“命名空間”。“外部模塊”現在簡稱為“模塊” 模塊在其自身的作用域里執行,而不是在全局作用域里。
這意味著定義在一個模塊里的變量,函數,類等等在模塊外部是不可見的,除非你明確的使用export形式一導出他們。相反,如果想使用其他模塊導出的變量,函數、類、接口等的時候,你必須要導入他們,可以使用import形式之一

模塊的概念(自己的理解)
我們可以把一些公共的功能單獨抽離成一個文件作為一個模塊。
模塊里面的變量 函數 類等默認是私有的,如果我們要在外部訪問模塊里面的數據(變量、函數、類)
我們需要通過export暴露莫苦熬里面的數據(變量、函數、類)。
暴露后通過import引入模塊就可以使用模塊里面暴露的數據(變量、函數、類)

引用名字過長的時候 可以使用 xx as aa來,此后調用使用aa代替xx即可

import { getData as get } from './......'

你是前端嘛?是的話,我就不用寫了 和js沒差的 不是的話 那你就先成為一個前端再看吧

九、ts的命名空間

在代碼量較大的情況下,為了避免各種變量命名沖突,可將相似功能的函數、類、接口等放置到命名空間,可以將代碼包裹起來,只對外暴露需要外部訪問的對象,命名空間內的對象通過export暴露

命名空間和模塊的區別
命名空間:內部模塊,主要用于組織代碼,避免命名沖突
模塊:ts的外部模塊簡稱,例如代碼的復用,一個模塊里可能有多個命名空間

namespace A {...........}   //定義了一堆內容
namespace B {...........}   //定義了一堆內容  兩者中的內容可以有重復的

如果想要外部暴露,可以在需要暴露的內容前面加export,使用可以通過命名空間打點使用內部內容即可
把命名空間定義成模塊并且暴露使用

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,923評論 6 535
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,740評論 3 420
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,856評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,175評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,931評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,321評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,383評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,533評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,082評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,891評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,618評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,319評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,732評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,987評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,794評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,076評論 2 375