Vue3 学习笔记 (基础)

Vue3 学习笔记 (基础)

看视频学习的笔记,自用
bilibili 尚硅谷禹神

setup 一切的开始

  1. 组建中所用到的:数据、方法等都 应当 配置在 setup 中。没有写到 setup 中的函数或者属性在组件模板中无法访问。
  2. vue2 中的 data、computed等生命周期组件在 vue3 中可以写,但是不建议写
  3. setup 中没有 this
  4. 通常情况下 setup 组件是不能够返回 promise 的
  5. 当组件返回 promise 时,要确定被引用时,要使用 defineAsyncComponent 接收组件,并且使用 Suspense 来报过组件进行配合(后面文档有记载)
<script lang="ts">
export default {
  setup() {
    const name = '张三'
    const age = 18
    function sayHello() {
      alert("hello world")
    }
    return {
      name,     // 抛出 name 属性
      age,      // 抛出 age 属性
      sayHello  // 抛出 sayHello 函数
    }
  }
}
</script>
<template>
  <h1>人员信息</h1>
  <h2>姓名: {{ name }}</h2>
  <h2>年龄: {{ age }}</h2>
  <button @click="sayHello">sayHello</button>
</template>

ref 动态响应

ref 函数的作用是用于动态渲染。

  1. ref 会给普通的值类型属性更改为 RefImpl 对象,并且实现 get、set 两个函数。
  2. ref 会吧引用类型的对象更改为 Proxy 对象

使用 ref 时,除了在模板中,都需要操作实际的 value 否则无效

<script lang="ts">
import {ref} from "vue";

export default {
  setup() {
    const name = ref('张三')  // 使用 ref 来定义一个属性
    const age = ref(18)      // 使用 ref 来定义一个属性
    const job = ref({        // 使用 ref 来定义一个对象 ref 实际是通过 ES6 中的 Proxy 实现了这个对象的代理,进行了数据内部的处理
      type: '前端工程师',
      year: 2
    })

    function sayHello() {
      alert("hello world")
    }

    function changeInfo() {
      name.value = '李四' // 更改 name 属性的值
      age.value = 30     // 更改 age 属性的值
    }

    function changeJob() {
      const work = job.value    // 获取到 job 的这个对象
      work.type = '全栈'        // 更改 job 中 type 这个属性
      work.year = 10           // 更改 job 中 year 这个属性
    }

    return {
      name,
      age,
      job,
      sayHello,
      changeInfo,
      changeJob
    }
  }
}
</script>
<template>
  <h1>人员信息</h1>
  <h2>姓名: {{ name }}</h2>
  <h2>年龄: {{ age }}</h2>
  <h1>工作信息</h1>
  <h2>岗位类型: {{job.type}}</h2>
  <h2>工作年限: {{job.year}}</h2>
  <button @click="sayHello">sayHello</button>
  <br><br>
  <button @click="changeInfo">改变信息</button>
  <br><br>
  <button @click="changeJob">更换工作</button>
</template>

reactive 动态响应对象

  • 定义一个 对象类型 的响应式数据(基本类型不要用 reactive)
  • reactive 定义的响应式数据是深层响应的
  • 基于 ES6 的Proxy 实现。通过代理对象操作源对对象内部数据进行操作
<template>
  <h1>人员信息</h1>
  <h2>姓名: {{ name }}</h2>
  <h2>年龄: {{ age }}</h2>
  <h1>工作信息</h1>
  <h2>岗位类型: {{job.type}}</h2>
  <h2>工作年限: {{job.year}}</h2>
  <button @click="sayHello">sayHello</button>
  <br><br>
  <button @click="changeInfo">改变信息</button>
  <br><br>
  <button @click="changeJob">更换工作</button>
</template>
<script lang="ts">
import {ref, reactive} from "vue";

export default {
  setup() {
    const name = ref('张三')
    const age = ref(18)
    // 使用 reactive 来初始化对象
    const job = reactive({
      type: '前端工程师',
      year: 2
    })

    function sayHello() {
      alert("hello world")
    }

    function changeInfo() {
      name.value = '李四'
      age.value = 30
    }

    function changeJob() {
      // 直接更改属性,不需要再 .value 了
      job.type = '全栈'
      job.year = 10
    }

    return {
      name,
      age,
      job,
      sayHello,
      changeInfo,
      changeJob
    }
  }
}
</script>

Proxy 代理

Proxy 是 Es6 提供的对象代理函数。在在做对象时直接操作 Proxy 的代理,它会同步修改原来对象中的属性。使用代理可以完成对对象的原生监听

