22.compositionApi中的ref,reactive,readonly講解

reactive

如果想為在setup中定義的數據提供響應式的特性奔害,那么我們可以使用reactive函數

那么這是什么原因呢兴使?為什么就可以變成響應式的呢?
  • 這是因為當我們使用reactive函數處理我們的數據之后,數據再次被使用時就會進行依賴收集蝉揍;
  • 當數據發(fā)生改變時绪抛,所有收集到的依賴都是進行對應的響應式操作(比如更新界面)泰偿;
  • 事實上,我們編寫的data選項归露,也是在內部交給了reactive函數將其編程響應式對象的熙卡;
<template>
  <div>
    <div>數量:{{ state.count }}</div>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { reactive } from "vue";
export default {
  setup() {
    //reactive函數把對象參數處理過后杖刷,返回一個響應式對象,響應式對象內部的key的值都是響應式的
    const state = reactive({
      count: 100,
    });

    const increment = () => {
      state.count++;
      console.log(state.count);
    };

    return {
      state,
      increment,
    };
  },
};
</script>

<style lang="scss" scoped></style>

reactive函數把對象參數處理過后,返回一個響應式對象,
響應式對象內部的key的值都是響應式的
缺陷:響應式變量被存放到對象中驳癌,不管在template還是在setup中使用都需要從對象中獲取

reactive函數的參數類型

reactive API對傳入的類型是有限制的滑燃,它要求我們必須傳入的是一個對象或者數組類型:

  • 如果我們傳入一個基本數據類型(String、Number颓鲜、Boolean)會報一個警告表窘;
    image.png

ref API

ref函數 會返回一個可變的響應式對象ref對象,該對象作為一個 響應式的引用 維護著它內部的值甜滨,這就是ref名稱的來源乐严;

  • 它內部的值是在ref對象的 value屬性中被維護的;
這里有兩個注意事項:
  • 在template模板中使用ref對象的值時衣摩,Vue會自動幫助我們進行解包操作昂验,所以我們并不需要在模板中通過 ref.value 的方式使用,直接使用ref對象就行
  • 但是在 setup 函數內部,它依然是一個 ref引用既琴, 所以對其進行操作時占婉,我們依然需要使用 ref.value的方式;
template模板中的對ref對象的解包是一個淺層的解包
  • 如果包裹著ref對象的是普通對象呛梆,vue不會自動幫我們把ref對象解包
  • 如果包裹著ref對象的是reactive函數返回的可響應式對象锐涯,vue依然會自動幫我們把ref對象解包
<template>
  <div>
    <!-- 在template模板中使用ref對象,vue會自動幫我們解包
    不需要再去value屬性中獲取值 -->
    <div>數量:{{ count }}</div>

    <!-- template中的解包是淺層的解包填物,
    如果包裹響應式變量的對象是普通對象纹腌,vue不會自動幫我們解包 -->
    <div>數量:{{ info.count.value }}</div>

    <!-- 如果包裹響應式變量的對象是reactive函數返回的對象,
    vue會自動幫我們解包滞磺,不需要通過state.count.value獲取 -->
    <div>數量:{{ state.count }}</div>

    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { ref, reactive } from "vue";
export default {
  setup() {
    //ref函數返回一個ref對象升薯,參數存儲在ref對象的value屬性中
    //ref對象是一個可響應式對象
    const count = ref(100);
    const info = { count }; //info是一個普通對象,此對象的count屬性的值是count這個ref對象
    const state = reactive({
      //state是一個響應式對象击困,此對象的屬性count的值count這個ref對象
      count,
    });

    const increment = () => {
      count.value++; //ref對象的值存儲在value屬性中
      console.log(count.value);
    };

    return {
      count,
      info,
      state,
      increment,
    };
  },
};
</script>

<style lang="scss" scoped></style>

readonly

我們通過reactive或者ref可以獲取到一個響應式的對象涎劈,但是某些情況下,我們傳入給其他地方(組件)的這個響應式對象希望在另外一個地方(組件)被使用阅茶,但是不能被修改蛛枚,這個時候如何防止這種情況的出現呢?

Vue3為我們提供了readonly的方法脸哀;
  • readonly會返回原生對象的只讀代理(也就是它依然是一個Proxy蹦浦,這是一個proxy的set方法被劫持,并且不
    能對其進行修改)撞蜂;
