Vue項(xiàng)目的提升開(kāi)發(fā)速度

現(xiàn)如今的開(kāi)發(fā),比如是內(nèi)部使用的管理平臺(tái)這種項(xiàng)目大都時(shí)間比較倉(cāng)倉(cāng)促。實(shí)際上來(lái)說(shuō)在使用了webpack + vue 這一套來(lái)開(kāi)發(fā)的話已經(jīng)大大了提高了效率。但是對(duì)于我們的開(kāi)發(fā)層面。還是有很多地方可以再次提高我們的項(xiàng)目開(kāi)發(fā)效率,讓我們更加專注于業(yè)務(wù),畢竟時(shí)間就是生命。下面我們挨個(gè)來(lái)探討。
巧用Webpack

Webpack是實(shí)現(xiàn)我們前端項(xiàng)目工程化的基礎(chǔ),但其實(shí)她的用處遠(yuǎn)不僅僅如此,我們可以通過(guò)Webpack來(lái)幫我們做一些自動(dòng)化的事情。首先我們要了解require.context()這個(gè)API

require.context()

您可以使用require.context()函數(shù)創(chuàng)建自己的上下文。 它允許您傳入一個(gè)目錄進(jìn)行搜索,一個(gè)標(biāo)志指示是否應(yīng)該搜索子目錄,還有一個(gè)正則表達(dá)式來(lái)匹配文件。

其實(shí)是Webpack通過(guò)解析 require() 的調(diào)用,提取出來(lái)如下這些信息:

Directory: ./template
Regular expression: /^.*\.ejs$/

然后來(lái)創(chuàng)建我們自己的上下文,什么意思呢,就是我們可以通過(guò)這個(gè)方法篩選出來(lái)我們需要的文件并且讀取

下面我們來(lái)簡(jiǎn)單看一看使用:

/**
* @param directory 要搜索的文件夾目錄不能是變量,否則在編譯階段無(wú)法定位目錄
* @param useSubdirectories  是否搜索子目錄
* @param regExp 匹配文件的正則表達(dá)式
* @return function 返回一個(gè)具有 resolve, keys, id 三個(gè)屬性的方法
          resolve() 它返回請(qǐng)求被解析后得到的模塊 id
          keys() 它返回一個(gè)數(shù)組,由所有符合上下文模塊處理的請(qǐng)求組成。 
          id 是上下文模塊里面所包含的模塊 id. 它可能在你使用 module.hot.accept 的時(shí)候被用到
*/
require.context('demo', useSubdirectories = false, regExp = /\.js$/)
// (創(chuàng)建了)一個(gè)包含了 demo 文件夾(不包含子目錄)下面的、所有文件名以 `js` 結(jié)尾的、能被 require 請(qǐng)求到的文件的上下文。

不要困惑,接下來(lái)我們來(lái)探討在項(xiàng)目中怎么用。

組織路由

對(duì)于Vue中的路由,大家都很熟悉,類似于聲明式的配置文件,其實(shí)已經(jīng)很簡(jiǎn)潔了。現(xiàn)在我們來(lái)讓他更簡(jiǎn)潔

  1. 分割路由
    首先為了方便我們管理,我們把router目錄下的文件分割為以下結(jié)構(gòu)
router                           // 路由文件夾
  |__index.js                    // 路由組織器:用來(lái)初始化路由等等
  |__common.js                   // 通用路由:聲明通用路由
  |__modules                     // 業(yè)務(wù)邏輯模塊:所以的業(yè)務(wù)邏輯模塊
        |__index.js              // 自動(dòng)化處理文件:自動(dòng)引入路由的核心文件
        |__home.js               // 業(yè)務(wù)模塊home:業(yè)務(wù)模塊
        |__a.js                  // 業(yè)務(wù)模塊a

  1. modules文件夾中處理業(yè)務(wù)模塊

modules文件夾中存放著我們所有的業(yè)務(wù)邏輯模塊,至于業(yè)務(wù)邏輯模塊怎么分,我相信大家自然有自己的一套標(biāo)準(zhǔn)。我們通過(guò)上面提到的require.context()接下來(lái)編寫自動(dòng)化的核心部分index.js

const files = require.context('.', true, /\.js$/)