Proxy 参数 ( 源对象,操作对象)

如:

    const person = {
      name: '张三',
      age: 18
    }
    const student = new Proxy(person, {})
    student.name = '李四' // 修改代理中的name属性 相当于 person.name = '李四'
    console.log(student)  // Proxy {name: '李四', age: 18}
    console.log(person) // {name: '李四', age: 18}

get / set / delete


    const person = {
      name: '张三',
      age: 18
    }

    const student = new Proxy(person, {
      get(target, propName: string): unknown {
        console.log(`读取了 student 中的 ${propName} 属性`)
        return Reflect.get(target, propName)
      },
      set(target, propName: string, value): boolean {
        console.log(`写入了 student 中的 ${propName} 值为 ${value}`)
        return Reflect.set(target, propName, value)
      },
      deleteProperty(target, propName: string): boolean {
        console.log(`删除了 student 中的 ${propName} 属性`)
        return Reflect.deleteProperty(target, propName)
      }
    })

    student.name = '李四' // 修改代理中的name属性 相当于 person.name = '李四'
    console.log(student.name)  // 李四
    // 读取了 student 中的 name 属性
    console.log(student)  // Proxy {name: '李四', age: 18}
    Reflect.deleteProperty(student, 'age')  // 删除 age 属性
    console.log(JSON.stringify(student)) // Proxy {name: '李四'}
    console.log(JSON.stringify(person)) // {name: '李四'}

computed 计算属性

需要从 vue 中进入 computed 函数

import { reactive, computed } from "vue";

<script lang="ts">
import { reactive, computed } from "vue";

export default {
  setup() {
    const person = reactive({
      firstName: '张',
      lastName: '三'
    })
    // 设置一个叫 fullName 的计算属性
    Reflect.set(person, 'fullName', computed({
      get() {
        return person.firstName + '-' + person.lastName
      },
      set(value: string) {
        const split = value.split('-')
        person.firstName = split[0]
        person.lastName = split[1]
      }
    }))
    return {
      person
    }
  }
}
</script>

<template>
  <div>
    姓: <input type="text" v-model="person.firstName">
    名: <input type="text" v-model="person.lastName">
    全名: <input type="text" v-model="person.fullName">
  </div>
</template>

watch 监听

需要从 vue 中心如 watch 函数

注意:

  1. reactive 定义的对象在使用 watch 监听时无法正确的获得 oldVal
  2. vue3 目前版本中 watch 监听对象是默认深度监听的,且 deep 也无法关闭

watch 的三个参数

  1. 被监听的值/对象
  2. 监听触发回调函数。两个回调参数 ( 改变后的值/对象,改变前的值/对象 )
  3. 配置项。两个配置 {deep: boolean, immediate: boolean} ; deep: 深度监听; immediate: 初始触发监听
<script lang="ts">
import { ref, reactive, watch } from "vue";

export default {
  setup() {
    let sum = ref(0)
    let msg = ref(0)
    const person = reactive({
      firstName: '',
      lastName: '',
      fullName: '',
      job: {
        year: 10
      }
    })
    // 1. 普通监听
    watch(sum, (newVal, oldVal) => {
      console.log(newVal, oldVal)
      msg.value = newVal
    })
    // 2. 普通监听
    watch(msg, (newVal, oldVal) => {
      console.log(newVal, oldVal)
      sum.value = newVal
    })
    // 3. 组合监听
    watch([sum, msg], (newVal, oldVal) => {
      console.log(newVal, oldVal) // newVal: ['sum', 'msg'],  oldVal: ['sum', 'msg']
    }, { immediate: true }) // 初始触发 与 vue2 中 watch 里的 immediate 一致
      
    // 4. 监听 reactive 生成对象中的某一个属性
    watch(() => person.job.year, (newVal, oldVal) => {
      console.log(newVal, oldVal)
    })
      
    // 5. 监视的是 reactive 对象中某个对象属性时,超过 1 层的属性对象将会无法监听,需要添加 deep:true 配置才有效
    watch(() => person.job, (newVal, oldVal) => {
      console.log(newVal, oldVal)
    }, {deep: true})  
      
    // 6. 监听 ref 生成的对象
    const person2 = ref({
      firstName: '',
      lastName: '',
      fullName: '',
      job: {
        year: 10,
        work: {
          address: '南京'
        }
      }
    })
    // 当被监听的是一个由 ref 生成的对象时,那么监听时需要监听它实际的值
    watch(person2.value, (newVal, oldVal) => {
      console.log(newVal, oldVal)
    })
    return {
      person,
      sum,
      msg
    }
  }
}
</script>

