vue3+jsx使用遞歸組件實(shí)現(xiàn)無限級(jí)菜單

評(píng)論放鏈接好像會(huì)被吞挑社,demo地址:https://gitee.com/zqw127/vue3-jsx-project

之前我用vue2實(shí)現(xiàn)了一版,地址為:vue中使用遞歸組件實(shí)現(xiàn)無限級(jí)菜單
想要實(shí)現(xiàn)的功能就是根據(jù)路由信息自動(dòng)生成對(duì)應(yīng)的菜單攀涵。

這次用vue3+jsx再實(shí)現(xiàn)一版酥泞,思路沒有變化伞鲫,但是寫起來基本完全不同了戏售,主要變化有:
1.composition api寫法與vue2中的區(qū)別
2.使用jsx+ts
3.router變化
最主要的變化還是第二個(gè)拗秘,下面我會(huì)把涉及到的內(nèi)容以我的理解講出來卓嫂,如果有理解更到位的大佬,歡迎指教哦聘殖。當(dāng)然最基礎(chǔ)的jsx與ts用法下面就不說了。至于jsx寫法與傳統(tǒng)vue文件寫法兩者的優(yōu)缺點(diǎn)行瑞,網(wǎng)上的大佬已經(jīng)說了很多了奸腺,主要看自己喜歡,我覺得可以不用血久,但不能問起來說不出(懂的·都懂)突照。

vue中使用jsx

1.安裝@vue/babel-plugin-jsx

npm run @vue/babel-plugin-jsx --save

2.在項(xiàng)目的babel.config.js中的plugins添加,下面是在腳手架生成文件基礎(chǔ)下添加:

module.exports = {
  presets: ['@vue/cli-plugin-babel/preset'],
  plugins: ['@vue/babel-plugin-jsx']
}

3.創(chuàng)建tsx文件以及用法
使用ts寫jsx的文件就是tsx文件氧吐,用tsx文件來代替我們平常寫的vue文件讹蘑,下面是兩種文件的區(qū)別:
.vue文件:

<template>
  <div>{{bar}}</div>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
  setup () {
    const bar = ref('hello')
    return {
      bar
    }
  }
})
</script>

.tsx文件:

import { defineComponent, ref } from 'vue'
export default defineComponent({
 setup () {
    const bar = ref('hello')
    return () => {
      return <div>{bar.value}</div>
    }
  }
})

上面就是簡(jiǎn)單的用法區(qū)別末盔,當(dāng)setup返回一個(gè)函數(shù)時(shí),就是返回一個(gè)render函數(shù)座慰,這個(gè)函數(shù)返回的內(nèi)容就當(dāng)作組件的模板使用陨舱,下面是一些jsx在vue中基礎(chǔ)用法:

v-bind或props:
<div data={data}></div> // 變量與js表達(dá)式需要用一對(duì)大括號(hào)引起來

v-for:
{
  [1,2,3].map((item) => {
    return <div key={item}>{item}<div>
  })
}

v-if:
{ flag ? <div>超人鴨<div> : null }

v-on:
const fn = () => {
  .....
}
<div onClick={fn}>點(diǎn)擊</div>
需要傳遞參數(shù):
<div onClick={() => { fn(111) }}>點(diǎn)擊</div>

class:
<div class="a">超人鴨</div>

基礎(chǔ)的用法就是這些,還有v-model版仔、v-show我們的插件內(nèi)部已經(jīng)實(shí)現(xiàn)了游盲,可以直接用,具體可以看@vue/babel-plugin-jsx蛮粮,插槽的用法在下面會(huì)說到益缎。

功能介紹以及實(shí)現(xiàn)思路

上面說到,實(shí)現(xiàn)的功能就是根據(jù)路由信息使用遞歸組件實(shí)現(xiàn)無限級(jí)菜單然想,其實(shí)就是去生成菜單組件莺奔,先看看生成的菜單:

image.png

