Vue基本使用

vue的安装
  1. CDN引入
    开发环境版本,包含了有帮助的命令行警告
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    生产环境版本,优化了尺寸和速度
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>

  2. 方式二:下载和引入
    开发版本:https://cn.vuejs.org/js/vue.js
    生产版本:https://cn.vuejs.org/js/vue.min.js

  3. 方式三:NPM安装
    $ npm install vue

  • vue实例传入的options
    el:
    类型:string | HTMLElement
    作用:决定之后Vue实例会管理哪一个DOM
    data:
    类型:Object | Function(组件中data必须是一个函数)
    作用:Vue实例对应的数据对象
    methods
    类型:{[key:string]:Function}
    作用:定义属于Vue的一些方法,可以在其他地方调用,也可以在指令中使用
数据传递
  • 数据的单向传递
    把数据交给vue实例对象,实例对象将数据交给界面
<div id="box1">
    {{ message }}
    <p></p>
</div>

<script>
    // 创建一个vue实例
    let box = new Vue({
        // vue作用域
        el: "#box1",
        // 作用域的数据
        data: {
            message: "Hello Vue"
        }
    })
</script>
常用指令
  • v-once
    只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
<div id="box1">
    <p v-once>原始数据:{{ message1 }}</p>
    <p>当前数据:{{ message1 }}</p>
</div>
<script>
    let vue1 = new Vue({
        el: "#box1",
        data: {
            message1: "test111"
        }
    })
    // 原始数据不会变化
    vue1.message1 = '6666666'
</script>
  • v-html
    更新元素的 innerHTML。注意:内容按普通 HTML 插入 - 不会作为 Vue 模板进行编译。
    会按照html格式进行解析。
<div id="app">
  <h2 v-html="url"></h2>
</div>
<script>
  let app = new Vue({
    el: "#app",
    data: {
      url: "<a href='https://www.baidu.com'>百度一下</a>"
    }
  })
  • v-text
    更新元素的 textContent。如果要更新部分的 textContent,需要使用 {{ Mustache }} 插值。很少用
<div id="app">
  <h2>{{message}}</h2>
  <h2 v-text="message"></h2>
</div>
<script>
  // 更新元素的 textContent。如果要更新部分的 textContent,需要使用 {{ Mustache }} 插值。
  let app = new Vue({
    el: "#app",
    data: {
      message: "hello"
    }
  })
</script>
  • v-pre
    跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
<div id="app">
  <h2>{{message}}</h2>
  <h2 v-pre>{{message}}</h2>
</div>
<script>
  // 第一个h2标签,显示hello
  // 第二个h2标签,显示{{message}}
  let app = new Vue({
    el: "#app",
    data: {
      message: "hello"
    }
  })
</script>
  • v-cloak
    某些情况,浏览器可能会直接显示未编译Mustache标签,可以使用 v-cloak 指令来解决这一问题。需要配合css使用。
    这个指令保持在元素上直到关联实例结束编译。和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。
<style type="text/css">
<!--    属性选择器-->
    [v-cloak] {
        display: none;
    }
</style>

<div id="box2">
    <p v-cloak>{{ message2 }}</p>
</div>

<script>
    let vue2 = new Vue({
        el: "#box2",
        data: {
            message2: "test clock"
        }
    })
  • v-bind
    想要给元素绑定数据,可以使用{{}} v-text v-html,
    如果想给元素的属性绑定数据,只能使用v-bind。

v-bind:属性名称="绑定的数据"
:属性名称="绑定的数据"

赋值的数据可以是任意合法的js表达式。

  1. 绑定属性
<div id="box2">
    <input type="text" v-bind:value="name">
    <input type="text" :value="age">
    <input type="text" :value="age + 1">
</div>
<script>
    let vue2 = new Vue({
        el: '#box2',
        data: {
            name: '我是v-bind',
            age: 18
        }
    })
</script>
  1. 绑定类名
    v-bind绑定class注意事项:
    (1) 类名要放到{}或[]中;
    (2) 类名要加引号;
    (3) 绑定类名时,可以使用三目运算符实现按需绑定;
    (4) 绑定类名时,可以通过对象来决定是否需要绑定;
  <style>
    .active {
      color: red;
    }
    .bgColor {
      background-color: darkorange;
    }
    .largeSize {
      font-size: 30px;
    }
  </style>

