<Dart基礎>Dart語法(上)

Dart基礎系列:

說明:
Dart系列的開篇(Dart簡介)總結了Dart語言的相關知識,涉及到一些基礎的概念,并介紹了如何搭建其開發環境。從這一篇開始,我將對Dart的語法進行總結,分為上下兩篇,其中本篇的內容如下:

內容:

  • 關鍵字
  • 數據類型
    變量與常量
    數據類型(內置類型)
  • 操作符
    算數運算符;關系運算符;邏輯運算符;賦值運算符;
    位和移位操作符;條件表達式;類型判定操作符;其他操作符
    級聯操作符
  • 控制語句
  • 注釋

一、關鍵字

關鍵字
abstract [1] do import [1] super
as [1] var continue dynamic [1]
assert [2] else interface sync *[2]
enum is implements [1] export [1]
async *[2] this library [1] throw
await new covariant true
break null external [1] factory [1]
case try extends typedef [1]
catch false operator [1] switch
class final finally void
const part [1] rethrow while
in for return with
mixin get [1] set [1] yield *[2]
default if static [1] deferred [1]

帶有[1] 的關鍵字是 內置關鍵字。避免把內置關鍵字當做標識符使用。 也不要把內置關鍵字 用作類名字和類型名字。 有些內置關鍵字是為了方便把 JavaScript 代碼移植到 Dart 而存在的。 例如,如果 JavaScript 代碼中有個變量的名字為 factory, 在移植到 Dart 中的時候,你不必重新命名這個變量。

帶有[2] 的關鍵字,是在 Dart 1.0 發布以后又新加的,用于 支持異步相關的特性。 你不能在標記為 async*、或者 sync* 的方法體內 使用 async、 await、或者 yield 作為標識符。 詳情請參考:異步支持

所以其他單詞都是 保留詞。 你不能用保留詞作為關鍵字。

二、數據類型

1、變量與常量

  • 變量聲明與初始化:
    1.使用var 聲明變量,此時沒有明確類型,編譯的時候根據值明確類型
    2.明確變量類型,來幫助 Dart 去捕獲異常以及 讓代碼運行的更高效
    3.未初始化時,變量默認值為null
    4.如果對象不限于單一類型(沒有明確的類型),請使用Object或dynamic關鍵字
      var name = ‘Bob’; 
      Object name1 = '張三';
       //動態類型
      dynamic name2 = '李四';
      // 顯示聲明將被推斷類型, 可以使用String顯示聲明字符串類型
      String name3 = 'Bob' ;
    
  • final and const
    1.被finalconst 修飾的變量只能賦值一次,不可更改變量值
    2.一個 final 變量只能被初始化一次; const變量是一個編譯時常量,(Const變量是隱式的final),如果 const 變量在類中,請定義為 static const。
    3.被final或者const修飾的變量,變量類型可以省略,建議指定數據類型。
    4.被final修飾的頂級變量或類變量在第一次聲明的時候就需要初始化,否則會提示錯誤:
    // The final variable 'outSideFinalName' must be initialized.
    final String outSideFinalName
    
    5.const關鍵字不只是聲明常數變量,您也可以使用它來創建常量值,以及聲明創建常量值的構造函數,任何變量都可以有一個常量值。
     // 注意: [] 創建的是一個空的list集合
     // const []創建一個空的、不可變的列表(EIL)。
     var varList = const []; // varList 當前是一個EIL
     final finalList = const []; // finalList一直是EIL
     const constList = const []; // constList 是一個編譯時常量的EIL
    
     // 可以更改非final,非const變量的值
     // 即使它曾經具有const值
     varList = ["haha"];
    
     // 不能更改final變量或const變量的值
     // 這樣寫,編譯器提示:a final variable, can only be set once
     // finalList = ["haha"];
     // 這樣寫,編譯器提示:Constant variables can't be assigned a value  
     // constList = ["haha"];
    
    注意:實例變量可以為 final 但是不能是 const 。

2、數據類型(內置類型)