菜單其實(shí)只有兩種狀態(tài):
1.菜單目錄,下面還有子菜單的变泄,展現(xiàn)出來就是點(diǎn)擊可以收縮子菜單項(xiàng)(上圖中的用戶管理令哟、菜單1、菜單1-2)
2.菜單項(xiàng)杖刷,就是沒有下一級(jí)了励饵,點(diǎn)擊可以跳轉(zhuǎn)到具體頁(yè)面。
整個(gè)菜單就是由這兩種組件組成滑燃,我使用element-ui中的導(dǎo)航組件來實(shí)現(xiàn):
菜單目錄:el-submenu
菜單項(xiàng):el-menu-item
而菜單目錄中可以任意嵌套菜單目錄和菜單項(xiàng)役听,el-submenu也是可以的。
注:vue3中用的是element-plus哦表窘,如果對(duì)這個(gè)組件不熟悉建議先看一下文檔哦典予,導(dǎo)航組件文檔

然后是路由信息
下面是在腳手架生成的 router/index.ts文件中改 routes對(duì)象而已,其他配置不動(dòng)乐严。

export const routes: Array<RouteRecordRaw> = [
  {
    path: '/',
    name: 'LAYOUT_VIEW',
    component: Layout,
    meta: { isLogin: true, hidden: true },
    redirect: '/user'
  },
  {
    path: '/user',
    name: 'USER_MANAGE',
    component: Layout,
    meta: { title: '用戶管理', icon: 'el-icon-s-tools', alwaysShow: true },
    redirect: '/user/info',
    children: [
      {
        path: 'info',
        name: 'USER_INFO',
        component: () => import('@/views/userInfo/index'),
        meta: { title: '用戶信息' }
      }
    ]
  },
  {
    path: '/test1',
    name: 'TEST1',
    component: Layout,
    meta: { title: '菜單1', icon: 'el-icon-s-tools', alwaysShow: true },
    children: [
      {
        path: 'test1-1',
        name: 'TEST1-1',
        component: () => import('@/views/test.vue'),
        meta: { title: '菜單1-1' }
      },
      {
        path: 'test1-2',
        name: 'TEST1-2',
        component: () => import('@/views/test.vue'),
        meta: { title: '菜單1-2', alwaysShow: true },
        children: [
          {
            path: 'test1-2-1',
            name: 'TEST1-2-1',
            component: () => import('@/views/test.vue'),
            meta: { title: '菜單1-2-1' }
          }
        ]
      }
    ]
  },
  {
    path: '/test2',
    name: 'TEST2',
    component: Layout,
    meta: { title: '菜單2', icon: 'el-icon-s-tools', alwaysShow: false },
    children: [
      {
        path: 'test2-1',
        name: 'TEST2-1',
        component: () => import('@/views/test.vue'),
        meta: { title: '菜單2-1' }
      }
    ]
  },
  {
    path: '/login',
    name: 'LOGIN',
    component: () => import('@/views/login/index.vue'),
    meta: { isLogin: false, hidden: true }
  }
]

這個(gè)路由信息就對(duì)應(yīng)了上面生成的菜單組件瘤袖。用來生成菜單組件最主要的邏輯就是根據(jù)路由有沒有children屬性,如果有昂验,那就是菜單目錄捂敌,對(duì)應(yīng)el-submenu,如果沒有既琴,那就是菜單項(xiàng)占婉,對(duì)應(yīng)el-menu-item。其中layout就是一個(gè)放著<router-view>的布局組件甫恩,然后關(guān)鍵信息都在每個(gè)路由的meta中:

  • title代表菜單的名稱
  • icon就是圖標(biāo)的類名逆济,這里用了element自帶的
  • hidden就表示不在菜單中顯示,比如登錄路由,404頁(yè)等
  • alwaysShow是一個(gè)額外的邏輯奖慌,當(dāng)路由的children只有一項(xiàng)時(shí)抛虫,默認(rèn)是直接展示菜單項(xiàng)的,就是不展示那種可以收縮的菜單目錄简僧,只有配置了這個(gè)alwaysShow屬性后才作菜單目錄渲染建椰。當(dāng)然這是我自己的邏輯,可以隨意改涎劈。

我這樣寫就要求每個(gè)路由信息都要有meta對(duì)象广凸。接下來就可以拿著這個(gè)路由信息去生成組件了。

