indexDB講解與封裝

indexedDB,非關(guān)系型數(shù)據(jù)庫(kù)胳搞,W3C標(biāo)準(zhǔn)推薦

indexedDB是一種輕量級(jí)NOSQL數(shù)據(jù)庫(kù)卸例,是由瀏覽器自帶。相比Web Sql更加高效肌毅,包括索引筷转、事務(wù)處理和查詢功能。

在HTML5本地存儲(chǔ)中悬而,IndexedDB存儲(chǔ)的數(shù)據(jù)是最多的呜舒,不像webStorage的4M,IndexedDB存儲(chǔ)空間是無上限且永久的笨奠。

indexedDB支持度情況:

http://caniuse.com/#search=indexdb

對(duì)于ios10以前的版本有下面這一條說明:

Partial support in Safari & iOS 8 & 9 refers to seriously buggy behavior as well as complete lack of support in WebViews.

部分支持Safari和iOS 8和9指的是嚴(yán)重的錯(cuò)誤行為以及在WebViews完全缺乏支持袭蝗。

Ok,如果般婆,我們要用indexedDB到腥,對(duì)于ios10之前的版本,那到底有多嚴(yán)重呢蔚袍?

這個(gè)api里面有詳細(xì)的介紹乡范,其實(shí)基本的一些操作是可以用的。

https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API

在討論過indexedDB是否可用后,我們來正式學(xué)習(xí)一下它:

indexedDB特點(diǎn):

  1. 鍵值對(duì)存儲(chǔ):IndexedDB內(nèi)部采用對(duì)象倉(cāng)庫(kù)(object store)存放數(shù)據(jù)篓足。所有類型的數(shù)據(jù)都可以直接存入,包括JavaScript對(duì)象闰蚕。在對(duì)象倉(cāng)庫(kù)中栈拖,數(shù)據(jù)以“鍵值對(duì)”的形式保存,每一個(gè)數(shù)據(jù)都有對(duì)應(yīng)的鍵名没陡,鍵名是獨(dú)一無二的涩哟,不能有重復(fù),否則會(huì)拋出一個(gè)錯(cuò)誤盼玄。

  2. 異步:IndexedDB操作時(shí)不會(huì)鎖死瀏覽器贴彼,用戶依然可以進(jìn)行其他操作,這與localStorage形成對(duì)比埃儿,后者的操作是同步的器仗。異步設(shè)計(jì)是為了防止大量數(shù)據(jù)的讀寫,拖慢網(wǎng)頁(yè)的表現(xiàn)童番。

  3. 支持事務(wù):IndexedDB支持事務(wù)(transaction)精钮,這意味著一系列操作步驟之中,只要有一步失敗剃斧,整個(gè)事務(wù)就都取消轨香,數(shù)據(jù)庫(kù)回到事務(wù)發(fā)生之前的狀態(tài),不存在只改寫一部分?jǐn)?shù)據(jù)的情況幼东。

  4. 同域限制 :您也受到同域限制臂容,每一個(gè)數(shù)據(jù)庫(kù)對(duì)應(yīng)創(chuàng)建該數(shù)據(jù)庫(kù)的域名。來自不同域名的網(wǎng)頁(yè)根蟹,只能訪問自身域名下的數(shù)據(jù)庫(kù)脓杉,而不能訪問其他域名下的數(shù)據(jù)庫(kù)。

  5. 儲(chǔ)存空間大:IndexedDB的儲(chǔ)存空間比localStorage大得多简逮,一般來說不少于250MB丽已。IE的儲(chǔ)存上限是250MB,Chrome和Opera是剩余空間的某個(gè)百分比买决,F(xiàn)irefox則沒有上限沛婴。

  6. 支持二進(jìn)制儲(chǔ)存: IndexedDB不僅可以儲(chǔ)存字符串,還可以儲(chǔ)存二進(jìn)制數(shù)據(jù)督赤。