<body>
<div id="app">
  <!--
  <div :class="{classA: isTrue }"></div>
  <div :class="[classA, classB]"></div>
  <div :class="[classA, { classB: isB, classC: isC }]">
  -->
<!--  对象语法 用的较多-->
  <p v-bind:class="{'active': isActive, 'bgColor': isBg}">{{message}}</p>
  <p v-bind:class="getClasses()">{{message}}</p>
<!--  数组语法-->
  <p v-bind:class="['largeSize', 'active']">{{message}}</p>
  <p v-bind:class="['largeSize', {'active': isActive}]">{{message}}</p>
</div>

<script>
  let app = new Vue({
    el: "#app",
    data: {
      message: "hello",
      isActive: true,
      isBg: true
    },
    methods: {
      getClasses: function () {
        return {'active': this.isActive, 'bgColor': this.isBg}
      }
    }
  })
</script>
  1. 绑定样式
    v-bind绑定style注意事项:
    (1) 将样式代码赋值到对象中,给style属性赋值,取值必须用引号;
    (2) 样式如果带'-',也必须用引号,如'font-size',没有'-'的style属性也可以加引号;
<div id="app">
<!--  对象语法-->
  <p :style="{color: 'green'}">{{message}}</p>
  <p :style="{color: 'yellow', 'fond-size': '30px'}">{{message}}</p>
  <p :style="{'color': 'aqua', 'fond-size': '20px'}">{{message}}</p>
  <p :style="obj">v-bind绑定style,通过model中的对象</p>
  <p :style="addStyle()">v-bind绑定style,通过model中的对象</p>

<!--  数组语法-->
  <p :style="[{'color': 'red'}, {'fond-size': '20px'}]">{{message}}</p>
</div>
<script>
  let vue2 = new Vue({
    el: '#app',
    data: {
      message: "hello",
      obj: {
        color: 'chocolate',
        size: '40px'
      }
    },
    methods: {
      addStyle: function () {
        return this.obj
      }
    }
  })
</script>
  • 计算属性
  1. 基本使用
    只要返回的结果没有变化,计算属性只会被执行一次。
<div id="app">
<!--  显示名字全称 中间空格隔开-->
  <h2>{{firstName + ' ' + lastName}}</h2>
  <h2>{{firstName}} {{lastName}}</h2>
  <h2>{{getFullName()}}</h2>
<!--  计算属性方式-->
  <h2>{{fullName}}</h2>
</div>
<script>
  let app = new Vue({
    el: "#app",
    data: {
      firstName: "Li",
      lastName: "xiaolong"
    },
    computed: {
      fullName: function () {
        return this.firstName + " " + this.lastName
      }
    },
    methods: {
      getFullName: function () {
        return this.firstName + " " + this.lastName
      }
    }
  })
</script>
  1. 计算属性的复杂操作
<div id="app">总价格:{{totalPrice}}</div>
<script>
  let app = new Vue({
    el: "#app",
    data: {
      books: [
        {id: 110, name: '代码大全',price: 105},
        {id: 111, name: '深入理解计算机原理', price: 98},
        {id: 112, name: '现代操作系统', price: 87}
      ]
    },
    computed: {
      totalPrice: function () {
        totalPrice = 0;
        // for (let i = 0; i < this.books.length; i++){
        //   totalPrice += this.books[i]['price']
        // }
        // ES6语法
        // for (let i in this.books) {
        //   totalPrice += this.books[i]['price']
        // }
        for (let book of this.books){
          totalPrice += book['price']
        }
        return totalPrice
      }
    }
  })

  movies = ['海贼王', '名侦探柯南', '火影忍者']
  for (let i = 0; i < movies.length; i++){
    console.log(movies[i])
  }
  // ES6语法一
  for (let i in movies){
    console.log(movies[i])
  }
  // ES6语法二
  for (let item of movies){
    console.log(item)
  }
</script>
  1. 计算属性setter和getter