console.log(files.keys()) // ["./home.js"] 返回一個(gè)數(shù)組
let configRouters = []
/**
* inject routers
*/
files.keys().forEach(key => {
  if (key === './index.js') return
  configRouters = configRouters.concat(files(key).default) // 讀取出文件中的default模塊
})
export default configRouters // 拋出一個(gè)Vue-router期待的結(jié)構(gòu)的數(shù)組

自動(dòng)化部分寫完了,那業(yè)務(wù)組件部分怎么寫? 這就更簡(jiǎn)單了

import Frame from '@/views/frame/Frame'
import Home from '@/views/index/index'
export default [
    // 首頁(yè)
    {
      path: '/index',
      name: '首頁(yè)',
      redirect: '/index',
      component: Frame, 
      children: [ // 嵌套路由
        {
          path: '',
          component: Home
        }
      ]
    }
]

  1. common路由處理 我們的項(xiàng)目中有一大堆的公共路由需要處理比如404阿,503阿等等路由我們都在common.js中進(jìn)行處理。
export default [
  // 默認(rèn)頁(yè)面
  {
    path: '/',
    redirect: '/index',
    hidden:true
  },
  // 無(wú)權(quán)限頁(yè)面
  {
    path: '/nopermission',
    name: 'nopermission',
    component: () => import('@/views/NoPermission')
  },
  // 404
  {
    path: '*',
    name: 'lost',
    component: () => import('@/views/404')
  }
]

  1. 路由初始化 這是我們的最后一步了,用來(lái)初始化我們的項(xiàng)目路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import RouterConfig from './modules' // 引入業(yè)務(wù)邏輯模塊
import CommonRouters from './common' // 引入通用模塊
Vue.use(VueRouter)
export default new VueRouter({
  mode: 'history',// 需要服務(wù)端支持
  scrollBehavior: () => ({ y: 0 }),
  routes: RouterConfig.concat(CommonRouters)
})

估計(jì)有些朋友代碼寫到這還不知道到底這樣做好處在哪里。我們來(lái)描述一個(gè)場(chǎng)景,比如按照這種結(jié)構(gòu)來(lái)劃分模塊。正常的情況是我們創(chuàng)建完home.js要手動(dòng)的把這個(gè)模塊import到路由文件聲明的地方去使用。但是有了上面的index.js,在使用的時(shí)候你只需要去創(chuàng)建一個(gè)home.js并拋出一個(gè)符合VueRouter規(guī)范的數(shù)組,剩下的就不用管了。import RouterConfig from './modules' // 引入業(yè)務(wù)邏輯模塊 已經(jīng)幫你處理完了。另外擴(kuò)展的話你還可以把hooks拿出來(lái)作為一個(gè)單獨(dú)文件。

全局組件統(tǒng)一聲明

同樣的道理,有了上面的經(jīng)驗(yàn),我們照葫蘆畫瓢來(lái)處理一下我們的全局組件。這就沒(méi)什么可說(shuō)的了,直接上核心代碼

1.組織結(jié)構(gòu)

components                       // 組件文件夾
  |__xxx.vue                     // 其他組件
  |__global                      // 全局組件文件夾
        |__index.js              // 自動(dòng)化處理文件
        |__demo.vue              // 全局demo組件

2.global處理

import Vue from 'vue'
let contexts = require.context('.', false, /\.vue$/)
contexts.keys().forEach(component => {
  let componentEntity = contexts(component).default
  // 使用內(nèi)置的組件名稱 進(jìn)行全局組件注冊(cè)
  Vue.component(componentEntity.name, componentEntity)
})

  1. 使用和說(shuō)明
    這個(gè)使用起來(lái)就更簡(jiǎn)單了,直接在app.js引用這個(gè)文件就行。

注意:我之前看到有些人做法是使用組件名去區(qū)分全局組件和普通組件,然后通過(guò)正則去判斷需不需要全局注冊(cè)。我是直接把全局的組件放到global文件夾下,然后組件的注冊(cè)名稱直接使用component.name。至于使用哪種方式就比較看個(gè)人了。

充分利用NodeJS

