JS學習21(離線應(yīng)用與客戶端儲存)

Web應(yīng)用與傳統(tǒng)客戶端最大的區(qū)別就是需要連接網(wǎng)絡(luò)弟塞,沒有網(wǎng)絡(luò)整個應(yīng)用就無法運行,這個一直是Web應(yīng)用最大的痛點之一。
HTML5為了解決這個問題添加了對離線應(yīng)用的支持泳叠。開發(fā)離線Web應(yīng)用有幾個關(guān)鍵點。確保應(yīng)用知道設(shè)備是否能上網(wǎng)以便下一步執(zhí)行正確的操作茶宵,然后應(yīng)用還必須能訪問一定的資源危纫。最后必須有一塊本地空間用于保存數(shù)據(jù),無論是否能上網(wǎng)都能讀寫數(shù)據(jù)乌庶。

離線檢測

為檢測設(shè)備是離線還是在線种蝶,HTML5定義了navigator.onLine這個屬性值為true表示設(shè)備可以上網(wǎng)。
還有兩個事件:online和offline瞒大,這兩個事件會在網(wǎng)絡(luò)狀態(tài)變化時在window對象上觸發(fā)螃征。

EventUtil.addHandler(window, "online", function(){
    alert("online");
});
EventUtil.addHandler(window, "offline", function(){
    alert("Offline");
});

支持離線檢測的瀏覽器有IE6+、navigator.onLine透敌、Firefox3盯滚、Safari4、Opera10.6拙泽、Chrome淌山、iOS 3.2版Safari、Android 版 WebKit顾瞻。

應(yīng)用緩存

application cache泼疑,這是專門為了開發(fā)離線Web應(yīng)用而設(shè)計的,它從瀏覽器緩存中分出來一部分荷荤,想要在這個部分中保存數(shù)據(jù)退渗,可以使用一個描述文件,列出要下載和緩存的資源蕴纳。這里有個簡單的例子:

CACHE MANIFEST
#Comment

file.js
file.css

這里僅簡單的列出了要下載的文件会油。描述文件的選項非常多,想要進一步了解的話給大家一個網(wǎng)址咯古毛。Go offline with application cache
要將描述文件與頁面關(guān)聯(lián)起來翻翩,可以使用都许,下面的屬性。

<html manifest="/offline.manifest">

同時嫂冻,有相應(yīng)的JS API提供給開發(fā)者來獲取其狀態(tài)胶征。
這個API的核心是applicationCache對象,這個對象有一個status屬性桨仿,表示應(yīng)用緩存的狀態(tài):

  • 0:無緩存
  • 1:閑置睛低,應(yīng)用緩存未更新
  • 2:檢查中,正在下載描述文件并檢查更新
  • 3:下載中服傍,應(yīng)用緩存正在下載描述文件中指定的資源
  • 4:更新完成钱雷,應(yīng)用緩存已經(jīng)更新了資源,且所有資源下載完畢吹零,可以通過swapCache()來使用了
  • 5:廢棄罩抗,應(yīng)用緩存的描述文件已經(jīng)不存在了,頁面無法再訪問應(yīng)用緩存

同時針對上面的狀態(tài)也有相應(yīng)的事件:

  • checking灿椅,查找更新時觸發(fā)
  • error澄暮,檢查更新或下載資源期間發(fā)生錯誤時觸發(fā)
  • noupdate,檢查描述文件發(fā)現(xiàn)沒有更新時觸發(fā)
  • downloading阱扬,開始下載資源時觸發(fā)
  • progress,下載的過程中不斷觸發(fā)
  • updateready伸辟,下載完畢且可以使用swapCache()時觸發(fā)
  • cached麻惶,應(yīng)用緩存完整可用時觸發(fā)

在頁面剛剛加載時,會自動檢查有沒有描述文件是否更新信夫,并根據(jù)具體情況觸發(fā)上述事件窃蹋。
有用的方法有兩個:

  • update(),會去檢查描述文件是否更新静稻,就像頁面剛剛加載那樣警没,并觸發(fā)相應(yīng)的事件
  • swapCache(),在新緩存可用時可以調(diào)用這個方法來啟用新應(yīng)用緩存
