vue3 做一個(gè)后臺(tái)管理用的輕量級(jí)路由 + 菜單

Vue3 的后臺(tái)管理的項(xiàng)目想要做個(gè)菜單的話熟掂,一般會(huì)使用 VueRouter 設(shè)置路由嗜侮,然后用UI庫的菜單組件(比如 el-menu)設(shè)置各種屬性稽犁,然后還需要考慮權(quán)限等問題沮翔。
這樣做雖然很靈活陨帆,但是對(duì)于簡(jiǎn)單項(xiàng)目就有點(diǎn)麻煩。那么我們能不能簡(jiǎn)化一下操作鉴竭,只設(shè)置一次歧譬,就可以實(shí)現(xiàn)菜單、路由外加權(quán)限的功能呢搏存?

技術(shù)棧 / 基礎(chǔ)工具

  • vue3,script setup
  • 動(dòng)態(tài)組件矢洲、異步組件
  • window.history
  • element-plus:el-menu璧眠、el-tabs

在線演示

https://naturefw.gitee.io/nf-rollup-ui-controller
可以來這里看看效果,好吧其實(shí)也沒啥特別的读虏,看效果也沒啥區(qū)別责静,只是使用的時(shí)候比較很方便。

源碼

https://gitee.com/naturefw/nf-rollup-ui-controller

思路

首先模仿 VueRouter 設(shè)置一個(gè)路由盖桥,這里簡(jiǎn)化一下灾螃,只考慮單層路由。然后再設(shè)置上菜單需要的屬性揩徊。
因?yàn)橐龆?jí)菜單腰鬼,所以再設(shè)置一個(gè)分組信息,另外再加上圖標(biāo)(icon)的設(shè)置塑荒,這樣基本就夠用了熄赡。
然后設(shè)置頁面布局,根據(jù)設(shè)置綁定菜單(el-menu)齿税,加載組件即可彼硫。

設(shè)置路由和菜單

import { defineAsyncComponent } from 'vue'
import home from './home.vue'
import { Loading, Connection, Edit, FolderOpened } from '@element-plus/icons'

// 基礎(chǔ)路徑
const baseUrl = '/nf-rollup-ui-controller'

/**
 * 一級(jí)菜單,設(shè)計(jì)包含哪些二級(jí)菜單
 */
const group = [
  {
    id: 1,
    title: '基礎(chǔ)控件',
    icon: FolderOpened,
    children: [
      'base_html',
      'base_ui',
      'base_transmit',
      'base_item'
    ]
  },
  {
    id: 2,
    title: '復(fù)合控件',
    icon: FolderOpened,
    children: [
      'nf_form',
      'nf_find',
      'nf_grid',
      'nf_button',
      'nf_crud'
    ]
  }
]

/**
 * 二級(jí)菜單凌箕,設(shè)置路徑拧篮、標(biāo)題、圖標(biāo)和加載的組件
 */
const routes = {
  base_html: {
    path: '/base-html',
    title: '原生HTML',
    icon: Edit,
    component: () => import('./ui/base/c-01html.vue')
  },
  base_ui: {
    path: '/base-ui',
    title: 'UI庫組件',
    icon: Edit,
    component: () => import('./ui/base/c-02UI.vue')
  },
  base_transmit: {
    path: '/base-transmit',
    title: '傳聲筒',
    icon: '',
    component: () => import('./ui/base/c-03transmit.vue')
  } 
}

  • 設(shè)置基礎(chǔ)路徑
    本地開發(fā)可以使用根目錄牵舱,但是項(xiàng)目發(fā)布后可能無法使用根目錄了串绩,這時(shí)候就需要設(shè)置一個(gè)基礎(chǔ)路徑,以應(yīng)對(duì)只能使用二級(jí)目錄的情況仆葡。

  • 預(yù)留權(quán)限接口
    這里的 children 只是記錄了路由的 key 赏参,而不是完整的路由配置志笼,這樣設(shè)計(jì)是為了以后可以方便的加上權(quán)限,可以按照權(quán)限過濾掉沒有權(quán)限的路由(模塊)的key把篓,這樣加權(quán)限就方便多了纫溃。

  • 圖標(biāo)的設(shè)置方式
    因?yàn)?element-plus 使用“組件”形式的圖標(biāo),所以還得用動(dòng)態(tài)組件的方式來加載圖標(biāo)韧掩,需要在設(shè)置的地方引入需要的圖標(biāo)紊浩,然后設(shè)置到菜單的屬性里面,這樣就可以實(shí)現(xiàn)圖標(biāo)的設(shè)置了疗锐。

  • 組件的設(shè)置
    采用異步組件(defineAsyncComponent)來加載需要的組件坊谁,設(shè)置方式和 VueRouter 保持一致。