在開發(fā)中常見的readonly方法會傳入三個類型的參數:
  • 類型一:普通對象盲镶;
  • 類型二:reactive返回的對象;
  • 類型三:ref的對象蝌诡;

readonly的使用

在readonly的使用過程中溉贿,有如下規(guī)則:

  • readonly返回的對象都是不允許修改的;
  • 但是經過readonly處理的原來的對象是允許被修改的浦旱;
    • 比如 const info = readonly(obj)宇色,info對象是不允許被修改的;
    • 當obj被修改時颁湖,readonly返回的info對象也會被修改宣蠕;
    • 但是我們不能去修改readonly返回的對象info;
  • 其實本質上就是readonly返回的對象的setter方法被劫持了而已爷狈;

readonly的使用場景

在我們傳遞給其他組件數據時植影,往往希望其他組件使用我們傳遞的內容,但是不允許它們修改時涎永,就可以使用readonly了思币;
需求:父組件App.vue傳遞給子組件Home.vue的響應式變量鹿响,在父組件內部修改了響應式變量的值,子組件中的數據要會響應式更新谷饿,但是子組件不能修改通過屬性從父組件接收到的響應式變量的值
App.vue

<template>
  <div>
    <button @click="update">app:修改</button>
    <home :info="readonlyInfo2" :name="readonlyInfo3" />
  </div>
</template>

<script>
import { ref, reactive, readonly } from "vue";
import Home from "./Home.vue";
export default {
  name: "App",
  components: {
    Home,
  },
  setup() {
    // 1.info1為一個普通對象
    const info = { name: "why" };
    const readonlyInfo1 = readonly(info);

    // 2.info2為一個reactive返回的響應式對象
    //reactive對象被readonly函數轉換后的返回值的用法和之前的reactive對象一樣惶我,只是不能被修改
    const info2 = reactive({ name: "why" });
    const readonlyInfo2 = readonly(info2);

    // 3.info3是一個ref對象
    //ref對象被readonly函數轉換后的返回值的用法和之前的ref對象一樣,只是不能被修改
    //依然可以在template中自動解包
    const info3 = ref("why");
    const readonlyInfo3 = readonly(info3);

    const update = () => {
      info.name = "lily";
      info2.name = "kobe";
      info3.value = "curry";
    };

    // 所以傳給子組件時可以把readonlyInfo2或readonlyInfo3傳給子組件
    //在子組件內部只能使用博投,但不能修改readonlyInfo2或readonlyInfo3中的屬性的值
    //但是在當前組件可以通過info2或info3修改屬性的值绸贡,子組件中也會響應式更新

    return {
      readonlyInfo2,
      readonlyInfo3,
      info2,
      info3,
      update,
    };
  },
};
</script>

<style></style>

Home.vue

<template>
  <div>
    <div>名字: {{ name }}</div>
    <div>信息: {{ info.name }}</div>
    <button @click="updateName">修改名字</button>
    <button @click="updateInfo">修改信息</button>
  </div>
</template>

<script>
export default {
  props: {
    info: {
      type: Object,
      required: true,
    },
    name: {
      type: String,
      required: true,
    },
  },
  setup(props) {
    const updateName = () => {
      props.name = "coder"; //報錯
    };
    const updateInfo = () => {
      props.info.name = "coder"; //報錯
    };

    return {
      updateName,
      updateInfo,
    };
  },
};
</script>

<style lang="scss" scoped></style>

image.png

image.png

所以傳給子組件時可以把readonlyInfo2或readonlyInfo3只讀變量傳給子組件
在子組件內部只能使用,但不能修改readonlyInfo2中的屬性的值或readonlyInfo3的值
但是在當前組件可以通過info2或info3修改屬性的值毅哗,子組件中也會響應式更新

Reactive判斷的API

isProxy
  • 檢查對象是否是由 reactive 或 readonly創(chuàng)建的 proxy听怕。
isReactive
  • 檢查對象是否是由 reactive創(chuàng)建的響應式代理:
  • 如果該代理是 readonly 建的,但包裹了由 reactive 創(chuàng)建的另一個代理虑绵,它也會返回 true尿瞭;
isReadonly
  • 檢查對象是否是由 readonly 創(chuàng)建的只讀代理。
toRaw
  • 返回 reactive 或 readonly 代理的原始對象(不建議保留對原始對象的持久引用翅睛。請謹慎使用)声搁。