放著node這么好得東西不用真是有點(diǎn)浪費(fèi),那么我們來(lái)看看node能為我們?cè)黾有首龀鍪裁簇暙I(xiàn)。

有這么一個(gè)場(chǎng)景,我們每次創(chuàng)建模塊的時(shí)候都要新建一個(gè)vue文件和對(duì)應(yīng)的router配置,而且新頁(yè)面的大部分東西都還差不多,還得去復(fù)制粘貼別得頁(yè)面。這想想就有點(diǎn)low。那既然有了node我們可不可以通過(guò)node來(lái)做這寫亂七八糟得事情? 下面來(lái)把我們的想法付諸于顯示。

我們實(shí)現(xiàn)這個(gè)功能主要要借助Nodefsprocess, 感興趣的話可以深入研究一下。

首先我們要編寫我們的node腳本,這里是一個(gè)比較簡(jiǎn)單的版本。什么驗(yàn)證文件夾或者文件的都沒(méi)有,只是來(lái)實(shí)現(xiàn)我們這個(gè)想法:

/*
 * fast add new module script
 */
const path = require('path')
const fs = require('fs')
const chalk = require('chalk')
const reslove = file => path.resolve(__dirname, '../src', file)
// symbol const
const RouterSymbol = Symbol('router'),
      ViewsSymbol = Symbol('views')
// root path
const rootPath = {
  [RouterSymbol]: reslove('router/modules'),
  [ViewsSymbol]: reslove('views')
}
//loggs
const errorLog = error => console.log(chalk.red(`${error}`))
const defaultLog = log => console.log(chalk.green(`${log}`))
// module name
let moduleName = new String()
let fileType = new String()
//const string
const vueFile = module => (`<template>

</template>

<script>
export default {
  name: '${module}',
  data () {
    return {

    }
  },
  methods: {

  },
  created() {
    
  }
}
</script>

<style lang="less">

</style>
`)
// route file
const routerFile = module => (`// write your comment here...
export default [
  {
    path: '/${module}',
    name: '',
    redirect: '/${module}',
    component: () => import('@/views/frame/Frame'),
    children: [
      {
        path: '',
        fullPath: '',
        name: '',
        component: () => import('@/views/${module}/index')
      }
    ]
  }
]
`)
/**
 * generate file
 * @param {*} filePath 
 * @param {*} content 
 * @param {*} dirPath 
 */
const generateFile = async (filePath, content, dirPath = '') =>{
  try {
    // create file if file not exit
    if (dirPath !== '' && ! await fs.existsSync(dirPath)) {
      await fs.mkdirSync(dirPath)
      defaultLog(`created ${dirPath}`)
    }
    if (! await fs.existsSync(filePath)) {
      // create file
      await fs.openSync(filePath, 'w')
      defaultLog(`created ${filePath}`)
    }
    await fs.writeFileSync(filePath, content, 'utf8')
  } catch (error) {
    errorLog(error)
  }
}
// module-method map
const generates = new Map([
  ['view', async (module) => {
    // module file
    const filePath = path.join(rootPath[ViewsSymbol], module)
    const vuePath = path.join(filePath, '/index.vue')
    await generateFile(vuePath, vueFile(module), filePath)
  }],
  // router is not need new folder
  ['router',async (module) => {
    const routerPath = path.join(rootPath[RouterSymbol], `/${module}.js`)
    await generateFile(routerPath, routerFile(module))
  }]
])
defaultLog(`請(qǐng)輸入模塊名稱(英文):`)
// files
const files = ['view', 'router']
// 和命令行進(jìn)行交互 獲取的創(chuàng)建的模塊名稱
process.stdin.on('data', (chunk) => {
  try {
    if (!moduleName) {
      moduleName = chunk
    } else {
      chunk = chunk.slice(0,-2) // delete /n
      defaultLog(`new module name is ${chunk}`)
      files.forEach(async (el, index) => {
        // 執(zhí)行創(chuàng)建語(yǔ)句
        await generates.get(`${el}`).call(null, chunk.toString())
        if (index === files.length-1) {
          process.stdin.emit('end')
        }
      })
    }
  } catch (error) {
    errorLog(error)
  }
})
process.stdin.on('end', () => {
  defaultLog('create module success')
})

