AJAX入門

AJAX(Async Javascript and Xml):在AJAX中的異步不是異步編程中的異步,而是泛指“局部刷新”,但是在AJAX請求中盡可能使用異步獲取數(shù)據(jù)(因?yàn)楫惒綌?shù)據(jù)獲取不會(huì)阻塞下面代碼的執(zhí)行)

AJAX的操作

//=>創(chuàng)建AJAX實(shí)例:IE6中是不兼容的,使用的是new ActiveXObject來實(shí)現(xiàn)的
let xhr = new XMLHttpRequest();

//=>打開請求:發(fā)送請求之前的一些配置項(xiàng)
//1.HTTP METHOD 請求方式
//2.URL 向服務(wù)器端發(fā)送請求的API接口地址
//3.ASYNC 設(shè)置AJAX請求的同步異步,默認(rèn)是異步(寫TRUE也是異步),F(xiàn)ALSE是同步,項(xiàng)目中都使用異步編程,防止阻塞后續(xù)代碼執(zhí)行
//4.USER-NAME/USER-PASS:用戶名密碼,一般不用
xhr.open([HTTP METHOD],[URL],[ASYNC],[USER-NAME],[USER-PASS]);

//=>事件監(jiān)聽:一般監(jiān)聽的都是 READY-STATE-CHANGE 事件(AJAX狀態(tài)改變事件),基于這個(gè)事件可以獲取服務(wù)器返回的響應(yīng)頭/響應(yīng)主體內(nèi)容
xhr.onreadystatechange= () => {
    if(xhr.readyState === 4 && xhr.status === 200){
       xhr.responseText;
    }
};

//=>發(fā)送AJAX請求:從這步開始,當(dāng)前AJAX任務(wù)開始,如果AJAX是同步的,后續(xù)代碼不會(huì)執(zhí)行,要等到AJAX狀態(tài)成功后在執(zhí)行,反之異步不會(huì)
xhr.send([body]);

AJAX狀態(tài)(READY-STATE)

0 => UNSENT  剛開始創(chuàng)建XHR,還沒有發(fā)送
1 => OPENED  已經(jīng)執(zhí)行了OPEN操作
2 => HEADERS_RECEIVED 已經(jīng)發(fā)送AJAX請求(AJAX任務(wù)開始),響應(yīng)頭信息已經(jīng)被客戶端接收了(響應(yīng)頭中包含了:服務(wù)器的時(shí)間、返回的HTTP狀態(tài)碼...)
3 => LOADING 響應(yīng)主體內(nèi)容正在返回
4 => DONE 響應(yīng)主體內(nèi)容已經(jīng)被客戶端接收

關(guān)于XHR的屬性和方法

  • xhr.response 響應(yīng)主體內(nèi)容
  • xhr.responseText 響應(yīng)主體的內(nèi)容是字符串(JSON或者XML格式字符串都可以)
  • xhr.responseXML 響應(yīng)主體的內(nèi)容是XML文檔
  • xhr.status 返回的HTTP狀態(tài)碼
  • xhr.statusText 狀態(tài)碼的描述
  • xhr.timeout 設(shè)置請求超時(shí)的時(shí)間
  • xhr.withCredentials 是否允許跨域
  • xhr.abort() 強(qiáng)制中斷AJAX請求
  • xhr.getAllResponseHeaders() 獲取所有響應(yīng)頭信息
  • xhr.getResponseHeader([key]) 獲取KEY對應(yīng)的響應(yīng)頭信息,例如:xhr.getResponseHeader('date')就是在獲取響應(yīng)有中的服務(wù)器時(shí)間
  • xhr.open() 打開URL請求
  • xhr.overrideMimeType() 重寫MIME類型
  • xhr.send() 發(fā)送AJAX請求
  • xhr.setRequestHeader() 設(shè)置請求頭
let xhr = new XMLHttpRequest();
xhr.open('GET', 'temp.json');
xhr.setRequestHeader('leonard', '@@@');//=>設(shè)置的請求頭信息不能出現(xiàn)中文而且必須在OPEND之后才可以設(shè)置成功

/* xhr.timeout = 200;
   xhr.ontimeout = () => {
     console.log('請求超時(shí),請稍后重試');
  };
*/

xhr.onreadystatechange = () => {
      if (!/^(2|3)\d{2}$/.test(xhr.status)) return; 
      if (xhr.readyState === 2) {
          let time = xhr.getResponseHeader('date');
          console.log(time, new Date(time));
      }

      if (xhr.readyState === 4) {
            console.log(xhr.responseText);
      }
  };