indexedDB的主要方法:

1.創(chuàng)建數(shù)據(jù)庫(kù)window.indexedDB.open()

我們可以這樣創(chuàng)建或打開一個(gè)本地的數(shù)據(jù)庫(kù)對(duì)象

var openRequest =window.indexedDB.open(name, version);
var db;
openRequest.onupgradeneeded = function(e) {
  console.log("Upgrading...");}
openRequest.onsuccess = function(e) {
  console.log("Success!");
  db = e.target.result;
}
openRequest.onerror = function(e) {
  console.log("Error");
  console.dir(e);
}

(1)第一次打開數(shù)據(jù)庫(kù)時(shí)嘁灯,會(huì)先觸發(fā)upgradeneeded事件,然后觸發(fā)success事件躲舌。

(2)open方法返回的是一個(gè)對(duì)象(IDBOpenDBRequest)丑婿,回調(diào)函數(shù)定義在這個(gè)對(duì)象上面。

(3)回調(diào)函數(shù)接受一個(gè)事件對(duì)象event作為參數(shù),它的target.result屬性就指向打開的IndexedDB數(shù)據(jù)庫(kù)羹奉。

如圖為chrom瀏覽器中的打開后的對(duì)象

image.jpeg

2.indexedDB實(shí)例對(duì)象的方法—createObjectStore

createObjectStore方法用于創(chuàng)建存放數(shù)據(jù)的“對(duì)象倉(cāng)庫(kù)”(object store)秒旋,類似于傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)的表格。

db.createObjectStore("test", { keyPath: "email" });

db.createObjectStore("test2", { autoIncrement: true });

上面代碼中的keyPath屬性表示诀拭,所存入對(duì)象的email屬性用作每條記錄的鍵名(由于鍵名不能重復(fù)迁筛,所以存入之前必須保證數(shù)據(jù)的email屬性值都是不一樣的),默認(rèn)值為null耕挨;autoIncrement屬性表示细卧,是否使用自動(dòng)遞增的整數(shù)作為鍵名(第一個(gè)數(shù)據(jù)為1,第二個(gè)數(shù)據(jù)為2筒占,以此類推)贪庙,默認(rèn)為false。一般來說翰苫,keyPath和autoIncrement屬性只要使用一個(gè)就夠了止邮,如果兩個(gè)同時(shí)使用,表示鍵名為遞增的整數(shù)奏窑,且對(duì)象不得缺少指定屬性农尖。

if(!db.objectStoreNames.contains("firstOS")) {
   db.createObjectStore(“firstOS”);
}

上面代碼先判斷某個(gè)“對(duì)象倉(cāng)庫(kù)”是否存在,如果不存在就創(chuàng)建該對(duì)象倉(cāng)庫(kù)良哲。

3.indexedDB實(shí)例對(duì)象的方法—transaction

transaction方法用于創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)事務(wù)盛卡。向數(shù)據(jù)庫(kù)添加數(shù)據(jù)之前,必須先創(chuàng)建數(shù)據(jù)庫(kù)務(wù)筑凫。

transaction方法返回一個(gè)事務(wù)對(duì)象滑沧,該對(duì)象的objectStore方法用于獲取指定的對(duì)象倉(cāng)庫(kù)。

var transaction = db.transaction(["firstOS"],"readwrite");

var store = transaction.objectStore("firstOS");

transaction方法接受兩個(gè)參數(shù):

第一個(gè)參數(shù)是一個(gè)數(shù)組巍实,里面是所涉及的對(duì)象倉(cāng)庫(kù)滓技,通常是只有一個(gè);

第二個(gè)參數(shù)是一個(gè)表示操作類型的字符串棚潦。readonly(只讀)和readwrite(讀寫)令漂。

transaction方法有三個(gè)事件,可以用來定義回調(diào)函數(shù)丸边。

abort: 事務(wù)中斷; complete: 事務(wù)完成; error: 事務(wù)出錯(cuò)叠必。