shallowReactive
  • 創(chuàng)建一個響應式代理,它跟蹤其自身 property 的響應性捕发,但不執(zhí)行嵌套對象的深層響應式轉換 (深層還是原生對象)疏旨。
shallowReadonly
  • 創(chuàng)建一個 proxy,使其自身的 property 為只讀扎酷,但不執(zhí)行嵌套對象的深度只讀轉換(深層還是可讀檐涝、可寫的)。
案例
<template>
  <div>
    <div>reactive: {{ info.friend.name }}</div>
    <div>shallowReactive: {{ info1.friend.name }}</div>
    <button @click="updateInfo">修改info</button>
    <button @click="updateInfo1">修改info1</button>
  </div>
</template>

<script>
import {
  reactive,
  readonly,
  shallowReadonly,
  isProxy,
  isReactive,
  isReadonly,
  shallowReactive,
} from "vue";
export default {
  name: "App",
  setup() {
    //reactive創(chuàng)建的reactive對象霞玄,不管內嵌多少層都是響應式的骤铃,即inof.friend.name值改變拉岁,頁面也會響應式更新
    const info = reactive({ name: "why", age: 18, friend: { name: "kobe" } });
    //shallowReactive創(chuàng)建的reactive對象坷剧,只有其自身的屬性是響應式的,內嵌對象的屬性不是響應式的喊暖,
    //即inof.friend.name值改變惫企,頁面不會響應式更新
    const info1 = shallowReactive({
      name: "why",
      age: 18,
      friend: { name: "kobe" },
    });
    const updateInfo = () => {
      info.friend.name = "curry";
      console.log("info", info.friend.name);
    };
    const updateInfo1 = () => {
      info1.friend.name = "curry";
      console.log("info1", info1.friend.name);
    };

    //readonlyInfo.name和readonlyInfo.friend.name都不可以被修改
    const readonlyInfo = readonly(info);
    //shallowReadonlyInfo.friend.name可以被修改,shallowReadonlyInfo.name不能被修改
    const shallowReadonlyInfo = shallowReadonly(info);

    const message = readonly({ name: "蘋果", price: 18 });
    console.log(isProxy(message)); //true
    console.log(isProxy(info)); //true
    console.log(isProxy(readonlyInfo)); //true

    console.log(isReactive(info)); //true
    console.log(isReactive(readonlyInfo)); //true
    console.log(isReactive(info.friend)); //true
    console.log(isReactive(info1.friend)); //false

    console.log(isReadonly(readonlyInfo)); //true

    return {
      info,
      info1,
      updateInfo,
      updateInfo1,
    };
  },
};
</script>

<style></style>

image.png

toRefs

如果我們使用ES6的解構語法陵叽,對reactive返回的對象state進行解構獲取值狞尔,解構出來的變量name, age,只是普通的值,和原reactive對象state沒有關系,

  • 修改reactive返回的state對象的屬性name,age的值巩掺,不會影響之前已經解構出的name, age變量偏序,
  • 修改變量name和age的值,也不會影響原reactive返回的state對象
  • 在template模板中使用變量name, age,當變量name, age值改變時胖替,頁面中數據不會響應式更新
const info = reactive({ name: "why", age: 18 });
let { name, age } = info;
那么有沒有辦法讓我們解構出來的屬性是響應式的呢研儒?
  • Vue為我們提供了一個toRefs的函數豫缨,可以將reactive返回的對象中的屬性都轉成ref;
  • 那么我們再次進行解構出來的 name 和 age 本身都是 ref對象端朵;
  • 這種做法相當于已經在state.name和ref.value之間建立了 鏈接好芭,任何一個修改都會引起另外一個變化;
    • 也就是修改name.value值冲呢,state.name也會發(fā)生改變舍败,
    • 修改state.name的值,name.value也會發(fā)生改變
    • 如果在template模板中使用了變量name, age敬拓,name.value和age.value的值改變邻薯,頁面中的數據也會響應式更新
    • toRefs函數的參數必須是reactive對象
const info = reactive({ name: "why", age: 18 });
let { name, age } = toRefs(info);
案例1:使用es6解構出的變量為普通的值:

解構出的變量的值是普通的值,不是響應式變量乘凸,值修改弛说,頁面中的數據不會響應式更新,與原reactive也沒有關系