xhr.send(null); 

AJAX中的同步異步

  • 異步情況
    let xhr=new XMLHttpRequest();       // readyState 0
    xhr.open('GET','/temp/list',true);  // readyState 1
    xhr.onreadystatechange=()=>{
       if(xhr.readyState===2){console.log(1);}
       if(xhr.readyState===4){console.log(2);}
    };
    xhr.send();
    console.log(3);
    //=> 3 1 2
    
  • 同步情況:同步狀態(tài)下主任務(wù)隊(duì)列在readyState未變成4之前一直被占用,所以即使觸發(fā)了onreadystatechange,也無法執(zhí)行
    //=>注意send位置不同結(jié)果是不一樣的
    let xhr=new XMLHttpRequest();
    xhr.open('GET','/temp/list',true);
    xhr.onreadystatechange=()=>{
       if(xhr.readyState===2){console.log(1);}
       if(xhr.readyState===4){console.log(2);}
    };
    xhr.send();
    console.log(3);
    //=> 2 3
    
    let xhr=new XMLHttpRequest();
    xhr.open('GET','/temp/list',true);
    xhr.send();
    xhr.onreadystatechange=()=>{
       if(xhr.readyState===2){console.log(1);}
       if(xhr.readyState===4){console.log(2);}
    };
    console.log(3);
    //=> 3
    

JQUERY中的AJAX

???????我們發(fā)現(xiàn),每次寫AJAX請求都要經(jīng)歷“經(jīng)典四步”,寫起來特別麻煩,所以需要借助一些已經(jīng)封裝好了的AJAX(當(dāng)然,你也可以自己封裝2333)來進(jìn)行數(shù)據(jù)請求,這樣顯得方便快捷

  • $.ajax([URL],[OPTIONS]) / $.ajax([OPTIONS])
  • $.get / $.post / $.getJSON / $.getScript 這些方法都是基于$.ajax構(gòu)建出來的快捷方法
//=>$.ajax中OPTIONS常用的參數(shù)
 /*
  * URL:請求的API接口地址
  * METHOD:請求的方式
  * DATA:傳遞給服務(wù)器的信息可以放到DATA中
  *   如果是GET請求是基于問號(hào)傳參傳遞過去的
  *   如果是POST請求是基于請求主體傳遞過去的
  *
  *   DATA的值可以是對象也可以是字符串(一般常用對象)
  *     如果是對象類型,JQ會(huì)把對象轉(zhuǎn)換為 xxx=xxx&xxx=xxx 的模式(x-www-form-urlencoded)
  *     如果是字符串,我們寫的是什么就傳遞什么
  *
  * DATA-TYPE:預(yù)設(shè)置獲取結(jié)果的數(shù)據(jù)格式 TEXT/JSON/JSONP/HTML/SCRIPT/XML...(服務(wù)器返回給客戶端的響應(yīng)主體中的內(nèi)容一般都是字符串[JSON格式居多]),而設(shè)置DATA-TYPE='JSON',JQ會(huì)內(nèi)部把獲取的字符串轉(zhuǎn)為JSON格式的對象 =>“他不會(huì)影響服務(wù)返回的結(jié)果,只是把返回的結(jié)果進(jìn)行了二次處理”
  * ASYNC:設(shè)置同步或者異步(TRUE->異步 FALSE->同步)
  * CACHE:設(shè)置GET請求下是否建立緩存(默認(rèn)TRUE->建立緩存 FALSE->不建立緩存),當(dāng)我們設(shè)置FALSE,并且當(dāng)前請求是GET請求,JQ會(huì)在請求的URL地址末尾追加隨機(jī)數(shù)(時(shí)間輟)
  *
  * SUCCESS:回調(diào)函數(shù),當(dāng)AJAX請求成功執(zhí)行,JQ執(zhí)行回調(diào)函數(shù)的時(shí)候會(huì)把從響應(yīng)主體中獲取的結(jié)果(可能二次處理了)當(dāng)做參數(shù)傳遞給回調(diào)函數(shù)
  * ERROR:請求失敗后執(zhí)行的回調(diào)函數(shù)
  */
$.ajax({
   url: '/temp/list',
   method: 'GET',
   data: {
       name: 'Leonard',
       age: 18
   },
   dataType: 'json',
   async: true,
   cache: false,
   success: (result, textStatus, xhr) => {
       console.log(result);
       console.log(textStatus);
       console.log(xhr.getResponseHeader('date'));//=>jq重構(gòu)的XHR
   },
   error: () => {}
});

