2021-06-18vue第三天

一、组件

(1)组件只有 导入并注册 后才能使用
(2)HTML对字母大小写不敏感。组件名、属性名使用短横线连接,就不要再用大写字母了。

1. 全局组件的注册

Vue.component(" 组件名称 ",{
  data:组件数据,
  template:组件模板内容
}
调用组件:<组件名称> </组件名称>

(1)组件中的 data 参数必须是 函数 ,同时这个函数要求返回一个对象。(因为函数可以形成闭包,保证每次组件调用时都有独立的数据。)
(2)组件模板 template 必须是 单个根元素。也就是所有模板内容都要放到一个大盒子内。
(3)组件模板 template 可以是 字符串,也可以是 ES6 的 模板字符串。(主要解决传统字符串不能随意换行的问题)
(4)组件可以在 HTML标签内调用(vue实例对象),也可以在其他组件的模板 template 中调用
(5)组件命名时,可以用 短横线连接,也可以用 驼峰式 命名法。
(6)组件调用时,如果是在HTML标签内调用(vue实例对象),组件名必须 转化为 短横线连接;如果是在其他组件的 template 中调用,也可以用驼峰式。
(7)组件可以重复使用多次 。因为data中返回的是一个对象,所以 每个组件中的数据是私有的,即每个实例可以维护一份被返回对象的独立的拷贝。
(8)自定义组件的注册要放到 vue实例对象 之前。vue实例对象也是组件

      <div class="box">
      <!-- 多次调用,数据独立 -->
      <btn-count></btn-count>
      <btn-count></btn-count>
    </div>

    <script src="./vue.js"></script>

    <script>
      // 组件的全局注册
      Vue.component('btn-count', {
        data: function () {
          return { count: 0 };
        },
        // 使用模板字符串,并调用其他组件。
        template: `<div>
            <button v-on:click="handle">点击了{{count}}次</button>
            <HelloWorld></HelloWorld>
            </div>`,
        methods: {
          handle: function () {
            this.count += 2;
          },
        },
      });

      // 使用驼峰式命名法和普通字符串定义组件
      Vue.component('HelloWorld', {
        data: function () {
          return { msg: 'HelloWorld!' };
        },
        template: '<div>{{this.msg}}</div>',
      });

      // 创建vue实例对象
      var vm = new Vue({
        el: '.box',
        data: {},
      });
    </script>
2. 局部组件的注册

components: {
   HelloWorld:{
      template: '<div>局部组件</div>',
    },
}

(1)在vue实例对象中添加 components 属性。components 是一个对象,属性名是 组件名,属性值是 配置对象
(2)和自定义局部指令、局部过滤器一样,局部组件只能在注册它的父组件内使用
也就是,在vue实例对象中注册的局部组件只能在vue实例对象中使用。其他的全局组件不能使用。

    <div class="box">
      <!-- 调用局部组件 -->
      <hello-world></hello-world>
    </div>

    <script src="./vue.js"></script>

    <script>
      var hw = {
        template: '<div>局部组件</div>',
      };

      var vm = new Vue({
        el: '.box',
        // 注册局部组件
        components: {
          HelloWorld: hw,
        },
      });
    </script>
3. 组件统一注册为全局组件(重点)

(1)想要把多个组件注册为全局可用的子组件,直接在 main.js 中用 Import导入,然后用 Vue.component( ) 注册,代码很多,不合适。
(2)这里,我们把导入和注册的代码单独封装到一个工具组件中。在main.js里,使用 Vue.use( )方法 执行工具组件中的代码。
(3)Vue.use( )方法接收一个配置对象,对象里面有一个 install( vue )函数,参数Vue是 Vue实例对象。

首先在工具组件Component中执行组件的全局注册

// 该文件负责所有的公共的组件的全局注册  
// 1.导入组件
import PageTools from './PageTools'
export default {
  install(Vue) {
    //  2.全局注册组件
    Vue.component('PageTools', PageTools)
  }
}

然后在 main.js中调用工具组件Component,执行其中的代码。

import Component from '@/components'
Vue.use(Component) // 注册自己的插件

二、vue 调试工具的安装

三、组件之间的相互传值

1. 父组件向子组件传值 (自定义属性)

Vue.component("child",{
props:[ " title "],
template:" <div> {{ title } </div>
}
在父组件中调用:< child v-bind:title=" title "> </child>

① 父子组件的形成

  • 通过路由的 children 属性可以形成 父子组件 的关系;
  • 通过在父组件内 导入、注册、调用子组件也可以形成父子组件的关系;
  • 父组件调用子组件时,可以用 <子组件名称 />的形式,还可以用路由中学的<component v-bind:is="子组件名称" />的方式调用子组件。
    注意:使用 <component>标签时,不仅要注册子组件,还要把子组件的名字在data中定义。

② 父组件调用子组件时,通过给子组件 【添加自定义属性】 的形式传值。

③ 父组件传值时, 可以是静态的,也可以 用 v-bind绑定父组件的data数据

④ 子组件在内部添加 【props】 属性来接收父组件传递的数据。props是一个 数组

⑤ 这样就可以在子组件模板 template 内使用传递的数据了。

props 数组中接收的数据,可以是 数据名称的字符串

props 数组中接收的数据也可以是一个对象,规定每个数据的类型、是否必须等。

props: {
   channel: {
      //可选数据类型
      type: [Object,Number,String],
      //是否必要
      required: true
      //默认值, 数组和对象必须用下面的方式定义
      default:function(){
          return {}
      }
       //校验规则,防止传入数据不符合要求导致代码崩溃。
      validator: function (value) {
        return value >= 0
      }
    } 
}

⑧ 在HTML标签中使用 属性名 时,必须转化为短横线连接;在 template 模板中可以使用驼峰式命名。

<div class="box">
      <div>{{fmsg}}</div>
      <!-- 在父组件中调用子组件 -->
      <child v-bind:fmsg="fmsg" content="传递的静态内容"></child>
    </div>

    <script src="./vue.js"></script>

    <script>
      // 子组件
        Vue.component('child', {
          props: ["fmsg","content"],
          data: function () {
            return {
              msg: '子组件本身的内容',
            }
          },
          template: '<div>{{msg + "---" + fmsg + "---" + content}}</div>',
        });

      var vm = new Vue({
        el: '.box',
        data: { fmsg: '父组件的内容' },
      });
    </script>

⑨ 一个组件想要被 重用,某些数据就不要写在data中变成组件的私有数据,而是写在 props数组中,这样可以由父组件在调用时传入。

⑩ 父组件通过props传递给子组件的数据时异步执行的。比如父组件内点击表格中的某一行数据,可以把当前行的id传给弹出层子组件,但是弹出层子组件不能用props中的id发起Ajax请求获取数据,而是应该在子组件封装获取数据的方法,在父组件中调用子组件方法。

父组件渲染页面时,执行到子组件占位符时就会渲染子组件,不论子组件是否显示在页面上。但是此时props传递的数据还没传递给子组件。

this.$nextTick(() => { }) 是vue提供的方法,他会等待DOM元素更新之后再去执行后面的操作。

vue中数据和dom渲染是异步的(数据驱动视图是异步的),所以,要让dom结构随数据改变这样的操作,都应该放进 this.$nextTick() 的回调函数中。

created()中使用方法时,dom还没有渲染,如果此时在该钩子函数中进行dom赋值数据(或者其它dom操作),无异于徒劳,所以,此时this.$nextTick()就会被大量使用,而与created()对应的是mounted()的钩子函数则是在dom完全渲染后才开始渲染数据,所以在mounted()中操作dom基本不会存在渲染问题。

2. 组件之间传递的值的类型

① 字符串、数字型、布尔型、数组、对象。
② 子组件被调用时,父组件传递的 数字型布尔型的值,如果没有绑定 v-bind,则传递的是 字符串 类型。

   <div class="box">
      <!-- 调用子组件,传递五种类型的值 -->
      <child :str="str" :num="10" :boolen="true" :arr="arr" :obj="obj"></child>
    </div>

    <script src="./vue.js"></script>

    <script>
      // 子组件
      Vue.component('child', {
        // 子组件接收传递过来的五种值
        props: ['str', 'num', 'boolen', 'arr', 'obj'],
        // 子组件在模板中使用传递过来的值
        template: `<div>
            <div>{{str}}</div>
            <div>{{num}}</div>
            <div>{{boolen}}</div>
            <ul>
                <li v-for="item in arr">{{item}}</li>
            </ul>
            <ul>
                <li v-for="(v,k,i) in obj">{{v + k}}</li>
            </ul>
            </div>`,
      });

      var vm = new Vue({
        el: '.box',
        data: {
          str: '你好',
          arr: ['吴磊', '王祖贤', '吴彦祖'],
          obj: {
            name: '吴磊',
            gender: '男',
          },
        },
      });
    </script>
3. 子组件向父组件传值 (自定义事件)

Vue.component('child', {
   template:
    "<div>
       <button v-on:click='$emit("change",5)'>子组件按钮</button>
     </div>",
});
调用子组件:<child v-on:change="handle($event)"></child>

① 子组件的 props 属性使用原则:单向数据流。即在子组件中修改数据不会同步到父组件,而子组件的数据来自父组件,父组件的数据一旦发生变化,子组件的数据就白修改了。

② 具体来说:不要在子组件内修改数字型、布尔型、字符串数据,不能对数组、对象重新赋值,但是可以修改数组和对象的元素与属性。

③ 父组件在调用子组件时,给子组件注册 自定义事件,并在methods中声明事件的处理函数。

④ 在子组件的 template 模板中,用 this.$emit 触发自定义事件。(可以直接在template模板中绑定,也可以在methods中绑定。)事件的第一个参数是 事件名称,第二个参数是 想要传递的值

⑤ 如果传递多个值,可以用 对象 的形式。并且可以传递 事件对象$event

⑥ 父组件通过 $event 获取到子组件传递的值。

     <div class="box">
      <div v-bind:style="{fontSize: fontSize +'px'}">{{msg}}</div>
      <!-- 在父组件中调用子组件 -->
      <child v-on:change="handle($event)"></child>
    </div>

    <script src="./vue.js"></script>

    <script>
      // 子组件,直接在template模板中绑定$emit事件
      Vue.component('child', {
        template: `<div>
                <button v-on:click='$emit("change",5)'>子组件按钮</button>
                </div>`,
      });

      var vm = new Vue({
        el: '.box',
        data: { msg: '父组件的内容', fontSize: 16 },
        methods: {
          handle: function (val) {
            this.fontSize += val;
          },
        },
      });
    </script>
4. 子组件对父组件的数据 【使用并修改】

如果子组件既要使用父组件中的数据,又要修改父组件的数据。

(1) 传统做法:

① 父组件调用子组件时,用v-bind绑定数据进行传递;子组件在props属性中接收。
② 子组件修改数据时,用$emit绑定方法;父组件监听此方法,并在事件函数中修改数据。

(2) 新方法:v-model(vue3.0有变化!!!)

① 父组件调用子组件时,用 v-model 绑定数据进行传递;子组件在props属性中接收。

<FollowUser v-model="fatherData" ></FollowUser>

② 子组件接收数据时,数据名称固定为 value
③ 子组件修改数据时,用$emit触发自定义事件,事件名称固定为 input父组件无需注册和声明此事件
④ 如果子组件想要修改数据名称和事件名称,则在组件内添加 model属性

model: {
    prop: 'data', //默认名称为value
    event: 'changeData'  //默认名称为input
  },
props:[ 'data' ],
methods:{
   handler( ){ this.$emit('changeData',newData)}
}

注意:v-model绑定数据只能用一次。

(3)新方法:.sync(vue3.0已删除!!!)

① 父组件传递数据时,在数据名称后面添加 .sync修饰符

<child :dialog-visible.sync="dialogVisible" />

② 此时,子组件就可以按照下面的格式修改这个数据,而父组件不用注册$emit的事件。

this.$emit('update:dialogVisible', false)

update: 是固定写法,参数false是修改的值。

(4)子组件中 this.$parent 可以获取到父组件的实例对象。
(5)vue3.0 v-model

父组件调用子组件时,用 v-model 绑定数据,子组件用 prop接收数据,
this.$emit("update:数据名",最新值) 进行修改。

5.父组件向后代子组件传值

通过 依赖注入 ,父组件声明数据,后代子组件接收数据并使用。当某个父组件的数据被多个子组件使用时使用这种方法。

① 父组件声明数据:

provide: function () {
    return {
      articleID: this.articleID
    }
  },

② 后代子组件接收数据

inject: {
    articleID: {
      type: [Number, String, Object],
      default: null
    }
  }
6. 兄弟组件传值(了解)

① 定义一个 事件中心

var hub = new Vue()

② 在接收数据的组件内,添加 mounted钩子函数 ,在mounted函数内书写 监听事件的函数。监听的事件处理的是本组件的数据
注意: 这里使用箭头函数是因为 this 指向的问题。

mounted: function() {
  hub.$on( '自定义事件名', (形参) => { });
}

③ 在传递数据的组件内,为HTML标签绑定事件 hub.$emit( '自定义事件名',传递的数据)。触发的是兄弟组件的事件。

handle: function(){
  hub.$emit( '自定义事件名',实参)
}

④ 在父组件内,给html元素绑定事件,通过 hub.$off( "自定义事件名") 销毁事件。

<button v-on:click="handle">销毁事件</button>
handle: function () {
   hub.$off('自定义事件名');
}

四、组件插槽

1. 组件插槽基本用法

通过组件插槽,可以在调用子组件时,向标签内填写内容。

① 在子组件的 template 模板中添加一个固定的标签 <slot> </slot>作为插槽。
② 在父组件中调用子组件时,可以向标签内填写内容,标签中的内容被传递到子组件插槽中,显示到页面。
③ 在父组件中调用子组件时,如果向标签内添加内容,则<slot></slot>标签内的默认内容会被覆盖。

<div class="box">
      <!-- 调用子组件 -->
      <child>你好!</child>
    </div>

    <script src="./vue.js"></script>

    <script>
      // 子组件
      Vue.component('child', {
        template: `<div>
                <strong>错误提示:</strong>
                <slot>默认内容</slot>
                </div>`,
      });

      // vue实例对象--父组件
      var vm = new Vue({
        el: '.box',
        data: {},
      });
    </script>
2.具名插槽 (重点)

具名插槽的两种使用情况:
(1)在项目中,想要给组件库中的组件,添加一些 自定义内容,组件本身会提供相应的 具名插槽 ,我们只需要使用插槽填充内容即可。
(2)对于自己写的组件,我们需要在子组件预留插槽位置,然后父组件调用时给插槽填充内容。

① 在子组件的 template 模板中,可以给 插槽<slot>标签 添加名字。

<slot name="名字"> </slot>

② 在父组件中调用子组件时,可以在标签内部 添加任意标签,并给这些标签添加slot名字后,标签内的内容就会被传递给子组件对应的具名插槽。

<child>
 <p slot="名字"> 传递的内容 </p>
</child>

③ 如果想给一个具名插槽添加 多个标签的内容 的话,使用 <template>标签 包裹。

<child>
  <template slot="名字">
    <p> 传递的内容1 </p>
    <span>传递内容2</span>
  </template>
</child>

如果使用 template 包裹,则使用插槽时,还可以用 v-slot:名称 的形式。

<template v-slot:"名字">
</template>

或者直接用 # 插槽名称

   <div class="box">
      <!-- 调用子组件,给插槽传递内容 -->
      <child>
        <p slot="header">放在header插槽中的内容</p>
        <p>放在无名插槽中的内容</p>
        <p slot="footer">放在footer插槽中的内容</p>
      </child>
<template slot="名字">
    <p> 传递的内容1 </p>
    <span>传递内容2</span>
  </template>
      <!-- 调用子组件,给每个插槽传递多个内容  -->
      <child>
        <template slot="header">
          <p>放在header插槽中的内容1</p>
          <p>放在header插槽中的内容2</p>
        </template>
        <template>
          <p>放在无名插槽中的内容1</p>
          <p>放在无名插槽中的内容2</p>
        </template>
        <template slot="footer">
          <p>放在footer插槽中的内容1</p>
          <p>放在footer插槽中的内容2</p>
        </template>
      </child>
    </div>

    <script src="./vue.js"></script>

    <script>
      // 子组件
      Vue.component('child', {
        template: `<div>
                <header>
                    <slot name="header"></slot>
                </header>
                <main>
                    <slot></slot>
                </main>
                <footer>
                    <slot name="footer"></slot>
                </footer>
                </div>`,
      });

      // vue实例对象--父组件
      var vm = new Vue({
        el: '.box',
        data: {},
      });
    </script>
3. 作用域插槽 (slot-scope)
  • 父组件获取到子组件的数据,并加工处理。
  • 当我们希望子组件的样式由外部使用组件的地方定义,因为可能有多种地方要使用该组件,但样式希望不一样 这个时候我们需要使用作用域插槽。

① 父组件通过 绑定属性 向子组件传递数据。
② 子组件在 template 模板中使用数据时,提供一个 作用域插槽。并给插槽绑定自定义属性。属性名是自定义的 info,属性值时要操作的数据 item

<li :key='item.id' v-for='item in list'>
   <slot v-bind:info='item'>{{item.name}}</slot>
</li>

③ 父组件调用子组件时,在标签内添加 <template slot-scope='自定义名称'>标签。
并添加 slot-scope属性,属性值是 自定义的 slotProps。通过 slotProps.info可以获得子组件的数据item。

<template slot-scope='slotProps'>
<strong v-if='slotProps.info.id==3' class="current">
{{slotProps.info.name}}
</strong>
</template>

   <div class="box">
      <!-- 调用子组件 -->
      <child v-bind:star="star">
        <!-- template模板 -->
        <template slot-scope="slotProps">
          <span v-if="slotProps.info.id==2" class="current"
            >{{slotProps.info.name}}</span
          >
          <span v-else>{{slotProps.info.name}}</span>
        </template>
      </child>
    </div>

    <script src="./vue.js"></script>

    <script>
      // 子组件
      Vue.component('child', {
        props: ['star'],
        template: `<div>
            <ul>
                <li v-for="item in star">
                <slot v-bind:info="item">{{item.name}}</slot>    
                </li>
            </ul>
        </div>`,
      });

      // vue实例对象--父组件
      var vm = new Vue({
        el: '.box',
        data: {
          star: [
            { id: 1, name: '吴磊' },
            { id: 2, name: '王祖贤' },
            { id: 3, name: '吴彦祖' },
          ],
        },
      });
    </script>
4. 项目中使用作用域插槽 (重点)

(1)使用场景:
和具名插槽一样,如果使用的是组件库提供的组件,它内部已经预留好了作用域插槽的位置,我们只需要使用插槽填充内容即可。

(2)使用说明:
在项目中,当 v-for循环数据 进行渲染页面时(某些组件默认具有循环渲染的功能),有些地方不是直接把数据丢到标签里,就能渲染出我们想要的样式,此时,我们就添加一个 <template> 标签作为对作用域插槽的调用。<template>标签既可以自定义HTML结构,也可以获取到 当前循环项 的数据。

(3)例如:
① ElementUI组件库中提供的 表格组件,给table表格绑定了 v-bind:data 属性后,就可以使用 data数组 中的数据进行渲染HTML页面了。

② 但是数据中的 level 是一个数字,而我们想要的效果是一个tag按钮。此时,可以使用<template>标签绑定作用域插槽 slot-scope="scope",其最主要的作用是:可以通过 scope.row 拿到当前循环项的数据对象。

     <el-table :data="rightsList" border stripe>
          <el-table-column type="index" ></el-table-column>
          <el-table-column label="" prop="authName"></el-table-column>
          <el-table-column label="" prop="path"></el-table-column>
          <el-table-column label="" prop="level">
              <template slot-scope="scope">
                  <div>{{scope.row}}</div>
              </template>
          </el-table-column>
      </el-table>

③ 也可以在调用插槽时绑定解构后的数据,如 slot-scope="{row}",此时,row就是当前循环项的数据对象。

总结

  1. 不使用组件库的组件时,我们给标签添加 v-for="(item,index) in array,来循环渲染数据。此时,可以通过 item 很方便地获取到 每个循环项的信息

  2. 使用了组件库提供的组件模板后,很多组件会默认具有循环渲染的功能,不需要我们用 v-for 绑定标签。此时,我们就借助 作用域插槽模板 ,来获取 每个循环项的信息

  3. 父组件向子组件传值,或者从vuex中映射过来的数据和方法,
    在代码中 都要加 this 使用。用 import 导入的方法则不需要用 this
    而在template模板中使用数据都 不能加this

  4. js 文件必须导入 vuex 模块后才能使用其中的数据。组件可以直接 this.$store调用、或是映射vuex中的数据和方法。

  5. 组件模板中的数据只能使用data 或 父组件传递的 props 或 路由规则传递的静态参数。如果用import 导入了一些数据,必须先引入到data中,才能在模板中使用。

  6. 单文件组件,可以根据 路由 形成组件的父子关系。路由链接、路由占位符、路由组件、路由规则 必不可少。
    也可以直接在父组件内 导入、注册、调用 子组件。

  7. 组件的重用:父组件调用子组件,传递一些必要数据;子组件接收数据,根据这些数据,在组件内部发起Ajax请求,获取渲染页面所需要的数据,并渲染页面。
    由于每个父组件重用子组件时传递的必要数据不相同,所以渲染出来的子组件也不同。

  8. ref可以获取到元素的DOM对象;如果ref作用在 组件上(自定义组件或者组件库的组件)时,可以得到该组件的 实例,也就是 this

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,525评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,203评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,862评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,728评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,743评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,590评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,330评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,244评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,693评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,885评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,001评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,723评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,343评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,919评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,042评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,191评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,955评论 2 355

推荐阅读更多精彩内容