<script>
/* 每个计算属性都包含一个getter和一个setter方法(setter不常用)*/
  let app = new Vue({
    el: "#app",
    data: {
      firstName: "wang",
      lastName: "xiaolan"
    },
    computed: {
      fullName: {
        set: function (name) {
          const names = name.split(' ');
          this.firstName = names.length > 0 ? names[0] : '';
          this.lastName = names.length > 1 ? names[1] : '';
        },
        get: function () {
          return this.firstName + ' ' + this.lastName;
        }
      }
    }
  })
</script>
  • v-on
  1. v-on的使用
    作用:绑定事件监听器
    缩写:@
    预期:Function | Inline Statement | Object
    参数:event
<div id="app">
  <h2>{{counter}}</h2>
  <button v-on:click="increment">+</button>
  <button @click="decrement">-</button>
</div>

<script>
  let app = new Vue({
    el: '#app',
    data: {
      counter: 0
    },
    methods: {
      increment() {
        this.counter ++;
      },
      decrement() {
        this.counter --;
      }
    }
  })
</script>
  1. v-on参数
    如果调用的方法不需要额外参数,那么方法后的()可以不添加,如果方法本身有一个参数,那么会默认将原生事件event参数传递进去
    如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件
<!--  事件调用的方法没有参数-->
  <button @click="btn1Click()">按钮1</button>
  <button @click="btn1Click">按钮1</button>
<!--  写函数时省略了(),但是方法本身需要一个参数-->
  <button @click="btn2Click('test')">按钮2</button> <!-- btn2Click:  test-->
  <button @click="btn2Click()">按钮2</button>   <!-- btn2Click:  undefined-->
  <button @click="btn2Click">按钮2</button>     <!-- btn2Click:  MouseEvent…-->

  <button @click="btn3Click()">按钮3</button>   <!-- btn3Click:  undefined MouseEvent...-->
  <button @click="btn3Click">按钮3</button>     <!-- btn3Click:  MouseEvent... MouseEvent...-->
  <button @click="btn3Click('test')">按钮3</button>   <!-- btn3Click:  test MouseEvent...-->
  <button @click="btn3Click('test', $event)">按钮3</button> <!-- btn3Click:  test MouseEvent...-->
</div>
<script>
  let app = new Vue({
    el: '#app',
    data: {
      counter: 0
    },
    methods: {
      increment() {
        this.counter ++;
      },
      decrement() {
        this.counter --;
      },
      btn1Click() {
        console.log('btn1Click');
      },
      btn2Click(a) {
        console.log('btn2Click: ', a);
      },
      btn3Click(a, event) {
        console.log('btn3Click: ', a, event);
      }
    }
  })
</script>
  1. v-on的修饰符
    .once - 只触发一次回调
    .prevent - 调用 event.preventDefault() ,阻止默认行为
    .self - 只有当前元素本身触发事件时,才执行回调函数
    .stop - 调用 event.stopPropagation(),阻止事件冒泡
    .capture - 添加事件侦听器时使用 capture 模式
    .native - 监听组件根元素的原生事件
    .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调
<div id="app">
<!--  .stop - 阻止事件冒泡-->
  <div @click="divClick">aaaaaaaaa
    <button @click.stop="btnClick">按钮</button>
  </div>

<!--  .prevent - 阻止默认事件-->
  <form action="...">
    <input type="submit" value="提交" @click.prevent="submitClick">
  </form>

<!-- .{keyCode | keyAlias} 监听键盘某个键帽 -->
  <input type="text" @keyup.enter="keyup">

<!--  .once - 只触发一次回调-->
  <button @click.once="btn2Click">按钮2</button>
</div>
<script>
  let app = new Vue({
    el: '#app',
    data: {

    },
    methods: {
      divClick() {
        console.log('divClick');
      },
      btnClick() {
        console.log('btnClick');
      },
      submitClick() {
        console.log('submitClick');
      },
      keyup() {
        console.log('keyup');
      },
      btn2Click() {
        console.log('btn2Click');
      }
    }
  })
