面試題目整理

vue相關(guān)

1.VNode是什么策治?什么是虛擬dom赡模?

在vue.js中存在一個VNode類罢猪,使用它可以實例化不同類型的vnode實例,這些實例可以被渲染成真實的dom對象幸海。
虛擬dom是通過 js 對象來描述真實 DOM 結(jié)構(gòu)和屬性祟身。例如:

//下面是一個a標(biāo)簽
<a class="demo" style="color: red" href="#">
    文本內(nèi)容
</a>
// 用VNode的實例對象來描述
{
  tag: 'a',
  data: {
    calss: 'demo',
    attrs: {
      href: '#'
    },
    style: {
      color: 'red'
    }
  },
  children: ['文本內(nèi)容']
}

由于真實dom頻繁排版與重繪的效率低,對虛擬DOM進行頻繁修改物独,然后一次性對比并修改真實DOM中需要改的部分袜硫,最后在真實DOM中進行排版與重繪,減少過多DOM節(jié)點排版與重繪損耗挡篓。

舉個例子:下面有一段html代碼

<ul id='list'>
    <li class='item'>Item 1</li>
    <li class='item'>Item 2</li>
</ul>

用js對象模擬如下

{
    tag:'ul',
    attrs:{
        id:'list'
    },
    children:[
        {
            tag:'li',
            attrs:{  className:'item'  },
            children:['Item 1']
        },
        {
            tag:'li',
            attrs:{  className:'item'  },
            children:['Item 2']
         }
    ]
}

如果我們要把Item 2改成Item B婉陷,我們會先生成類似上面的js DOM結(jié)構(gòu)如下

{
    tag:'ul',
    attrs:{
        id:'list'
    },
    children:[
        {
            tag:'li',
            attrs:{  className:'item'  },
            children:['Item 1']
        },
        {
            tag:'li',
            attrs:{  className:'item'  },
            children:['Item B'] //注意此處Item 2改編成了Item B
         }
    ]
}

然后通過對比發(fā)現(xiàn)改變的只有Item B;現(xiàn)在提供兩種改變的思路:

  • 1.直接刪掉所有Item官研,再把Item1 和 Item B加進來秽澳。
  • 2.先生成最終js的DOM結(jié)構(gòu),然后對比之前的js DOM結(jié)構(gòu)戏羽,找出差異部分再改變 担神。
    只從思路上分析,第一種更加簡單快捷始花;然而實際是妄讯,瀏覽器最最最耗費性能的就是DOM操作,dom操作是最昂貴的酷宵,現(xiàn)在的瀏覽器執(zhí)行js是非澈ッ常快的,所以虛擬DOM有其存在的價值浇垦。
vdom如何應(yīng)用炕置,核心API是什么?(這個可以先不看)

要我們自己去實現(xiàn)一個虛擬dom,大概過程應(yīng)該有以下三步:

  • compile:如何把真實DOM編譯成vnode朴摊。
  • diff:我們要如何知道oldVnode和newVnode之間有什么變化默垄。
  • patch:如果把這些變化用打補丁的方式更新到真實dom上去。
    vue的虛擬dom實現(xiàn)參考了snabbdom.js的實現(xiàn)仍劈。

snabbdom.js核心API是兩個函數(shù)厕倍,一個h函數(shù)(用來創(chuàng)建vnode),一個patch函數(shù)(用來對比變化并替換)贩疙。


image.png

image.png
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="container"></div>
    <button id="btn-change">change</button>


    <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom.js"></script>
    <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-class.js"></script>
    <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-props.js"></script>
    <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-style.js"></script>
    <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-eventlisteners.js"></script>
    <script src="https://cdn.bootcss.com/snabbdom/0.7.3/h.js"></script>
    <script>
        var snabbdom = window.snabbdom;

        //定義path
        var path = snabbdom.init([
            snabbdom_class,
            snabbdom_props,
            snabbdom_style,
            snabbdom_eventlisteners
        ])

        //定義h
        var h = snabbdom.h;

        var container = document.getElementById('container');

        //生成vnode
        var vnode = h('ul#list',{},[
            h('li.item',{},'Item 1'),
            h('li.item',{},'Item 2')
        ]);
        path(container,vnode);

        document.getElementById('btn-change').addEventListener('click',function () {
           //生成newVnode
            var newVnode = h('ul#list',{},[
                h('li.item',{},'Item 1'),
                h('li.item',{},'Item B'),
                h('li.item',{},'Item 3')
            ]);
            path(vnode,newVnode);
        });
    </script>