編寫組件

文件結(jié)構(gòu):

image.png

因?yàn)閑lement的菜單組件最外層是一個(gè)<el-menu></el-menu>蛛枚,所以在index.tsx中編寫外部包裹的組件谅海,sidebarItem就是真正實(shí)現(xiàn)遞歸邏輯的組件。

先看index.tsx:

import { defineComponent, computed } from 'vue'
import '../style/sidebar.scss'
import { routes } from '@/router/index' // 將在router中定義的routes引入
import { useRoute } from 'vue-router'
import SidebarItem from './sidebarItem'

export default defineComponent({
  setup () {
    // 過濾掉第一層不顯示的路由蹦浦,比如登錄路由
    const isShowRoutes = computed(() => {
      return routes.filter((item) => {
        return !item.meta!.hidden
      })
    })
    // 當(dāng)前路由的路徑扭吁,為和el-menu的高亮項(xiàng)對(duì)應(yīng)
    const currentPath = computed(() => {
      return useRoute().path
    })

    return () => {
      return <div class="layout-sidebar-wrapper">
        <el-scrollbar style="height:100%">
          <el-menu default-active={currentPath.value}
            backgroundColor="#304156"
            text-color="#bfcbd9"
            unique-opened={false}
            active-text-color="#409EFF"
            collapse-transition={false}
            mode="vertical">
            {
              isShowRoutes.value.map((route) => {
                return <SidebarItem item={route}
                  basePath={route.path}
                  key={route.path}>
                </SidebarItem>
              })
            }
          </el-menu>
        </el-scrollbar>
      </div>
    }
  }
})

這代碼塊沒高亮看著挺難受,下面把幾個(gè)代碼解釋一下以及與vue2寫法的區(qū)別
上面也說到在setup返回一個(gè)函數(shù)就是渲染函數(shù)盲镶,在里面返回組件的模板侥袜,其他邏輯沒變。
使用路由溉贿,需要在vue-router中引入:

vue2獲取當(dāng)前路由的信息:
this.$route

vue3:
import { useRoute } from 'vue-router'
const route = useRoute()

vue2路由跳轉(zhuǎn):
this.$router.push('/')
or
this.$router.push({
  path: '/'
})

vue3:
import { useRouter } from 'vue-router'
const router = useRouter()
router.push('/')

計(jì)算屬性:

vue2:
computed: {
  currentPath() {
    return this.$route.path
  }
}

vue3:
import { computed } from 'vue'
const currentPath = computed(() => {
  return useRoute().path
})
使用需要:
currentPath.value

類型斷言枫吧,ts中的一個(gè)語(yǔ)法,因?yàn)閠s不確定我們每個(gè)路由都有meta信息宇色,所以上面第一個(gè)計(jì)算屬性中的item.meta可能為undefined九杂,所以在后面加上一個(gè)!表示我們確定這個(gè)屬性一定存在:

item.meta!.hidden

最后將isShowRoutes去遍歷渲染<SidebarItem>組件,就相當(dāng)于v-for宣蠕,<SidebarItem>組件要接收一個(gè)item也就是一個(gè)路由對(duì)象信息例隆,一個(gè)basePath就是每一個(gè)路由信息的基礎(chǔ)路徑這兩個(gè)props。這里使用tsx就有一個(gè)明顯的優(yōu)點(diǎn)抢蚀,會(huì)對(duì)props作類型校驗(yàn)镀层。具體可以自己去試一下。

sidebarItem.tsx

import { defineComponent, PropType } from 'vue'
import { RouteRecordRaw, useRouter } from 'vue-router'
import path from 'path'