設(shè)計(jì)加載組件和刷新的處理方法

然后設(shè)計(jì)兩個(gè)函數(shù)滑臊,一個(gè)是加載組件的口芍,一個(gè)是頁面刷新后根據(jù) url路徑 加載組件的函數(shù)盈罐。

// 加載路由指定的組件
const getComponent = (key) => {
  const route = routes[key]
  if (route) {
    // 設(shè)置標(biāo)題
    document.title = route.title
    // 設(shè)置url地址
    window.history.pushState(null, null, baseUrl + route.path)
    // 返回組件
    return defineAsyncComponent(route.component)
  } else {
    return home
  }
}

// 刷新時(shí)依據(jù)url加載組件
const refresh = (cb) => {
  const path = window.location.pathname
  if (path === '/' || path === baseUrl) {
    // 首頁
  } else {
    const tmp = path.replace(baseUrl, '')
    // 加載組件
    for (const key in routes) {
      const route = routes[key]
      if (route.path === tmp) {
        if (typeof cb === 'function'){
          cb(key)
        }
        break
      }
    }
  }
}

// 導(dǎo)出配置和函數(shù)
export {
  group,
  routes,
  getComponent,
  refresh
}
  • 設(shè)置標(biāo)題和 URL 地址
    點(diǎn)擊菜單抓艳,加載組件,順便設(shè)置一下瀏覽器的標(biāo)題和 URL 的路徑娜饵。
    雖然現(xiàn)在瀏覽器都是標(biāo)簽的形式关划,沒有太大的空間顯示標(biāo)題小染,不過設(shè)置一下標(biāo)題也不麻煩。
    然后用 window.history.pushState 設(shè)置一下瀏覽器的 URL 路徑贮折,這樣設(shè)置不會(huì)導(dǎo)致瀏覽器向服務(wù)器請(qǐng)求頁面裤翩。

  • 刷新自動(dòng)加載組件
    刷新頁面后如果不做設(shè)置的話,是不會(huì)依據(jù) URL 加載對(duì)應(yīng)的組件的调榄,所以還需要我們寫個(gè)函數(shù)處理一下踊赠。
    首先獲取 URL 的路徑(pathName),然后到路由設(shè)置里面查找對(duì)應(yīng)的組件振峻,然后加載即可臼疫。
    這里做了一個(gè)回調(diào)函數(shù),可以更方便一些扣孟。

綁定菜單

做一個(gè)菜單的組件烫堤,比如叫做 menu.vue,引入上面的設(shè)置凤价,然后綁定到 el-menu 上面鸽斟。

  <el-menu
    class="el-menu-vertical-demo"
    @select="select"
    background-color="#6c747c"
    text-color="#fff"
    active-text-color="#ffd04b"
  >
    <el-sub-menu v-for="(item, index) in group"
      :key="index"
      :index="item.id"
    >
      <template #title>
        <component
          :is="item.icon"
          style="width: 1.5em; height: 1.5em; margin-right: 8px;"
        >
        </component>
        <span>{{item.title}}</span>
      </template>
      <el-menu-item v-for="(key, index) in item.children"
        :key="index"
        :index="key">
        <template #title>
          <component
            :is="routes[key].icon"
            style="width: 1.5em; height: 1.5em; margin-right: 8px;"
          >
          </component>
          {{routes[key].title}}
        </template>
      </el-menu-item>
    </el-sub-menu>
  </el-menu>

