Vue3+TS+Vite 入門指南

最近嘗試上手 Vue3+TS+Vite,對(duì)比起 Vue2 有些不適應(yīng)杜窄,但還是真香~

上手前先說(shuō)下 Vue3 的一些變化吧~

Vue3 的變化

Vue3 帶來(lái)的變化主要有以下幾個(gè)方面:

  • 使用層面

    • 對(duì)比起 Vue2 啟動(dòng)速度快很多利耍,新項(xiàng)目從 1s 升級(jí)到不到 500ms
    • vite.config.ts 配置文件修改后無(wú)需重啟服務(wù)就能更新
  • 代碼層面

    • 函數(shù)式編程蚌本,方便組合邏輯,如mixin容易命名沖突隘梨,數(shù)據(jù)來(lái)源不清晰
    • 新增 refreative API定義變量
    • 更好的 ts 支持
    • 組件文件中 template 模板內(nèi)無(wú)需用根節(jié)點(diǎn)標(biāo)簽包著組件元素
  • 底層設(shè)計(jì)

    • 雙向數(shù)據(jù)綁定從 defineProperty for in 循環(huán)變量改成 proxy舷嗡。defineProperty 是改變?cè)瓕?duì)象屬性標(biāo)簽轴猎;而 proxy 未改變?cè)瓕?duì)象,而是產(chǎn)生新的代理對(duì)象进萄,js 引擎更喜歡穩(wěn)定的對(duì)象
    • 重新定義 vdom 對(duì)比思路:
      • 區(qū)分動(dòng)靜態(tài) dom捻脖,只對(duì)比動(dòng)態(tài)數(shù)據(jù) dom,用block 標(biāo)記動(dòng)態(tài)標(biāo)簽內(nèi)部的靜態(tài)標(biāo)簽
      • 使用最長(zhǎng)遞增子序列算法中鼠,找到所有不需要移動(dòng)的元素
    • compile 編譯優(yōu)化可婶,把大量計(jì)算放在 node 層,最后瀏覽器只需執(zhí)行最少的代碼

底層設(shè)計(jì)層面的改變決定了 vue3 比 vue2 更快

下面介紹上手步驟~ (官網(wǎng)鏈接)

創(chuàng)建項(xiàng)目

使用 vite 命令創(chuàng)建初始項(xiàng)目

# npm 6.x
npm create vite@latest my-vue-app --template vue

# npm 7+, extra double-dash is needed:
npm create vite@latest my-vue-app -- --template vue

cd my-vue-app

npm install
npm run dev

Vite 配置

功能一致的配置大多跟 vue-cli 配置大同小異援雇,不過(guò)多贅述

resolve

resolve.alias:當(dāng)使用文件系統(tǒng)路徑的別名時(shí)矛渴,請(qǐng)始終使用絕對(duì)路徑。相對(duì)路徑的別名值會(huì)原封不動(dòng)地被使用惫搏,因此無(wú)法被正常解析具温。

/* vite.config.ts */
resolve: {
   //文件系統(tǒng)路徑的別名, 絕對(duì)路徑
   alias: {
     "@": path.resolve(__dirname, "src"), 
   }
}

sass配置

安裝sass依賴和配置 vite.config.ts 預(yù)定義全局變量

npm i sass -D
/* vite.config.ts */
css: {
    preprocessorOptions: {
      scss: {
        additionalData: '@import "./src/assets/scss/var.scss";'
      }
    }
}

開啟服務(wù)配置

開啟 http 服務(wù)

/* vite.config.ts */
server:{
    host: 'dev.moon.cn',
    port: 3000
}

開啟 https 服務(wù)

/* vite.config.ts */
let httpsConfig = {
  key: fs.readFileSync("C:/Users/ca/wps.cn/_wildcard.wps.cn+3-key.pem"),
  cert: fs.readFileSync("C:/Users/ca/wps.cn/_wildcard.wps.cn+3.pem")
};

server:{
    https: httpsConfig,
    host: 'dev.moon.cn',
    port: 443,
    open: true
}

預(yù)構(gòu)建依賴優(yōu)化

默認(rèn)情況下,Vite 會(huì)抓取你的 index.html 來(lái)檢測(cè)需要預(yù)構(gòu)建的依賴項(xiàng)筐赔。如果指定了 build.rollupOptions.input铣猩,Vite 將轉(zhuǎn)而去抓取這些入口點(diǎn)。

optimizeDeps.include