</body>
</html>

diff算法大概結(jié)構(gòu)

      const vDom = {
            tag:'ul',
            attrs:{id:'list'},
            children:[
                {
                    tag:'li',
                    attrs: {className:'item'},
                    children:['item1']
                },{
                    tag:'li',
                    attrs:{className:'item'},
                    children:['item2']
                }
            ]
        };
        function createElement(vnode) {
            let tag = vnode.tag,
                attrs = vnode.attrs || {},
                children = vnode.children || [];
            if(!tag){return null;}
            //創(chuàng)建真實的DOM元素
            let elem = document.createElement(tag);
            //屬性
            let attrName;
            for(attrName in attrs){
                if(attrs.hasOwnProperty(attrName)){
                    //給elem添加屬性
                    elem.setAttribute(attrName,attrs[attrName]);
                }
            }
            //子元素
            children.forEach(function (childVNode) {
                //給elem添加子元素
               elem.appendChild(createElement(childVNode))
            });

            // 返回真實的dom元素
            return elem;
        }
        const newVNode = {
            tag:'ul',
            attrs:{id:'list'},
            children:[
                {
                    tag:'li',
                    attrs: {className:'item'},
                    children:['item1']
                },{
                    tag:'li',
                    attrs:{className:'item'},
                    children:['item222']
                },{
                    tag:'li',
                    attrs:{className:'item'},
                    children:['item3']
                }
            ]
        };
        function updateChildren(vNode,newVNode) {
            let children = vNode.children || [],
                newChildren = newVNode.children || [];

            children.forEach(function (childVNode,index) {
                let newChildVNode = newChildren[index];
                if(childVNode.tag===newChildVNode.tag){
                    updateChildren(childVNode,newChildVNode);
                }else{
                    replaceNode(childVNode,newChildVNode);
                }

            });
        }
        function replaceNode(vNode,newVNode) {
            let elem = vNode.elem,
                newElem = createElement(newVNode);

            //替換
            //...
        }
        //節(jié)點新增和刪除
        //節(jié)點重新排序
        //節(jié)點屬性讹弯、樣式、事件綁定
        //如何極致壓榨性能
2.v-show 與 v-if 區(qū)別这溅?
  • v-show是css切換组民,v-if是完整的銷毀和重新創(chuàng)建;
  • 使用頻繁切換時用v-show,運行時較少改變時用v-if;
  • v-if="false" v-if是條件渲染悲靴,當(dāng)false的時候不會渲染臭胜。
3.計算屬性和 watch 的區(qū)別?

計算屬性是自動監(jiān)聽依賴值的變化癞尚,從而動態(tài)返回內(nèi)容耸三,監(jiān)聽是一個過程,在監(jiān)聽的值變化時浇揩,可以觸發(fā)一個回調(diào)仪壮,并做一些事情。
所以區(qū)別來源于用法胳徽,只是需要動態(tài)值积锅,那就用計算屬性;需要知道值的改變后執(zhí)行業(yè)務(wù)邏輯养盗,才用 watch缚陷。

4.computed 和 methods 有什么區(qū)別?

methods是一個方法往核,它可以接受參數(shù)箫爷,而computed不能,computed是可以緩存的聂儒,methods不會蝶缀。

5.vue的生命周期
  • beforeCreate
    vue實例的掛載元素el和數(shù)據(jù)對象data都為undefined,還未初始化薄货。
  • created
    vue實例的數(shù)據(jù)對象有了,el還沒有碍论。
  • beforeMount:
    掛載開始之前被調(diào)用谅猾,相關(guān)的render函數(shù)首次被調(diào)用(虛擬DOM),實例已完成以下的配置: 編譯模板,把data里面的數(shù)據(jù)和模板生成html税娜,完成了el和data 初始化坐搔,注意此時還沒有掛在html到頁面上。
  • mounted:
    掛載完成敬矩,也就是模板中的HTML渲染到HTML頁面中概行,此時一般可以做一些ajax操作,mounted只會執(zhí)行一次弧岳。
  • 更新前后 beforeUpdate/updated
    當(dāng)data變化時凳忙,會觸發(fā)beforeUpdate和updated方法。
  • beforeDestory
    在實例銷毀之前調(diào)用禽炬,實例仍然完全可用涧卵,這一步還可以用this來獲取實例,一般在這一步做一些重置的操作腹尖,比如清除掉組件中的定時器 和 監(jiān)聽的dom事件柳恐。
  • destoryed
    在實例銷毀之后調(diào)用,調(diào)用后热幔,所以的事件監(jiān)聽器會被移出乐设,所有的子實例也會被銷毀,該鉤子在服務(wù)器端渲染期間不被調(diào)用绎巨。
