基于NUXT.JS搭建一款VUE版SSR前端框架(解決SPA應(yīng)用的SEO優(yōu)化優(yōu)化問題)

小仙男·言在前

關(guān)于框架:為了解決VUE的SPA單頁應(yīng)用對SEO搜索引擎優(yōu)化不友好的問題夹抗,這幾天一直在調(diào)研各種SSR框架凤优。比如https://doc.ssr-fc.com/https://fmfe.github.io/genesis-docs/ 都是比較不錯,且有自己理念和想法的框架癣朗。但是對于公司來說技術(shù)規(guī)范差異太大,團(tuán)隊學(xué)習(xí)成本比較高,思來想去它碎,還是基于NUXT.JS自己搭建一套SSR框架慢慢完善吧。

本文沒有附帶框架,大家直接進(jìn)入【NUXT官網(wǎng)】按官網(wǎng)提示初始化框架即可扳肛!

關(guān)于本文檔:本文檔是從官網(wǎng)文檔中摘錄的一些重點內(nèi)容傻挂,以及加入了自己的一些調(diào)整和對官網(wǎng)內(nèi)容的理解和解釋。

關(guān)于官網(wǎng):NUXT中文網(wǎng) 特別適合新手學(xué)習(xí)挖息,文檔及案例十分清楚詳盡金拒,可以說有手就行。但是套腹,中文網(wǎng)的更新不及時绪抛,有些章節(jié)(比如fetch鉤子中不能使用this)甚至存在明顯錯誤,所以有一定技術(shù)水平的寶子电禀,建議直接查看 NUXT英文官網(wǎng) 幢码。

【一、框架概述】

1尖飞、框架介紹

  • SSR 技術(shù)(即服務(wù)端渲染技術(shù))症副,區(qū)別于原先純Vue框架的SPA應(yīng)用(即單頁應(yīng)用)。SPA應(yīng)用只有一個index.html的入口文件政基,頁面顯示的所有內(nèi)容均靠客戶端JS進(jìn)行渲染贞铣,對于搜索引擎(SEO)優(yōu)化來說,整個網(wǎng)站只有一個空頁面沮明,十分不友好辕坝。而服務(wù)端渲染技術(shù),是借助node.js作為框架服務(wù)端荐健,在初次訪問一個頁面的時候圣勒,先在服務(wù)端預(yù)請求接口,并在服務(wù)端組裝完成的html頁面后摧扇,返回給客戶端呈現(xiàn)圣贸。
  • Nuxt.js是基于Vue框架的一款服務(wù)端渲染框架,提供了特有的框架結(jié)構(gòu)和服務(wù)端渲染生命周期扛稽。

2吁峻、開發(fā)環(huán)境

  • 本框架基于Node.js+Webpack+vue+Nuxt.js進(jìn)行開發(fā),提供ElementUI作為UI框架在张。開發(fā)前需全局安裝Node.jswebpack開發(fā)環(huán)境用含。
  • 框架推薦Node.js版本為v16.15.0,最低版本不得低于12帮匾,推薦安裝nvmn等node版本管理工具啄骇。

3、分支要求

3橡类、關(guān)于本文檔

  • <font color="#dd0000"><b>本文檔所述內(nèi)容,已經(jīng)是從官網(wǎng)中摘錄的【重中之重】芽唇,開發(fā)前請【詳盡】【仔細(xì)】【通讀】本文檔9嘶!匆笤!尤其是<a href='#five'>【五研侣、數(shù)據(jù)請求】</a> 與 <a href='#six-8'>【六-8、重要Q&A】</a>E谂酢R逶! </b></font>
  • 文檔描述存在錯誤的地方寓盗,請以【NUXT英文官網(wǎng)】為準(zhǔn)。

4璧函、框架版本更新

【二、啟動與部署】

# 安裝框架以來
$ npm install

# 啟動本地開發(fā)環(huán)境蘸吓,默認(rèn)端口號:3000
$ npm run dev

# 編譯并在生產(chǎn)環(huán)境啟動
$ npm run build
$ npm run start