使用動(dòng)態(tài)組件(component)加載圖標(biāo) ,其他的按照 el-menu 的要求進(jìn)行設(shè)置即可利诺,這樣一個(gè)簡(jiǎn)單的二級(jí)菜單就做好了富蓄。

然后設(shè)置一個(gè)組件屬性,用于傳遞選擇的菜單慢逾。


const props = defineProps({
  events: Object
})
const events = props.events

// 二級(jí)菜單被選中
const select = (index, indexPath) => {
  events.currIndex = index  // 路由的key
}

設(shè)計(jì)頁面布局

采用 el-container 做頁面布局立倍,左面是菜單灭红,右面加載對(duì)應(yīng)的組件。

  <el-container>
    <el-aside width="200px">
      <!--菜單-->
      <nf-menu :events="events" />
    </el-aside>
    <el-main>
      <!--二級(jí)導(dǎo)航-->
      <component
        :is="getComponent(events.currIndex)"
      >
      </component>
    </el-main>
  </el-container>

引入配置和函數(shù)口注,設(shè)置選擇的菜單的對(duì)象变擒,這樣就可以了。


const events = reactive({
  currIndex: ''
})

refresh((key) => {
  events.currIndex = key
})

加上權(quán)限過濾

設(shè)計(jì)權(quán)限的時(shí)候寝志,需要標(biāo)注可以訪問哪些菜單娇斑,也就是組件,然后設(shè)置好對(duì)應(yīng)的菜單(路由)的 key 即可材部。綁定的地方換成過濾后的數(shù)組即可毫缆。

實(shí)現(xiàn)多tab標(biāo)簽頁

上面的方法是實(shí)現(xiàn)了“單頁”的方式,點(diǎn)一個(gè)菜單加載一個(gè)組件乐导,再點(diǎn)一個(gè)菜單苦丁,替換掉原來的組件。
如果想做成 tab 標(biāo)簽頁的形式要怎么做呢物臂?
其實(shí)也很簡(jiǎn)單芬骄,我們只需要增加一個(gè) 數(shù)組 (Set,tabs) 用于存放點(diǎn)擊過的菜單的key鹦聪,然后依據(jù) tabs 綁定 el-tabs 即可。

  • 設(shè)置容器和監(jiān)聽
const tabs = reactive(new Set([])) // 點(diǎn)擊過且沒有關(guān)閉的二級(jí)菜單蒂秘,做成動(dòng)態(tài)tab標(biāo)簽

// 監(jiān)聽當(dāng)前路由泽本,設(shè)置 tabs
    watch(() =>currentRoute.key, (key) => {
      tabs.add(key)
      const route = this.routes[key] ?? {title: '首頁', path: '/'}
      // 設(shè)置標(biāo)題
      document.title = route.title
      // 設(shè)置url地址
      window.history.pushState(null, null, this.baseUrl + route.path)
    })
  • 綁定el-tabs
  <el-tabs
    v-model="currentRoute.key"
    type="card"
  >
    <el-tab-pane
      v-for="key in tabs"
      :key="key"
      :label="routes[key].title"
      :name="key"
    >
     <template #label>
        <span>{{routes[key].title}} &nbsp; 
          <circle-close-filled
            style="width: 1.0em; height: 1.0em; margin-top: 8px;"
            @click.stop="removeTab(key)" />
        </span>
      </template>
      <component :is="routerControl[key]">
      </component>
    </el-tab-pane>
  </el-tabs>

這樣就可以了。

把零散的代碼封裝成 函數(shù)庫 + 組件

基本功能測(cè)試通過姻僧,回顧一下代碼规丽,還是有一些麻煩,我們可以進(jìn)一步封裝一下:

  • 路由+菜單的函數(shù)庫
  • 菜單組件(nf-menu)
  • 路由視圖——單頁(router-view)
  • 路由視圖——tabs(router-view-tabs)

這樣封裝之后就方便多了撇贺,另外順便重構(gòu)一下代碼赌莺。

路由的函數(shù)庫

我們可以用 ES6 的 class 來定義,實(shí)現(xiàn)各種基礎(chǔ)功能松嘶。

import { defineAsyncComponent, reactive, watch, inject } from 'vue'