</script>
  • v-if
    如果取值是true就渲染元素,否则就不渲染元素。(如果条件不满足,不会创建这个元素)
    v-if 可以从模型中获取元素,也可以直接赋值一个表达式。
    v-else 前面必须有 v-if 或者 v-else-if ;
    v-if 和 v-else 中间不能插入其它内容;
  <div v-if='isShow'>
    <h2>abc</h2>
    <p>abc</p>
    <div>abc</div>
  </div>
  <h2 v-else>isShow为false时,显示</h2>

  <p v-if="score>=90">优秀</p>
  <p v-else-if="score>=80">良好</p>
  <p v-else-if="score>=60">及格</p>
  <p v-else>不及格</p>
</div>
<script>
  let app = new Vue({
    el: '#app',
    data: {
     isShow: true,
      score: 88
    }
  })
</script>
  • v-show
    如果取值是true就渲染元素,否则就不渲染元素。
    v-if 和 v-show 区别:
    v-if: 只要取值是false,就不会创建元素;
    v-show: 取值为false也会创建元素,会设置元素的display为none;

一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

  • v-for

格式:
v-for="item in movies"
v-for="(item, index) in movies"
v-for="(value, key) in obj"

官方推荐在使用v-for时,给对应的元素或组件添加上一个:key属性
key的作用主要是为了高效的更新虚拟DOM

    <div id="app">
        <ul>
            <li v-for="item in movies">{{item}}</li>
        </ul>
        <br><br>
        <ul>
            <li v-for="(item, index) in movies">{{index}}----------{{item}}</li>
        </ul>
        <br><br>
        <ul>
            <li v-for="(value, key) in obj">{{key}}----------{{value}}</li>
        </ul>

        <ul>
            <li v-for="item in letters" :key="item">{{item}}</li>
        </ul>
    </div>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                message: 'hello vue!',
                movies: ['姜子牙', '急先锋', '流浪地球', '极速车神'],
                obj: {
                    name: 'xiaolan',
                    age: 13
                },
                letters: ['A', 'B', 'C', 'D', 'E']
            }
        })
        // 在最后插入
        app.movies.push('盗梦空间')
        // 在第二个元素急先锋后插入
        app.movies.splice(2, 0, '少年的你')
        // B后面插入F
        app.letters.splice(2, 0, 'F')
    </script>
  • v-model
    可以用 v-model 指令在表单 <input>、<textarea> 及 <select> 元素上创建双向数据绑定。
    v-model其实是一个语法糖,它的背后本质上是包含两个操作:
    1.v-bind绑定一个value属性
    2.v-on指令给当前元素绑定input事件
<div id="box2">
    <input type="text" v-model="text_message" placeholder="填写内容">
    <p>Message is: {{ text_message }}</p>
</div>
<script>
    let box2 = new Vue({
        el: "#box2",
        data: {
            text_message: ''
        }
    })
</script>
  • v-model结合radio使用
<div id="app">
  <label for="male">
    <input type="radio" id="male" name="sex" value="男" v-model="sex">男
  </label>
  <label for="female">
    <input type="radio" id="female" name="sex" value="女" v-model="sex">女
  </label>
  <h2>您选择的性别是:{{sex}}</h2>
</div>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      sex: '男'
    }
  })

</script>
  • v-model结合checkbox使用
<div id="app">
  <!--  1.checkbox单选框-->
  <h1>checkbox单选框</h1>
  <label for="agree">
    <input type="checkbox" id="agree" v-model="isAgree">同意协议
  </label>
  <h2>您选择的是:{{isAgree}}</h2>
  <button :disabled="!isAgree">下一步</button>

  <!--  2.checkbox多选框-->
  <h1>checkbox多选框</h1>
  <input type="checkbox" value="篮球" v-model="hobbies">篮球
  <input type="checkbox" value="打游戏" v-model="hobbies">打游戏
  <input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球
  <input type="checkbox" value="足球" v-model="hobbies">足球
  <h2>选择的爱好是:{{hobbies}}</h2>
</div>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      isAgree: false,
      hobbies: []
    }
  })