const SidebarItem = defineComponent({
  name: 'SidebarItem',
  props: {
    item: {
      type: Object as PropType<RouteRecordRaw>,
      required: true
    },
    basePath: {
      type: String,
      required: true
    }
  },
  setup (props) {
    const router = useRouter()

    let data: Partial<RouteRecordRaw> = { // 存儲(chǔ)當(dāng)前路由的處理后的信息
    }

    const resolvePath = (routePath: string): string => {
      return path.resolve(props.basePath, routePath)
    }

    const navigation = (path: string) => {
      router.push(path)
    }

    return () => {
      const handleRoute = () => {
        const { item } = props

        // 最后一層的情況皿曲,渲染菜單項(xiàng)
        if (!item.children) {
          data = { ...item, path: '' }
          return <el-menu-item onClick={() => { navigation(resolvePath(data.path!)) }} index={resolvePath(data.path!)}>
            <span>{data.meta!.title}</span>
          </el-menu-item>
        }
        
        // 把當(dāng)前這一層路由中的children的hidden過濾點(diǎn)
        const showingChildren = item.children.filter((item) => {
          return item.meta && !item.meta.hidden
        })
        item.children = showingChildren
        
        // 如果當(dāng)前路由只有一個(gè)children并且這個(gè)children沒有children屬性唱逢,并且沒有設(shè)置alwaysShow這個(gè)屬性,當(dāng)菜單項(xiàng)渲染
        if (showingChildren.length === 1 && !showingChildren[0].children && (item.meta && !item.meta.alwaysShow)) {
          data = showingChildren[0]
          return <el-menu-item index={resolvePath(data.path!)} onClick={() => { navigation(resolvePath(data.path!)) }}>
            <span>{data.meta!.title}</span>
          </el-menu-item>
        }

        const slots = {
          title: () => {
            return <div>
              {item.meta!.icon ? <i class={item.meta!.icon}></i> : null}
              <span>{item.meta!.title ? item.meta!.title : '未定義菜單名稱'}</span>
            </div>
          }
        }
        
        // 有children屬性屋休,沒其他特殊情況坞古,作菜單目錄渲染,遞歸引用
        return <el-submenu index={resolvePath(item.path)} v-slots={slots}>
          {item.children.map((child) => {
            return <SidebarItem item={child} basePath={resolvePath(child.path)} key={child.path}></SidebarItem>
          })}
        </el-submenu>
      }
      return <div>{handleRoute()}</div>
    }
  }
})

export default SidebarItem

這個(gè)組件就比較復(fù)雜了博投,下面從上到下把幾塊解釋一下:

  • PropType
vue中定義props的類型只能定義js的基本類型,對(duì)于Object盯蝴、Array毅哗、Function之類的類型在ts檢驗(yàn)中基本等于沒用听怕,所以需要PropType來定義具體的類型

用法:
item: {
  在PropType的<>填入具體的類型
  type: Object as PropType<RouteRecordRaw>,
  required: true
}

RouteRecordRaw是路由信息的類型,是vue-router自帶的虑绵,把它引入就行:
import { RouteRecordRaw } from 'vue-router'
  • Partial
Partial是ts的一個(gè)語(yǔ)法尿瞭,將傳入的類型全部變成可選的,來避免一些麻煩

用法:
interface Type{
  a: string;
  b: number;
}
let c: Partial<Type> = {}
此時(shí)c的類型就是:
{
  a?: string;
  b?: number;
}
  • 遞歸組件
    我們?cè)趘ue2中使用遞歸組件只要聲明了name屬性就可以直接在template中使用翅睛,但是在tsx中声搁,使用遞歸組件需要明確的定義:
const SidebarItem = defineComponent({
  setup(){
    return () => {
      return <SidebarItem></SidebarItem>
    }
  }
})
最后別忘了把組件導(dǎo)出:
export default SidebarItem
  • 插槽
    image.png

    上面這一塊的就是插槽的引入,先看看我們?cè)静宀鄣膶懛ú斗ⅲ苯涌磂lement官方對(duì)el-submenu的寫法:
<el-submenu index="1">
  <template v-slot:title>
    <i class="el-icon-location"></i>
    <span>導(dǎo)航一</span>
  </template>
  <el-menu-item index="1-1">選項(xiàng)1</el-menu-item>
  <el-menu-item index="1-2">選項(xiàng)2</el-menu-item>
  <el-menu-item index="1-3">選項(xiàng)3</el-menu-item>
</el-submenu>