const flag = Symbol('nf-router-menu___')

/**
 * 一個(gè)簡(jiǎn)單的路由
 * @param {*} baseUrl 基礎(chǔ)路徑
 * @param {*} routes 路由設(shè)置
 * * {
 * *   base_html: { // 路由的 name
 * *     path: '/base-html',
 * *     title: '原生HTML',
 * *     icon: Edit,
 * *     component: () => import('./ui/base/c-01html.vue')
 * *   },
 * *   其他路由設(shè)置 
 * * }
 * @returns 
 */
class Router {
  constructor (info) {
    // 設(shè)置當(dāng)前選擇的路由
    this.currentRoute = reactive({
      key: ''
    })
    this.baseUrl = info.baseUrl // 基礎(chǔ)路徑艘狭,應(yīng)對(duì)網(wǎng)站的二級(jí)目錄
    this.home = info.home // 默認(rèn)的首頁
    this.group = info.group // 一級(jí)菜單,分組翠订,設(shè)置包含的二級(jí)菜單(路由)
    this.routes = info.routes // 路由設(shè)置巢音,二級(jí)菜單
    /**
     * 'key', 'key' // 保存路由的key(name)
     */
    this.tabs = reactive(new Set([])) // 點(diǎn)擊過且沒有關(guān)閉的二級(jí)菜單,做成動(dòng)態(tài)tab標(biāo)簽
    // 把路由里的組件轉(zhuǎn)換一下
    this.routerControl = {}
    this.setup()
  }
  /**
   * 初始化設(shè)置
   */
  setup = () => {
    // 監(jiān)聽當(dāng)前路由尽超,設(shè)置 tabs
    watch(() => this.currentRoute.key, (key) => {
      if (key !== 'main' ) this.tabs.add(key)
      const route = this.routes[key] ?? {title: '首頁', path: '/'}
      // 設(shè)置標(biāo)題
      document.title = route.title
      // 設(shè)置url地址
      window.history.pushState(null, null, this.baseUrl + route.path)
    })
    // 把路由里的組件轉(zhuǎn)換一下
    for (const key in this.routes) {
      const r = this.routes[key]
      this.routerControl[key] = defineAsyncComponent(r.component)
    }
  }
  // 加載路由指定的組件
  getComponent = () => {
    if (this.currentRoute.key === '') {
      return this.home
    } else {
      const route = this.routes[this.currentRoute.key]
      if (route) {
        // 返回組件
        return defineAsyncComponent(route.component)
      }
    }
  }
  // 刪除tab
  removeTab = (key) => {
    // 轉(zhuǎn)換為數(shù)組官撼,便于操作
    const arr = Array.from(this.tabs)
    
    if (arr.length === 1) {
      // 只有一個(gè)tab,刪除后激活桌面
      this.tabs.delete(key)
      this.currentRoute.key = 'home'
      return
    }

    // 判斷是否當(dāng)前tab似谁,如果是當(dāng)前tab傲绣,激活左面或者右面的tab
    if (this.currentRoute.key === key) {
      // 查找當(dāng)前tab的數(shù)組序號(hào)
      const index = arr.indexOf(key)
      // 判斷當(dāng)前tab的位置
      if (index === 0) {
        // 第一位掠哥,激活后面的
        this.currentRoute.key = arr[1]
      } else {
        // 激活前面的
        this.currentRoute.key = arr[index - 1]
      }
    }
    // 刪除
    this.tabs.delete(key)
  }

  // 刷新時(shí)依據(jù)url加載組件
  refresh = () => {
    const path = window.location.pathname
    if (path === '/' || path === this.baseUrl) {
      // 首頁
    } else {
      const tmp = path.replace(this.baseUrl, '')
      // 驗(yàn)證路由
      for (const key in this.routes) {
        const route = this.routes[key]
        if (route.path === tmp) {
          this.currentRoute.key = key
          break
        }
      }
    }
  }
}

/**
 * 創(chuàng)建簡(jiǎn)易路由
 */