<template>
  <div>
    <h1>名字:{{ name }},年齡:{{ age }}</h1>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年齡</button>
  </div>
</template>

<script>
import { reactive } from "vue";
export default {
  name: "App",
  setup() {
    const info = reactive({ name: "why", age: 18 });
    //通過此種對象解構的方式翰意,獲取的name,age變量的值木人,只是普通的值,因為不是ref對象或reactive對象冀偶,所以不具備響應式 ,
    //修改其值醒第,頁面也不會重新渲染
    //相當于下面寫法:name = 'why'   age = 18
    let { name, age } = info;

    const changeName = () => {
      info.name = "kobe"; //修改info.name,name不會發(fā)生改變
      console.log(info.name, name); //kobe  why
    };
    const changeAge = () => {
      age++; //修改age,頁面中的數據也不會響應式更新进鸠, info.age不會發(fā)生改變稠曼,
      console.log(info.age, age); //18  19
    };

    return {
      name,
      age,
      changeAge,
      changeName,
    };
  },
};
</script>

<style></style>

image.png
案例2:使用ref創(chuàng)建ref對象, 參數為reactive對象的某個屬性的值:

ref函數只是獲取了reactive對象的某個屬性的值,ref函數返回的ref對象和原reactive對象沒有其他關系客年,互不影響

<template>
  <div>
    <h1>名字:{{ name }},年齡:{{ age }}</h1>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年齡</button>
  </div>
</template>

<script>
import { reactive, ref, toRefs } from "vue";
export default {
  name: "App",
  setup() {
    const info = reactive({ name: "why", age: 18 });
    //下面這種方式霞幅,變量age和name獲取的只是info對應屬性的值,
    //修改變量age和name的value量瓜,或者修改info的name,age屬性的值司恳,都不會影響對方
    const name = ref(info.name);
    const age = ref(info.age);

    const changeName = () => {
      info.name = "kobe"; //修改info.name,name.value不會發(fā)生改變
      console.log(info.name, name.value); //kobe  why
    };
    const changeAge = () => {
      age.value++; //修改age,頁面中的數據會響應式更新绍傲, info.age不發(fā)生改變扔傅,
      console.log(info.age, age.value); //18  19
    };

    return {
      name,
      age,
      changeAge,
      changeName,
    };
  },
};
</script>

<style></style>

案例3:使用toRefs解構出的變量為ref對象:

使用toRefs會將reactive返回的對象中的屬性都轉成ref,
從info解構出的變量都是ref對象烫饼,且跟原reactive對象的對應屬性建立了鏈接猎塞,一個變量,另一個也會改變

<template>
  <div>
    <h1>名字:{{ name }},年齡:{{ age }}</h1>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年齡</button>
  </div>
</template>

<script>
import { reactive, ref, toRefs } from "vue";
export default {
  name: "App",
  setup() {
    const info = reactive({ name: "why", age: 18 });
    // 使用toRefs會將reactive返回的對象中的屬性都轉成ref杠纵,
    //從info解構出的變量都是ref對象荠耽,且根原reactive對象的對應屬性建立了鏈接,一個變量比藻,另一個也會改變
    let { name, age } = toRefs(info);

    const changeName = () => {
      info.name = "kobe"; //修改info.name铝量,name.value會發(fā)生改變
      console.log(info.name, name.value); //kobe  kobe
    };
    const changeAge = () => {
      age.value++; //修改age,頁面中的數據會響應式更新伊履, info.age也會發(fā)生改變,
      console.log(info.age, age.value); //19  19
    };

    return {
      name,
      age,
      changeAge,
      changeName,
    };
  },
};
</script>

<style></style>

image.png

toRef

如果我們只希望轉換一個reactive對象中的屬性為ref, 那么可以使用toRef的方法:
使用toRef函數返回一個ref對象款违,和原reactive對象中對應屬性建立了鏈接唐瀑,一個改變,另一個也改變

<template>
  <div>
    <h1>名字:{{ name }},年齡:{{ age }}</h1>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年齡</button>
  </div>
</template>