這就是我們之前的寫法疏旨,el-submenu就是有一個(gè)叫title的具名插槽,換成tsx寫法就是我上面那種扎酷,通過傳入一個(gè)對(duì)象檐涝,對(duì)象里面配置各個(gè)函數(shù),每個(gè)函數(shù)返回要插入的dom法挨,具體可以看jsx的介紹文檔谁榜,各種用法都挺詳細(xì)的:

image.png

  • 注意點(diǎn)
    上面有一個(gè)navigation函數(shù),作用就是點(diǎn)擊菜單項(xiàng)進(jìn)行路由跳轉(zhuǎn)凡纳,我一開始是這樣寫的:
const navigation = (path: string) => {
  const router = useRouter()
  router.push(path)
}

就是將路由的聲明放在方法中窃植,但是這樣router會(huì)變成undefined,需要放在setup外層聲明荐糜,可能是跟執(zhí)行的時(shí)機(jī)有關(guān)巷怜,setup會(huì)在相當(dāng)于vue2的beforeCreate和create之間的這個(gè)時(shí)期執(zhí)行,但是和路由具體的關(guān)系我還不太清楚狞尔,待我去研究一哈丛版。

這樣整個(gè)功能就實(shí)現(xiàn)了,之后只需要在路由添加配置路由信息偏序,菜單就會(huì)自動(dòng)生成页畦。歡迎指教哦。

補(bǔ)充:jsx中子組件怎么寫插槽

上面在實(shí)現(xiàn)功能中講到了在jsx中插槽如何使用研儒,但都是在使用別人的插槽豫缨,emmm也就是一直插別的組件,也就是在父組件中使用插槽端朵。那我們?nèi)绾卧趈sx定義自己的插槽呢好芭,其實(shí)就是在子組件中寫插槽。

  1. 先看看之前在.vue文件中如何寫插槽:
    默認(rèn)插槽:
在子組件:
<div>
    <span>children</span>
    <slot></slot>
</div>

在父組件:
<children>
    哈哈哈
</children>
哈哈哈就會(huì)填充到子組件的slot標(biāo)簽里面

具名插槽

在子組件:
<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <div>
    <slot></slot>
  </div>
</div>

在父組件:
<children>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>
  <p>A paragraph for the main content.</p>
  <p>And another one.</p>
</children>

v-slot 只能添加在 <template>標(biāo)簽上
任何沒有被包裹在帶有 v-slot 的 <template> 中的內(nèi)容都會(huì)被視為默認(rèn)插槽的內(nèi)容冲呢,比如上面的兩個(gè)p標(biāo)簽舍败,就會(huì)渲染在默認(rèn)插槽中。
默認(rèn)插槽其實(shí)有個(gè)default的名字,所以上面的父組件也可以寫成:

<children>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>
  <template v-slot:default>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </template>
</children>

作用域插槽
作用域插槽就是子組件通過插槽把子組件里面的變量傳遞給父組件

在子組件里面:
<span>
  <slot name="user" v-bind:user="user">
  </slot>
</span>
data(){
  return: {
    user: {
      name: '超人鴨'
    }
  }
}

在父組件中:
<children>
  // slotProps是自己起的名字邻薯,可以隨便起
  <template v-slot:user="slotProps">
      {{ slotProps.user.name}}
  </template>
</children>

在子組件中的slot標(biāo)簽都可以綁定很多變量裙戏,vue會(huì)把這些變量都放在一個(gè)對(duì)象上,然后在父組件上通過這個(gè)對(duì)象去點(diǎn)出來綁定的變量厕诡,既然是一個(gè)對(duì)象累榜,那就可以解構(gòu),所以上面父組件的寫法可以變成下面這樣:

在父組件中:
<children>
  <template v-slot:user="{user}">
      {{ user.name}}
  </template>
</children>

上面就是在.vue文件中使用插槽的寫法灵嫌,下面直接看在jsx中如何寫插槽:
默認(rèn)插槽

在子組件:
export default defineComponent({
  setup (props, { slots }) {
    return () => {
      return <div>{slots}</div>
    }
  }
})