# 將網(wǎng)站打包成靜態(tài)化頁面
$ npm run generate

【三善炫、框架結(jié)構(gòu)】

  • 詳細(xì)目錄結(jié)構(gòu)介紹及使用,參照<a href='#six'>【六库继、其他規(guī)范與Q&A】</a>
-- 框架根目錄
  -- .nuxt        Nuxt運營和編譯自動生成
  -- dist         執(zhí)行Nuxt靜態(tài)化時生成
  -- api          全局通用的Api請求函數(shù)(非Nuxt提供)
  -- assets       靜態(tài)資源目錄箩艺,存放全局css、image等
  -- components   自定義組件目錄宪萄,此目錄下組件無需引入艺谆,按需使用即可
  -- layout       布局文件,參考https://www.nuxtjs.cn/guide/views
  -- middleware   中間件拜英,類似于路由守衛(wèi)
  -- modules      模塊静汤,用于設(shè)置全局監(jiān)聽等,參考https://www.nuxtjs.cn/guide/modules
  -- pages        頁面目錄居凶,Nuxt會根據(jù)此目錄自動生成路由虫给,參考https://www.nuxtjs.cn/guide/routing
  -- plugins      插件目錄,自定義各種插件侠碧,參考https://www.nuxtjs.cn/guide/plugins
   > global.js    (全局變量與全局方法)
   > plugin.js    (全局引入第三方組件)
   > request.js   (全局請求封裝)
   > filter.js    (全局過濾器封裝)
   > util.js      (全局工具函數(shù)封裝)
   > all.client.js(僅在客戶端執(zhí)行插件抹估,暫時替代原app.vue)
     
  -- static       不需要webpack編譯的靜態(tài)文件,一般存放ico等文件
  -- store        Vue狀態(tài)樹弄兜,與原寫法有所不同药蜻,參考https://www.nuxtjs.cn/guide/vuex-store
  -- utils        工具類包 (非Nuxt提供)
  .editorconfig   
  .gitignore
  env.js          環(huán)境變量配置瓷式,分dev、test谷暮、pro三種環(huán)境
  nux.config.js   Nuxt的所有配置項蒿往,參考https://www.nuxtjs.cn/api/configuration-build
  package-lock.json
  package.json
  README.md       框架使用文檔
  ReleaseNote.md  版本更新說明

【四、生命周期】

-- Nuxt完整生命周期
  【服務(wù)端渲染】
    -- 全局
  nuxtServerInit    第一個:nuxt中第一個運行的生命周期
  RouteMiddleware   第二個:中間件湿弦,類似于原框架的路由導(dǎo)航守衛(wèi)
    -- 組件
  validate          是用來校驗url參數(shù)符不符合
  asyncData         Nuxt專屬生命周期瓤漏,可用于數(shù)據(jù)請求,只有page可用颊埃,子組件內(nèi)部不可用
  beforeCreate      Vue生命周期蔬充,但是服務(wù)端會執(zhí)行(不可用于數(shù)據(jù)請求,數(shù)據(jù)請求相關(guān)操作會在客戶端執(zhí)行)
  created           Vue生命周期班利,但是服務(wù)端會執(zhí)行(同上)
  fetch             Nuxt專屬生命周期饥漫,可用于數(shù)據(jù)請求, page和子組件都可用 
  
  【客戶端渲染】
    -- 全局
  * `@/plugins/all.client.js` (并非Nuxt生命周期罗标,是只在客戶端運行的插件庸队。此框架中用于暫時替代原框架中在App.vue中進(jìn)行的全局初始化操作。)
    -- 組件
  beforeCreate
  created
  beforeMount
  mounted
  ... (其他Vue后續(xù)生命周期)
  