默認(rèn)情況下茴丰,不在 node_modules 中的达皿,鏈接的包不會(huì)被預(yù)構(gòu)建天吓。使用此選項(xiàng)可強(qiáng)制預(yù)構(gòu)建鏈接的包。

/* vite.config.ts */
optimizeDeps: {
  include: ['axios'],
},

optimizeDeps.exclude

在預(yù)構(gòu)建中強(qiáng)制排除的依賴項(xiàng)峦椰。

eslint 配置

vue3tseslint 配置需另外自行配置失仁,除了需配置 eslint 規(guī)則外還需調(diào)整 vite 的相關(guān)配置,感興趣的話可以看看我另一篇文章(內(nèi)附配置解析)们何,或者直接看完整源碼萄焦,這里不做贅述。

TypeScript

TypeScript 是添加了類型系統(tǒng)的 JavaScript冤竹,適用于任何規(guī)模的項(xiàng)目拂封,在編譯階段進(jìn)行類型檢查。

基礎(chǔ)知識(shí)可直接看中文文檔鹦蠕,英文比較好的小伙伴可以直接看官方文檔冒签,這里不做贅述,這里分享一些值得說(shuō)的地方

類型/接口/泛型

  • 類型:類型(type)不是定義一個(gè)新類型钟病,而是一個(gè)類型別名萧恕,使類型更具體化

  • 接口:接口(interface)則是描述一個(gè)對(duì)象的形狀,對(duì)值所具有的結(jié)構(gòu)進(jìn)行類型檢查肠阱。接口的作用類似于抽象類票唆,不同點(diǎn)在于接口中的所有方法和屬性都是沒(méi)有實(shí)值的,換句話說(shuō)接口中的所有方法都是抽象方法屹徘。接口主要負(fù)責(zé)定義一個(gè)類的結(jié)構(gòu)走趋,接口可以去限制一個(gè)對(duì)象的接口,對(duì)象只有包含接口中定義的所有屬性和方法時(shí)才能匹配接口噪伊。同時(shí)簿煌,可以讓一個(gè)類去實(shí)現(xiàn)接口,實(shí)現(xiàn)接口時(shí)類中要保護(hù)接口中的所有屬性鉴吹。

  • 泛型:支持多種數(shù)據(jù)結(jié)構(gòu)姨伟,有函數(shù)泛型,類泛型豆励,接口泛型等夺荒。

你可能想問(wèn)什么時(shí)候用類型,什么時(shí)候用接口肆糕?Typescript團(tuán)隊(duì)的建議是

