学习vue后,容易遗忘的知识点

1. 指令语法的简写、完整写法和注意事项

因为项目中大多用简写,所以完整写法一般很少见到,
尤其是双向绑定,见到完整写法后才知道实际绑定到value属性上面。

1.1. 单向绑定(v-bind)

完整写法:v-bind:href="xxx"
简写::href="xxx"

1.2. 双向绑定(v-model)

完整写法:v-model:value="xxx"
简写:v-model="xxx"

1.3. 监听事件(v-on)

完整写法:v-on:click="xxx"
简写:@click="xxx"

注意事项:

<a :[attributeName]="url"> ... </a>
<a @[eventName]="doSomething">
  • v-model 只能绑定表单元素或组件
    v-model 会忽略任何表单元素上初始的 value、checked 或 selected attribute。它将始终将当前绑定的 JavaScript 状态视为数据的正确来源。你应该在 JavaScript 中使用data 选项来声明该初始值。

  • v-on 绑定方法时,如果既想要event事件参数,还想手动传一些参数,可以使用如下写法

<!-- 使用特殊的 $event 变量 -->
<button @click="warn('Form cannot be submitted yet.', $event)">
  Submit
</button>

<!-- 使用内联箭头函数 -->
<button @click="(event) => warn('Form cannot be submitted yet.', event)">
  Submit
</button>




2. 双向绑定修饰符

可以再v-model后加修饰符,简化开发

2.1. 修饰符 .lazy

在输入框上绑定v-model时,默认是在每次input事件后更新数据,加.lazy后会变成每次change事件后更新数据

<input v-model.lazy="msg" />

2.2. 修饰符 .number

如果你想让用户输入自动转换为数字,你可以在 v-model 后添加 .number 修饰符来管理输入

<input v-model.number="age" />

2.3. 修饰符 .trim

如果你想要默认自动去除用户输入内容中两端的空格,你可以在 v-model 后添加 .trim 修饰符

<input v-model.trim="msg" />




3. 监听事件修饰符

可以再v-on后加修饰符,简化开发

3.1. 修饰符 .stop

阻止事件冒泡

<!-- 单击事件将停止传递 -->
<a @click.stop="doThis"></a>

3.2. 修饰符 .prevent

阻止浏览器的默认事件

<!-- 提交事件将不再重新加载页面 -->
<form @submit.prevent="onSubmit"></form>

3.3. 修饰符 .self

只有触发事件元素为绑定事件元素本身时才有效,不处理冒泡的事件

<!-- 仅当 event.target 是元素本身时才会触发事件处理器 -->
<!-- 例如:事件处理器不来自子元素 -->
<div @click.self="doThat">...</div>

3.4. 修饰符 .native

.native事件修饰符是用来在父组件中给子组件[自定义组件]绑定一个原生的事件,就将子组件变成了普通的HTML标签看待。

<!-- 给Demo组件的根节点绑定click事件 -->
<Demo @click.native="doThat">...</Demo>

3.5. 修饰符 .capture

事件的阶段顺序是:外层捕获、内层捕获、内层冒泡、外层冒泡
v-on默认是冒泡阶段处理事件,加 .capture 后改为捕获阶段处理事件

<!-- 添加事件监听器时,使用 `capture` 捕获模式 -->
<!-- 例如:指向内部元素的事件,在被内部元素处理前,先被外部处理 -->
<div @click.capture="doThis">...</div>

3.6. 修饰符 .once

只能触发一次事件

<!-- 点击事件最多被触发一次 -->
<a @click.once="doThis"></a>

3.7. 修饰符 .passive

【浏览器只有等内核线程执行到事件监听器对应的JavaScript代码时,才能知道内部是否会调用preventDefault函数来阻止事件的默认行为,所以浏览器本身是没有办法对这种场景进行优化的。这种场景下,用户的手势事件无法快速产生,会导致页面无法快速执行滑动逻辑,从而让用户感觉到页面卡顿。】

通俗点说就是每次事件产生,浏览器都会去查询一下是否有preventDefault阻止该次事件的默认动作。我们加上passive就是为了告诉浏览器,不用查询了,我们没用preventDefault阻止默认动作。

这里一般用在滚动监听,@scoll,@touchmove 。因为滚动监听过程中,移动每个像素都会产生一次事件,每次都使用内核线程查询prevent会使滑动卡顿。我们通过passive将内核线程查询跳过,可以大大提升滑动的流畅度。