這樣我們就分別創(chuàng)建了vue和router的文件,而且已經(jīng)注入了內(nèi)容。按照我們提前聲明的組件
注意:這只是一個(gè)簡(jiǎn)單的思路,通過(guò)Node強(qiáng)大的文件處理能力,我們能做的事情遠(yuǎn)不止這些。

通用mixins

如果我們有大量的表格頁(yè)面,仔細(xì)一扒拉你發(fā)現(xiàn)非常多的東西都是可以復(fù)用的例如分頁(yè),表格高度,加載方法, laoding聲明等一大堆的東西。下面我們來(lái)整理出來(lái)一個(gè)簡(jiǎn)單通用混入list.js

const list = {
  data () {
    return {
      // 這些東西我們?cè)趌ist中處理,就不需要在每個(gè)頁(yè)面再去手動(dòng)的做這個(gè)了。
      loading: false, // 伴隨loading狀態(tài)
      pageNo: 1, // 頁(yè)碼
      pageSize: 15, // 頁(yè)長(zhǎng)
      totalCount: 0, // 總個(gè)數(shù)
      pageSizes: [15, 20, 25, 30], //頁(yè)長(zhǎng)數(shù)
      pageLayout: 'total, sizes, prev, pager, next, jumper', // 分頁(yè)布局
      list: []
    }
  },
  methods: {
    // 分頁(yè)回掉事件
    handleSizeChange(val) {
      this.pageSize = val
      // todo
    },
    handleCurrentChange (val) {
      this.pageNo = val
      // todo
    },
    /**
     * 表格數(shù)據(jù)請(qǐng)求成功的回調(diào) 處理完公共的部分(分頁(yè),loading取消)之后把控制權(quán)交給頁(yè)面
     * @param {*} apiResult 
     * @returns {*} promise
     */
    listSuccessCb (apiResult = {}) {
      return new Promise((reslove, reject) => {
        let tempList = [] // 臨時(shí)list
        try {
          this.loading = false
          // todo
          // 直接拋出
          reslove(tempList)
        } catch (error) {
          reject(error)
        }
      })
    },
    /**
     * 處理異常情況
     * ==> 簡(jiǎn)單處理  僅僅是對(duì)表格處理為空以及取消loading
     */
    listExceptionCb (error) {
      this.loading = false
      console.error(error)
    }
  },
  created() {
    // 這個(gè)生命周期是在使用組件的生命周期之前
    this.$nextTick().then(() => {
      // todo
    })
  }
}
export default list

下面我們直接在組件中使用這個(gè)mixins

import mixin from '@/mixins/list' // 引入
import {getList} from '@/api/demo'
export default {
  name: 'mixins-demo',
  mixins: [mixin], // 使用mixins
  data () {
    return {
    }
  },
  methods: {
    // 加載列表
    load () {
      const para = {
      }
      this.loading = true
      getList(para).then((result) => {
        this.listSuccessCb(result).then((list) => {
          this.list = list
        }).catch((err) => {
          console.log(err)
        })
      }).catch((err) => {
        this.listExceptionCb(err)
      })
    }
  },
  created() {
    this.load()
  }
}

使用了mixins之后一個(gè)簡(jiǎn)單的有l(wèi)oadoing, 分頁(yè),數(shù)據(jù)的表格大概就只需要上面這些代碼。

mixins做公共數(shù)據(jù)的管理

有些時(shí)候我們有一些公共的數(shù)據(jù)它可能3,4個(gè)模塊取使用但是又達(dá)不到全局的這種規(guī)模。這個(gè)時(shí)候我們就可以用mixins去管理他們,比如我們有幾個(gè)模塊要使用用戶類型這個(gè)列表,我們來(lái)看使用mixins來(lái)實(shí)現(xiàn)共享。

// types.js
import {getTypes} from '@/api/demo' // ajax
export default {
  data () {
    return {
      types: [] // ==>  {name: '', value: ''}
    }
  },
  methods: {
    // 獲取列表
    getAllTypesList () {
      getApiList().then((result) => {
        // todo
        this.types = result // 假設(shè)result就是我們需要使用的數(shù)據(jù)
      }).catch((err) => {
        console.error(err)
      })
    }
  },
  created() {
    // 在需要使用這個(gè)mixins的時(shí)候取自動(dòng)請(qǐng)求數(shù)據(jù)  這個(gè)可要可不要  你想在父組件中執(zhí)行也是ok的
    this.getAllTypesList()
  }
}