<script>
import { reactive, toRef } from "vue";
export default {
  name: "App",
  setup() {
    const info = reactive({ name: "why", age: 18 });
    let { age } = info; //變量age的值為普通的值
    // 從info解構name變量轉換為ref對象插爹,
    //ref對象name和原reactive對象info的屬性name建立了鏈接哄辣,一個改變,另一個也改變
    let name = toRef(info, "name");

    const changeName = () => {
      info.name = "kobe"; //修改info.name赠尾,name.value會發(fā)生改變力穗,頁面中的數據會響應式更新
      console.log(info.name, name.value); //kobe  kobe
    };
    const changeAge = () => {
      age++; //age值改變,頁面中的數據不會響應式更新气嫁,不會引起info.age值的改變
      console.log(age, info.age); //19 18
    };

    return {
      name,
      age,
      changeAge,
      changeName,
    };
  },
};
</script>

<style></style>

ref其他的API

unref
  • 如果我們想要獲取一個ref引用中的value当窗,那么也可以通過unref方法:
  • 如果參數是一個 ref,則返回內部值寸宵,否則返回參數本身崖面;
  • 這是 val = isRef(val) ? val.value : val 的語法糖函數;
isRef
  • 判斷值是否是一個ref對象梯影。
shallowRef
  • 創(chuàng)建一個淺層的ref對象巫员;
triggerRef
  • 手動觸發(fā)和 shallowRef 相關聯(lián)的副作用:
案例:ref函數創(chuàng)建的深層響應式對象和shallowRef創(chuàng)建的淺層響應式對象的區(qū)別

ref函數返回的ref對象,是深層響應的甲棍,其內嵌的對象的屬性發(fā)生改變简识,頁面中的數據也會響應式
shallowRef創(chuàng)建ref對象為淺層響應,

  • 即只有其ref.value的值發(fā)生改變感猛,頁面才會響應式更新七扰,
  • ref.value.name發(fā)生改變,頁面不會響應式更新更新
<template>
  <div>
    <h1>info:{{ info.name }}</h1>
    <h1>info1:{{ info1.name }}</h1>
    <button @click="changeInfoName">修改info名字</button>
    <button @click="changeInfo1Name">修改info1名字</button>
  </div>
</template>

<script>
import { ref, shallowRef, triggerRef } from "vue";
export default {
  name: "App",
  setup() {
    //ref函數返回的ref對象陪白,是深層響應的颈走,
    //其內嵌的對象的屬性發(fā)生改變,頁面中的數據也會響應式更新
    const info = ref({
      name: "why",
      age: 18,
    });

    //shallowRef創(chuàng)建ref對象為淺層響應拷泽,
    //即只有其ref.value的值發(fā)生改變疫鹊,頁面才會響應式更新袖瞻,
    //ref.value.name發(fā)生改變司致,頁面不會響應式更新
    const info1 = shallowRef({
      name: "why",
      age: 18,
    });

    const changeInfoName = () => {
      info.value.name = "curry";
      console.log(info.value.name);
    };
    const changeInfo1Name = () => {
      info.value.name = "curry";
      console.log(info.value.name);
    };

    return {
      info,
      info1,
      changeInfoName,
      changeInfo1Name,
    };
  },
};
</script>

<style></style>


triggerRef的用法

如果希望淺層響應ref對象的內嵌對象的值改變時,頁面上的數據響應式更新聋迎,

  • 需要使用triggerRef函數手動觸發(fā)淺層ref對象相關的副作用脂矫,
  • 參數為要觸發(fā)副作用淺層ref對象
<template>
  <div>
    <h1>info:{{ info.name }}</h1>
    <button @click="changeInfoName">修改info名字</button>
  </div>
</template>

<script>
import { shallowRef, triggerRef } from "vue";
export default {
  name: "App",
  setup() {
    //shallowRef創(chuàng)建ref對象為淺層響應,
    //即只有其ref.value的值發(fā)生改變霉晕,頁面才會響應式更新庭再,
    //ref.value.name發(fā)生改變捞奕,頁面不會響應式更新
    const info = shallowRef({
      name: "why",
      age: 18,
    });

    const changeInfoName = () => {
      info.value.name = "curry";
      console.log(info.value.name);
      //如果希望info.value.name值改變時,頁面上的數據響應式更新拄轻,
      //需要使用triggerRef函數手動觸發(fā)淺層ref對象相關的副作用颅围,
      //參數為要觸發(fā)副作用淺層ref對象
      triggerRef(info);
    };

    return {
      info,
      changeInfoName,
    };
  },
};
</script>

<style></style>

案例:unref和isRef的用法
<template>
  <div></div>
</template>