EventUtil.addHandler(applicationCache, "updateready", function(){               
    applicationCache.swapCache();
});

數(shù)據(jù)存儲

隨著Web應(yīng)用的出現(xiàn)振湾,也產(chǎn)生了應(yīng)該直接在客戶端上儲存用戶信息能力的要求杀迹,包括用戶的登陸信息,偏好設(shè)置或其他數(shù)據(jù)押搪。最最開始解決這個問題的方案是cookie树酪。

Cookie

Cookie最初是用來在客戶端儲存會話信息的。該標準要求服務(wù)器對任意HTTP請求發(fā)送Set-Cookie HTTP頭作為相應(yīng)的一部分大州,其中包含會話的信息续语。例如:

HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value
Other-header: other-header-value

這里就設(shè)置了一個以name為名稱,value為值的一個cookie厦画。
瀏覽器會儲存這樣的會話信息疮茄。并在這之后通過為每一個請求添加Cookie HTTP頭部將信息發(fā)送回服務(wù)器:

GET /index.html HTTP/1.1
Cookie: name=value
Other-header: other-header-value

這個信息對于服務(wù)器來說就可以唯一驗證請求的身份
限制
cookie在性質(zhì)上是綁定在特定域名下的。當設(shè)定了一個cookie,再給創(chuàng)建它的域名發(fā)送請求時都會包含這個cookie力试,而發(fā)向其他域的請求中并不會包含這個cookie徙邻。這個限制保證了cookie只能讓批準的接受者訪問。
每個域的cookie總數(shù)是有限的懂版,各瀏覽器不同鹃栽,最小的規(guī)定一個域有30個cookie,大小一般不超過4095B躯畴。
cookie的構(gòu)成
cookie由瀏覽器保存的一下幾塊信息構(gòu)成:

  • 名稱:一個唯一確定cookie的名稱
  • 值:儲存在cookie中的字符串值
  • 域:這個cookie對哪個域有效民鼓,如果這個域包含子域,那對子域同樣有有效蓬抄。如果設(shè)定是沒有明確指定丰嘉,這個值會被認為是設(shè)置cookie的那個域
  • 路徑:用于指定向域中的哪個路徑發(fā)送cookie,例如嚷缭,你可以指定cookie只發(fā)送到www.baidu.com/img饮亏,那再訪問www.baidu.com時就不會發(fā)送cookie。及時它們同域
  • 失效時間:cookie應(yīng)該被刪除的時間戳阅爽,默認瀏覽器會話結(jié)束就刪除
  • 安全標志:指定后路幸,cookie只有在使用SSL連接時才會發(fā)送到服務(wù)器

設(shè)置時像這樣:

HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value; expires=Mon, 22-Jan-07 07:10:24 GMT; domain=.wrox.com path=/; secure
Other-header: other-header-value

JS中的cookie
JS中訪問cookie的接口是BOM的document.cookie。
獲取時付翁,這個屬性返回字符串简肴,包括當前頁面可用的(根據(jù)cookie的域,路徑百侧,失效時間等等)所有cookie的名稱和值組成的鍵值對砰识。

name1=value1;name2=value2;name3=value3

這些是經(jīng)過URI編碼的值。要使用decodeURIComponent()解碼佣渴。
設(shè)置時和使用HTTP頭部設(shè)置一樣:

document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Nicholas") + "; domain=.wrox.com; path=/";

由于在JS中使用cookie不是很直觀辫狼,寫個工具類比較好。