可以使用接口就盡量使用接口般堆,因?yàn)榻涌诟`活,更容易處理

很多時(shí)候 interface 和 type 是相同的诚啃,但有一個(gè)明顯區(qū)別在于 interface 可以重復(fù)定義淮摔,類型注解會(huì)累加,而 type 重復(fù)定義會(huì)報(bào)錯(cuò)

類型聲明

類型聲明(Type Declaration) 或者類型定義(Type Definition) 文件是一個(gè)以.d.ts作為文件后綴名的TypeScript文件始赎。文件中只包含與類型相關(guān)的代碼和橙,不包含邏輯代碼仔燕,它們的作用旨在為開發(fā)者提供類型信息,所以它們只在開發(fā)階段起作用魔招。

typescript編譯后會(huì)將類型信息移除晰搀,類型信息僅在開發(fā)階段起作用。

全局類型/變量聲明

先在項(xiàng)目 src 目錄中新建 global.d.ts 文件

全局類型聲明

項(xiàng)目的根目錄有 tsconfig.json 可以配置 TypeScript办斑,include 屬性包含了需要校驗(yàn) ts 的文件外恕。ts 默認(rèn)會(huì)將 xx.d.ts 類型文件中的類型注冊(cè)成全局的,下面舉個(gè)栗子:

// global.d.ts
type T1 = number
// 組件內(nèi) 
<script lang="ts"> 
    let num1: T1 = 1
</script>

全局變量聲明

有三種方式聲明全局變量乡翅,掛載在瀏覽器的 window 對(duì)象中

  • 使用 window

global.d.ts文件

// 若想不帶window使用userId鳞疲,但需重復(fù)聲明
declare let userId: string 

interface Window {
  userId: string
}

注:不聲明且不帶window使用開發(fā)模式不會(huì)報(bào)錯(cuò),但打包時(shí)會(huì)報(bào)錯(cuò)

組件文件

window.userId = '1'
console.log(userId)
  • 使用 global 配合 windowvar蠕蚜,需加 export尚洽,否則會(huì)打包報(bào)錯(cuò)
// global.d.ts
export {}

declare global {
  interface Window {
    // 使用foo全局變量時(shí)得帶window,否則打包會(huì)報(bào)錯(cuò)
    foo: string
  }
  var age: number
}
// 組件內(nèi)
globalThis.age = 18
window.foo = '1'
console.log(age, window.foo)

注:加上export后其他聲明會(huì)失效靶累,其他聲明可另起 *.d.ts 文件定義

  • 使用var
// global.d.ts
declare var age: number
// 組件內(nèi)
globalThis.age = 18
console.log(age)

每種方式各有利弊腺毫,自行選擇

第三方庫(kù)聲明

第三方庫(kù)需有類型聲明,可自動(dòng)生成或者自己寫挣柬,有興趣可移步潮酒。

Vue3 + TS

vue3新增了composition api的寫法,更接近react的寫法凛忿,下面介紹ts下的vue3寫法和生命周期

setup 語(yǔ)法糖

一個(gè)組件選項(xiàng)澈灼,在組件被創(chuàng)建之前props 被解析之后執(zhí)行店溢。它是組合式 API 的入口。

<script setup> 是在單文件組件 (SFC) 中使用組合式 API 的編譯時(shí)語(yǔ)法糖委乌。相比于普通的 <script> 語(yǔ)法床牧,它具有更多優(yōu)勢(shì):

  • 更少的樣板內(nèi)容,更簡(jiǎn)潔的代碼遭贸。
  • 能夠使用純 Typescript 聲明 props 和拋出事件戈咳。
  • 更好的運(yùn)行時(shí)性能 (其模板會(huì)被編譯成與其同一作用域的渲染函數(shù),沒(méi)有任何的中間代理)壕吹。
  • 更好的 IDE 類型推斷性能 (減少語(yǔ)言服務(wù)器從代碼中抽離類型的工作)著蛙。

使用這個(gè)語(yǔ)法,需要將 setup attribute 添加到 <script> 代碼塊上:

<script setup lang="ts">
</script>

里面的代碼會(huì)被編譯成組件 setup() 函數(shù)的內(nèi)容耳贬。這意味著與普通的 <script> 只在組件被首次引入的時(shí)候執(zhí)行一次不同踏堡,<script setup> 中的代碼會(huì)在每次組件實(shí)例被創(chuàng)建的時(shí)候執(zhí)行

setup 函數(shù)在生命周期方面咒劲,它是在 beforeCreate 鉤子之前調(diào)用的顷蟆。

生命周期

選項(xiàng)式 API 的生命周期選項(xiàng)和組合式 API 之間的映射

  • beforeCreate -> 使用 setup()
  • created -> 使用 setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeUnmount -> onBeforeUnmount
  • unmounted -> onUnmounted
  • errorCaptured -> onErrorCaptured
  • renderTracked -> onRenderTracked
  • renderTriggered -> onRenderTriggered
  • activated -> onActivated
  • deactivated -> onDeactivated

TIP: 因?yàn)?setup 是圍繞 beforeCreatecreated 生命周期鉤子運(yùn)行的诫隅,所以不需要顯式地定義它們。換句話說(shuō)帐偎,在這些鉤子中編寫的任何代碼都應(yīng)該直接在 setup 函數(shù)中編寫逐纬。

響應(yīng)式 ref

接受一個(gè)內(nèi)部值并返回一個(gè)響應(yīng)式且可變的 ref 對(duì)象。ref 對(duì)象僅有一個(gè) .value property削樊,指向該內(nèi)部值豁生。和從 setup() 函數(shù)中返回值一樣,ref 值在模板中使用的時(shí)候會(huì)自動(dòng)解包漫贞。

可以在調(diào)用 ref 時(shí)傳遞一個(gè)泛型參數(shù)以覆蓋默認(rèn)推斷

import { ref } from "vue";

let str = ref<string>("test");

還可以指定復(fù)雜類型

const foo = ref<string | number>('foo') // foo 的類型:Ref<string | number>

foo.value = 123 // ok!

props/emit

  • 僅限類型的 props/emit 聲明
defineProps<{ title: string }>();

const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()
  • props 設(shè)置默認(rèn)值

    有兩種方法設(shè)置默認(rèn)值

    • 使用運(yùn)行時(shí)聲明

      運(yùn)行時(shí)聲明 的方式只能設(shè)置參數(shù)類型甸箱、默認(rèn)值、是否必傳绕辖、自定義驗(yàn)證摇肌。報(bào)錯(cuò)為控制臺(tái)warn警告。
      若想設(shè)置[ 編輯器報(bào)錯(cuò)仪际、編輯器語(yǔ)法提示 ]則需要使用類型聲明的方式围小。

      const props = defineProps({
        modelValue: { type: Boolean, default: false },
        title: { type: String, default: '彈窗提示' },
        msg: { type: String, default: '彈窗信息' }
      })
      
    • 使用類型聲明時(shí)的默認(rèn) props 值

      僅限類型的 defineProps 聲明的不足之處在于,它不能給 props 定義默認(rèn)值树碱。需配合 withDefaults 編譯器宏解決:

interface Props {
  title?: string;
  msg?: string;
}

withDefaults(defineProps<Props>(), {
  title: "提示",
  msg: "是否跳轉(zhuǎn)到app?",
});

defineProps肯适、withDefaults 是只在 <script setup> 語(yǔ)法糖中才能使用的編譯器宏。他不需要導(dǎo)入且會(huì)隨著 <script setup> 處理過(guò)程一同被編譯掉成榜。

v-model 雙向綁定

vue2 中的 v-model 的使用是通過(guò)傳遞 value 屬性和接收 input 事件實(shí)現(xiàn)框舔,vue3 則換成了 modelValue 屬性,接收的方法是update:modelValue赎婚。

以下彈窗例子以Page.vue為父組件刘绣,Dialog.vue為子組件,關(guān)鍵代碼如下:

/* Page.vue */
<template>
  <Dialog v-model="dialogVisible"></Dialog>
  <div class="bottom-btn" @click="onTap">點(diǎn)擊按鈕</div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import Dialog from "./Dialog.vue";

let dialogVisible = ref<boolean>(false);
function onTap() {
  dialogVisible.value = true;
}
<script>
/* Dialog.vue */
<template>
  <div class="dialog" v-show="modelValue">
      <span class="dialog-content-btn" @click="onConfirm">確定</span>
  </div>
</template>

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

interface Props {
  modelValue?: boolean;
}
let props = withDefaults(defineProps<Props>(), {
  modelValue: false // v-model綁定的屬性值
});

// 傳遞的方法
const emit = defineEmits<{
  (e: "update:modelValue", visible: boolean): boolean;
}>();

function onConfirm() {
    emit("update:modelValue", false);
}
<script>

遇到的問(wèn)題

做好所有配置后挣输,主要遇到以下兩個(gè)問(wèn)題

vite 打包報(bào)錯(cuò)/告警

"@charset" must be the first rule in the file }@charset "UTF-8";

告警如圖:

原因:使用了scss類庫(kù) sass纬凤,scss編譯的時(shí)候,因?yàn)楸痪幾g的文件里可能有中文導(dǎo)致

解決:在vite.config.js里面撩嚼,加一個(gè)sass的配置停士,把charset關(guān)掉就行了
官網(wǎng)對(duì)css預(yù)處理的api

vite.config.js 中的配置

export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        charset: false
      }
    }
  }
})

去除 Typescript 全局變量的 eslint 報(bào)錯(cuò)

1. 使用 var 定義全局變量

var 相關(guān)聲明下會(huì)帶下劃線,并報(bào)錯(cuò)

Unexpected var, use let or const instead.

解決:在 .eslintrc 配置文件中增加規(guī)則

rules: {
    // 全局變量允許使用 var
    'no-var': 'off',
}

2. 使用 global 定義全局變量

global 相關(guān)聲明下會(huì)帶下劃線完丽,并報(bào)錯(cuò)

Augmentations for the global scope can only be directly nested in external modules or ambient module declarations.

解決:在 global.d.ts 聲明文件中添加一行代碼

export {}

注:新增后會(huì)導(dǎo)致該文件中的其他變量/類型等聲明失效恋技,其他聲明可另起 *.d.ts 文件定義

Vite 為什么更快

Vite 主要通過(guò)以下幾個(gè)方面進(jìn)行優(yōu)化:

  • 啟動(dòng)應(yīng)用時(shí)按需提供代碼
  • 瀏覽器緩存(協(xié)商緩存和強(qiáng)緩存)進(jìn)行代碼更新
  • 使用 esbuild 預(yù)構(gòu)建依賴和加快構(gòu)建速度

啟動(dòng)時(shí)間和更新時(shí)間

啟動(dòng)時(shí)間

以往的打包工具當(dāng)冷啟動(dòng)開發(fā)服務(wù)器時(shí),基于打包器的方式啟動(dòng)必須優(yōu)先抓取并構(gòu)建你的整個(gè)應(yīng)用逻族,然后才能提供服務(wù)蜻底。而且存在性能瓶頸——使用 JavaScript 開發(fā)的工具通常需要很長(zhǎng)時(shí)間(甚至是幾分鐘!)才能啟動(dòng)開發(fā)服務(wù)器瓷耙,即使使用 HMR朱躺,文件修改后的效果也需要幾秒鐘才能在瀏覽器中反映出來(lái)刁赖。

Vite 通過(guò)在一開始將應(yīng)用中的模塊區(qū)分為 依賴源碼 兩類,并只在瀏覽器請(qǐng)求源碼時(shí)進(jìn)行轉(zhuǎn)換并按需提供源碼长搀,改進(jìn)了開發(fā)服務(wù)器啟動(dòng)時(shí)間宇弛。而且esbuild 預(yù)構(gòu)建依賴使用的語(yǔ)言是go,比以 JavaScript 編寫的打包器預(yù)構(gòu)建依賴快 10-100 倍源请。

更新時(shí)間

在 Vite 中枪芒,HMR 是在原生 ESM 上執(zhí)行的。當(dāng)編輯一個(gè)文件時(shí)谁尸,Vite 只需要精確地使已編輯的模塊與其最近的 HMR 邊界之間的鏈?zhǔn)Щ?a target="_blank">[1](大多數(shù)時(shí)候只是模塊本身)舅踪,使得無(wú)論應(yīng)用大小如何,HMR 始終能保持快速更新良蛮。

Vite 同時(shí)利用 HTTP 頭來(lái)加速整個(gè)頁(yè)面的重新加載(再次讓瀏覽器為我們做更多事情):源碼模塊的請(qǐng)求會(huì)根據(jù) 304 Not Modified 進(jìn)行協(xié)商緩存抽碌,而依賴模塊請(qǐng)求則會(huì)通過(guò) Cache-Control: max-age=31536000,immutable 進(jìn)行強(qiáng)緩存,因此一旦被緩存它們將不需要再次請(qǐng)求决瞳。

預(yù)構(gòu)建依賴的前因后果

Vite 預(yù)構(gòu)建依賴原因有二:

  • CommonJS 和 UMD 兼容性: 開發(fā)階段中货徙,Vite 的開發(fā)服務(wù)器將所有代碼視為原生 ES 模塊。因此皮胡,Vite 必須先將作為 CommonJS 或 UMD 發(fā)布的依賴項(xiàng)轉(zhuǎn)換為 ESM痴颊。

  • 性能: Vite 通過(guò)預(yù)構(gòu)建依賴將有許多內(nèi)部模塊的 ESM 依賴關(guān)系轉(zhuǎn)換為單個(gè)模塊,從而減少瀏覽器的請(qǐng)求數(shù)量屡贺,提升頁(yè)面加載性能蠢棱。

    lodash-es 有超過(guò) 600 個(gè)內(nèi)置模塊,當(dāng)執(zhí)行 import { debounce } from 'lodash-es' 時(shí)甩栈,瀏覽器同時(shí)發(fā)出 600 多個(gè) HTTP 請(qǐng)求泻仙;通過(guò)預(yù)構(gòu)建 lodash-es 成為一個(gè)模塊,就只需要一個(gè) HTTP 請(qǐng)求量没。

自動(dòng)依賴搜尋

如果沒(méi)有找到相應(yīng)的緩存饰豺,Vite 將抓取你的源碼,并自動(dòng)尋找引入的依賴項(xiàng)(即 "bare import",表示期望從 node_modules 解析)戏仓,并將這些依賴項(xiàng)作為預(yù)構(gòu)建包的入口點(diǎn)崖蜜。

在服務(wù)器已經(jīng)啟動(dòng)之后,如果遇到一個(gè)新的依賴關(guān)系導(dǎo)入祟峦,而這個(gè)依賴關(guān)系還沒(méi)有在緩存中,Vite 將重新運(yùn)行依賴構(gòu)建進(jìn)程并重新加載頁(yè)面。

對(duì)于 monorepo 倉(cāng)庫(kù)中的某個(gè)依賴成為另一個(gè)包的依賴妓蛮,Vite 會(huì)自動(dòng)偵測(cè)沒(méi)有從 node_modules 解析的依賴項(xiàng),并將鏈接的依賴視為源碼圾叼。它不會(huì)嘗試打包被鏈接的依賴蛤克,而是會(huì)分析被鏈接依賴的依賴列表捺癞。

緩存

文件系統(tǒng)緩存

Vite 會(huì)將預(yù)構(gòu)建的依賴緩存到 node_modules/.vite。它根據(jù)幾個(gè)源來(lái)決定是否需要重新運(yùn)行預(yù)構(gòu)建步驟:

  • package.json 中的 dependencies 列表
  • 包管理器的 lockfile构挤,例如 package-lock.json, yarn.lock髓介,或者 pnpm-lock.yaml
  • 可能在 vite.config.js 相關(guān)字段中配置過(guò)的

只有在上述其中一項(xiàng)發(fā)生更改時(shí),才需要重新運(yùn)行預(yù)構(gòu)建筋现。

如果要強(qiáng)制 Vite 重新構(gòu)建依賴唐础,你可以用 --force 命令行選項(xiàng)啟動(dòng)開發(fā)服務(wù)器,或者手動(dòng)刪除 node_modules/.vite 目錄矾飞。

瀏覽器緩存

解析后的依賴請(qǐng)求會(huì)以 HTTP 頭 max-age=31536000,immutable 強(qiáng)緩存一膨,以提高在開發(fā)時(shí)的頁(yè)面重載性能。一旦被緩存洒沦,這些請(qǐng)求將永遠(yuǎn)不會(huì)再到達(dá)開發(fā)服務(wù)器豹绪。如果安裝了不同的版本(這反映在包管理器的 lockfile 中),則附加的版本 query 會(huì)自動(dòng)使它們失效申眼。如果你想通過(guò)本地編輯來(lái)調(diào)試依賴項(xiàng)瞒津,你可以:

  1. 通過(guò)瀏覽器調(diào)試工具的 Network 選項(xiàng)卡暫時(shí)禁用緩存;
  2. 重啟 Vite dev server豺型,并添加 --force 命令以重新構(gòu)建依賴仲智;
  3. 重新載入頁(yè)面。

為何不用 ESBuild 打包姻氨?

雖然 esbuild 快得驚人钓辆,且是一個(gè)在構(gòu)建庫(kù)方面比較出色的工具,但一些針對(duì)構(gòu)建 應(yīng)用 的重要功能仍然還在持續(xù)開發(fā)中 —— 特別是代碼分割和 CSS 處理方面肴焊。就目前來(lái)說(shuō)前联,Rollup 在應(yīng)用打包方面更加成熟和靈活。

最后

最后附上完整代碼娶眷,如對(duì)前端自動(dòng)化部署有興趣似嗤,可繼續(xù)看在本文 vue3 基礎(chǔ)上搭建的 CICD

相關(guān)文章

Monorepo實(shí)戰(zhàn)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市届宠,隨后出現(xiàn)的幾起案子烁落,更是在濱河造成了極大的恐慌,老刑警劉巖豌注,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伤塌,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡轧铁,警方通過(guò)查閱死者的電腦和手機(jī)每聪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人药薯,你說(shuō)我怎么就攤上這事绑洛。” “怎么了童本?”我有些...
    開封第一講書人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵真屯,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我巾陕,道長(zhǎng)讨跟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任鄙煤,我火速辦了婚禮晾匠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘梯刚。我一直安慰自己凉馆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開白布亡资。 她就那樣靜靜地躺著澜共,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锥腻。 梳的紋絲不亂的頭發(fā)上嗦董,一...
    開封第一講書人閱讀 51,775評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音瘦黑,去河邊找鬼京革。 笑死,一個(gè)胖子當(dāng)著我的面吹牛幸斥,可吹牛的內(nèi)容都是我干的匹摇。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼甲葬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼廊勃!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起经窖,我...
    開封第一講書人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤坡垫,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后画侣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體葛虐,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年棉钧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宪卿,死狀恐怖的诵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情佑钾,我是刑警寧澤西疤,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站休溶,受9級(jí)特大地震影響代赁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜兽掰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一芭碍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧孽尽,春花似錦窖壕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至熏挎,卻和暖如春速勇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背坎拐。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工烦磁, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人廉白。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓个初,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親猴蹂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子院溺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

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