<!-- 滚动事件的默认行为 (scrolling) 将立即发生而非等待 `onScroll` 完成 -->
<!-- 以防其中包含 `event.preventDefault()` -->
<div @scroll.passive="onScroll">...</div>

注意事项:

  • 修饰语可以使用链式书写,也可以只有修饰符
<!-- 修饰语可以使用链式书写 -->
<a @click.stop.prevent="doThat"></a>

<!-- 也可以只有修饰符 -->
<form @submit.prevent></form>
  • 使用修饰符时需要注意调用顺序,因为相关代码是以相同的顺序生成的。
    因此使用 @click.prevent.self 会阻止元素及其子元素的所有点击事件的默认行为。
    而 @click.self.prevent 则只会阻止对元素本身的点击事件的默认行为。

  • 请勿同时使用 .passive 和 .prevent,因为 .passive 已经向浏览器表明了你不想阻止事件的默认行为。
    如果你这么做了,则 .prevent 会被忽略,并且浏览器会抛出警告。




4. 绑定class和style

4.1. 对象方式绑定class

<!-- 对象的key为class名,value为布尔值,为true时绑定class,为false时不绑定class -->
<div :class="{ active: isActive, 'text-danger': hasError }"></div>

4.2. 数组方式绑定class

<!-- 固定的class -->
<div :class="['abc-class', 'def-class']"></div>
<!-- 动态的class -->
<div :class="[activeClass, errorClass]"></div>
<!-- 数组中有条件地渲染某个 class,你可以使用三元表达式 -->
<div :class="[isActive ? activeClass : '', errorClass]"></div>
<!-- 也可以在数组中嵌套对象 -->
<div :class="[{ active: isActive }, errorClass]"></div>
<!-- 自定义组件上也可以绑定class,class会绑定到该组件的根元素上,与该元素上已有的class合并 -->
<MyComponent :class="{ active: isActive }" />

4.3. 对象方式绑定style

<!-- 按照json格式写样式,例如font-size这种样式则属性名写为fontSize -->
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
<!-- 样式多值时写法 -->
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>

4.4. 数组方式绑定style

<!-- 数组内是对象,对象写法见对象方式绑定style -->
<div :style="[baseStyles, overridingStyles]"></div>

注意事项:

  • vue会合并我们写的class和style,所以可以同时写普通标签和单向绑定
<div
  class="static"
  :class="{ active: isActive, 'text-danger': hasError }"
></div>
  • 组件内可以通过 $attrs.class 获取当前组件所绑定的class,例:
<!-- Test组件模板内容 -->
<template>
    <Hello class="hello-class"></Hello>
</template>

<!-- Hello组件模板内容 -->
<template>
    <div>
        <div :class="$attrs.class">测试</div>
    </div>
</template>




5. 过滤器

5.1. 在组件的选项中定义本地的过滤器

export default {
    name: 'Test',
    data: {
      return {
        mesg: '你好'
      }
    },
    filters: {
      // 把首字母转为大写的过滤器
      capitalize(str) {
         return str.charAt(0).toUpperCase() + str.slice(1)
      }
    }
}

5.2. 定义全局过滤器

// 全局过滤器 - 独立于每个vm实例之外,用Vue.filter()方法定义
// Vue.filter()有两个参数,第一个参数是过滤器的名字,第二个参数是过滤器的处理函数
Vue.filter('capitalize', (str) => {
  return str.chatAt(0).toUpperCase() + str.slice(1)
})

5.3. 使用过滤器

<!-- 在{{}}中通过“管道符”调用 capitalize 过滤器,对 message 的值进行格式化-->
<p>{{message | capitalize}}</p>

<!-- 在v-bind中通过管道符 调用 formatId 过滤器,对 rawId 的值进行格式化-->
<div v-bind:id="rawId | farmatId"></div>

注意事项:

  • 过滤器传参
<!-- arg1 和 arg2 是传递给 filterA 的参数-->
<p>{{ message | filterA(arg1,arg2) }}</p>

// 过滤器处理函数中的形参列表中:
// 第一个参数:永远都是“管道符”前面待处理的值
// 第二个参数开始: 才是调用过滤器时传递过来的 arg1 和 arg2 参数
Vue.filter('filterA', (meg, arg1, arg2) => {
  // 过滤器的处理逻辑
})
  • 过滤器可链式调用,执行顺序为从左到右