const createRouter = (info) => {
  // 創(chuàng)建路由,
  const router = new Router(info)
  // 使用vue的插件秃诵,設(shè)置全局路由
  return (app) => {
    // 便于模板獲取
    app.config.globalProperties.$router = router
    // 便于代碼獲取
    app.provide(flag, router)
  }
}
// 在代碼里獲取路由
const useRouter = () => {
  return inject(flag)
}

export {
  createRouter,
  useRouter
}

首先定義一個(gè)class续搀,存放需要的各種屬性和處理方法,然后做一個(gè)Vue的插件顷链,便于做初始化的設(shè)置和全局變量目代。最后做一個(gè)獲取路由的函數(shù)即可。

菜單組件:nf-menu

  <el-menu
    ref="domMenu"
    class="el-menu-vertical-demo"
    default-active="1"
    @select="(index) => {$router.currentRoute.key = index}"
    background-color="#6c747c"
    text-color="#fff"
    active-text-color="#ffd04b"
  >
    <el-sub-menu v-for="(item, index) in $router.group"
      :key="index"
      :index="item.id"
    >
      <template #title>
        <component
          :is="item.icon"
          style="width: 1.5em; height: 1.5em; margin-right: 8px;"
        >
        </component>
        <span>{{item.title}}</span>
      </template>
      <el-menu-item v-for="(key, index) in item.children"
        :key="index"
        :index="key">
        <template #title>
          <component
            :is="$router.routes[key].icon"
            style="width: 1.5em; height: 1.5em; margin-right: 8px;"
          >
          </component>
          {{$router.routes[key].title}}
        </template>
      </el-menu-item>
    </el-sub-menu>
  </el-menu>

封裝的不夠細(xì)致嗤练,主要目的是可以偷懶用著方便就好榛了。
不求靈活,只求方便煞抬,簡(jiǎn)單粗暴的實(shí)現(xiàn)功能即可霜大。

單頁路由視圖:router-view

<template>
  <component :is="$router.getComponent()">
  </component>
</template>

這個(gè)就很簡(jiǎn)單了,用動(dòng)態(tài)組件加載需要的組件即可革答。

動(dòng)態(tài)tab標(biāo)簽頁:router-view-tabs

  <el-tabs
    v-model="$router.currentRoute.key"
    type="card"
  >
    <el-tab-pane label="桌面" :name="main">
      <component :is="$router.home">
      </component>
    </el-tab-pane>
    <el-tab-pane
      v-for="key in $router.tabs"
      :key="key"
      :label="$router.routes[key].title"
      :name="key"
    >
     <template #label>
        <span>{{$router.routes[key].title}} &nbsp; 
          <circle-close-filled
            style="width: 1.0em; height: 1.0em; margin-top: 8px;"
            @click.stop="$router.removeTab(key)" />
        </span>
      </template>
      <component :is="$router.routerControl[key]">
      </component>
    </el-tab-pane>
  </el-tabs>

這個(gè)稍微復(fù)雜一點(diǎn)战坤,用屬性綁定 el-tabs,設(shè)置屬性残拐、圖標(biāo)和事件 途茫。

在項(xiàng)目里的使用方法

首先定義一個(gè)路由,然后在 main.js 里面掛載溪食。然后布局里面加載組件即可囊卜。

  • 定義路由和菜單
    /router/index.js
import { Loading, Connection, Edit, FolderOpened } from '@element-plus/icons'
import { createRouter } from '/nf-ui-core'
import home from '../views/home.vue'

export default createRouter({
  /**
   * 基礎(chǔ)路徑
   */
  baseUrl: '/nf-rollup-ui-controller',
  /**
   * 首頁
   */
  home: home,
  /**
   * 一級(jí)菜單,設(shè)計(jì)包含哪些二級(jí)菜單
   */
  group = [
    {
      id: 1,
      title: '基礎(chǔ)控件',
      icon: FolderOpened,
      children: [
        'base_html',
        'base_ui',
        'base_transmit',
        'base_item'
      ]
    },
    {
      id: 2,
      title: '復(fù)合控件',
      icon: FolderOpened,
      children: [
        'nf_form',
        'nf_find',
        'nf_grid',
        'nf_button',
        'nf_crud'
      ]
    }
  ],

  /**
   * 二級(jí)菜單错沃,設(shè)置路徑栅组、標(biāo)題、圖標(biāo)和加載的組件
   */
  routes = {
    base_html: {
      path: '/base-html', title: '原生HTML', icon: Edit,
      component: () => import('../views/ui/base/c-01html.vue')
    },
    base_ui: {
      path: '/base-ui', title: 'UI庫組件', icon: Edit,
      component: () => import('../views//ui/base/c-02UI.vue')
    }, 
    ... 略
  }
})
  • 在 main.js 里掛載路由和組件