幾點說明:

  1. beforeCreate/created 是Vue的生命周期闯割,但是會在服務(wù)端和客戶端各執(zhí)行一次彻消,但這兩個鉤子,僅供了解宙拉,不能用于數(shù)據(jù)請求宾尚。
  2. asyncDatafetch都是Nuxt提供的生命周期,都可用于數(shù)據(jù)請求谢澈。只是寫法略有不同(參考后續(xù)章節(jié)<a href='#five'>【五煌贴、數(shù)據(jù)請求】</a>)。
  3. @/plugins/all.client.js 并非Nuxt生命周期锥忿,是只在客戶端運行的插件牛郑。但是Nuxt框架去掉了app.vue,此插件的生命周期敬鬓,近似于原來的app.vue井濒,故暫時用于替代原框架中在App.vue中進(jìn)行的全局初始化操作(是否恰當(dāng)暫時不知)。

<a name='five'>【五列林、數(shù)據(jù)請求】</a>

1. 數(shù)據(jù)請求鉤子

1.1 鉤子相關(guān)說明

  • asyncDatafetch都是Nuxt提供的生命周期瑞你,都可用于數(shù)據(jù)請求,都會在服務(wù)端預(yù)請求數(shù)據(jù)進(jìn)行組裝希痴;
  • asyncData只能在pages級別的頁面中調(diào)用者甲,在子組件內(nèi)部不能調(diào)用;fetch則可以同時在頁面和子組件中調(diào)用砌创;
  • 官方建議數(shù)據(jù)請求均采用asyncData虏缸,但為了保持與老框架寫法的一致鲫懒,本框架暫時建議采用fetch(后果未知)
  • fetch請求相比于asyncData的已知缺陷有:
    • ① 數(shù)據(jù)請求較慢,本框架Demo刽辙,從index頁進(jìn)入Detail頁窥岩,當(dāng)使用fetch請求時,可明顯看到瀏覽器選項卡的title出現(xiàn)一瞬間undefined
  • 盡管beforeCreate/created也可以在服務(wù)端渲染宰缤,但是這兩個鉤子的數(shù)據(jù)請求操作只會在客戶端執(zhí)行颂翼,原則上不用于頁面初始化。

1.2 asyncData

  • asyncData 中不能訪問this慨灭,但是可以在第一參數(shù)中朦乏,拿到context上下文,使用context.app訪問Vue根示例氧骤;
    • context上下文還包含store呻疹、route、params筹陵、query等數(shù)據(jù)刽锤,詳見context上下文
  • asyncData中無法拿到組件實例(this),不能訪問組件實例中的data method等方法朦佩。
  • 詳細(xì)介紹:asyncData
  • 【請求示例】
// ① 使用return返回的對象并思,將直接初始化到組件`data`中
async asyncData({app, params}) {
    const { code, data } = await app.$get('/policy/findById/'+params.id)
    return {detail: data}
},
// ② return一個Promise,將在Promise執(zhí)行完成后吕粗,將數(shù)據(jù)初始化到組件`data`中
asyncData({app, params}) {
    return app.$get('/policy/findById/'+params.id).then(res => {
      return {detail: data}
    })
},
// ③ 第二個參數(shù)為callback回調(diào)函數(shù),可直接傳入數(shù)據(jù)旭愧,初始化到組件`data`中
asyncData({app, params}, callback) {
    app.$get('/policy/findById/'+params.id).then(res => {
      callback(null, {detail: data}) 
    })
},

1.3 fetch

  • fetch 分兩種情況(新版本后支持第二種情況):
    • ① 第一個參數(shù)接受context上下文颅筋,則與asyncData一樣,不能訪問this和組件實例输枯; (這種情況议泵,也不支持像asyncData一樣通過return或者回調(diào)函數(shù)修改data內(nèi)容)
    • ② 不接受任何參數(shù)時,則可以正常訪問this桃熄。(可以近似的看成created的用法先口,區(qū)別是 必須要使用await 或者return一個primary)
  • 詳細(xì)介紹:fetch英文文檔 (中文文檔嚴(yán)重延遲,存在錯誤)
  • 【請求示例】