在組件中引用

import typeMixin from '@/mixins/types'
export default {
  name: 'template',
  mixins: [typeMixin],
  data () {
    return {
      // types這個(gè)數(shù)組在使用組件中不用多余的定義,直接拿來(lái)用就行
      type: ''
    }
  },
  methods: {
  }
}

至于mixins中得數(shù)據(jù)我們可以在組件中直接使用

<!--  -->
<el-select v-model="type" clearable placeholder="請(qǐng)選擇類型">
    <el-option v-for="item in types" :key="item.id" :label="item.templateName" :value="item.id"></el-option>
  </el-select>

我們這樣就可以不用vuex來(lái)去管理那些只有在模塊間復(fù)用幾次的數(shù)據(jù),而且非常方便得去取我們想要得數(shù)據(jù),連定義都省了。但是這有一個(gè)缺點(diǎn)。就是每次都會(huì)去重新請(qǐng)求這些數(shù)據(jù)。如果你不在乎這一點(diǎn)點(diǎn)瑕疵的話,我覺(jué)得用起來(lái)是完全ok得。
注意: mixins它固然是簡(jiǎn)單的,但是注釋和引用一定要做好,不然的話新成員進(jìn)入團(tuán)隊(duì)大概是一臉的懵逼,而且也不利于后期的維護(hù)。也是一把雙刃劍。另外:全局mixins一定要慎用,如果不是必須要用的話我還是不建議使用。

進(jìn)一步對(duì)組件進(jìn)行封裝

大家都知道組件化的最大的好處就是高度的可復(fù)用性和靈活性。但是組件怎么封裝好,封裝到什么程度讓我們更方便。這是沒(méi)有標(biāo)準(zhǔn)的答案的。我們只有根據(jù)高內(nèi)聚,低耦合的這個(gè)指導(dǎo)思想來(lái)對(duì)我們的業(yè)務(wù)通用組件來(lái)進(jìn)行封裝,讓我們的業(yè)務(wù)頁(yè)面結(jié)構(gòu)更加的簡(jiǎn)潔,加快我們的開(kāi)發(fā)效率。封裝多一點(diǎn)的話頁(yè)面可能會(huì)變成這樣:

<template>
  <box-content>
    <!-- 頭部標(biāo)題部分 -->
    <page-title>
      <bread slot="title" :crumbs="[{name: 'xx管理', path: '', active: true, icon: ''}, {name: 'xxxx', path: '', active: true, icon: ''}]"></bread>
    </page-title>
    <!-- 表格部分 -->
    <div>
      <base-table v-loading="loading" :columns="headers" :list="list" :page-no ="pageNo" :page-size="pageSize" :total-count="totalCount" @delete="deleteItm"  @change-size="handleSizeChange" @change-page="handleCurrentChange">
      </base-table>
    </div>
  </box-content>
</template>

有什么東西一目了然。

無(wú)狀態(tài)組件

最容易勾起我們封裝欲望的就是無(wú)狀態(tài)HTML組件,例如我們除去header, menu之后的content部分。沒(méi)有什么需要復(fù)雜的交互,但是我們每個(gè)頁(yè)面又都得寫。你說(shuō)不拿它開(kāi)刀拿誰(shuí)開(kāi)??

<template>
  <div class="container-fluid" :class="[contentClass]">
      <el-row>
          <el-col :span="24">
              <!-- box with #fff bg -->
              <div class="box">
                  <div class="box-body">
                      <slot></slot>
                  </div>
              </div>
          </el-col>
      </el-row>
  </div>
</template>
ElementUI table組件封裝

ElementUI中得組件其實(shí)已經(jīng)封裝得很優(yōu)秀了,但是表格使用得時(shí)候還是有一堆得代碼在我看來(lái)是不需要在業(yè)務(wù)中重復(fù)寫得。封裝到靠配置來(lái)進(jìn)行表格得書寫得一步我覺(jué)得就差不多了,下面是一個(gè)小demo

