項(xiàng)目實(shí)戰(zhàn)之本地存儲(chǔ)篇

在前端項(xiàng)目開發(fā)中,前端的本地存儲(chǔ)是必不可少的偶翅,今天小編就前端的本地存儲(chǔ)在項(xiàng)目中的使用詳細(xì)的介紹一下伴奥。前端本地存儲(chǔ)主要有:

  • cookie
  • localStorage
  • sessionStorage
  • webSQL/indexDB

接下來就這三種前端常用的存儲(chǔ)方式進(jìn)行介紹。

cookie

cookie就是存儲(chǔ)在客戶端的一小段文本焰扳,大小不能超過4kb,在請(qǐng)求接口的時(shí)候误续,cookie會(huì)被請(qǐng)求攜帶著吨悍,進(jìn)而被服務(wù)器所讀取使用。
打開瀏覽器控制臺(tái)蹋嵌,F(xiàn)12>>Application>>Cookies,隨便選擇一個(gè)域育瓜,我們可以看到里面有很多cookie,如下所示:

image

主要屬性

  • Name

cookie的名稱

  • Value

cookie的值,大小最大4Kb

  • Domain

cookie存儲(chǔ)的域名

  • Path

cookie存儲(chǔ)的路徑

  • Size

cookie的大小

  • Expires/Max-Age

這兩個(gè)屬性涉及到 cookie 的存活時(shí)間

Expires 屬性指定一個(gè)具體的到期時(shí)間栽烂,到了這個(gè)指定的時(shí)間之后躏仇,瀏覽器就不再保留這個(gè) cookie ,它的值是 UTC 格式恋脚,可以使用 Date.prototype.toUTCString() 格式進(jìn)行轉(zhuǎn)換。

Max-Age 屬性制定了從現(xiàn)在開始 cookie 存在的秒數(shù)钙态,比如 60 * 60 (即一小時(shí))慧起。過了這個(gè)時(shí)間以后,瀏覽器就不再保留這個(gè) Cookie册倒。

Max-Age的優(yōu)先級(jí)比Expires高蚓挤,如果兩者都不設(shè)置,則這個(gè)cookie會(huì)在瀏覽器關(guān)閉的時(shí)候失效驻子。

  • HttpOnly

如果設(shè)置了該屬性灿意,意思就是這個(gè)cookie不能被JavaScript取到,也就防止了cookie被腳本讀取崇呵,然后當(dāng)發(fā)起請(qǐng)求的時(shí)候缤剧,該cookie才會(huì)被帶上。

  • Secure

指定瀏覽器只有在加密協(xié)議 HTTPS 下才能發(fā)送cookie域慷,不需要設(shè)置荒辕,當(dāng)協(xié)議是https時(shí),會(huì)自動(dòng)開啟犹褒。

使用方式

  • 設(shè)置cookie
/**
 * 設(shè)置cookie
 * @param {*} key 名稱
 * @param {*} val 值
 * @param {*} time 失效時(shí)間
 */

export const setCookie = (key, val, time) => {

  var date = new Date();

  var expiresDays = time;

  //將時(shí)間轉(zhuǎn)換為cookie設(shè)置時(shí)間的格式

  date.setTime(date.getTime() + expiresDays * 24 * 3600 * 1000);

  document.cookie = key + "=" + val + ";expires=" + date.toDateString();

}
  • 獲取cookie
/**
 * 獲取cookie
 * @param {*} key 名稱
 */

export const getCookie = (key) => {

  var getCookie = document.cookie.replace(/[ ]/g, "");

  var arrCookie = getCookie.split(";")

  var tips;

  for (var i = 0; i < arrCookie.length; i++) {

    var arr = arrCookie[i].split("=");

    if (key == arr[0]) {

      tips = arr[1];

      break;

    }

  }

  return tips;

}
  • 刪除cookie

刪除cookie的話抵窒,可以直接調(diào)用設(shè)置cookie的方法,將失效時(shí)間置為-1叠骑,如下:

setCookie(key,'',-1)

localStorage/sessionStorage