2.1、num(數值)

1、int:其取值通常位于 -253 和 253 之間
2、double:64-bit (雙精度) 浮點數,符合 IEEE 754 標準。
3、數值型操作:

  • 運算符:+-*、/、~/、%
    其中~/為整除
  • 常用屬性:isNaN (是否非數字),isEven(是否為偶數),isOdd(是否為奇數)
  • 常用方法:abs()round(),floor(),ceil()toInt(),toDouble()
     int a = 1;
     print(a);
     
     double b = 1.12;
     print(b);
     
     // String -> int
     int one = int.parse('1');
     // 輸出3
     print(one + 2);
     
     // String -> double
     var onePointOne = double.parse('1.1');
     // 輸出3.1
     print(onePointOne + 2);
    
     // int -> String
     String oneAsString = 1.toString();
     // The argument type 'int' can't be assigned to the parameter type 'String'
     //print(oneAsString + 2);
     // 輸出 1 + 2
     print('$oneAsString + 2');
     // 輸出 1 2
     print('$oneAsString 2');
    
     // double -> String 注意括號中要有小數點位數,否則報錯
     String piAsString = 3.14159.toStringAsFixed(2);
     // 截取兩位小數, 輸出3.14
     print(piAsString);
     
     String aString = 1.12618.toStringAsFixed(2);
     // 檢查是否四舍五入,輸出1.13,發現會做四舍五入
     print(aString);
    
2.2、String(字符串)