var CookieUtil = {
    get: function (name){
        var cookieName = encodeURIComponent(name) + "=",
            cookieStart = document.cookie.indexOf(cookieName),
            cookieValue = null;
        if (cookieStart > -1){
            var cookieEnd = document.cookie.indexOf(";", cookieStart);
            if (cookieEnd == -1){
                cookieEnd = document.cookie.length;

            }
            cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));
        }
        return cookieValue;
    },
    set: function (name, value, expires, path, domain, secure) {
        var cookieText = encodeURIComponent(name) + "=" +
            encodeURIComponent(value);
        if (expires instanceof Date) {
            cookieText += "; expires=" + expires.toGMTString();
        }
        if (path) {
            cookieText += "; path=" + path;
        }
        if (domain) {
            cookieText += "; domain=" + domain;
        }
        if (secure) {
            cookieText += "; secure";
        }
        document.cookie = cookieText;
    },
    unset: function (name, path, domain, secure){
        this.set(name, "", new Date(0), path, domain, secure);
    }
};
CookieUtil.set("book", "Professional JavaScript");
alert(CookieUtil.get("book"));
CookieUtil.unset("book");
alert(CookieUtil.get("book"));

子cookie
因為cookie有單域名下數(shù)量的限制辛润,一些開發(fā)人員使用了一種稱為子cookie的概念膨处,子cookie是存放在單個cookie中更小段的數(shù)據(jù),也就是使用cookie值來儲存多個名值對砂竖。最常見的格式如下:

name=name1=value1&name2=value2&name3=value3&name4=value4&name5=value5

這樣對于獲取到cookie就又多了一層障礙灵迫,為了更好的操縱cookie當然要在來個工具類咯~

var SubCookieUtil = {

    //獲取這個name的cookie中所有的子cookie并放入一個對象中
    getAll: function(name){
        var cookieName = encodeURIComponent(name) + "=",
            cookieStart = document.cookie.indexOf(cookieName),
            cookieValue = null,
            cookieEnd,
            subCookies,
            len,
            i,
            parts,
            result = {};
        if (cookieStart > -1){
            cookieEnd = document.cookie.indexOf(";", cookieStart);
            if (cookieEnd == -1){
                cookieEnd = document.cookie.length;
            }
            cookieValue = document.cookie.substring(cookieStart +
                cookieName.length, cookieEnd);
            if (cookieValue.length > 0){
                subCookies = cookieValue.split("&");
                for (i=0, len=subCookies.length; i < len; i++){
                    parts = subCookies[i].split("=");
                    result[decodeURIComponent(parts[0])] =
                        decodeURIComponent(parts[1]);
                }
                return result;
            }
        }
        return null;
    },
    //使用getAll方法返回的子cookie的對象,找到想要的子cookie
    get: function (name, subName){
        var subCookies = this.getAll(name);
        if (subCookies){
            return subCookies[subName];
        } else {
            return null;
        }
    },
    //將所有子cookie和相應(yīng)參數(shù)序列化存進cookie里
    setAll: function(name, subcookies, expires, path, domain, secure){
        var cookieText = encodeURIComponent(name) + "=",
            subcookieParts = new Array(),
            subName;
        for (subName in subcookies){
            //這里使用hasOwnProperty來確定不會循環(huán)到原型鏈中其實不是子cookie的屬性
            if (subName.length > 0 && subcookies.hasOwnProperty(subName)){
                subcookieParts.push(encodeURIComponent(subName) + "=" +
                    encodeURIComponent(subcookies[subName]));
            }
        }
        if (subcookieParts.length > 0){
            cookieText += subcookieParts.join("&");
            if (expires instanceof Date) {
                cookieText += "; expires=" + expires.toGMTString();
            }
            if (path) {
                cookieText += "; path=" + path;
            }
            if (domain) {
                cookieText += "; domain=" + domain;
            }
            if (secure) {
                cookieText += "; secure";
            }
        } else {
            cookieText += "; expires=" + (new Date(0)).toGMTString();
        }
            document.cookie = cookieText;
    },
    //更改一個子cookie,這個方法會先找到這個子cookie所在的cookie中所有的子cookie,將這個新子cookie放到存著所有子cookie的對象中
    //再調(diào)用setAll方法保存
    set: function (name, subName, value, expires, path, domain, secure) {
        var subcookies = this.getAll(name) || {};
        subcookies[subName] = value;
        this.setAll(name,subcookies,expires, path, domain, secure);
    },
    unset: function (name, subName, path, domain, secure){
        var subcookies = this.getAll(name);
        if (subcookies){
            delete subcookies[subName];
            this.setAll(name, subcookies, null, path, domain, secure);
        }
    },
    unsetAll: function(name, path, domain, secure){
        this.setAll(name, null, new Date(0), path, domain, secure);
    }
};
document.cookie="data=name=Nicholas&book=Professional%20JavaScript";
var data = SubCookieUtil.getAll("data");
alert(data);
alert(data.name); //"Nicholas"
alert(data.book); //"Professional JavaScript"
alert(SubCookieUtil.get("data", "name")); //"Nicholas"
alert(SubCookieUtil.get("data", "book"));
alert(SubCookieUtil.get("data", "class"));
SubCookieUtil.set("data", "class", "how to kill people");
alert(SubCookieUtil.get("data", "class"));