transaction.oncomplete = function(event) {
    // some code
};

4.transaction對(duì)象—添加數(shù)據(jù): add方法

獲取對(duì)象倉(cāng)庫(kù)以后,就可以用add方法往里面添加數(shù)據(jù)了妹窖。

var transaction = db.transaction(["firstOS"],"readwrite");
var store = transaction.objectStore(“firstOS”);
var o = {p: 123};
var request = store.add(o,1);
request.onerror = function(e) {
   console.log("Error",[e.target.error.name](http://e.target.error.name));
}
request.onsuccess = function(e) {
  console.log("數(shù)據(jù)添加成功纬朝!");
}

add方法的第一個(gè)參數(shù)是所要添加的數(shù)據(jù),第二個(gè)參數(shù)是這條數(shù)據(jù)對(duì)應(yīng)的鍵名(key)骄呼,上面代碼將對(duì)象o的鍵名設(shè)為1共苛。如果在創(chuàng)建數(shù)據(jù)倉(cāng)庫(kù)時(shí)判没,對(duì)鍵名做了設(shè)置,這里也可以不指定鍵名隅茎。上述操作也可以寫成鏈?zhǔn)降?/p>

下圖為一個(gè)學(xué)生對(duì)象添加到數(shù)據(jù)庫(kù)中在chrom瀏覽器中的存儲(chǔ)情況:

image.jpeg
image.jpeg

5.transaction對(duì)象—其他方法

(1)更新記錄:put方法澄峰,更新數(shù)據(jù)倉(cāng)庫(kù)中的對(duì)象

var o = { p:456 };
var request = store.put(o);

(2)讀取數(shù)據(jù):get方法,通過鍵值key獲取數(shù)據(jù)倉(cāng)庫(kù)中的對(duì)象

var request = store.get(key);

(3)刪除記錄:delete方法辟犀,通過鍵值key刪除數(shù)據(jù)倉(cāng)庫(kù)中的對(duì)象

var request = store.delete(key);

(4)清空數(shù)據(jù)倉(cāng)庫(kù):clear方法俏竞,刪除整個(gè)object store中的數(shù)據(jù)

var request = store.clear();

(5)遍歷數(shù)據(jù):openCursor方法,利用游標(biāo)遍歷數(shù)據(jù)踪蹬,下面詳細(xì)講一下這個(gè)方法

var request = store.openCursor();

6.transaction對(duì)象—遍歷數(shù)據(jù):openCursor方法

(1)利用游標(biāo)遍歷數(shù)據(jù)

var request = store.openCursor();
request.onsuccess = function(e) {
  var cursor = e.target.result;
  if(cursor && cursor !== null) {
      console.log("Key", cursor.key);
      console.dir("Data", cursor.value);
      cursor.continue();
  }else{
console.log(“遍歷結(jié)束");
}
request.onerror = function(e) {
   console.log("Error",[e.target.error.name](http://e.target.error.name));
}

(2)利用游標(biāo) 返回 或 刪除 指定的數(shù)據(jù)

var request = store.openCursor();
var data = [];
request.onsuccess = function(e) {
  var cursor = e.target.result;
if(cursor && cursor !== null) {
  if(cursor.[value.name](http://value.name) === ‘jack’){
  data.push(cursor.value);
  // 或者在此刪除數(shù)據(jù)
  // cursor.delete();
  }
  cursor.continue();
}else{
  console.log(“遍歷結(jié)束”)臣咖;
  // 在此resolve(data);
}
request.onerror = function(e) {
  console.log("Error",[e.target.error.name](http://e.target.error.name));
}

7.indexedDB實(shí)例對(duì)象的方法—索引createIndex與index

如圖一個(gè)學(xué)生對(duì)象跃捣,創(chuàng)建索引:

image.jpeg

(1)createIndex方法用于創(chuàng)建索引。

var store = db.createObjectStore('student',{keyPath: “id”});

store.createIndex(‘emailIndex’,'email',{unique:true});                      //郵箱

store.createIndex(‘classIndex’,'class',{unique:false});                     //班級(jí)

store.createIndex(‘sexIndex','sex',{unique:false});                          //性別

store.createIndex(‘classSexIndex’,['class','sex'],{unique:false});    //班級(jí)+性別

(2)createIndex方法接受三個(gè)參數(shù)夺蛇,第一個(gè)是索引名稱疚漆,第二個(gè)是建立索引的屬性名,第三個(gè)是參數(shù)對(duì)象刁赦,用來設(shè)置索引特性娶聘,unique表示索引所在的屬性是否有唯一值。

var index = store.index(“emailIndex");

index.get('jack').onsuccess=function(e){
   var student=e.target.result;
   console.log(student.id);
}

Index.get用來獲取唯一索引甚脉,如果不是唯一的丸升,就要用到游標(biāo)

8.IDBKeyRange對(duì)象—指定游標(biāo)范圍

索引的有用之處,還在于可以指定讀取數(shù)據(jù)的范圍牺氨。這需要用到瀏覽器原生的IDBKeyRange對(duì)象狡耻。

IDBKeyRange對(duì)象的作用是生成一個(gè)表示范圍的Range對(duì)象。生成方法有四種:

lowerBound方法:指定范圍的下限猴凹。

upperBound方法:指定范圍的上限夷狰。

bound方法:指定范圍的上下限。

only方法:指定范圍中只有一個(gè)值郊霎。

var r1 = IDBKeyRange.upperBound(x); All keys ≤ x

var r2 = IDBKeyRange.upperBound(x, true); All keys < x

var r3 = IDBKeyRange.lowerBound(y); All keys ≥ y

var r4 = IDBKeyRange.lowerBound(y, true); All keys > y

var r5 = IDBKeyRange.bound(x, y); All keys ≥ x && ≤ y

var r6 = IDBKeyRange.bound(x, y, true, true); All keys > x &&< y

var r7 = IDBKeyRange.bound(x, y, true, false); All keys > x && ≤ y

var r8 = IDBKeyRange.bound(x, y, false, true); All keys ≥ x &&< y

var r9 = IDBKeyRange.only(z); // The key = z

如下圖所示的方法沼头,便可

利用索引查詢與特定條件匹配的所有記錄

利用sexIndex查找所有男同學(xué)的信息

getIndex(‘student’,’sexIndex’,’male’);

利用classSexIndex查找所有二年六班的女同學(xué)的信息

getIndex(‘student’,’classSexIndex’,[‘二年六班’,’female’]);

由此可見书劝,在項(xiàng)目中使用进倍,對(duì)于數(shù)據(jù)庫(kù)的封裝飾很有必要的,

image.jpeg

下面我在項(xiàng)目中封裝的indexedDB的一些部分购对,僅供參考:

dbModule.factory('iDbService',["$http", "$q", function ($http,$q) {
  var myDB = {
    name : 'localIndexDB',
    version : 1,
    db : null
  };

  var openDB = function (name, version, stores) {
    console.log('openDB');
    var d = $q.defer();
    var _name = [myDB.name](http://myDB.name) || name;
    var _version = myDB.version || version;

    //打開數(shù)據(jù)庫(kù)
    var result = window.indexedDB.open(_name,_version);

    //錯(cuò)誤
    result.onerror = function(e){
      console.log("Open DB Error!");
      d.reject("error");
    };

    //正確打開
    result.onsuccess = function(e){
      myDB.db = e.target.result ;
      console.log('success');
      d.resolve("success");
    };

    //數(shù)據(jù)庫(kù)版本變更
    result.onupgradeneeded = function(e){
      myDB.db = e.target.result ;
      if(!myDB.db.objectStoreNames.contains('users')){
        myDB.db.createObjectStore('users',{keyPath: "id"});
      }
      if(!myDB.db.objectStoreNames.contains('infos')){
        myDB.db.createObjectStore('infos',{autoIncrement: true});
      }
      if(!myDB.db.objectStoreNames.contains('problem')){
        var store = myDB.db.createObjectStore('problem',{keyPath: "fqid"}); // 建數(shù)據(jù)倉(cāng)庫(kù)object store
        store.createIndex('minTaskIndex',['fmid','fstate'],{unique:false}); // 創(chuàng)建索引
      }
      console.log('upgradeneeded');
      d.resolve("upgradeneeded");
    };
    return d.promise;
  };

  openDB();

  // 通過key查詢數(shù)據(jù)
  var get = function (storeName,key) {
    var d = $q.defer();//promise
    var _db = myDB.db;
    var transaction = _db.transaction(storeName,'readonly');
    var store = transaction.objectStore(storeName);
    var result = store.get(key);
    result.onsuccess = function (e) {
      var data = e.target.result;
      console.log('indexDb 一條數(shù)據(jù)查詢結(jié)果為:');
      console.log(data);
      d.resolve(data);
    };
    result.onerror = function (e) {
      d.reject();
    };
    return d.promise;
  };

  // 查詢一個(gè)object store的所有數(shù)據(jù)
  var getAll = function(storeName){
    var d = $q.defer();//promise
    var _db = myDB.db;
    var transaction = _db.transaction(storeName,'readonly');
    var store = transaction.objectStore(storeName);
    var result = store.openCursor();  //  打開一個(gè)游標(biāo)
    var data = [];
    result.onsuccess = function (e) {
      var cursor = e.target.result;
      if (cursor && cursor !== null) {
        var problem = cursor.value;
        var jsonStr = JSON.stringify(problem);
        data.push(problem);
        cursor.continue();
      }else {
        console.log('indexDb 一張表數(shù)據(jù)查詢結(jié)果為:');
        // console.log(data);
        d.resolve(data);
      }
    };
    result.onerror = function (e) {
      d.reject();
    };
    return d.promise;
  };

  // 根據(jù)索引,查詢與特定條件匹配的所有記錄
  var getIndex = function(storeName,indexName,params){
    var d = $q.defer();//promise
    console.log('索引查詢的params');
    console.log(params);
    var _db = myDB.db;
    var transaction = _db.transaction(storeName,'readonly');
    var store = transaction.objectStore(storeName);
    var index = store.index(indexName);
    var range = IDBKeyRange.only(params);
    var result = index.openCursor(range);  //  打開一個(gè)游標(biāo)
    var data = [];
    result.onsuccess = function (e) {
      var cursor = e.target.result;
      if (cursor && cursor !== null) {
        var problem = cursor.value;
        var jsonStr = JSON.stringify(problem);
        data.push(problem);
        cursor.continue();
      }else {
        console.log('indexDb' + storeName + '表中' + indexName + '索引,數(shù)據(jù)查詢結(jié)果為:');
        // console.log(data);
        d.resolve(data);
    };
    result.onerror = function (e) {
      d.reject();
    };
    return d.promise;
  };

  // 新增數(shù)據(jù)
  var add = function (storeName,value) {
    var d = $q.defer();
    var _db = myDB.db;
    var transaction = _db.transaction(storeName,'readwrite');
    var store = transaction.objectStore(storeName);
    var result = store.add(value);
    result.onsuccess = function(e) {
      console.log("create note success!");
      console.log(myDB);
      d.resolve();
    };
    result.onerror = function(e) {
      console.log("can't create database,error:" + result.error);
      d.reject();
    };
    return d.promise;
  };

  // 插入更新數(shù)據(jù)
  var put = function (storeName,value) {
    var d = $q.defer();
    var _db = myDB.db;
    var transaction = _db.transaction(storeName,'readwrite');
    var store = transaction.objectStore(storeName);
    var result = store.put(value);
    result.onsuccess = function(e) {
      console.log("create note success!");
      d.resolve();
    };
    result.onerror = function(e) {
      console.log("can't create database,error:" + result.error);
      d.reject();
    };
    return d.promise;
  };

  // 通過key刪除對(duì)象
  var remove = function (storeName,key) {
    var _db = myDB.db;
    var transaction = _db.transaction(storeName,'readwrite');
    var store = transaction.objectStore(storeName);
    var result = store.delete(key);
    result.onsuccess = function (e) {
        console.log(e);
    };
    result.onerror = function (e) {
        console.log(e);
    };
  };
  // clear方法可以清空object store
  var clear = function (storeName) {
    var _db = myDB.db;
    var transaction = _db.transaction(storeName,'readwrite');
    var store = transaction.objectStore(storeName);
    var result = store.clear();
    result.onsuccess = function (e) {
        console.log(e);
    };
    result.onerror = function (e) {
        console.log(e);
    };
  };

  // 刪除與特定條件匹配的所有記錄
  var removeData = function(storeName,arg,value){
    var d = $q.defer();//promise
    console.log('刪除匹配值的arg+value');
    console.log(arg);
    console.log(value);
    var _db = myDB.db;
    var transaction = _db.transaction(storeName,'readwrite');
    var store = transaction.objectStore(storeName);
    var result = store.openCursor();  //  打開一個(gè)游標(biāo)
    result.onsuccess = function (e) {
      var cursor = e.target.result;
      if (cursor && cursor !== null) {
        if(cursor.value[arg[0]] === value[0] && cursor.value[arg[1]] === value[1]) {
          var request = cursor.delete();
          request.onsuccess = function() {
            console.log('Deleted this cursor data.');
          };
        } else {
          console.log('131231312');
        }
        cursor.continue();
      }else {
        console.log('Entries displayed.');
        d.resolve();
      }
    };
    result.onerror = function (e) {
      d.reject();
    };
    return d.promise;
  };
  return {
    openDB: openDB,
    get: get,
    getAll: getAll,
    getIndex: getIndex,
    add: add,
    put: put,
    remove: remove,
    clear: clear,
    removeData: removeData
  };
}]);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末背捌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子洞斯,更是在濱河造成了極大的恐慌毡庆,老刑警劉巖坑赡,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異么抗,居然都是意外死亡毅否,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門蝇刀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來螟加,“玉大人,你說我怎么就攤上這事吞琐±μ剑” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵站粟,是天一觀的道長(zhǎng)黍图。 經(jīng)常有香客問我,道長(zhǎng)奴烙,這世上最難降的妖魔是什么助被? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮切诀,結(jié)果婚禮上揩环,老公的妹妹穿的比我還像新娘。我一直安慰自己幅虑,他們只是感情好丰滑,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著倒庵,像睡著了一般吨枉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哄芜,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天貌亭,我揣著相機(jī)與錄音,去河邊找鬼认臊。 笑死圃庭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的失晴。 我是一名探鬼主播剧腻,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼涂屁!你這毒婦竟也來了书在?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤拆又,失蹤者是張志新(化名)和其女友劉穎儒旬,沒想到半個(gè)月后栏账,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡栈源,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年挡爵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甚垦。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡茶鹃,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出艰亮,到底是詐尸還是另有隱情闭翩,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布迄埃,位于F島的核電站疗韵,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏调俘。R本人自食惡果不足惜伶棒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一旺垒、第九天 我趴在偏房一處隱蔽的房頂上張望彩库。 院中可真熱鬧,春花似錦先蒋、人聲如沸骇钦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽眯搭。三九已至,卻和暖如春业岁,著一層夾襖步出監(jiān)牢的瞬間鳞仙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工笔时, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棍好,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓允耿,卻偏偏與公主長(zhǎng)得像借笙,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子较锡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348