路由的跳轉(zhuǎn)方式
  • <router-link to='home'> router-link標(biāo)簽會渲染為<a>標(biāo)簽近尚。
  • 編程式導(dǎo)航 也就是通過js跳轉(zhuǎn) 比如 router.push('/home')
6.nextTick()

在下次 DOM 更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)。在修改數(shù)據(jù)之后认烁,立即使用這個回調(diào)函數(shù)肿男,獲取更新后的 DOM。

// 修改數(shù)據(jù)
vm.msg = 'Hello'
// DOM 還未更新
Vue.nextTick(function () {
  // DOM 更新
})
7.slot插槽
  • 單個插槽
    當(dāng)子組件模板只有一個沒有屬性的插槽時却嗡,父組件傳入的整個內(nèi)容片段將插入到插槽所在的 DOM 位置舶沛,并替換掉插槽標(biāo)簽本身。
  • 命名插槽
    solt元素可以用一個特殊的特性name來進一步配置如何分發(fā)內(nèi)容窗价。多個插槽可以有不同的名字如庭。這樣可以將父組件模板中 slot 位置,和子組件 slot 元素產(chǎn)生關(guān)聯(lián)撼港,便于插槽內(nèi)容對應(yīng)傳遞

js相關(guān)

1.繼承的方法有哪些坪它?并解釋各個繼承詳情。
/**1.構(gòu)造函數(shù)繼承**/
function parent(){
  this.colors = ['red','blue'];
}
function children(){
  parent.call( this );
}
var c1 = new children();
console.log( c1.colors );   // ['red','blue']
/**2.實例繼承**/
function parent2(){
  this.colors = ['red','blue'];
}
function children2(){}
children2.prototype = new parent2();
var c2_1 = new children2();
var c2_2 = new children2();
console.log( c2_1.colors ); // ['red','blue']
console.log( c2_2.colors ); // ['red','blue']
c2_1.colors.push('white');  
console.log( c2_2.colors ); // ['red','blue','white']
/**3.組合繼承**/
function parent3(){
  this.colors = ['red','blue'];
}
function children3(){
  parent3.call(this);
}
children3.protopype = new parent3();
var c3_1 = new children3();
var c3_2 = new children3();
console.log( c3_1.colors ); // ['red','blue']
console.log( c3_2.colors ); // ['red','blue']
c3_1.colors.push('white');
console.log( c3_2.colors ); // ['red','blue']

/**4.組合寄生繼承(最優(yōu) 記住這個就可以)**/
function parent4(){
  this.colors = ['red','blue'];
}
function children4(){
  parent4.call(this);
}
children4.prototype = Object.create(parent4);
children4.prototype.constructor = children4;
var c4_1 = new children4();
var c4_2 = new parent4();
console.log( c4_1 instanceof parent4 );  //false
console.log( c4_2 instanceof parent4 );  //true
2.什么是閉包帝牡?

簡單講往毡,閉包就是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù)。
外部函數(shù)調(diào)用之后在其內(nèi)部聲明的變量本應(yīng)該被銷毀靶溜,但閉包的存在使我們?nèi)匀豢梢栽L問外部函數(shù)的變量對象开瞭,這就是閉包的重要概念懒震。

 function outer(){
     var a = 1;
     return function(){
         console.log(a++);
     }
 }
var b = outer();
b();//1
b();//由于a的值不會被釋放,再次調(diào)用結(jié)果為2

應(yīng)用場景嗤详,比如單例模式个扰,防抖函數(shù),節(jié)流函數(shù)等葱色。

/**單例模式  得到的始終是同一個對象*/
(function (global) {
    function SimpleObj() {
        var instance = null;
        return function () {
            if (instance == null) {
                instance = {
                    name: 'simapleobj'
                }
            }
            return instance;
        }
    }
    global.getInstance = SimpleObj();
})(window)
getInstance(); //{name: "simapleobj"}
var a = getInstance();
console.log(a); //{name: "simapleobj"}
var b = getInstance();
console.log(b); //{name: "simapleobj"}
a.name = 'ACE';
console.log(a); //{name: "ACE"}
console.log(b); //{name: "ACE"}
var c = getInstance();
console.log(c); //{name: "ACE"}
getInstance(); //{name: "ACE"}