JS不能訪問的cookie
為了保證cookie的安全,有的cookie會不允許JS獲取

Web儲存機制

Web Storage的目標是克服cookie的限制晦溪,當數(shù)據(jù)需要被嚴格控制在客戶端上時瀑粥,無需持續(xù)的將數(shù)據(jù)發(fā)回到服務(wù)器。其兩個主要目標是:

  • 提供一種在cookie之外儲存會話數(shù)據(jù)的途徑
  • 提供一種儲存大量可以夸會話存在的數(shù)據(jù)的機制

Storage類型
可以以名值對的方式儲存字符串值三圆,有如下方法:

  • clear()
  • getItem(name)
  • key(index)
  • removeItem(name)
  • setItem(name, value)

sessionStorage對象
這個對象儲存特定于某個會話的數(shù)據(jù)狞换,這也就意味著這里的數(shù)據(jù)只保存到瀏覽器關(guān)閉避咆。不過刷新頁面時這里的數(shù)據(jù)是可以存住的。存在這里的數(shù)據(jù)只能由最初儲存數(shù)據(jù)的頁面訪問修噪。sessionStorage 其實是Storage的一個實例查库,所以上面的方法同樣可用。

sessionStorage.setItem("name", "Nicholas");
sessionStorage.book = "Professional JavaScript";
for (var i=0, len = sessionStorage.length; i < len; i++){
    var key = sessionStorage.key(i);
    var value = sessionStorage.getItem(key);
    alert(key + "=" + value);
}
sessionStorage.removeItem("book");

globalStorage對象
這個對象的目的是跨會話存儲數(shù)據(jù)黄琼,但是有域的限制樊销,在儲存數(shù)據(jù)時,首先要指定的就是域:

globalStorage["wrox.com"].name = "Nicholas";  
var name = globalStorage["wrox.com"].name; 

globalStorage不是Storage的實例globalStorage["wrox.com"]才是哦脏款。
這個域名下的所有子域可以訪問這里的數(shù)據(jù)围苫。
對每個空間訪問的限制是根據(jù)域名,協(xié)議撤师,端口來限制的剂府,同一個域名。使用HTTP訪問就訪問不到HTTPS時存的數(shù)據(jù)剃盾。端口號不同也是一樣腺占。

globalStorage[location.host ].name = "Nicholas";
globalStorage[location.host ].book = "Professional JavaScript";
globalStorage[location.host ].removeItem("name");
var book = globalStorage[location.host ].getItem("book");

localStorage對象
這個對象是為了取代globalStorage而存在的。這個也是跨會話的痒谴,不需要指定域名衰伯,只有完全相同的域名才能訪問,子域名都不行积蔚。

localStorage.setItem("name", "Nicholas");
localStorage.book = "Professional JavaScript";
var name = localStorage.getItem("name");
var book = localStorage.book;
alert(name);

Storage事件
對storage對象進行的任何修改都會觸發(fā)storage事件嚎研,這個事件的event有如下屬性:

  • domain
  • key
  • newValue
  • oldValue

各瀏覽器對這個事件的支持并不全面
大小限制
各瀏覽器對Storage大小的限制并不相同,不過都是根據(jù)域名來區(qū)分的库倘。