// ① 使用return返回一個Promise
fetch() {
    return this.getDetail()
},
// ②  使用await/async
async fetch() {
    await this.getDetail()
},
methods: {
    // ① 使用await編寫methods方法
    async getDetail(id){
        const { code, data } = await this.$get('/policy/findById/'+this.$route.params.id)
        this.detail = data
    }
    // ② 使用return Promise編寫methods方法
    getDetail(id){
        return this.$get('/policy/findById/'+this.$route.params.id).then(resw => {
          this.detail = res.data
        })
    }
}

2. 數(shù)據(jù)請求方式

2.1 【框架推薦】 使用vue實例直接調(diào)用

  • 本框架會將$request/$get/$post掛在到vue根示例瞳收,建議直接只用this或上下文context.app調(diào)用
  • 【請求示例】
// 以this調(diào)用為例碉京,如果是在`asyncData`中,需要使用上下文`context.app`調(diào)用
// ① get
this.$get('/policy/findById/'+this.$route.params.id)
// ②  post
this.$post('/policy/findAll/',{page:1,size:10,params:{}})
// ③  request
this.$request({
    url: '/policy/findAll/',
    method: 'post',
    data: {page:1,size:10,params:{}}
})

2.2 兼容老框架的api分離式調(diào)用

  • 本框架推薦使用五 2.1的方式調(diào)用螟深,但是也兼容了老框架的api分離式調(diào)用谐宙,用于提取可復(fù)用的公共請求
  • 公共請求的api文件界弧,統(tǒng)一放在@/api/*.js管理凡蜻。
  • 【請求示例】
/**
 * @/api/index.js
 */ 
import request from '@/utils/request'
export function getPageList(data) {
    return request.post('/policy/findAll', data)
}
/**
 * @/pages/index.vue
 */ 
import { getPageList } from "@/api/index.js"
export default {
    fetch() {
        return this.getPageList(this.pageDto)
    },
    methods: {
        getPageList(pageDto) {
            return getPageList(pageDto).then(res => {
              this.pageList = res.data.result
            })
        }
    },
}

3. 其他注意事項

  • 原則上搭综,所有初始化渲染數(shù)據(jù)的請求,都要在服務(wù)端渲染函數(shù)(asyncDatafetch)中進(jìn)行划栓,極個別無法在服務(wù)端渲染的請求兑巾,可以在Vue的生命周期(createdmounted)中初始化;
  • 服務(wù)端渲染的生命周期(即asyncData/fetch)忠荞,不能使用任何瀏覽器專屬的對像(如DOM對象)蒋歌,也就是documentwindow,以及window的各種對象和方法钻洒,例如setTimeout奋姿、setIntervallocalStorage素标、sessionStorage等称诗;
    有上述需求的初始化邏輯,可以放到createdmounted中初始化头遭。

<a name='six'>【六寓免、其他規(guī)范與Q&A】</a>

1. 關(guān)于pages

  • 本框架路由采用約定式路由,即不再使用route.js進(jìn)行路由聲明计维,而是由框架根據(jù)pages目錄自動生成路由袜香,詳見路由
  • 文件夾或者文件,如果以_開頭鲫惶,表示此為動態(tài)路由蜈首,可以傳入不同參數(shù),在組件內(nèi)容欠母,可以使用上下文或者this.$router取到路由參數(shù)欢策;
    • 例如: /pages/news/detail/_id.vue/pages/news/detail/_id/index.vue
    • 訪問: http://domain.com/pages/news/detail/12345 (上述兩種寫法均為這一路徑)

【注意】

  • ① 使用_id.vue的寫法赏淌,表示id為可選參數(shù)踩寇,即可以通過http://domain.com/pages/news/detail訪問。如果要對id進(jìn)行限制或驗證六水,可以在組件內(nèi)使用validate()驗證俺孙;
  • ② 使用/_id/index.vue的寫法,表示id為必選參數(shù)掷贾,訪問http://domain.com/pages/news/detail會報404睛榄。如果只要求id必填,而沒有其他格式限制想帅,可以使用此方式懈费。
  • validate()驗證示例
// return true表示驗證通過,return false表示驗證失敗 404
validate({ params }) {
    return /^\d+$/.test(params.id)
},