localStorage/sessionStorage是在html5中新加入的技術(shù)李皇,兩者除了數(shù)據(jù)的時(shí)效性不一樣之外,其他都一樣宙枷。大小一般為5MB掉房,存儲(chǔ)的時(shí)候,僅僅在客戶端存儲(chǔ)慰丛,不會(huì)隨著請(qǐng)求的調(diào)用而傳遞到服務(wù)器卓囚。

localStorage不手動(dòng)刪除則永久有效,sessionStorage僅在當(dāng)前會(huì)話有效

下面F12>>Application>>Cookies看一個(gè)存儲(chǔ)示例:

image

可以看到诅病,其只有兩個(gè)屬性哪亿,也就是key(名稱)、value(值)

使用方式

localStorage和sessionStorage都具有相同的操作方法睬隶,例如setItem、getItem和removeItem等页徐,為了使用方便苏潜,我們對(duì)其進(jìn)行二次封裝,示例如下:

  • 存儲(chǔ)Storage
/**
 * 存儲(chǔ)Storage
 */
export const setStore = (params = {}) => {
  let {
    name,//名稱
    content,//內(nèi)容
    type,//類型
  } = params;
  let obj = {
    dataType: typeof (content),
    content: content,
    type: type,
    datetime: new Date().getTime()
  }
  if (type) window.sessionStorage.setItem(name, JSON.stringify(obj));
  else window.localStorage.setItem(name, JSON.stringify(obj));
}
  • 獲取Storage
/**
 * 判斷是否為空
 */
function validatenull (val) {
  if (typeof val === 'boolean') {
    return false
  }
  if (typeof val === 'number') {
    return false
  }
  if (val instanceof Array) {
    if (val.length == 0) return true
  } else if (val instanceof Object) {
    if (JSON.stringify(val) === '{}') return true
  } else {
    if (val == 'null' || val == null || val == 'undefined' || val == undefined || val == '') return true
    return false
  }
  return false
}

/**
 * 獲取Storage
 */
export const getStore = (params = {}) => {
  let {
    name,//名稱
    debug//是否需要轉(zhuǎn)換類型
  } = params;
  let obj = {},
    content;
  obj = window.sessionStorage.getItem(name);
  if (validatenull(obj)) obj = window.localStorage.getItem(name);
  if (validatenull(obj)) return;
  try {
    obj = JSON.parse(obj);
  } catch{
    return obj;
  }
  if (debug) {
    return obj;
  }
  if (obj.dataType == 'string') {
    content = obj.content;
  } else if (obj.dataType == 'number') {
    content = Number(obj.content);
  } else if (obj.dataType == 'boolean') {
    content = eval(obj.content);
  } else if (obj.dataType == 'object') {
    content = obj.content;
  }
  return content;
}
  • 刪除Storage
/**
 * 刪除localStorage
 */
export const removeStore = (params = {}) => {
  let {
    name,
    type
  } = params;
  if (type) {
    window.sessionStorage.removeItem(name);
  } else {
    window.localStorage.removeItem(name);
  }

}
  • 獲取全部Storage
/**
 * 獲取全部Storage
 */
export const getAllStore = (params = {}) => {
  let list = [];
  let {
    type
  } = params;
  if (type) {
    for (let i = 0; i <= window.sessionStorage.length; i++) {
      list.push({
        name: window.sessionStorage.key(i),
        content: getStore({
          name: window.sessionStorage.key(i),
          type: 'session'
        })
      })
    }
  } else {
    for (let i = 0; i <= window.localStorage.length; i++) {
      list.push({
        name: window.localStorage.key(i),
        content: getStore({
          name: window.localStorage.key(i),
        })
      })

    }
  }
  return list;

}
  • 清空全部Storage
/**
 * 清空全部Storage
 */
export const clearStore = (params = {}) => {
  let { type } = params;
  if (type) {
    window.sessionStorage.clear();
  } else {
    window.localStorage.clear()
  }

}

cookie变勇、localStorage恤左、sessionStorage異同