<template>
  <div>
    sum: <input type="text" v-model="sum">
    smg: <input type="text" v-model="msg">
      
    姓: <input type="text" v-model="person.firstName">
    名: <input type="text" v-model="person.lastName">
    全名: <input type="text" v-model="person.fullName">
    工作年限: <input type="text" v-model="person.job.year">
  </div>
</template>

watchEffect 监听

<script lang="ts">
import { ref, reactive, watch, watchEffect } from "vue";

export default {
  setup: function () {
    const person = reactive({
      firstName: '',
      lastName: '',
      fullName: '',
      job: {
        year: 10,
        work: {
          address: '南京'
        }
      }
    })

    // watchEffect 默认开启了 immediate: true
    // watchEffect 不需要指定监视谁,它更类似于一个computed,在函数中用到的属性一旦发生改变,都将会触发这个函数
    // watchEffect 更注重程序的执行过程,没有返回值
    watchEffect(()=> {
      const name = person.fullName
      const address = person.job.work.address
      console.log("watchEffect 被执行了")
    })

    return {
      person,
    }
  }
}
</script>

<template>
  <div>
    姓: <input type="text" v-model="person.firstName">
    名: <input type="text" v-model="person.lastName">
    全名: <input type="text" v-model="person.fullName">
    工作年限: <input type="text" v-model="person.job.year">
    工作信息: <input type="text" v-model="person.job.work.address">
  </div>
</template>

setup 进阶

setup 提供了两个参数

  1. props 属性

  2. context 上下文

    属性有 attrs, emit, expose, slots

    attrs: 值为对象,收录了所有 props 中没有声明但被传递的属性。相当于 Vue2 中的 $attrs

    emit: 分发自定义时间的函数。相当于 Vue2 中的 $emit

    expose:

    slots: 收到的插槽内容。相当于 Vue2 中的 $slots

hook

hook 本质是一个函数,用于复用可用代码

hook 文件 .../usePoint.ts

import {reactive, onMounted, onUnmounted} from "vue";

export default function () {
const point = reactive({
x: 0,
y: 0
})

function onclick(event: MouseEvent) {
point.x = event.pageX
point.y = event.pageY
}

onMounted(() => window.addEventListener('click', onclick))
onUnmounted(() => window.addEventListener('click', onclick))
return point
}

引入 hook 的文件

<script lang="ts">
import usePoint from "@/hooks/usePoint";

export default {
  setup: function () {
    const point = usePoint()
    return {
      point
    }
  }
}
</script>

<template>
  <div>
    鼠标位置 x {{point.x}} y {{point.y}}
  </div>
</template>

toRef 函数

<script lang="ts">
import { reactive, toRef } from "vue";

export default {
  setup: function () {
    const person = reactive({
      job: {
        year: 10,
        work: {
          address: '南京'
        }
      }
    })
    // 使用 toRef 可以将Proxy中的属性与变量名进行桥接,更改被桥接的名字或者这个变量名时,两边都会进行同样的更改
    let address = toRef(person.job.work, 'address')
    return {
      person,
      address
    }
  }
}
</script>

<template>
  <div>
    我的地址: <input type="text" v-model="address">
    person 中的地址: <input type="text" v-model="person.job.work.address">
  </div>
</template>

toRefs 函数

 <script lang="ts">
import { reactive, toRefs } from "vue";

export default {
  setup: function () {
    const person = reactive({
      job: {
        year: 10,
        work: {
          address: '南京'
        }
      }
    })
    // toRefs 可以将对象中的第一层全部 toRef 出来为一个新的对象
    const obj = toRefs(person)
    return {
      person,
      ...toRefs(person) // 直接展开这个对象,那么即可以立即在模板中直接使用
    }
  }
}
</script>

<template>
  <div>
    我的地址: <input type="text" v-model="job.work.address">
    person 中的地址: <input type="text" v-model="person.job.work.address">
  </div>
</template>

不常用函数

readonly 只读函数

对象、值一旦使用了 readonly 函数,那么这个对象、值将不能再被修改。只能被读取

<script lang="ts">
import { reactive, readonly } from "vue";

export default {
  setup: function () {
    // 浅层次的 reactive 声明一个对象。这种声明方式只会考虑第一层数据的响应式。超过一层的数据改变时将不会改变源对象
    let person = reactive({
      firstName: '',
      lastName: '',
      fullName: '',
      job: {
        year: 10,
        work: {
          address: '南京'
        }
      }
    })
    person = readonly(person)
    return {
      person,
    }
  }
}
</script>