2. 關(guān)于plugins

  • 用于自定義框架所需的各種插件博脑,聲明插件后在nuxt.config.js中引入插件即可憎乙,類似于原框架main.js相關(guān)功能票罐。詳見插件
  • 框架已有的插件包(具體用戶參照各插件的頂部注釋):
    • plugin.js用于全局引入各種npm包;
    • global.js用于聲明全局變量與全局方法泞边;
    • request.js實現(xiàn)了全局請求封裝(對應(yīng)@/utils/request.js);
    • filter.js實現(xiàn)了全局請求封裝(對應(yīng)@/utils/filter.js);
    • util.js實現(xiàn)了全局請求封裝(對應(yīng)@/utils/util.js);
    • all.client.js只在客戶端引入该押,用于替代原框架中app.vue中的各種初始化操作;
  • 其他插件可根據(jù)需要自行定義阵谚,*.js表示服務(wù)端客戶端均導(dǎo)入蚕礼;*.client.js表示僅在客戶端導(dǎo)入;*.server.js表示只在服務(wù)端導(dǎo)入梢什;

3. 關(guān)于layout

  • 用于定義框架中的各種布局文件奠蹬,可根據(jù)需要自行定義,詳見布局與視圖
  • 默認(rèn)視圖為default.vue嗡午,默認(rèn)所有頁面都將調(diào)用囤躁;error.vue是錯誤視圖,當(dāng)頁面出現(xiàn)問題時荔睹,自動調(diào)用狸演;
  • 其他視圖,可根據(jù)需要自行定義僻他,并在組件內(nèi)部聲明引用宵距。
  • 【組件調(diào)用示例】
export default {
    // 需要調(diào)用的視圖名稱,不寫默認(rèn)調(diào)用default.vue
    layout: 'onlyBody',
    data(){
      return {}
    }
}

4. 關(guān)于components

  • 用于定義框架中的各種自定義組件吨拗,可根據(jù)需要自行定義满哪。
  • 自定義組件中的數(shù)據(jù),一般應(yīng)從頁面?zhèn)魅肴芭瘢绻枰俳M件內(nèi)部獲取數(shù)據(jù)哨鸭,應(yīng)該使用fetch(子組件中不支持asyncData)。
  • components中聲明的各種組件携龟,在使用時兔跌,無需import導(dǎo)入勘高。直接使用組件名按需調(diào)用即可峡蟋。
  • 【使用示例】
<template>
  <div>
    // Header組件
    <Header />
  </div>
</template>

5. 關(guān)于store

  • store文件夾為Nuxt提供用于定義Vuex狀態(tài)樹的文件夾,詳細(xì)文檔參照:Vuex狀態(tài)樹华望。
  • 此文件夾下面的xxx.js蕊蝗,分別表示一個模塊,例如index.js對應(yīng)$store.state.xxx赖舟,而user.js對應(yīng)$store.state.user.xxx
  • 本框架中store中模塊的定義與普通Vue框架大體相同蓬戚,只是Nuxt框架會自動引用Vuex并加載到構(gòu)建配置重,無需我們自己new Vuex()
  • 【使用示例】
/**
 * 【注意區(qū)別】
 * state mutations action不再是包裹在一個對象中宾抓,并在new Vuex()的時候傳入子漩。 而是分別作為單獨模塊使用export導(dǎo)出即可豫喧。
 */
export const state = () => ({
    counter: 0
})
export const mutations = {
    increment(state) {
        state.counter++
    }
}

6. 關(guān)于middleware

  • middleware是框架中用于聲明中間件的文件夾,聲明后在nuxt.config.js中配置中間件即可幢泼,詳細(xì)文檔參照:中間件紧显。
  • @/middleware/router.js為已經(jīng)升級聲明好的路由守衛(wèi)中間件,可替代原框架中router.beforeEach中的路由守衛(wèi)功能缕棵;