???????心動(dòng)不如行動(dòng),接下來模仿JQ封裝一個(gè)簡易版的AJAX

~(function(window) {
    function AJAX(options) {
        return new init(options);
    }

    let init = function init(options = {}) {
        //=>初始化參數(shù)
        let {
            url,
            method = 'GET',
            data = null,
            dataType = 'JSON',
            async = true,
            cache = true,
            success,
            error
        } = options;

        //=>把配置項(xiàng)掛載到實(shí)例上
        ['url', 'method', 'data', 'dataType', 'async', 'cache', 'success', 'error'].forEach(item => {
            this[item] = eval(item);
        });

        //=>發(fā)送AJAX請求
        this.sendAjax();
    };

    AJAX.prototype = {
        constructor: AJAX,
        init,
        //=>發(fā)送AJAX請求
        sendAjax() {
            this.handleData();
            this.handleCache();

            //=>SEND
            let {method, url, async, error, success, data} = this,
                xhr = new XMLHttpRequest;
            xhr.open(method, url, async);
            xhr.onreadystatechange = () => {
                if (xhr.readyState === 4) {
                    //=>ERROR
                    if (!/^(2|3)\d{2}$/.test(xhr.status)) {
                        error && error(xhr.statusText, xhr);
                        return;
                    }
                    //=>SUCCESS
                    let result = this.handlDataType(xhr);
                    success && success(result, xhr);
                }
            };
            xhr.send(data);
        },
        //=>處理DATA-TYPE
        handlDataType(xhr) {
            let dataType = this.dataType.toUpperCase(),
                result = xhr.responseText;
            switch (dataType) {
                case 'TEXT':
                    break;
                case 'JSON':
                    result = JSON.parse(result);
                    break;
                case 'XML':
                    result = xhr.responseXML;
                    break;
            }
            return result;
        },
        //=>處理CACHE
        handleCache() {
            let {url, method, cache} = this;
            if (/^GET$/i.test(method) && cache === false) {
                //=>URL末尾追加時(shí)間輟
                url += `${this.check()}_=${+(new Date())}`;
                this.url = url;
            }
        },
        //=>處理DATA
        handleData() {
            let {data, method} = this;
            if (!data) return;
            //=>如果是個(gè)OBJECT對象,我們把它轉(zhuǎn)換為x-www-form-urlencoded這種模式,方便后期傳遞給服務(wù)器
            if (typeof data === 'object') {
                let str = ``;
                for (let key in data) {
                    if (data.hasOwnProperty(key)) {
                        str += `${key}=${data[key]}&`;
                    }
                }
                data = str.substring(0, str.length - 1);
            }

            //=>根據(jù)請求方式不一樣,傳遞給服務(wù)器的方式也不同
            if (/^(GET|DELETE|HEAD|TRACE|OPTIONS)$/i.test(method)) {
                this.url += `${this.check()}${data}`;
                this.data = null;
                return;
            }
            this.data = data;
        },
        //=>檢測URL中是否存在問號(hào)
        check() {
            return this.url.indexOf('?') > -1 ? '&' : '?';
        }
    };

    init.prototype = AJAX.prototype;
    window.ajax = AJAX;
})(window);

???????不過問題又來了,我們發(fā)現(xiàn)JQ中的AJAX在處理多個(gè)請求中會(huì)出現(xiàn)“回調(diào)地獄”的尷尬情形,那不行,雖然我的代碼沒那么美觀,但也不能容忍它這么丑吧,得想想法子

//=>回調(diào)地獄出現(xiàn)
$.ajax({
     url: '/temp/list',
     success: result => {
         $.ajax({
             url: '/temp/info',
             success: result => {
                 $.ajax({
                     url: '/temp/add',
                     method:'POST',
                     success: result => {
                              ...
                     }
                 });
             }
         });
     }
});

//=>解決方案1:發(fā)布訂閱
let $planA = $.Callbacks(),
    $planB = $.Callbacks();
$.ajax({
    url: '/temp/list',
    success: result => {
        $planA.fire(result);
    }
});

$planA.add(result => {
    $.ajax({
        url: '/temp/list',
        success: result => {
            $planB.fire(result);
        }
    });
});

$planB.add(result => {
    ...
});

//=>解決方案2:Promise
let queryA = function queryA() {
  return new Promise(resolve => {
     $.ajax({
         url: '/temp/list',
         success: resolve
     });
  });
};