<template>
  <div>
<!--    下面都无法更改到源数据-->
    姓: <input type="text" v-model="person.firstName">
    名: <input type="text" v-model="person.lastName">
    全名: <input type="text" v-model="person.fullName">
    工作年限: <input type="text" v-model="person.job.year">
    工作信息: <input type="text" v-model="person.job.work.address">
    <br>
    <span>{{JSON.stringify(person)}}</span>
  </div>
</template>

shallowReactive、shallowRef、shallowReadonly

浅响应式。相当于弱化了的 reactive 和 ref

  • shallowReactive 只处理对象最外层的响应式
  • shallowRef 只处理基本的数据类型响应式,不进行对象的响应式处理
  • shallowReadonly 将对象的第一层设置为只读,其他可读
<script lang="ts">
import { shallowReactive, shallowRef } from "vue";

export default {
  setup: function () {
    // 浅层次的 reactive 声明一个对象。这种声明方式只会考虑第一层数据的响应式。超过一层的数据改变时将不会改变源对象
    const person = shallowReactive({
      firstName: '',
      lastName: '',
      fullName: '',
      job: {
        year: 10,
        work: {
          address: '南京'
        }
      }
    })
    return {
      person,
    }
  }
}
</script>

<template>
  <div>
    姓: <input type="text" v-model="person.firstName">
    名: <input type="text" v-model="person.lastName">
    全名: <input type="text" v-model="person.fullName">
    工作年限: <input type="text" v-model="person.job.year">
    工作信息: <input type="text" v-model="person.job.work.address">
    <br>
    <span>{{JSON.stringify(person)}}</span>
  </div>
</template>

toRaw 回归原始

reactive 生成的对象一旦被 toRaw 以后,就不在是 Proxy 代理对象了。也不再具有动态响应的作用

<script lang="ts">
import { reactive, toRaw } from "vue";

export default {
  setup: function () {
    // 浅层次的 reactive 声明一个对象。这种声明方式只会考虑第一层数据的响应式。超过一层的数据改变时将不会改变源对象
    let person = reactive({
      firstName: '',
      lastName: '',
      fullName: '',
      job: {
        year: 10,
        work: {
          address: '南京'
        }
      }
    })
    person = toRaw(person)
    return {
      person
    }
  }
}
</script>

<template>
  <div>
<!--    下面都无法更改到源数据-->
    姓: <input type="text" v-model="person.firstName">
    名: <input type="text" v-model="person.lastName">
    全名: <input type="text" v-model="person.fullName">
    工作年限: <input type="text" v-model="person.job.year">
    工作信息: <input type="text" v-model="person.job.work.address">
    <br>
    <span>{{JSON.stringify(person)}}</span>
  </div>
</template>

markRaw 标记原始

对象的某个属性被标记标记了原始以后,将不会被动态响应

<script lang="ts">
import { reactive, markRaw } from "vue";

export default {
  setup: function () {
    // 浅层次的 reactive 声明一个对象。这种声明方式只会考虑第一层数据的响应式。超过一层的数据改变时将不会改变源对象
    let person = reactive({
      firstName: '',
      lastName: '',
      fullName: '',
    })
    let job = {
      year: 10,
      work: {
        address: '南京'
      }
    }
    job = markRaw(job)
    Reflect.set(person, 'job', job)
    return {
      person
    }
  }
}
</script>

<template>
  <div>
    姓: <input type="text" v-model="person.firstName">
    名: <input type="text" v-model="person.lastName">
    全名: <input type="text" v-model="person.fullName">
<!--    下面都无法更改到源数据-->
    工作年限: <input type="text" v-model="person.job.year">
    工作信息: <input type="text" v-model="person.job.work.address">
    <br>
    <span>{{JSON.stringify(person)}}</span>
  </div>
</template>

响应式数据的类型判断

isRef: 检查一个值是否为 ref 对象

isReactive: 检查一个对象是否由 reactive 创建的响应式代理

isReadonly: 检查一个对象是否有 readonly 创建的只读代理

isProxy: 检查一个对象是否有 reactive 或者 readonly 方法创建的代理

感觉很重要,但是用的不多

customRef 自定义 ref 的实现

这是一个官方的实现案例,延迟更新新效果

<script lang="ts">
import { customRef } from "vue";
import { NodeJS } from "timers";