7. 關(guān)于modules

  • 用于自定義模塊的文件夾孵班,可以在模塊中對Nuxt啟動部署的各種生命周期設(shè)置監(jiān)聽,詳細(xì)文檔參照:模塊招驴。
  • @/modules/generator.ts實現(xiàn)了一個對靜態(tài)化結(jié)束generate:done時進(jìn)行監(jiān)聽并處理的示例篙程。
const generator: any = function () {
    this.nuxt.hook('generate:done', (context: any) => {
        // TODO samething
    })
}
export default generator
  • 類似this.nuxt.hook('generate:done',() => {})的Nuxt框架hooks還有很多,例如:ready别厘、error虱饿、render:beforebuild:compile等等……詳細(xì)參見INTERNALS

<a name='six-8'>8. 其他Q&A</a>

1)每個頁面丹允,必須使用head設(shè)置title郭厌,必要時還需在詳情頁設(shè)置description。(5癖巍U勰!切記EI仁邸!)

export default {
    head() {
        return {
            // title必須設(shè)置OА3斜! 列表可以直接寫“xxx列表”食零,詳情頁等有不同標(biāo)題的困乒,要用新聞標(biāo)題、商品標(biāo)題等作為title前綴贰谣。
            title: this.detail.title + '_新聞詳情',
            meta: [
                // 詳情頁娜搂,需要設(shè)置不同的description。 this.$getDesc 為全局封裝的從富文本中截取100字符的description
                { hid: 'description', name: 'description', content: this.$getDesc(this.detail.details) },
            ],
        }
    }
}

2)pages目錄中的層級結(jié)構(gòu)吱抚,務(wù)必按照功能梳理清楚百宇,比如“news(新聞)”的列表、詳情都要在一個文件夾中秘豹。

<font color="#dd0000"><b>(P!!目錄結(jié)構(gòu)一旦確定啄刹,原則上不可再調(diào)整d套!J木)</b></font>

3)框架中的其他重要文件之【CSS篇】2采!

  • 框架各種css文件谭企,位于@/assets/css/中廓译。框架推薦使用scss語言债查,使用"sass": "~1.32.13"進(jìn)行編譯非区;
  • common.scss 為全局公共CSS,請將全局樣式表聲明于此盹廷≌鞒瘢或自行定義CSS文件,并在此文件中import導(dǎo)入俄占;
  • font.scss 用于定義本框架各種字體管怠、圖標(biāo)庫等;
  • variables.scss 聲明了框架的各種全局Scss變量缸榄,可以在所有頁面使用渤弛。
    • 注意:全局主題色,請用$mainColor表示甚带,不要在各自文件中自行聲明她肯!
  • element-variables.scss 是ElementUI的主題聲明文件,如需全局調(diào)整ElementUI的配色鹰贵,請在此調(diào)整晴氨;

4)(未完待續(xù)…)其他任何框架問題,詳詢小仙男

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末碉输,一起剝皮案震驚了整個濱河市籽前,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌敷钾,老刑警劉巖枝哄,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異膘格,居然都是意外死亡峭范,警方通過查閱死者的電腦和手機(jī)财松,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人辆毡,你說我怎么就攤上這事∏蜃颍” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長情竹。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么挑秉? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任蒲赂,我火速辦了婚禮滥嘴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘镊叁。我一直安慰自己走触,他們只是感情好互广,可當(dāng)我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著像樊,像睡著了一般颤霎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天首量,我揣著相機(jī)與錄音,去河邊找鬼拣宏。 笑死勋乾,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的学歧。 我是一名探鬼主播各吨,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起砚哗,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蛛芥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后涯竟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡壹将,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年嗤攻,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诽俯。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡屯曹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出惊畏,到底是詐尸還是另有隱情恶耽,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布颜启,位于F島的核電站偷俭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏缰盏。R本人自食惡果不足惜涌萤,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一淹遵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧负溪,春花似錦透揣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至崖堤,卻和暖如春侍咱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背密幔。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工楔脯, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人胯甩。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓昧廷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親偎箫。 傳聞我的和親對象是個殘疾皇子麸粮,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,933評論 2 355

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