<script>
import { ref, isRef, unref } from "vue";
export default {
  name: "App",
  setup() {
    const info = ref({
      name: "why",
      age: 18,
    });

    const value = isRef(info) ? info.value : info;
    //unref是上面用法的語法糖
    const value1 = unref(info);
    console.log(value, value1);

    return {};
  },
};
</script>

<style></style>

image.png

customRef

創(chuàng)建一個自定義的ref,并對其依賴項跟蹤更新觸發(fā)進行顯示控制
  • customRef函數的參數為一個工廠函數恨搓,此工廠函數有個參數院促,每個參數都是一個函數
    • 第一個參數是追蹤函數track, 你可以通過調用track函數斧抱,來決定什么時候收集依賴
    • 第二個參數是觸發(fā)函數trigger常拓,你可以通過調用trigger函數,來決定什么時候觸發(fā)所有的依賴更新數據
  • 通過上面兩個函數辉浦,你可以決定什么時候收集依賴弄抬,什么時候觸發(fā)更新
  • 工廠函數需要返回一個有get和set的對象
這里我們使用一個的案例:
  • 對雙向綁定的屬性進行debounce(節(jié)流)的操作;

./hooks/useDebounceRef.js

import {
  customRef
} from 'vue'

export default function (value) {
  let timer = null
  //customRef函數的參數為一個工廠函數宪郊,此工廠函數有兩個參數掂恕,每個參數都是一個函數
  //第一個參數是追蹤函數track, 你可以通過調用track函數弛槐,來決定什么時候收集依賴
  //第二個參數是觸發(fā)函數trigger竹海,你可以通過調用trigger函數,來決定什么時候觸發(fā)所有的依賴去更新數據
  //通過上面兩個函數丐黄,你可以決定什么時候收集依賴斋配,什么時候觸發(fā)更新
  //工廠函數需要返回一個有get和set的對象
  return customRef((track, trigger) => {
    return {
      get() {
        track() //在獲取值的時候收集依賴
        return value
      },
      set(newVal) {
        clearTimeout(timer)
        timer = setTimeout(() => {
          value = newVal
          trigger() //在更新值后的1s后觸發(fā)更新
        }, 1000)
      }
    }
  })
}

App.vue

<template>
  <div>
    <input v-model="message" />
    <h1>{{message}}</h1>
  </div>
</template>

<script>
  import debounceRef from './hook/useDebounceRef.js'
  export default {
    setup() {
      let message = debounceRef('hello')

      return {
        message
      }
    }
  }
</script>

<style lang="scss" scoped>

</style>

此文檔主要內容來源于王紅元老師的vue3+ts視頻教程

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市灌闺,隨后出現的幾起案子艰争,更是在濱河造成了極大的恐慌,老刑警劉巖桂对,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件甩卓,死亡現場離奇詭異,居然都是意外死亡蕉斜,警方通過查閱死者的電腦和手機逾柿,發(fā)現死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宅此,“玉大人机错,你說我怎么就攤上這事「竿螅” “怎么了弱匪?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長璧亮。 經常有香客問我萧诫,道長斥难,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任帘饶,我火速辦了婚禮哑诊,結果婚禮上,老公的妹妹穿的比我還像新娘及刻。我一直安慰自己搭儒,他們只是感情好,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布提茁。 她就那樣靜靜地躺著淹禾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪茴扁。 梳的紋絲不亂的頭發(fā)上铃岔,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機與錄音峭火,去河邊找鬼毁习。 笑死,一個胖子當著我的面吹牛卖丸,可吹牛的內容都是我干的纺且。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼稍浆,長吁一口氣:“原來是場噩夢啊……” “哼载碌!你這毒婦竟也來了?” 一聲冷哼從身側響起衅枫,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤嫁艇,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后弦撩,有當地人在樹林里發(fā)現了一具尸體步咪,經...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年益楼,在試婚紗的時候發(fā)現自己被綠了猾漫。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡感凤,死狀恐怖悯周,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情俊扭,我是刑警寧澤队橙,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站萨惑,受9級特大地震影響捐康,放射性物質發(fā)生泄漏。R本人自食惡果不足惜庸蔼,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一解总、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧姐仅,春花似錦花枫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至馒疹,卻和暖如春佳簸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背颖变。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工生均, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人腥刹。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓马胧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親衔峰。 傳聞我的和親對象是個殘疾皇子佩脊,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內容