/*防抖函數(shù)*/
<input type="text">
<script>
    var input = document.querySelector("input");
    function debounce(func, delay) {
        let time;
        return function () {
            //保存this指向
            const context = this;
            //保存?zhèn)魅氲膮?shù)
            const args = arguments;
            //清除上次的延時器
            clearTimeout(time);
            //重新設(shè)置一個延時器递宅,延遲為delay毫秒
            time = setTimeout(function () {
                func.apply(context, args)
            }, delay)
        }
    }
    var inputEvent = debounce(function () {
        console.log("向后端發(fā)送請求");
    }, 1500);
    input.addEventListener("input", inputEvent);
</script>
3.原型鏈

每個函數(shù)有個prototype屬性,指向其原型對象苍狰,原型對象有一個constructor屬性指向構(gòu)造函數(shù)办龄;通過函數(shù)實例化(new)出來的對象有一個proto屬性,也指向函數(shù)的原型對象舞痰;原型對象也有__proto__屬性土榴,指向原型對象的原型對象,通過一層層往上指响牛,直到Object.prototype玷禽。

function foo(){}
let f = new foo();
console.log(f.__proto__===foo.prototype);//true
console.log(foo.prototype.constructor===foo);//true

4.如何解決跨域問題 詳解轉(zhuǎn)載

  • 1.通過jsonp跨域(只支持get方式)
    通常為了減輕web服務(wù)器的負載,我們把js呀打、css矢赁,img等靜態(tài)資源分離到另一臺獨立域名的服務(wù)器上,在html頁面中再通過相應(yīng)的標(biāo)簽從不同域名下加載靜態(tài)資源,而被瀏覽器允許,基于此原理赔退,我們可以通過script標(biāo)簽允跑,再請求一個帶參網(wǎng)址實現(xiàn)跨域通信辨绊。
    html代碼
<body>
    <script>
        function test(data) {
            alert(data.name);
        }
    </script>
    <script src="http://127.0.0.1:3000/jsonp?callback=test"></script>
</body>

服務(wù)端代碼(用的express)

router.get('/jsonp', function (req, res, next) {
  res.set({
    'Content-Type': 'json',
  });
  var data = {
    "name": "Monkey"
  };
  data = JSON.stringify(data);
  res.end(`${req.query.callback}(${data})`);
});
  • 2.跨域資源共享(CORS)
    普通跨域請求:只服務(wù)端設(shè)置Access-Control-Allow-Origin即可,前端無須設(shè)置;
    若要帶cookie請求:前后端都需要設(shè)置。
    前端設(shè)置
    1)原生ajax
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容

// 前端設(shè)置是否帶cookie
xhr.withCredentials = true;

xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');

xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        alert(xhr.responseText);
    }
};

2)jQuery ajax

$.ajax({
    ...
   xhrFields: {
       withCredentials: true    // 前端設(shè)置是否帶cookie
   },
   crossDomain: true,   // 會讓請求頭中包含跨域的額外信息抄邀,但不會含cookie
    ...
});

3)vue框架

//axios設(shè)置:
axios.defaults.withCredentials = true;

// vue-resource設(shè)置:
Vue.http.options.credentials = true;

服務(wù)端設(shè)置

var http = require('http');
var server = http.createServer();
var qs = require('querystring');

server.on('request', function(req, res) {
    var postData = '';

    // 數(shù)據(jù)塊接收中
    req.addListener('data', function(chunk) {
        postData += chunk;
    });

    // 數(shù)據(jù)接收完畢
    req.addListener('end', function() {
        postData = qs.parse(postData);

        // 跨域后臺設(shè)置
        res.writeHead(200, {
            'Access-Control-Allow-Credentials': 'true',     // 后端允許發(fā)送Cookie
            'Access-Control-Allow-Origin': 'http://www.domain1.com',    // 允許訪問的域(協(xié)議+域名+端口)
            /* 
             * 此處設(shè)置的cookie還是domain2的而非domain1,因為后端也不能跨域?qū)慶ookie(nginx反向代理可以實現(xiàn))昼榛,
             * 但只要domain2中寫入一次cookie認證境肾,后面的跨域接口都能從domain2中獲取cookie,從而實現(xiàn)所有的接口都能跨域訪問
             */
            'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'  // HttpOnly的作用是讓js無法讀取cookie
        });

        res.write(JSON.stringify(postData));
        res.end();
    });
});