IndexedDB

Indexed Database API,是用來在瀏覽器中保存結(jié)構(gòu)化數(shù)據(jù)的一種數(shù)據(jù)庫论矾。它的思想是創(chuàng)建一套API教翩,方便保存和讀取JavaScript對象,同時還支持查詢及搜索贪壳。
IndexedDB設(shè)計的操作完全是異步進行的饱亿。每次對數(shù)據(jù)庫的操作都會返回一個相應(yīng)的IDBRequest對象的實例來代表這次請求。在這個實例上可以設(shè)置事件闰靴,等待成功或失敗事件被觸發(fā)彪笼,在里面做相應(yīng)的操作。IndexedDB是全局對象蚂且。API不穩(wěn)定配猫,有的瀏覽器為其加了前綴。

var indexedDB = window.indexedDB || window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB;

數(shù)據(jù)庫
打開數(shù)據(jù)庫杏死,把數(shù)據(jù)庫名傳入泵肄,存在會打開捆交,不存在會創(chuàng)建并打開。打開的數(shù)據(jù)庫的請求是一個IDBRequest對象腐巢,通過事件來觀察請求是否成功品追。成功就會返回一個IDBDatabase對象。
可以給database設(shè)置一個版本號冯丙,同樣是返回一個IDBRequest肉瓦,同樣的操作模式。

var request, database;
request = indexedDB.open("admin");
request.onerror = function(event){
    alert("Something bad happened while trying to open: " +
        event.target.errorCode);
};
request.onsuccess = function(event){
    database = event.target.result;
    setVersion();
};
function setVersion() {
    if (database.version != "1.0"){
        request = database.setVersion("1.0");
        request.onerror = function(event){
            alert("Something bad happened while trying to set version: " +
                event.target.errorCode);
        };
        request.onsuccess = function(event){
            alert("Database initialization complete. Database name: " + database.name + ", Version: " + database.version);
        };
    } else {
        alert("Database already initialized. Database name: " + database.name + ", Version: " + database.version);
    }
}

對象儲存空間
建立了與數(shù)據(jù)庫的連接后胃惜,就可以使用對象儲存空間(相當于表泞莉,其中的對象相當于表中的紀錄)。
創(chuàng)建對象儲存空間蛹疯,需要兩個信息戒财,這個空間的名字,以及Key Path和Key Generator捺弦,這兩個值確定了這個空間中儲存的每個記錄以什么來標識饮寞。

  • No No:This object store can hold any kind of value, even primitive values like numbers and strings. You must supply a separate key argument whenever you want to add a new value.
  • Yes No:This object store can only hold JavaScript objects. The objects must have a property with the same name as the key path.
  • No Yes:This object store can hold any kind of value. The key is generated for you automatically, or you can supply a separate key argument if you want to use a specific key.
  • Yes Yes:This object store can only hold JavaScript objects. Usually a key is generated and the value of the generated key is stored in the object in a property with the same name as the key path. However, if such a property already exists, the value of that property is used as key rather than generating a new key.

創(chuàng)建空間需要在打開數(shù)據(jù)庫時返回的IDBRequest上的onupgradeneeded事件中進行,否則會報錯的列吼。這個事件會在新創(chuàng)建數(shù)據(jù)庫或更新數(shù)據(jù)庫版本號時(open()時傳入更高的版本號幽崩,數(shù)據(jù)庫的版本就會自己更新)被觸發(fā)。

request.onupgradeneeded = function (event) {
    var db = event.target.result;

    // Create an objectStore to hold information about our customers. We're
    // going to use "ssn" as our key path because it's guaranteed to be
    // unique - or at least that's what I was told during the kickoff meeting.
    var objectStore = db.createObjectStore("customers", { keyPath: "ssn" });

    // Create an index to search customers by name. We may have duplicates
    // so we can't use a unique index.
    objectStore.createIndex("name", "name", { unique: false });

    // Create an index to search customers by email. We want to ensure that
    // no two customers have the same email, so use a unique index.
    objectStore.createIndex("email", "email", { unique: true });

    // Use transaction oncomplete to make sure the objectStore creation is
    // finished before adding data into it.
    objectStore.transaction.oncomplete = function(event) {
        // Store values in the newly created objectStore.
        var customerObjectStore = db.transaction("customers", "readwrite").objectStore("customers");
        for (var i in customerData) {
            customerObjectStore.add(customerData[i]);
        }
    };
};