import { createApp } from 'vue'
import App from './App.vue'

// 基于element-plus 二次封裝的組件
import { nfElementPlus } from '/nf-ui-elp'

// 簡(jiǎn)易路由
import router from './router'

createApp(App)
  .use(nfElementPlus) // 全局注冊(cè)組件
  .use(router) // 注冊(cè)路由
  .mount('#app')
  • 在App.vue 里面做頁面布局
  <el-container>
    <el-aside width="200px">
      <!--菜單-->
      <nf-menu/>
    </el-aside>
    <el-main>
      <el-radio-group v-model="routerKind" size="mini">
        <el-radio-button label="單頁"></el-radio-button>
        <el-radio-button label="tabs"></el-radio-button>
      </el-radio-group> 可以切換單頁模式枢析、動(dòng)態(tài)tab模式
      <hr>
      <!--路由視圖-->
      <router-view v-if="routerKind === '單頁'"></router-view>
      <router-view-tabs v-if="routerKind === 'tabs'"></router-view-tabs>
    </el-main>
  </el-container>

這里為了演示玉掸,用了兩種模式,項(xiàng)目里選擇一個(gè)喜歡的就好醒叁。

是不是很簡(jiǎn)單司浪,把繁瑣的操作都封裝好,以后再用就簡(jiǎn)單多了辐益,只需要定義路由就好断傲。

疑問

  • 單層路由夠用嗎?
    對(duì)于我來說夠用了智政,如果以后發(fā)現(xiàn)有不夠用的地方還可以繼續(xù)完善认罩,不過肯定不會(huì)完善到 VueRouter 的程度,因?yàn)槟菢拥脑捫妫瑸樯恫恢苯佑?VueRouter 垦垂?

  • 太簡(jiǎn)陋了吧宦搬?
    是的,比較簡(jiǎn)陋劫拗,目前只是練練手间校,方便實(shí)現(xiàn)一些小功能的演示。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末页慷,一起剝皮案震驚了整個(gè)濱河市憔足,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌酒繁,老刑警劉巖滓彰,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異州袒,居然都是意外死亡揭绑,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門郎哭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來他匪,“玉大人,你說我怎么就攤上這事夸研“蠲郏” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵亥至,是天一觀的道長(zhǎng)畦徘。 經(jīng)常有香客問我,道長(zhǎng)抬闯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任关筒,我火速辦了婚禮溶握,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蒸播。我一直安慰自己睡榆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布袍榆。 她就那樣靜靜地躺著胀屿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪包雀。 梳的紋絲不亂的頭發(fā)上宿崭,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音才写,去河邊找鬼葡兑。 笑死奖蔓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的讹堤。 我是一名探鬼主播吆鹤,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼洲守!你這毒婦竟也來了疑务?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤梗醇,失蹤者是張志新(化名)和其女友劉穎知允,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體婴削,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡廊镜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了唉俗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗤朴。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖虫溜,靈堂內(nèi)的尸體忽然破棺而出雹姊,到底是詐尸還是另有隱情,我是刑警寧澤衡楞,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布吱雏,位于F島的核電站,受9級(jí)特大地震影響瘾境,放射性物質(zhì)發(fā)生泄漏歧杏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一迷守、第九天 我趴在偏房一處隱蔽的房頂上張望犬绒。 院中可真熱鬧,春花似錦兑凿、人聲如沸凯力。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咐鹤。三九已至,卻和暖如春圣絮,著一層夾襖步出監(jiān)牢的瞬間祈惶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留行瑞,地道東北人奸腺。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像血久,于是被迫代替她去往敵國(guó)和親突照。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

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