server.listen('8080');
console.log('Server is running at port 8080...');
  • WebSocket協(xié)議跨域
    WebSocket protocol是HTML5一種新的協(xié)議胆屿。它實現(xiàn)了瀏覽器與服務(wù)器全雙工通信奥喻,同時允許跨域通訊。
實現(xiàn)求和sum非迹,支持sum(1), sum(1,2,3,4), sum(1)(2)(3), console.log(sum(1)(2,3)(4)) = 10
function sum(...rest) {
    let rst = 0;
    rest.forEach(item => rst += item);
    let temp = function (...innerRest) {
        innerRest.forEach(item => rst += item)
        return temp;
    }
    temp.toString = function () {
        return rst;
    }
    return temp;
}
console.log(sum(1))
console.log(sum(1)(2))
console.log(sum(1, 2)(3))
console.log(sum(1, 2)(3)(4, 5))
chain = new Chain, chain.eat().sleep(5).eat().sleep(6).work()
class Chain {
    constructor(name) {
        console.log(name)
        this.stack = [];
        this.time = null;
    }
    async invoke() {
        console.log("invoke")
        if (this.time) {
            clearTimeout(this.time)
        }
        this.time = setTimeout(async () => {
            while (this.stack.length) {
                await this.stack.shift()();
            }
        }, 3000)
    }
    eat() {
        console.log("push eat")
        this.stack.push(
            function () {
                return new Promise(function (reslove) {
                    console.log("eat...")
                    reslove()
                })
            }
        )
        this.invoke()
        return this;
    }
    work() {
        console.log("push work")
        this.stack.push(
            function () {
                return new Promise(function (reslove) {
                    console.log("work...")
                    reslove()
                })
            }
        )
        this.invoke()
        return this;
    }
    sleep(delay) {
        console.log("push sleep")
        this.stack.push(
            function () {
                return new Promise(function (reslove) {
                    setTimeout(function () {
                        console.log("sleep " + delay + " 秒")
                        reslove()
                    }, delay * 1000)
                })
            }
        )
        this.invoke()
        return this;
    }
}
const c = new Chain("zhangsan");
const d = c.eat().sleep(1).work().sleep(2).eat();
d.sleep(2).work()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末环鲤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子憎兽,更是在濱河造成了極大的恐慌冷离,老刑警劉巖结闸,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異酒朵,居然都是意外死亡,警方通過查閱死者的電腦和手機扎附,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門蔫耽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人留夜,你說我怎么就攤上這事匙铡。” “怎么了碍粥?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵鳖眼,是天一觀的道長。 經(jīng)常有香客問我嚼摩,道長钦讳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任枕面,我火速辦了婚禮愿卒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘潮秘。我一直安慰自己琼开,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布枕荞。 她就那樣靜靜地躺著柜候,像睡著了一般。 火紅的嫁衣襯著肌膚如雪躏精。 梳的紋絲不亂的頭發(fā)上渣刷,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天,我揣著相機與錄音玉控,去河邊找鬼飞主。 笑死,一個胖子當(dāng)著我的面吹牛高诺,可吹牛的內(nèi)容都是我干的碌识。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼虱而,長吁一口氣:“原來是場噩夢啊……” “哼筏餐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起牡拇,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤魁瞪,失蹤者是張志新(化名)和其女友劉穎穆律,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體导俘,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡峦耘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了旅薄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辅髓。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖少梁,靈堂內(nèi)的尸體忽然破棺而出洛口,到底是詐尸還是另有隱情,我是刑警寧澤凯沪,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布第焰,位于F島的核電站,受9級特大地震影響妨马,放射性物質(zhì)發(fā)生泄漏挺举。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一身笤、第九天 我趴在偏房一處隱蔽的房頂上張望豹悬。 院中可真熱鬧,春花似錦液荸、人聲如沸瞻佛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伤柄。三九已至,卻和暖如春文搂,著一層夾襖步出監(jiān)牢的瞬間适刀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工煤蹭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留笔喉,地道東北人。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓硝皂,卻偏偏與公主長得像常挚,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子稽物,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,658評論 2 350

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