在創(chuàng)建了空間后寞钥,就可以用add()或put()來向其中添加要保存的對象慌申。對于添加唯一標識已經(jīng)存在的對象,add會報錯理郑,put則會更新原有值蹄溉。
事務(wù)
在創(chuàng)建好空間后,就相當于數(shù)據(jù)庫的結(jié)構(gòu)已經(jīng)確定了您炉,在這之后對數(shù)據(jù)的操作就要通過事務(wù)了柒爵。
創(chuàng)建事務(wù)需要指定針對哪個儲存空間以及讀寫模式,可以一下打開多個儲存空間赚爵。

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

取得事務(wù)索引后使用objectStore()訪問儲存空間棉胀,然后就可以使用add()、put()冀膝、get()唁奢、delete()、clear()窝剖。這五個方法都會返回一個請求對象师溅,通過事件來操作

var request = db.transaction("users").objectStore("users").get("007"); 
request.onerror = function(event){
    alert("Did not get the object!");
};
request.onsuccess = function(event){
    var result = event.target.result;
    alert(result.firstName);    //"James"
};
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末衩茸,一起剝皮案震驚了整個濱河市檐嚣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌采郎,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狂魔,死亡現(xiàn)場離奇詭異蒜埋,居然都是意外死亡,警方通過查閱死者的電腦和手機最楷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門整份,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人籽孙,你說我怎么就攤上這事烈评。” “怎么了犯建?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵讲冠,是天一觀的道長。 經(jīng)常有香客問我适瓦,道長竿开,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任玻熙,我火速辦了婚禮否彩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嗦随。我一直安慰自己列荔,他們只是感情好,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布枚尼。 她就那樣靜靜地躺著贴浙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪署恍。 梳的紋絲不亂的頭發(fā)上崎溃,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音锭汛,去河邊找鬼。 笑死袭蝗,一個胖子當著我的面吹牛唤殴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播到腥,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼朵逝,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了乡范?” 一聲冷哼從身側(cè)響起配名,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤啤咽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后渠脉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宇整,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年芋膘,在試婚紗的時候發(fā)現(xiàn)自己被綠了鳞青。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡为朋,死狀恐怖臂拓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情习寸,我是刑警寧澤胶惰,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站霞溪,受9級特大地震影響孵滞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜威鹿,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一剃斧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧忽你,春花似錦幼东、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至糟秘,卻和暖如春简逮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背尿赚。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工散庶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人凌净。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓悲龟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親冰寻。 傳聞我的和親對象是個殘疾皇子须教,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)斩芭,斷路器轻腺,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • 從三月份找實習到現(xiàn)在乐疆,面了一些公司,掛了不少贬养,但最終還是拿到小米挤土、百度、阿里煤蚌、京東耕挨、新浪、CVTE尉桩、樂視家的研發(fā)崗...
    時芥藍閱讀 42,243評論 11 349
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法筒占,類相關(guān)的語法,內(nèi)部類的語法蜘犁,繼承相關(guān)的語法翰苫,異常的語法,線程的語...
    子非魚_t_閱讀 31,625評論 18 399
  • 村上春樹的文字这橙,讓人上癮奏窑。 他的小說里,音樂和性是不可或缺的兩大元素屈扎。音樂高雅又不失穩(wěn)重埃唯,引領(lǐng)我們體會與音樂相伴的...
    婷你說閱讀 1,651評論 0 1
  • 2017年11月21號星期二哈爾濱晴-20°~-5° 學習是一種習慣,干什么都是一種習慣鹰晨,從十月一號回到家里就不開...
    c0deb784fc0b閱讀 235評論 0 0