let queryB = function queryB() {
    return new Promise(resolve => {
        $.ajax({
           url: '/temp/info',
           success: resolve
        });
    });
};

let queryC = function queryC() {
     return new Promise(resolve => {
         $.ajax({
             url: '/temp/add',
             method: 'POST',
             success: resolve
         });
     });
};

let promise = queryA();
promise.then(result => {
    console.log('A', result);
    return queryB();
}).then(result => {
    console.log('B', result);
    return queryC();
}).then(result => {
    console.log('C', result);
});

AXIOS

???????那么既然promise這么香,為何不用一個(gè)基于promise來管理的AJAX庫呢?AXIOS就是這樣一個(gè)寶藏,它是一個(gè)基于promise管理的類庫

  • 發(fā)送請求
// axios.get(url[,config])
axios.get('/temp/info', {
    params: {
        name: 'Leonard',
        age: 18
    }
});

//=>配置項(xiàng)中傳遞的內(nèi)容都相當(dāng)于基于請求主體專遞給服務(wù)器
//=>但是傳遞給服務(wù)器的內(nèi)容格式是RAW(JSON格式的字符串)
//=>不是X-WWW-FORM-URLENCODED
// axios.post(url[,data[,config]])
axios.post('/temp/add', {
     name: 'Leonard',
     age: 18
});