在setup的第二個(gè)參數(shù)是一個(gè)對(duì)象壹罚,里面有一個(gè)slots,感覺它就是為了jsx寫法而存在的(個(gè)人目前見解)
父組件的用法上面已經(jīng)說到了寿羞,這里再寫一遍吧猖凛,默認(rèn)插槽其實(shí)有個(gè)被省略的名字:default ,所以父組件中對(duì)默認(rèn)插槽有兩種用法:

1.
<children>
  <div>超人鴨</div>
</children>

2.
const slots = {
  default: () => {
    return <div>超人鴨</div>
  }
}
<children v-slots={slots}>
</children>

具名插槽:

在子組件
export default defineComponent({
  setup (props, { slots }) {
    return () => {
      return <div>
        <div>{slots}</div>
        // 這里需要做個(gè)判斷稠曼,只有存在才去渲染
        <div>{slots.header ? slots.header() : null}</div>
      </div>
    }
  }
})

在父組件:
const slots = {
  default: () => {
    return <div>超人鴨</div>
  },
  header: () => {
    return <div>header</div>
  }
}
<children v-slots={slots}>
</children>

使用jsx后其實(shí)比較清晰形病,父組件傳遞給子組件的插槽其實(shí)是個(gè)函數(shù),然后在子組件里面執(zhí)行霞幅,渲染函數(shù)返回的dom漠吻,還有一個(gè)注意的地方,在子組件中寫slots要單獨(dú)包裹一個(gè)標(biāo)簽司恳。
作用域插槽:
上面在說具名插槽的時(shí)候說到途乃,插槽其實(shí)就是子組件中去執(zhí)行父組件傳遞進(jìn)來的函數(shù),那把父組件中要使用子組件中的變量只需要把變量放在函數(shù)的參數(shù)上就可以扔傅。

在子組件:
export default defineComponent({
  setup (props, { slots }) {
    const list = reactive(
      ['1', '2', '3']
    )
    return () => {
      return <div>
        <div>{slots}</div>
        <div>{slots.header ? slots.header() : null}</div>
        <div>{slots.list ? slots.list(list) : null}</div>
      </div>
    }
  }
})

在父組件:
const slots = {
  default: () => {
    return <div>超人鴨</div>
  },
  header: () => {
    return <div>header</div>
  },
  list: (list: Array<any>) => {
    return list.map((item) => {
      return <div>{item}</div>
    })
  }
}
<children v-slots={slots}>
</children>

渲染:


image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末耍共,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子猎塞,更是在濱河造成了極大的恐慌试读,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荠耽,死亡現(xiàn)場(chǎng)離奇詭異钩骇,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)铝量,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門倘屹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人慢叨,你說我怎么就攤上這事纽匙。” “怎么了拍谐?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵烛缔,是天一觀的道長(zhǎng)馏段。 經(jīng)常有香客問我,道長(zhǎng)践瓷,這世上最難降的妖魔是什么毅弧? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮当窗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘寸宵。我一直安慰自己崖面,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布梯影。 她就那樣靜靜地躺著巫员,像睡著了一般。 火紅的嫁衣襯著肌膚如雪甲棍。 梳的紋絲不亂的頭發(fā)上简识,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音感猛,去河邊找鬼七扰。 笑死,一個(gè)胖子當(dāng)著我的面吹牛陪白,可吹牛的內(nèi)容都是我干的颈走。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼咱士,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼立由!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起序厉,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤锐膜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后弛房,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體道盏,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年庭再,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捞奕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拄轻,死狀恐怖颅围,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情恨搓,我是刑警寧澤院促,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布筏养,位于F島的核電站,受9級(jí)特大地震影響常拓,放射性物質(zhì)發(fā)生泄漏渐溶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一弄抬、第九天 我趴在偏房一處隱蔽的房頂上張望茎辐。 院中可真熱鬧,春花似錦掂恕、人聲如沸拖陆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)依啰。三九已至,卻和暖如春店枣,著一層夾襖步出監(jiān)牢的瞬間速警,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工鸯两, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留闷旧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓钧唐,卻偏偏與公主長(zhǎng)得像鸠匀,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子逾柿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容