數(shù)據(jù)存儲(chǔ)時(shí)間

  • cookie 可以自己設(shè)置失效時(shí)間
  • localStorage 不主動(dòng)清除贴唇,則永久存儲(chǔ)
  • sessionStorage 當(dāng)前頁面關(guān)閉時(shí)被刪除

大小

  • cookie 最大4kb
  • localStorage 最大5MB
  • sessionStorage 最大5MB

請(qǐng)求是否攜帶

  • cookie 每次請(qǐng)求會(huì)攜帶在請(qǐng)求頭中
  • localStorage 不攜帶,僅在客戶端存儲(chǔ)
  • sessionStorage 不攜帶飞袋,僅在客戶端存儲(chǔ)

易用性

  • cookie 原生api使用不友好戳气,需自己二次封裝
  • localStorage 原生接口可使用,也可以自己二次封裝
  • sessionStorage 原生接口可使用巧鸭,也可以自己二次封裝

個(gè)人推薦在項(xiàng)目中使用storage存儲(chǔ)瓶您,cookie存儲(chǔ)數(shù)據(jù)過多,會(huì)造成性能問題纲仍。當(dāng)然呀袱,大家可以根據(jù)實(shí)際情況進(jìn)行選擇,二次封裝方法已雙手奉上郑叠。

webSQL/indexDB

對(duì)于簡單的數(shù)據(jù)存儲(chǔ)夜赵,storage和cookie就已經(jīng)夠用了,但是如果需要存儲(chǔ)比較復(fù)雜的關(guān)系型數(shù)據(jù)乡革,再使用storage和cookie寇僧,就有點(diǎn)力不從心了。這個(gè)時(shí)候可以使用webSQL或者indexDB進(jìn)行存儲(chǔ)沸版。

webSQL

Web SQL數(shù)據(jù)庫API是一個(gè)獨(dú)立的規(guī)范嘁傀,在瀏覽器層面提供了本地對(duì)結(jié)構(gòu)化數(shù)據(jù)的存儲(chǔ),已經(jīng)被很多現(xiàn)代瀏覽器支持了推穷。

image
核心api
  • openDatabase() => 用來打開或創(chuàng)建數(shù)據(jù)庫(沒有時(shí)則創(chuàng)建心包,有則打開)
  • transaction() => 這個(gè)方法可以控制一個(gè)或多個(gè)事務(wù),以及基于這種情況提交或者回滾
  • executeSql() => 用于執(zhí)行實(shí)際的 SQL 查詢
判斷瀏覽器是否支持該功能

從上面的圖中可以看出馒铃,webSQL兼容性并不是太好蟹腾,因此使用時(shí),我們需要先判讀那瀏覽器是否支持区宇。

if (window.openDatabase) {
    // 操作 web SQL        
} else {
     alert('當(dāng)前瀏覽器不支持 webSQL !!!');
}
webSQL操作類封裝

webSQL操作類封裝代碼量較大娃殖,此處就不再展示,需要的小伙伴可以關(guān)注我公眾號(hào)回復(fù)【webSQL操作類】獲取议谷。下面給個(gè)簡單的例子:

var myDB = {
    name: 'formData',
    version: 1,
    db: null,
};
myDB.db = openDatabase(myDB.name, myDB.version, 'test', 100 * 1024 * 1024);
myDB.db.transaction(function(tx) {
    tx.executeSql('', [], function(tx, result) {
          if(result.rows.length!=0){
              //result.rows.item(i)
          }
    }, function(tx, error) {
        console.log(error);
    });
})

常用的SQL語句:

//新建表
'CREATE TABLE IF NOT EXISTS 表名 (列名稱1 PRIMARY KEY,列名稱2 UNIQUE ,列名稱3)'
//刪除表
'DROP TABLE 表名'
//清空表
'DELETE FROM 表名'
//刪除條目
'DELETE FROM 表名 WHERE 列名稱1 = ? and 列名稱2 = ?'
//新增一條
'INSERT INTO 表名 VALUES (?,?,?,?,?,?,?)' //為所有列添加值
'INSERT INTO 表名 (列名稱2,列名稱4,列名稱6) VALUES (?,?,?)' //為指定列添加值
//批量增加
insert into persons 
(id_p, lastname , firstName, city )
values
(200,'haha' , 'deng' , 'shenzhen'),
(201,'haha2' , 'deng' , 'GD'),
(202,'haha3' , 'deng' , 'Beijing')
//更新一條
'UPDATE 表名 SET 列名稱1 = ? where 列名稱2 = ? AND 列名稱3 = ?'
'UPDATE 表名 SET 列名稱1 = ?,列名稱2 = ?,列名稱3 = ? where 列名稱2 = ? AND 列名稱3 = ?'
 //根據(jù)主鍵存在與否炉爆,更新或添加一條數(shù)據(jù)
'replace into 表名 (列名稱1,列名稱2,列名稱3,列名稱4,列名稱5) VALUES (?,?,?,?,?) '
 //查找(更多查詢請(qǐng)根據(jù)自己的需要自由組合)
'select * from 表名 where 列名稱1 = ? and 列名稱1 >= ?' //常規(guī)查找
'select * from 表名 where 列名稱1 = ? or 列名稱1 >= ?' //常規(guī)查找

'select * from 表名 ORDER BY ?' //指定排序項(xiàng)
'select * from 表名 ORDER BY ? LIMIT 2;'//只查找符合條件的2條

WHERE 列名稱 IS NOT NULL //非空
WHERE 列名稱 LIKE "111%" //111開頭的
WHERE 列名稱 LIKE "%111" //111結(jié)尾的
WHERE 列名稱 LIKE "%111%" //包含111的
WHERE 列名稱 NOT LIKE "%111%" //不包含111的
'_a_'    //三位且中間字母是a的
'_a'    //兩位且結(jié)尾字母是a的
'a_'    //兩位且開頭字母是a的

WHERE 列名稱 GLOB > 111 //大于111
WHERE 列名稱 GLOB >= 111 //大于等于111
WHERE 列名稱 GLOB != 111 //不等于111 

WHERE 列名稱 GLOB '111*' //111開頭的
WHERE 列名稱 IN ( 25, 27 )  //值為25或27的
WHERE 列名稱 NOT IN ( 25, 27 )  //值不為25或27的
WHERE 列名稱 BETWEEN 25 AND 27  //值在25到27之間的
WHERE 列名稱 IN ( '25', '27' )  //注意:拼接sql時(shí)不要忘記引號(hào)

//索引
'CREATE INDEX IF NOT EXISTS 索引名 on 表名 (列名稱1, 列名稱2) '
'DROP INDEX 索引名'

indexDB

IndexedDB標(biāo)準(zhǔn)是HTML5官方認(rèn)可的本地?cái)?shù)據(jù)庫解決方案。其目的不是取代服務(wù)器端數(shù)據(jù)庫卧晓,它在一些特定場景下很有用,比如離線應(yīng)用芬首。IndexedDB是一種輕量級(jí)NOSQL數(shù)據(jù)庫,是由瀏覽器自帶逼裆。相比Web Sql更加高效郁稍,包括索引、事務(wù)處理和查詢功能胜宇。

image

從上圖可以看出indexDB的兼容性還是不錯(cuò)的耀怜。

使用indexDB
創(chuàng)建/打開一個(gè)數(shù)據(jù)庫

首先我們需要?jiǎng)?chuàng)建或者打開一個(gè)數(shù)據(jù)庫對(duì)象恢着,可以使用window.indexedDB.open()方法,示例如下:

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);
}

第一次打開數(shù)據(jù)庫時(shí)财破,會(huì)先觸發(fā)upgradeneeded事件掰派,然后觸發(fā)success事件

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

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

創(chuàng)建一個(gè)存放數(shù)據(jù)的“對(duì)象倉庫”

數(shù)據(jù)庫對(duì)象有了靡羡,我們還需要?jiǎng)?chuàng)建一個(gè)存放數(shù)據(jù)的“對(duì)象倉庫”,示例如下:

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

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