//=>一次并發(fā)多個(gè)請求
let sendAry = [
  axios.get('/temp/list'),
  axios.get('/temp/info'),
  axios.get('/temp/add')
]
axios.all(sendAry).then(result => {
  console.log(result);  //=>是一個(gè)數(shù)組,分別存儲(chǔ)著每一個(gè)請求的結(jié)果
})
//=> 也可以寫成
axios.all(sendAry).then(axios.spread((resA,resB,resC) => {...})
  • 請求返回信息
let promise = axios.get('/package.json', {
        params: {
            lx: 12
        }
    });
promise.then(result => {
        console.log(result);  //=>獲取的結(jié)果是一個(gè)對象
        /*
         * data:從服務(wù)器獲取的響應(yīng)主體內(nèi)容
         * headers:從服務(wù)器獲取的響應(yīng)的頭信息
         * request:創(chuàng)建的AJAX實(shí)例
         * status:狀態(tài)碼
         * statusText:狀態(tài)碼的描述
         * config:基于AXIOS發(fā)送請求的時(shí)候做的配置項(xiàng)
         */
}).catch(msg => {
    console.log(msg);  //=>請求失敗的原因
});
  • 初始化一些常用的配置項(xiàng)
//=>設(shè)置公共地址
axios.defaults.baseURL = 'https://www.easy-mock.com/mock/5b0412beda8a195fb0978627/temp';
//=>響應(yīng)攔截處理,可以直接取出響應(yīng)主體內(nèi)容以便后續(xù)使用
axios.interceptors.response.use(result => result.data);
//=>自定義校驗(yàn)規(guī)則
axios.defaults.validateStatus = status => /^(2|3)\d{2}$/.test(status);
//=>設(shè)置在POST請求中基于請求主體向服務(wù)器發(fā)送內(nèi)容的格式,默認(rèn)是RAW,項(xiàng)目中常用的是URL-ENCODEED格式
axios.defaults.headers['Content-Type'] = 'appliction/x-www-form-urlencoded';
//=>對請求內(nèi)容進(jìn)行處理
axios.defaults.transformRequest = data => {
//=>DATA:就是請求主體中需要傳遞給服務(wù)器的內(nèi)容(對象)
  let str = ``;
  for (let attr in data) {
      if (data.hasOwnProperty(attr)) {
           str += `${attr}=${data[attr]}&`;
      }
  }
  return str.substring(0, str.length - 1);
};
  • 更詳細(xì)地進(jìn)行學(xué)習(xí)可以參考axios
  • 最后,我們基于PROMISE再封裝一款簡易版AJAX庫
~(function(window) {
    //=>設(shè)置默認(rèn)的參數(shù)配置項(xiàng)
    let _default = {
        method: 'GET',
        url: '',
        baseURL: '',
        headers: {},
        dataType: 'JSON',
        data: null,
        params: null,
        cache: true
    };

    //=>基于PROMISE設(shè)計(jì)模式管理AJAX請求
    let ajaxPromise = function ajaxPromise(options) {
        let {url, baseURL, method, data, dataType, headers, cache, params} = options;

        //=>把傳遞的參數(shù)進(jìn)一步進(jìn)行處理
        if (/^(GET|DELETE|HEAD|OPTIONS)$/i.test(method)) {
            //=>GET系列
            if (params) {
                url += `${ajaxPromise.check(url)}${ajaxPromise.formatData(params)}`;
            }
            if (cache === false) {
                url += `${ajaxPromise.check(url)}_=${+(new Date())}`;
            }
            data = null;//=>請求主體清空
        } else {
            //=>POST系列
            if (data) {
                data = ajaxPromise.formatData(data);
            }
        }

        //=>基于PROMISE發(fā)送AJAX
        return new Promise((resolve, reject) => {
            let xhr = new XMLHttpRequest;
            xhr.open(method, `${baseURL}${url}`);
            //=>如果HEADERS存在,我們需要設(shè)置請求頭
            if (headers !== null && typeof headers === 'object') {
                for (let attr in headers) {
                    if (headers.hasOwnProperty(attr)) {
                        let val = headers[attr];
                        if (/[\u4e00-\u9fa5]/.test(val)) {
                            //=>VAL中包含中文:我們把它進(jìn)行編碼
                            val = encodeURIComponent(val);
                        }
                        xhr.setRequestHeader(attr, val);
                    }
                }
            }
            xhr.onreadystatechange = () => {
                if (xhr.readyState === 4) {
                    if (/^(2|3)\d{2}$/.test(xhr.status)) {
                        let result = xhr.responseText;
                        dataType = dataType.toUpperCase();
                        dataType === 'JSON' ? result = JSON.parse(result) : (dataType === 'XML' ? result = xhr.responseXML : null);
                        resolve(result);
                        return;
                    }
                    reject(xhr.statusText);
                }
            };
            xhr.send(data);
        });
    };

    //=>把默認(rèn)配置暴露出去,后期用戶在使用的時(shí)候可以自己設(shè)置一些基礎(chǔ)的默認(rèn)值(發(fā)送AJAX請求的時(shí)候按照用戶配置的信息進(jìn)行處理)
    ajaxPromise.defaults = _default;

    //=>把對象轉(zhuǎn)換為URLENCODED格式的字符串
    ajaxPromise.formatData = function formatData(obj) {
        let str = ``;
        for (let attr in obj) {
            if (obj.hasOwnProperty(attr)) {
                str += `${attr}=${obj[attr]}&`;
            }
        }
        return str.substring(0, str.length - 1);
    };
    ajaxPromise.check = function check(url) {
        return url.indexOf('?') > -1 ? '&' : '?';
    };

    ['get', 'delete', 'head', 'options'].forEach(item => {
        ajaxPromise[item] = function(url, options = {}) {
            options = {
                ..._default,//=>默認(rèn)值或者基于defaults修改的值
                ...options,//=>用戶調(diào)取方法傳遞的配置項(xiàng)
                url: url,//=>請求的URL地址(第一個(gè)參數(shù):默認(rèn)配置項(xiàng)和傳遞的配置項(xiàng)中都不會(huì)出現(xiàn)URL,只能這樣獲取)
                method: item.toUpperCase()
            };
            return ajaxPromise(options);
        };
    });

    ['post', 'put', 'patch'].forEach(item => {
        ajaxPromise[item] = function anonymous(url, data = {}, options = {}) {
            options = {
                ..._default,
                ...options,
                url: url,
                method: item.toUpperCase(),
                data: data
            };
            return ajaxPromise(options);
        };
    });

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

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

  • 走得慢 沒關(guān)系 至少依舊在前進(jìn) 只是某一刻 覺得好孤單 原地踏步時(shí) 恍然驚覺 伙伴已走遠(yuǎn)
    蝸牛sister閱讀 399評論 4 1
  • 我不得不承認(rèn),在骨子里,我仍是個(gè)很要強(qiáng)的人 我也不能否認(rèn),在心底深處,我仍希望可以跌入一個(gè)溫暖的懷抱 可是,人生 ...
    lucy大人閱讀 807評論 10 49
  • 今天吃過中午飯的時(shí)候,我看到爸爸媽媽忙的不可開交,便自告奮勇地對他們說:“今天我要替你們刷碗!” ...
    趙藝萌閱讀 213評論 0 2
  • 一,激發(fā)潛能矯正近視原理是什么? 近視原因 近視是因?yàn)殚L期看近,睫狀肌失去彈性或彈性不足,不能拉動(dòng)晶狀體變薄...
    瞳瞳復(fù)原閱讀 310評論 0 0