export default {
  setup: function () {

    function myRef(value:string) {
      let timer:NodeJS.Timeout = undefined
      return customRef((track, trigger) => {
        return {
          get() {
            track() // 1,告诉Vue跟踪这个值,使它每次变化都更新
            return value
          },
          set(newValue:string) {
            timer && clearTimeout(timer)
            timer = setTimeout(()=>{
              // 延迟更新
              value = newValue
              trigger() // 2. 通知Vue数据更新了
            }, 500)
          }
        }
      })
    }
    let name = myRef('你好啊')
    return {
      name
    }
  }
}
</script>

<template>
  <div>
    请输入: <input type="text" v-model="name">
    <br>
    输入内容为: {{name}}
    <br>
  </div>
</template>

provide/inject 后代组件传值

provide

// 父组件定义
import {provide} from 'vue';
export default({
  name: 'HomeView',
  setup() {
    let heirloom = ref('双鱼玉佩')
    // 通过 provide 将 car 传递给后代
    provide('heirloom', heirloom)
      
    return {
    }
  }
})

inject

<script lang="ts">
import {inject} from "vue";

export default {
  setup: function () {
    // 通过 inject 接收祖辈组件传值
    const heirloom = inject('heirloom')
    return {
      heirloom
    }
  }
}
</script>

<template>
  <div>
    <br>
    传家宝: {{heirloom}}
    <br>
  </div>
</template>

组件

teleport 传送组件

在这个组件内部写的所有组件都可以通过 teleport 的 to 属性传送到指定的位置去

如,这里传送到了 body 中

<script lang="ts">
import {inject, isRef, isReactive} from "vue";

export default {
  setup: function () {
    const car = inject('car')
    console.log(isRef(car))
    console.log(isReactive(car))
    return {
      car
    }
  }
}
</script>

<template>
  <div>
    <h1>Vue3</h1>
  </div>
  <teleport to="body">
    <div>传家宝: {{car}}</div>
    <div>传送到body去</div>
  </teleport>
</template>

如果想要传送到指定的 div 中,那么需要先在 index.html 中实现定义好这个div

如:

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <div class="dialog"></div> <!-- 传到这个div 中 -->
    <!-- built files will be auto injected -->
  </body>
</html>

<script lang="ts">
import {inject, isRef, isReactive} from "vue";

export default {
  setup: function () {
    const car = inject('car')
    console.log(isRef(car))
    console.log(isReactive(car))
    return {
      car
    }
  }
}
</script>

<template>
  <div>
    <h1>Vue3</h1>
  </div>
  <teleport to=".dialog">
    <div>传家宝: {{car}}</div>
    <div>传送到body去</div>
  </teleport>
</template>

Suspense 异步组件

用于需要从后台加载数据后才渲染的组件

<template>
  <div class="home">
    <Suspense>
<!--      suspense 提供了两个槽位
      default  是默认槽位,是代码正确运行后让用户看到的结果
      fallback 是代码异常或者加载缓慢时让用户看到的结果-->
      <template v-slot:default>
        <test-vue3></test-vue3>
      </template>
      <template v-slot:fallback>
        <div>加载中</div>
      </template>
    </Suspense>
  </div>
</template>
<script lang="ts">
// defineAsyncComponent 异步引入组件
import {defineAsyncComponent} from 'vue';

const TestVue3 = defineAsyncComponent(()=> import('@/components/TestVue3.vue'));
export default({
  name: 'HomeView',
  components: {
    TestVue3
  }
})
</script>

当组件是使用 defineAsyncComponent 来接收时,那么被使用的组件 setup 可以返回 promise

父组件

<template>
  <div class="home">
    <Suspense>
<!--      suspense 提供了两个槽位
      default  是默认槽位,是代码正确运行后让用户看到的结果
      fallback 是代码异常或者加载缓慢时让用户看到的结果-->
      <template v-slot:default>
        <test-vue3></test-vue3>
      </template>
      <template v-slot:fallback>
        <div>加载中</div>
      </template>
    </Suspense>
  </div>
</template>
<script lang="ts">
// defineAsyncComponent 异步引入组件
import {defineAsyncComponent} from 'vue';

const TestVue3 = defineAsyncComponent(()=> import('@/components/TestVue3.vue'));
export default({
  name: 'HomeView',
  components: {
    TestVue3
  }
})
</script>

子组件

<script lang="ts">
import {inject, isRef, isReactive} from "vue";

export default {
  setup: function () {
    const car = inject('car')
    console.log(isRef(car))
    console.log(isReactive(car))
    return new Promise((resolve, reject) => {
      setTimeout(()=> {
        resolve(1)
      }, 2000)
    })
  }
}
</script>

<template>
  <h1>Vue3</h1>
</template>

End

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

推荐阅读更多精彩内容