<template>
  <el-row>
    <el-col :span="24">
      <el-table :data="list" border size="mini" @selection-change="handleSelectionChange" :max-height="tableHeight" v-bind="$attrs"> <!--   -->
        <template v-for="(column, index) in columns">
          <slot name="front-slot"> </slot>
          <!-- 序號(hào) -->
          <el-table-column :key="index" v-if="column.type === 'selection'" type="selection" width="55"> </el-table-column>
          <!-- 復(fù)選框 -->
          <el-table-column :key="index" v-else-if="column.type === 'index'"  type="index" width="50" label="序號(hào)"> </el-table-column>
          <!-- 具體內(nèi)容 -->
          <el-table-column :key="index" v-else align="left" :label="column.title" :width="column.width">
            <template slot-scope="scope">
              <!-- 僅僅顯示文字 -->
              <label v-if="!column.hidden"> <!-- 如果hidden為true的時(shí)候 那么當(dāng)前格可以不顯示,可以選擇顯示自定義的slot-->
                <!-- 操作按鈕 -->
                <label v-if="column.type === 'operate'">
                  <a href="javascript:void(0)" class="operate-button" v-for="(operate, index) in column.operates" :key="index" @click="handleClick(operate, scope.row)">
                    {{operate.name}}
                    &nbsp;&nbsp;
                  </a>
                </label>
                <span v-else>
                  {{scope.row[column.key]}}
                </span>
              </label>
              <!-- 使用slot的情況下 -->
              <label v-if="column.slot">
                <!-- 具名slot -->
                <slot v-if="column.slot" :name="column.slot" :scope="scope"></slot>
              </label>
            </template>
          </el-table-column>
        </template>
        <!--默認(rèn)的slot -->
        <slot/>
      </el-table>
    </el-col>
  </el-row>
</template>

export default {
  name: 'base-table',
  props: {
    // 核心數(shù)據(jù)
    list: {
      type: Array,
      default: () => []
    },
    // columns
    columns: {
      type: Array,
      required: true,
      default: () => []
    }
  },
  data () {
    return {
      tableHeight: xxx
    }
  },
  methods: {
    // 處理點(diǎn)擊事件
    handleClick(action, data) {
      // emit事件
      this.$emit(`${action.emitKey}`, data)
    }
  }
}

使用:

<base-table v-loading="loading" :columns="headers" :list="list"  @view="viewCb">
  <!-- 自定義的slot -->
  <template slot="demoslot" slot-scope="{scope}">
    <span>
      {{scope.row}}
    </span>
  </template>
  <!-- 默認(rèn)的slot  如果交互很復(fù)雜 我們還可以直接使用表格內(nèi)部的組件 -->
  <el-table-column
    label="操作"
    width="200"
  >
    <template slot-scope="scope">
      <a href="javascript:void(0)" @click="defaultSlot(scope.row)">xxx</a>
    </template>
  </el-table-column>
</base-table>
export default {
  name: 'table-demo',
  data () {
    return {
      // 表格頭部配置
      headers: [
        { key: 'xxx', title: '測(cè)試' },
        { title: 'xxx', hidden: true, slot: 'demoslot'},
        {
          title: '操作', type: 'operate',
          operates: [
            {name: '詳情',emitKey: 'view'}
          ]
        }
      ]
    }
  },
  methods: {
    viewCb(){
      // todo
    },
    defaultSlot(){
      // todo
    }
  }
}
總結(jié)

這些東西并不是什么語(yǔ)法糖,是真正可以在項(xiàng)目中加快我們的效率。讓我們的自己乃至整個(gè)團(tuán)隊(duì)從繁雜的重復(fù)復(fù)制粘貼中解脫一點(diǎn)。至于速度和質(zhì)量的問(wèn)題。我是覺(jué)得使用公共組件質(zhì)量可控性會(huì)更高一些。我建議公共得東西注釋一定要寫得全面和詳細(xì),這樣可以極大的降低我們的交流成本。至于組件的封裝還是要看你的業(yè)務(wù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,491評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 176,263評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 62,946評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,708評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 55,186評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,409評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,939評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,774評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,976評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,209評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 34,641評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 35,872評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,650評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,958評(píng)論 2 373

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