<div v-bind:id="rawId | farmatId | capitalize"></div>




6. 自定义指令

6.1. 注册一个全局自定义指令

// 注册一个全局自定义指令 v-focus
Vue.directive('focus', {
  // 当绑定元素插入到 DOM 中。
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

6.2 指令钩子

const myDirective = {
  // 在绑定元素的 attribute 前
  // 或事件监听器应用前调用
  created(el, binding, vnode, prevVnode) {},
  // 在元素被插入到 DOM 前调用
  beforeMount(el, binding, vnode, prevVnode) {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都挂载完成后调用
  mounted(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件更新前调用
  beforeUpdate(el, binding, vnode, prevVnode) {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都更新后调用
  updated(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件卸载前调用
  beforeUnmount(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件卸载后调用
  unmounted(el, binding, vnode, prevVnode) {}
}

Vue.directive('directive', myDirective)
image.png




7. ref获取组件对象(VueComponent)或DOM节点

一般我们用ref是获取组件对象,但ref还可以获取DOM节点,这样就不需要使用“document.getElementById(id)”获取DOM节点了

<!-- ref 用于给节点打标识 -->
<a ref="testA" />
// 获取组件对象(VueComponent)或DOM节点
this.$refs.testA
this.$refs.['testA']




8. Mixin混入

混入 (mixins)定义了一部分可复用的方法或者计算属性。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。
例:创建一个MyMixin.js

export const myMixin = {
  data(){
    return {
      mesg: '我的混入',
    }
  },
  created() {
    console.log('mixin 对象的钩子被调用')
  }
}

使用MyMixin.js

import { MyMixin } from '@/mixins/MyMixin'
export default {
  name: 'Hello',
  mixins: [MyMixin],
  data () {
    return {
    }
  },
  created() {
    console.log('组件钩子被调用')
  }
}

注意事项:

  • vue会将混入的js和vue组件的配置项做合并,当属性名或方法名(不包含生命周期钩子函数)冲突时,以vue组件定义的为准。
    生命周期钩子函数是全都生效的,例如混入的js和vue组件都写了created方法,会先执行混入js的created方法,再执行vue组件的created方法。




9. 插件

插件 (Plugins) 是一种能为 Vue 添加全局功能的工具代码。
插件一般是封装了很多对Vue的配置,例如全局过滤器、全局自定义指令、通用变量和方法等...


例:创建一个Plugins.js

export default {
        // 使用插件后,Vue会调用此方法
    install(Vue, x, y, z) {
        console.log(x, y, z)
        // 全局过滤器
        Vue.filter('mySlice', function (value) {
            return value.slice(0, 4)
        })
        // 定义全局指令
        Vue.directive('fbind', {
            // 指令与元素成功绑定时(一上来)
            bind(element, binding) {
                element.value = binding.value
            },
            // 指令所在元素被插入页面时
            inserted(element, binding) {
                element.focus()
            },
            // 指令所在的模板被重新解析时
            update(element, binding) {
                element.value = binding.value
            }
        })
        // 定义混入
        Vue.mixin({
            data() {
                return {
                    x: 100,
                    y: 200
                }
            },
        })
        // 给Vue原型上添加一个方法(vm和vc就都能用了)
        Vue.prototype.hello = () => { alert('你好啊') }
    }
}

使用Plugins.js

// 引入Vue
import Vue from 'vue'
// 引入插件
import Plugins from './Plugins'
// 应用(使用)插件
Vue.use(Plugins, 1, 2, 3)




10. 全局事件总线

全局事件总线就是将VM或VueComponent绑定到所有组件都能看见的位置,组件根据需要去绑定监听事件或触发监听事件。


准备工作:在main.js中绑定全局变量$bus

// 引入Vue
import Vue from 'vue'
// 引入App
import App from './App.vue'
// 关闭Vue的生产提示
Vue.config.productionTip = false

// 创建vm
new Vue({
  el: '#app',
  render: h => h(App),
  beforeCreate() {
    // 安装全局事件总线,$bus就是当前应用的vm
    Vue.prototype.$bus = this
  },
})

使用$bus

mounted() {
  // 绑定监听事件(hello)
  this.$bus.$on('hello', (data) => {
    console.log('收到了数据', data)
  })
},
beforeDestroy() {
  // 组件销毁前要解绑监听事件
  this.$bus.$off('hello')
},
methods: {
  test() {
    // 触发监听事件(hello)
    this.$bus.$emit('hello', 123)
  }
},




11. 过度与动画

Vue提供了两个标签</transition>和</transition-group>来辅助实现过度与动画效果,
标签只是实现了进场和离场动画时样式class的动态绑定,具体动画效果是需要我们自己实现的。
transition的属性:

  • name:默认进场动画class为“v-enter-active”,离场动画class为“v-leave-active”。
    绑定name后会根据name决定class名称,例name="hello",
    则进场动画class为“hello-enter-active”,离场动画class为“hello-leave-active”。
  • appear:初始时,是否播放进场动画
  • enter-active-class:指定进场动画的class,可以配合第三方样式库使用
  • leave-active-class:指定离场动画的class,可以配合第三方样式库使用

11.1 动画效果

<template>
  <div>
    <button @click="isShow = !isShow">显示/隐藏</button>
    <!-- transition 标签内只能有一个根元素,在显示/隐藏时会给这个根元素绑定对应的class -->
    <transition name="hello" appear>
      <h1 v-show="isShow">你好啊!</h1>
    </transition>
  </div>
</template>

<script>
export default {
  name: 'Test',
  data() {
    return {
      isShow: true
    }
  },
}
</script>

<style scoped>
h1 {
  background-color: orange;
}
/* 进场动画class样式,指定播放哪个动画、播放几秒、是否匀速播放 */
.hello-enter-active {
  animation: atguigu 0.5s linear;
}
/* 退场动画class样式,指定播放哪个动画、播放几秒、是否匀速播放、设置倒放 */
.hello-leave-active {
  animation: atguigu 0.5s linear reverse;
}
@keyframes atguigu {
  from {
    transform: translateX(-100%);
  }
  to {
    transform: translateX(0px);
  }
}
</style>

11.2 过度效果

<template>
  <div>
    <button @click="isShow = !isShow">显示/隐藏</button>
    <transition-group name="hello" appear>
      <h1 v-show="!isShow" key="1">你好啊!</h1>
      <h1 v-show="isShow" key="2">拜拜咯!</h1>
    </transition-group>
  </div>
</template>

<script>
export default {
  name:'Test',
  data() {
    return {
      isShow:true
    }
  },
}
</script>

<style scoped>
h1 {
  background-color: orange;
}
/* 指定播放动画的时间和匀速播放 */
.hello-enter-active, .hello-leave-active{
  transition: 0.5s linear;
}
/* 进入的起点、离开的终点 */
.hello-enter, .hello-leave-to{
  transform: translateX(-100%);
}
/* 进入的终点、离开的起点 */
.hello-enter-to, .hello-leave{
  transform: translateX(0);
}
</style>

11.3 使用 animate.css 第三方动画库实现

animate.css官网:https://animate.style/
需要先安装动画库,命令:npm install animate.css
然后在组件中引入css就可以使用class了,命令:import 'animate.css'

image.png

例:

<template>
  <div>
    <button @click="isShow = !isShow">显示/隐藏</button>
    <transition-group 
      appear
      name="animate__animated animate__bounce" 
      enter-active-class="animate__swing"
      leave-active-class="animate__backOutUp"
    >
      <h1 v-show="!isShow" key="1">你好啊!</h1>
      <h1 v-show="isShow" key="2">拜拜咯!</h1>
    </transition-group>
  </div>
</template>

<script>
import 'animate.css'
export default {
  name:'Test',
  data() {
    return {
      isShow:true
    }
  },
}
</script>

<style scoped>
h1 {
  background-color: orange;
}
</style>




12. proxy代理

  • proxy代理是解决开发环境中的跨域问题,正式环境的跨域需要使用nginx反向代理或者是后端解决。

  • 在vue中使用proxy进行跨域的原理是:将域名发送给本地的服务器(启动vue项目的服务,比如loclahost:8080),再由本地的服务器去请求真正的服务器。

  • 跨域是指请求的协议、IP、端口与浏览器当前地址栏的协议、IP、端口不一致,
    正常情况下浏览器会将此请求的返回拦截,并在控制台报出跨域的错误。
    如果请求返回中加了一些允许跨域的请求头,浏览器就不会拦截。

  • 前台在报跨域错误的时候,实际上请求已经成功访问到后台,只是浏览器将请求的返回拦截了。

12.1 vue.config.js配置proxy代理

module.exports = {
  pages: {
    index: {
      // 入口
      entry: 'src/main.js',
    },
  },
  lintOnSave:false, //关闭语法检查
  // 开启代理服务器(方式一)
  /* devServer: {
    proxy: 'http://localhost:5000'
  }, */
  // 开启代理服务器(方式二)
  devServer: {
    proxy: {
      // '/demo1' 为请求路径前缀,可自定义,比如 '/api'、'/test'
      // 例:http://localhost:8080/demo1/test,请求路径前缀匹配成功则走此代理配置
      '/demo1': {
        // target 为实际接收请求的服务器地址,请求路径会动态从请求中截取
        // 例:http://localhost:8080/demo1/test,实际访问地址为:http://localhost:5000/demo1/test
        target: 'http://localhost:5000',
        // pathRewrite 为路径重写,将路径中匹配正则表达式的字符串替换,json中的key为正则表达式,value为替换的字符串
        // 例:http://localhost:5000/demo1/test,替换为:http://localhost:5000/test
        pathRewrite: { '^/demo1': '' },
        // ws 用于支持websocket,默认true
        ws: true,
        // 用于控制请求头中的host值,默认true(通常都配置true)
        // true:请求头中的host为接收请求服务器的地址,false:请求头中的host为代理服务器的地址
        changeOrigin: true
      },
      '/demo2': {
        target: 'http://localhost:5001',
        pathRewrite: { '^/demo2': '' },
      }
    }
  }
}




13. 插槽

13.1 默认插槽

<!-- Category组件内容 -->
<template>
  <div>
    <h3>分类</h3>
    <!-- 定义一个插槽(挖个坑,等着组件的使用者进行填充) -->
    <slot>我是一些默认值,当使用者没有传递具体结构时,我会出现</slot>
  </div>
</template>

<!-- 使用Category组件,在组件内写插槽内容(Category组件开始和结束标签之间的所有内容都是插槽内容) -->
<Category>
  <ul>
    <li v-for="index in 10" :key="index">{{index}}</li>
  </ul>
</Category>

13.2 具名插槽

<!-- Category组件内容 -->
<template>
  <div>
    <h3>分类</h3>
    <!-- 定义一个插槽(给slot标签加name属性,name就是插槽名字) -->
    <slot name="center">我是一些默认值,当使用者没有传递具体结构时,我会出现1</slot>
    <slot name="footer">我是一些默认值,当使用者没有传递具体结构时,我会出现2</slot>
  </div>
</template>

<!-- 使用Category组件,在组件内写插槽内容(slot属性的值对应插槽名字,可以将多个元素定义同一个插槽名字) -->
<Category>
  <ul slot="center">
    <li v-for="index in 10" :key="index">{{index}}</li>
  </ul>
  <a slot="footer" href="http://www.baidu.com">单机游戏</a>
  <a slot="footer" href="http://www.baidu.com">网络游戏</a>
  <!--
    设置插槽名字方法
    1.在标签上加slot属性,例:<a slot="footer"></a>
    2.在 template 标签上加 v-slot:,例:<template v-slot:footer></template>
  -->
  <template v-slot:footer>
    <h4>欢迎体验</h4>
  </template>
</Category>

13.3 插槽传数据

<!-- Category组件内容 -->
<template>
  <div>
    <h3>分类</h3>
    <!-- slot标签上的属性就是给插槽使用者传的数据,games是Category组件上data中的变量 -->
    <slot name="center" :games="games" msg="hello">我是默认的一些内容</slot>
  </div>
</template>

<!-- 使用Category组件,要接收数据插槽必须定义为templete组件,使用scope属性接收(此处接收参数时使用了ES6的解构赋值) -->
<Category>
  <template slot="center" scope="{games, msg}">
    <ol>
      <li style="color:red" v-for="(g,index) in games" :key="index">{{g}}</li>
    </ol>
    <h3>{{msg}}</h3>
  </template>
</Category>
<!-- 也可使用slot-scope属性接收数据,效果一样(此处接收参数时使用了ES6的解构赋值) -->
<Category>
  <template slot="center" slot-scope="{games, msg}">
    <ol>
      <li style="color:red" v-for="(g,index) in games" :key="index">{{g}}</li>
    </ol>
    <h3>{{msg}}</h3>
  </template>
</Category>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,980评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,422评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,130评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,553评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,408评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,326评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,720评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,373评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,678评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,722评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,486评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,335评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,738评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,283评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,692评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,893评论 2 335

推荐阅读更多精彩内容