</script>
  • v-model修饰符
    1.修饰符:lazy
    默认情况下,v-model默认是在input事件中同步输入框的数据的,一旦数据发生改变,对应的data中的数据就会自动发生改变;
    lazy修饰符可以让数据在失去焦点或回车时才会更新;

    2.修饰符:number
    默认情况下,在输入框中无论我们输入的是字母还是数字们都会被当做字符串类型进行处理;
    number修饰符可以将输入框中输入的内容自动转成数字类型;

    3.修饰符:trim
    trim修饰符可以去除内容左右两边的空格

  • 过滤器
    过滤器一般用来格式化插入的文本数据。
    使用过滤器格式:
    {{ message | filterA }}
    {{ message | filterA | filterB }}
    {{ message | filterA('arg1', arg2) }}

<div id="app">
  <h2>保留两位小数:{{price | showPrice}}</h2>
</div>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      price: 35
    },
    filters: {
      showPrice(price) {
        return '¥' + price.toFixed(2);
      }
    }
  })
</script>

利用过滤器对时间进行格式化

    <div id="time">
        <p>{{time_date | dataFormart}}</p>
    </div>
    <script>
        Vue.filter('dataFormart', function (value) {
            let date = new Date(value);
            let year = date.getFullYear() + '';
            let month = date.getMonth() + 1 + '';
            let day = date.getDate() + '';
            let hour = date.getHours() + '';
            let minute = date.getMinutes() + '';
            let second = date.getSeconds() + '';
            return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '')} ${hour.padStart(2, '0')}:${minute.padStart(2, '0')}:${second.padStart(2,'0')}`;
        });
        let vue2 = new Vue({
            el: '#time',
            data: {
                time_date: 1601673785000
            }
        })
    </script>
  • 自定义全局指令
    除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。
  1. 语法
    1.1 全局自定义指令:
    在任何一个Vue实例控制的区域中都可以使用。
Vue.directives('自定义指令名称', {
  生命周期名称: function (el) {
    指令逻辑代码
  }
})

 1.2. 局部指令:
只能在自定义的那个Vue实例中使用

directives: {
  自定义指令名称: {
    生命周期名称: function (el) {
      指令逻辑代码
    }
  }
}
  1. 指令生命周期方法
    自定义指令时一定要明确指令的业务逻辑代码更合适在哪个阶段执行
    例如:指令逻辑代码中没有用到元素事件,那么可以在bind阶段执行
    例如:指令逻辑代码中用到了元素事件,那么就需要在inserted阶段执行
  2. 自定义指令注意点
    使用时需要加上v-,而在自定义时不需要加v-;
    <div id="box1">
        <p v-red>测试red全局自定义指令</p>
        <p v-blue>测试blue局部自定义指令</p>
<!--    input被渲染出来后,就被选中-->
        <input type="text" v-focus>
    </div>

    <script>
        /*
        第一个参数:指令名称
        第二个参数:对象
        bind:指令被绑定到元素上的时候执行
        inserted:绑定指令的元素被添加到父元素上的时候调用
         */
        Vue.directive('red', {
            bind: function (el) {
                el.style.color = 'red';
            }
        });
        let vue1 = new Vue({
            el: '#box1',
            directives: {
                blue: {
                    bind: function (el) {
                        el.style.color = 'blue';
                    }
                },
                focus: {
                    inserted: function (el) {
                        el.focus();
                    }
                }
            }
        })
    </script>
  1. 自定义指令传参
    <div id="box2">
        <p v-color="'green'">自定义指令传参</p>
        <p v-color="pinkColor">自定义指令传参取data数据</p>
    </div>
    <script>
        let vue2 = new Vue({
            el: '#box2',
            data: {
              pinkColor: 'pink'
            },
            directives: {
                color: {
                    bind: function (el, color) {
                        el.style.color = color.value;
                    }
                }
            }
        })
    </script>
  • 过渡动画
  1. 给vue添加过渡动画
    1.1 将要执行动画的元素放到transaction组件中;
    1.2 当transaction中的元素显示时,会自动查找 .v-enter/ .v-enter-active/ .v-enter-to类名
    当transaction中的元素隐藏时,会自动查找 .v-leave/ .v-leave-active/ .v-leave-to类名
    1.3 只需在.v-enter/ ..v-leave-to中指定动画开始的状态
    在.v-enter-active / .v-leave-active中指定动画执行的状态
    即可完成过渡动画。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343