1、String的創建:
- 使用單引號'',雙引號""
- 使用三個 引號'''或雙引號""" 創建多行字符串
- 使用r 創建原始 raw 字符串
var s1 = '單引號字符串'; var s2 = "雙引號字符串"; var s3 = ''' 單引號多創建的多行的字符串, 第二行 '''; var s4 = """ 雙引號多創建的多行的字符串, 第二行 """; //使用r創建原始’raw‘字符串,\n不換行 var s5 = r"使用r創建原始’raw‘字符串,\n不換行";
2、字符串操作:

  • 運算符:+,*,==,[],

     String a = "hello";
     String b = a + " Dart!";
     //hello Dart!
     print(b);
     
     String c = b*2;
     //hello Dart!hello Dart!
     print(c);
     
     String d = "hello Dart!";
     //true
     print(d==b);
     
     String e = d[0];
     //h
     print(e);
    
  • 插值表達式:${expression}

    int e1 = 1;
    int e2 = 2;
    //a = 1
    print("a = $a");
    //e1 + e2 = 3
    print("e1 + e2 = ${e1 + e2}");
    
  • 常用屬性:length(長度),isEmpty(是否為空),isNotEmpty(是否非空)

  • 常用方法:contains()subString(),startsWith(),endsWith()indexOf(),lastIndexOf(),toLowerCase()toUpperCase(),trim()trimLeft()trimRight(),split(),replaceXxx()

  • 更多API詳見官網:String class

3、StringBuffer

  • 使用 StringBuffer 創建字符串,當調用其 toString() 函數時,才會創建一個 新的 String 對象。
  • write() :將參數字符串加入StringBuffer 對象中
  • writeAll() :此函數有一個可選的參數來指定每個字符串的分割符
    var sb = new StringBuffer();
    //這里用到了級聯操作符
    sb..write('Use a StringBuffer for ')
      ..writeAll(['efficient', 'string', 'creation'], ' ')
      ..write('.');
    
    var fullString = sb.toString();
    //Use a StringBuffer for efficient string creation.
    printI(fullString);
    
2.3、bool(布爾型)

1、使用bool表示布爾型
2、布爾值只有個true,false,它們都是編譯時常量。
3、Dart的類型安全意味著您不能使用 if(nonbooleanValue) 或 assert(nonbooleanValue) 等代碼, 相反Dart使用的是顯式的檢查值。

2.4、List(數組、列表)

1、List的創建:

  • 創建List:
    var lvs = [1, 2, 3];
    
  • 創建不可變的List:
    //其中的值不能修改
    var lcs = const [1, 2, 3];
    //報錯:unsupported operation: Cannot modify for an unmodifiable list
    lcs[0] = 5;
    
  • 構造創建:
    var lns = new List();
    

2、常用操作:

  • [] 取值,length 數組長度

  • 方法:
    add() 添加元素,insert() 在指定位置插入,
    remove() 移除元素,clear() 清空數組,
    indexOf() 獲取指定元素位置,lastIndexOf() 倒序獲取指定元素位置,
    sort() 排序,sublist() 截取數組,shuffle() ,
    asMap() 轉換為Map,forEach() 循環遍歷,
    更多API詳見官網:List<E> class

     //創建一個int類型的list
     List list = [10, 7, 23];
     // 輸出[10, 7, 23]
     print(list);
     
     // 使用List的構造函數,也可以添加int參數,表示List固定長度,不能進行添加 刪除操作
     var fruits = new List();
     
     // 添加元素
     fruits.add('apples');
     
     // 添加多個元素
     fruits.addAll(['oranges', 'bananas']);
     
     List subFruits = ['apples', 'oranges', 'banans'];
     // 添加多個元素
     fruits.addAll(subFruits);
     
     // 輸出: [apples, oranges, bananas, apples, oranges, banans]
     print(fruits);
     
     // 獲取List的長度
     print(fruits.length);
     
     // 獲取第一個元素
     print(fruits.first);
     
     // 獲取元素最后一個元素
     print(fruits.last);
     
     // 利用索引獲取元素
     print(fruits[0]);
     
     // 查找某個元素的索引號
     print(fruits.indexOf('apples'));
     
     // 刪除指定位置的元素,返回刪除的元素
     print(fruits.removeAt(0));
    
     // 刪除指定元素,成功返回true,失敗返回false
     // 如果集合里面有多個“apples”, 只會刪除集合中第一個改元素
     fruits.remove('apples');
    
     // 刪除最后一個元素,返回刪除的元素
     fruits.removeLast();
    
     // 刪除指定范圍(索引)元素,含頭不含尾
     fruits.removeRange(start,end);
    
     // 刪除指定條件的元素(這里是元素長度大于6)
     fruits.removeWhere((item) => item.length >6);
    
     // 刪除所有的元素
     fruits.clear();
    
  • 說明:List 是泛型類型,所以可以指定里面所保存的數據類型

       // This list should contain only strings.
       var fruits = new List<String>();
          
       fruits.add('apples');
       var fruit = fruits[0];
       assert(fruit is String);
       
       // Generates static analysis warning, num is not a string.
       fruits.add(5);  // BAD: Throws exception in checked mode.
    
2.5、Set(無序集合)

1、Dart 中的 Set 是一個無序集合,里面不能保護重復的數據。 由于是無序的,所以無法通過索引來從 set 中獲取數據。
2、相關方法:
add() 添加一個元素, addAll() 添加一個數組
contains() 是否包含一個元素,containsAll() 是否包含多個元素
intersection() 獲取兩個集合的交集
更多API詳見官網:Set<E> class

   void main() {
     var sts = new Set();
     sts.add("1");
     sts.addAll(['gold', 'titanium', 'xenon']);
     sts.add("1");  //重復添加相同元素被覆蓋
   
     //{1, gold, titanium, xenon}
     print(sts);
   
     //titanium
     print("" + sts.elementAt(2));
     
     //sts==>{1, gold, titanium, xenon}
     print("sts==>$sts");

     var sts2 = new Set.from(['xenon', 'argon']);
     //sts2==>{xenon, argon}
     print("sts2==>$sts2");

     var sts3 = sts.intersection(sts2);
     //sts3==>{xenon}
     print("sts3==>$sts3");
   }

注: List<E>Set<E>都繼承自EfficientLengthIterable<T> ,并最終繼承Iterable<E>類。

2.6、Map(集合)

1、說明:
· map 通常也被稱之為 字典或者 hash ,也是一個無序的集合,里面 包含一個 key-value 對。map 把 key 和 value 關聯起來可以 方便獲取數據。和 JavaScript 不同的是, Dart objects 不是 maps。
· 鍵和值都可以是任何類型的對象。
· 每個 鍵 只出現一次, 而一個值則可以出現多次。
2、創建:

     //方式一:
     var map1 = {
       "one" : [1, "strValue", true],
       "two" : "twoValue",
     };
     //創建不可變Map
     var mapConst = const {
       "one" : [1, "strValue", true],
       "two" : "twoValue",
     };

     //方式二:未指定泛型類型
     var map2 = new Map();

     //方式二:指定泛型類型
     var map3 = new Map<int, String>();

3、常用屬性/方法:
length Map長度, keys 返回所有key值,values 返回所有的value值
isEmpty() 是否為空Map, isNotEmpty() 是否為非空Map
[] 新增一個元素,remove() 移除一個元素,并將元素返回
containsKey() 是否包含一個key
putIfAbsent(key, function) 設置 key 的值,但是只有該 key 在 map 中不存在的時候才設置這個值,否則 key 的值保持不變。該函數需要 一個方法返回 value
forEach() 遍歷Map

     var map1 = {
       "one" : [1, "strValue", true],
       "two" : "twoValue",
     };
     
     //null
     print(map1["x"]);
     //[1, strValue, true]
     print(map1["one"]);

     //true
     print(map1.containsKey("one"));

     var result = map1.remove("two");
     //result==>twoValue,,map1==>{one: [1, strValue, true]}
     print("result==>$result,,map1==>$map1");

     //提示:the argument type 'int' can't be assigned to be parameter type 'String'
     //map1[1] = 123;

     var map11 = {
         "one" : [1, "strValue", true],
         "two" : "twoValue",
         2 : new List()
       };
     //不會提示錯誤
     map11[1] = 123;

     //新增一個元素
     map1["three"] = "addValue";

     var keys = map1.keys;
     //keys==>(one, three)
     print("keys==>$keys");
     var values = map1.values;
     //values==>([1, strValue, true], addValue)
     print("values==>$values");

     map1.putIfAbsent("four", ()=> 1+2);
     map1.putIfAbsent("four", ()=> "返回一個value");
     //map1==>{one: [1, strValue, true], three: addValue, four: 3}
     print("map1==>$map1");
     print("==========================");

     /*
     one==>[1, strValue, true]
     three==>addValue
     four==>3
     */
     map1.forEach((key, value)=> {
       print("$key==>$value")
     });

     print("==========================");
     /*
     one==[1, strValue, true]
     three==addValue
     four==3
      */
     for(var me in map1.entries) {
       print("${me.key}==${me.value}");
     }

說明:
1、從上面的代碼可以看出,在map中,如果初始的key值都是同一類型,則在通過[] 方式添加的時候,只能添加相同類型的值作為key。
2、雖然 Map 沒有實現 Iterable,但是 Map 的 keys 和 values 屬性實現了 Iterable。

  Iterable<K> get keys;
  Iterable<V> get values;

3、和Java一樣,在Map中也有一個內部類MapEntry<K, V>,可以通過其屬性entries獲取到MapEntry<K, V> 類型的迭代器Iterable,以此來進行遍歷。

2.7、dynamic(動態類型)

1、注意:
dynamic并非Dart中的內置類型,
沒有指定類型的變量的類型為 dynamic,
dynamic 一般在使用泛型時使用
2、示例:

dynamic a = 10;
//a==>10
print("a==>$a");
a = "六六六";
//a==>六六六
print("a==>$a");

var ls = new List<dynamic>();  //泛型,會在后面總結
ls.add("哈哈");
ls.add(333);
//ls==>[哈哈, 333]
print("ls==>$ls");
2.8、runes(符號文字)[不常用]
  • 簡介:
    在 Dart 中,runes 代表字符串的 UTF-32 code points。

    Unicode 為每一個字符、標點符號、表情符號等都定義了 一個唯一的數值。 由于 Dart 字符串是 UTF-16 code units 字符序列, 所以在字符串中表達 32-bit Unicode 值就需要 新的語法了。

    可以實現一些表情的符號文字。

  • Unicode code point的表示方式:

    \uXXXX
    

    這里的 XXXX 是4個 16 進制的數。

  • 示例:

    main() {
      var clapping = '\u{1f44f}';
      print(clapping);
      print(clapping.codeUnits);
      print(clapping.runes.toList());
    
      Runes input = new Runes(
          '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
      print(new String.fromCharCodes(input));
    }
    
    //打印結果:===============================
    ??
    [55357, 56399]
    [128079]
    ?  ??  ??  ??  ??  ??
    
2.9、Symbols(標志)[不常用]
  • 簡介:
    一個 Symbol object 代表 Dart 程序中聲明的操作符或者標識符。

    此標識符常用于對于通過名字來引用標識符的情況,特別是混淆后的代碼, 標識符的名字被混淆了,但是 Symbol 的名字不會改變。

    Symbol 字面量定義的是編譯時常量。

  • 使用:
    使用 Symbol 字面量來獲取標識符的 symbol 對象,也就是在標識符 前面添加一個 # 符號:

    #radix
    #bar
    

關于 symbols 的詳情,請參考 dart:mirrors - reflection。

三、操作符

1、算數運算符:
  • + 加、- 減、* 乘、/ 除、~/ 取整、% 取模(余)、-expr 負數
  • ++expr 先遞增、expr++ 后遞增、--expr 先遞減、expr--后遞減
2、關系運算符:
  • ==相等、!= 不等、>=大于等于、>大于、<=小于等于、< 小于
3、邏輯運算符:
  • ! 取反、&& 并且、|| 或者
4、賦值運算符:
  • =等于、+= 加等于、-= 減等于、
    *= 乘等于、/= 除等于、
    %= 取模(余)等于、~/= 取整等于
    <<= 左移等于、>>= 右移等于
    ^= 非等于、&=且等于、|=或等于
    ??= 判空等于:如果??=左邊的變量為無值,則將右邊的值賦值給變量,否則不賦值
    int a = 10;
    int b;
    a ??= 20;
    b ??=5;
    //a = 10      a有值10,所以不會賦值20
    print("a = $a");
    //b = 5        b無值,則將5賦值給b
    print("b = $b");
    
5、位和移位操作符

& 且、| 或、^ 非、<< 左移、>> 右移

5、條件表達式

condition ? expr1 : expr2 三目運算符
expr1 ?? expr2 返回其中不為空的表達式執行結果

String a = "Hello";
String b = "";
String c = "Dart";
String d = a ?? b;
String e = b ?? c;
//d = Hello
print("d = $d");
//e = Dart
print("e = $e");
6、類型判定操作符

as、is、和 is! 操作符是在運行時判定對象
as:類型轉換
is:如果對象是指定的類型返回 True
is!:如果對象是指定的類型返回 False
具體例子參考面向對象的總結

7、其他操作符
  • ():使用方法。代表調用一個方法
  • []:訪問 List。訪問 list 中特定位置的元素
    .:訪問 Member(成員)。訪問元素,例如 foo.bar 代表訪問 foo 的 bar 成員
    ?.:條件成員訪問。和 . 類似,但是左邊的操作對象不能為 null,例如 foo?.bar 如果 foonull 則返回 null,否則返回 bar 成員
8、級聯操作符

..:級聯操作符 (..) 可以在同一個對象上 連續調用多個函數以及訪問成員變量。使用級聯操作符可以避免創建臨時變量,并且寫出來的代碼看起來更加流暢。(具體詳見面向對象中的例子)

querySelector('#button') // Get an object.
  ..text = 'Confirm'   // Use its members.
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'));

說明:
第一個方法 querySelector() 返回了一個 selector 對象。后面的級聯操作符都是調用這個對象的成員,并忽略每個操作所返回的值。

四、控制語句

  • if...else,if...else if,if...else if...else
        int score = 95;
        if (score > 90) {
            print("優秀");
        } else if (score > 60) {
            print("及格");
        } else {
            print("完蛋玩意兒");
        }
        //優秀
    
  • for,for...in
    var list = [1, 2, 3, 4, 5];
    for (var item in list) {
       print(item);
    }
    
  • while do-while
        int count = 5;
        while(count > 0) {
            print("index => $count");
            count--;
        }
    
        int length = 5;
        do {
            print("index ==> $length");
            length--;
        } while(length > 0);
    
    
  • break continue
     List ls = [1, 2, 3, 4, 5, 6, 7, 8, 9];
     for (var i = 1; i<=ls.length; i++) {
         if (i%4==0) {
             break;
         }
         if (i%3==0) {
             continue;
         }
         print("index ==> ${ls[i]}");
     }
     
     //index ==> 2
     //index ==> 3
    
  • switch...case
    其中可以使用跳轉標簽(自定義標簽名稱)
    Stirng lang = “Dart";
    switch (lang) {
      D:
      case "Dart":
           print("This is Dart!");
           break;
      case "Java":
           print("This is Java!");
           break;
      case "Flutter":
           print("This is Flutter!");
           continue D;
           //break;  //不需要了
      default:
           print("This is NONE!");
           break;
    }
    
    打印結果為:
    This is Flutter!
    This is Dart!
    
  • assert (斷言)
    1、如果條件表達式結果不滿足需要,則可以使用 assert 語句倆打斷代碼的執行。
    2、斷言只在檢查模式下運行有效,如果在生產模式 運行,則斷言不會執行。
    3、assert 方法的參數可以為任何返回布爾值的表達式或者方法。
    如果返回的值為 true, 斷言執行通過,執行結束。 如果返回值為 false, 斷言執行失敗,會拋出一個異常 AssertionError
       // Make sure the variable has a non-null value.
       assert(text != null);
       
       // Make sure the value is less than 100.
       assert(number < 100);
       
       // Make sure this is an https URL.
       assert(urlString.startsWith('https'));
    

四、注釋

  • Dart 支持單行注釋、多行注釋和 文檔注釋。

  • 單行注釋:
    單行注釋以 // 開始。 // 后面的一行內容 為 Dart 代碼注釋。

       main() {
         // TODO: refactor into an AbstractLlamaGreetingFactory?
         print('Welcome to my Llama farm!');
       }
    
  • 多行注釋:
    多行注釋以 /* 開始, */ 結尾。 多行注釋可以嵌套。

       main() {
         /*
          * This is a lot of work. Consider raising chickens.
       
         Llama larry = new Llama();
         larry.feed();
         larry.exercise();
         larry.clean();
          */
       }
    
  • 文檔注釋:
    文檔注釋可以使用 /// 開始, 也可以使用 /** 開始 并以 */ 結束。

    在文檔注釋內, Dart 編譯器忽略除了中括號以外的內容。 使用中括號可以引用 classes、 methods、 fields、 top-level variables、 functions、 和 parameters。中括號里面的名字使用 當前注釋出現地方的語法范圍查找對應的成員。

       /// A domesticated South American camelid (Lama glama).
       ///
       /// Andean cultures have used llamas as meat and pack
       /// animals since pre-Hispanic times.
       class Llama {
         String name;
       
         /// Feeds your llama [Food].
         ///
         /// The typical llama eats one bale of hay per week.
         void feed(Food food) {
           // ...
         }
       
         /// Exercises your llama with an [activity] for
         /// [timeLimit] minutes.
         void exercise(Activity activity, int timeLimit) {
           // ...
         }
       }
    

    使用 SDK 中的 文檔生成工具可以解析文檔并生成 HTML 網頁。 關于生成的文檔示例,請參考 Dart API 文檔。 關于如何 組織文檔的建議,請參考 Dart 文檔注釋指南。

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

推薦閱讀更多精彩內容