keyPath表示的是存儲(chǔ)數(shù)據(jù)的鍵名抖锥,autoIncrement表示是否使用自動(dòng)遞增的整數(shù)作為鍵名亿眠。一般來說,兩個(gè)屬性有一個(gè)就可以了磅废。

創(chuàng)建一個(gè)數(shù)據(jù)庫事務(wù)對(duì)象

transaction方法用于創(chuàng)建一個(gè)數(shù)據(jù)庫事務(wù)纳像。向數(shù)據(jù)庫添加數(shù)據(jù)之前,必須先創(chuàng)建數(shù)據(jù)庫務(wù)拯勉。

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

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

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

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

第一個(gè)參數(shù)是一個(gè)數(shù)組宫峦,里面是所涉及的對(duì)象倉庫岔帽,通常是只有一個(gè);

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

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

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

transaction.oncomplete = function(event) {
    // some code
};
操作數(shù)據(jù)

transaction對(duì)象提供了一些api贾费,供我們操作數(shù)據(jù)。

  • 添加數(shù)據(jù) add()

獲取對(duì)象倉庫以后檐盟,就可以用add方法往里面添加數(shù)據(jù)了,示例如下:

var transaction = db.transaction(["firstOS"],"readwrite");
var store = transaction.objectStore(“firstOS”);
var data = {name: 'monkey'};
var request = store.add(data,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ù)倉庫時(shí),對(duì)鍵名做了設(shè)置羡忘,這里也可以不指定鍵名谎痢。

  • 更新數(shù)據(jù) put()
var data = { name: 'monkeysoft' };
var request = store.put(data);
  • 讀取數(shù)據(jù) get()
var request = store.get(key);
  • 刪除數(shù)據(jù) delete()
var request = store.delete(key);
  • 清空數(shù)據(jù)庫 clear()
var request = store.clear();
  • 遍歷數(shù)據(jù) openCursor()
var request = store.openCursor();
indexDB操作類封裝

indexDB操作類封裝代碼量較大,此處就不再展示卷雕,需要的小伙伴可以關(guān)注我公眾號(hào)回復(fù)【indexDB操作類】獲取

以上就是我對(duì)前端本地存儲(chǔ)的一些理解和整理节猿,如有錯(cuò),歡迎各位大佬指正爽蝴,免得誤人子弟~嘿嘿沐批。

我是monkeysoft,你的【三連】就是monkeysoft創(chuàng)作的最大動(dòng)力蝎亚,如果本文有任何錯(cuò)誤和建議九孩,歡迎大家留言!

文章持續(xù)更新发框,可以微信搜索 【小猴子的web成長之路】關(guān)注公眾號(hào)第一時(shí)間閱讀,關(guān)注之后后臺(tái)回復(fù)知識(shí)體系躺彬,更可領(lǐng)取小編精心準(zhǔn)備的前端知識(shí)體系,未來學(xué)習(xí)不再迷茫,更可加入技術(shù)群交流討論梅惯。

image

參考:
1宪拥、indexDB講解與封裝 http://www.reibang.com/p/136c268b8559

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市铣减,隨后出現(xiàn)的幾起案子她君,更是在濱河造成了極大的恐慌,老刑警劉巖葫哗,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缔刹,死亡現(xiàn)場離奇詭異,居然都是意外死亡劣针,警方通過查閱死者的電腦和手機(jī)校镐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捺典,“玉大人鸟廓,你說我怎么就攤上這事〗蠹海” “怎么了引谜?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長稀蟋。 經(jī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
  • 文/蒼蘭香墨 我猛地睜開眼贮缅,長吁一口氣:“原來是場噩夢啊……” “哼榨咐!你這毒婦竟也來了?” 一聲冷哼從身側(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ú)居荒郊野嶺守林人離奇死亡,尸身上長有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
  • 我被黑心中介騙來泰國打工琉朽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留焚挠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓漓骚,卻偏偏與公主長得像,于是被迫代替她去往敵國和親榛泛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蝌蹂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348