Vue+Vuex一步一步入坑指南

理解vue

引用一段官方的原話:

Vue.js(讀音 /vju?/,類似于 view) 是一套構(gòu)建用戶界面的漸進(jìn)式框架。與其他重量級(jí)框架不同的是,Vue 采用自底向上增量開(kāi)發(fā)的設(shè)計(jì)。Vue 的核心庫(kù)只關(guān)注視圖層凤覆,它不僅易于上手,還便于與第三方庫(kù)或既有項(xiàng)目整合姆怪。另一方面叛赚,當(dāng)與單文件組件Vue 生態(tài)系統(tǒng)支持的庫(kù)結(jié)合使用時(shí)澡绩,Vue 也完全能夠?yàn)閺?fù)雜的單頁(yè)應(yīng)用程序提供驅(qū)動(dòng)稽揭。

知乎也有相應(yīng)問(wèn)答:Vue2.0 中,“漸進(jìn)式框架”和“自底向上增量開(kāi)發(fā)的設(shè)計(jì)”這兩個(gè)概念是什么肥卡?溪掀,而我的理解就是:vue提供了最核心的的部分,開(kāi)發(fā)者則可以通過(guò)“增量”(即增加其它方案)進(jìn)行開(kāi)發(fā)步鉴,往里面疊加各種插件與組件揪胃,來(lái)完成功能需求。如果單純地使用vue也能達(dá)到想要的功能需求氛琢,但可能會(huì)讓代碼編寫起來(lái)會(huì)異常的混亂喊递,就不能體現(xiàn)vue的“輕”了。但如果接入其它方案阳似,一則代碼簡(jiǎn)單易讀骚勘,二則方便維護(hù),三則容易疊加式地接入更多方案。這就是vue “漸進(jìn)式框架” 的真諦之所在俏讹。

vue環(huán)境配置

vue官網(wǎng)給初學(xué)者的建議是以標(biāo)簽的方式引入vue.js庫(kù)当宴,直接上手使用。不過(guò)作為一個(gè)es2015的狂熱愛(ài)好者泽疆,Coding當(dāng)然得使用新標(biāo)準(zhǔn)了户矢。所以,第一步殉疼,開(kāi)發(fā)環(huán)境必須得先搭一個(gè)梯浪。而vue的開(kāi)發(fā)環(huán)境搭建也幾個(gè)命令的事。
我有兩種方法推薦:

1瓢娜、官網(wǎng)推薦vue-cli

npm i vue-cli -g

安裝完vue-cli驱证,則可以直接初始化項(xiàng)目。

vue init webpack vue-demo

安裝依賴包

npm i

運(yùn)行開(kāi)發(fā)模式

npm run dev

對(duì)于我來(lái)說(shuō)恋腕。我更不愿意花時(shí)間在學(xué)習(xí)搭建環(huán)境之上抹锄。所以我使用cooking進(jìn)行搭建開(kāi)發(fā)環(huán)境。

2荠藤、使用cooking搭建
安裝cooking-cli

npm i cooking-cli -g

安裝vue腳手架伙单,也可以安裝react,static之類的腳手架

npm i slush-cooking-vue -g

在用戶目錄~/.cooking目錄上安裝腳手架依賴(gulp相關(guān)包,注意此步驟不能少)

npm i -D gulp-install gulp gulp-rename gulp-template gulp-conflict

導(dǎo)入腳手架

cooking import vue -t

初始化項(xiàng)目(以上的步驟在之后的項(xiàng)目初始化則不需要重新做哈肖,則以后要初始化項(xiàng)目吻育,直接使用下面的步驟)。

cooking create vue-demo vue

初始化過(guò)程淤井,可以根據(jù)自己的需要配置相應(yīng)的參數(shù)布疼。因?yàn)閏ooking實(shí)際使用的是webpack的配置,只不過(guò)簡(jiǎn)化了配置項(xiàng)與配置過(guò)程币狠。在學(xué)習(xí)與開(kāi)發(fā)階段游两,完全可以無(wú)視這些過(guò)多的配置。

初始化項(xiàng)目的目錄結(jié)構(gòu)一般如下:

vue-demo
|-- src
   |-- assets
   |-- components
   |-- pages
   |-- app.vue
   |-- main.js
|-- static
|-- .babelrc
|-- .eslintrc
|-- packege.json
|-- cooking.conf.js
|-- Makefile

我以一個(gè)最簡(jiǎn)單的計(jì)數(shù)器需求進(jìn)行我的介紹漩绵。
需求: 定義一個(gè)小組件贱案,有加、減兩個(gè)按扭止吐,加+1宝踪,減-1,一個(gè)顯示結(jié)果的標(biāo)簽

vue組件化

在vue2.0時(shí)代碍扔,代碼的構(gòu)建方式瘩燥,分為獨(dú)立構(gòu)建與運(yùn)行構(gòu)建兩種方式。
1不同、獨(dú)立構(gòu)建:獨(dú)立構(gòu)建包含模板編譯器并支持 template 選項(xiàng)厉膀。 它也依賴于瀏覽器的接口的存在,所以你不能使用它來(lái)為服務(wù)器端渲染。
2站蝠、運(yùn)行時(shí)構(gòu)建:運(yùn)行時(shí)構(gòu)建不包含模板編譯器汰具,因此不支持 template 選項(xiàng),只能用 render 選項(xiàng)菱魔,但即使使用運(yùn)行時(shí)構(gòu)建留荔,在單文件組件中也依然可以寫模板,因?yàn)閱挝募M件的模板會(huì)在構(gòu)建時(shí)預(yù)編譯為 render 函數(shù)澜倦。運(yùn)行時(shí)構(gòu)建比獨(dú)立構(gòu)建要輕量30%聚蝶,只有 17.14 Kb min+gzip大小。

實(shí)現(xiàn)差別只在于new Vue()的時(shí)候藻治,獨(dú)立構(gòu)建可以掛載到el屬性上碘勉,模板依賴于dom,而運(yùn)行時(shí)構(gòu)建則通過(guò)render函數(shù)桩卵,將單文件組件作為render的回調(diào)函數(shù)的參數(shù)验靡。

運(yùn)行時(shí)構(gòu)建可以在服務(wù)端渲染,并且壓縮的體積更小雏节,則優(yōu)勢(shì)更明顯胜嗓,以下編碼皆使用運(yùn)行時(shí)構(gòu)建方式來(lái)構(gòu)建我的應(yīng)用。

獨(dú)立功能組件

把Counter組件自身的所有功能都寫在一個(gè)單獨(dú)文件里面钩乍,實(shí)現(xiàn)單文件組件辞州,相當(dāng)于組件自給自足,處理相應(yīng)的方法與邏輯寥粹。

// ./components/Counter.vue
<template>
    <div>
        <div>{{ count }}</div>
        <button @click="increment">+</button>
        <button @click="decrement">-</button>
    </div>
</template>

<script>
export default {
    name: 'counter',
    data() {
        return {
            count: 0
        }
    },
    methods: {
        increment() {
            this.count++
        },
        decrement() {
            this.count--
        }
    }
};
</script>

然后再app.vue引入Counter組件变过,此組件不需要傳入任何參數(shù)與方法。

// ./app.vue
<template>
    <counter></counter>
</template>

<script>
import Counter from './components/Counter'
export default {
    name: 'app',
    components: {
        Counter
    }
};
</script>

在入口函數(shù)main.js文件中涝涤,引入所有組件媚狰,執(zhí)行render函數(shù)。

import Vue from 'vue';
import App from './app';
new Vue({
    el: '#app',
    render: h => h(App)
});

需求完成妄痪。

可復(fù)用組件

處于可維護(hù)性與擴(kuò)展性上來(lái)說(shuō)哈雏,組件不能寫死楞件,組件的初始化數(shù)據(jù)往往來(lái)自后端傳過(guò)來(lái)的數(shù)據(jù)衫生。所以對(duì)于組件,一般將其靜態(tài)化土浸。即罪针,初始值及數(shù)據(jù)的變更邏輯都由父組件決定。
將組件靜態(tài)部分抽出來(lái):

// ./components/Counter.vue
<template>
    <div>
        <div>{{ count }}</div>
        <button @click="$emit('increment')">+</button>
        <button @click="$emit('decrement')">-</button>
    </div>
</template>
<script>
export default {
    props: {
        count: Number
    }
}
</script>

這樣黄伊,我們傳入了不可變更的屬性值props泪酱,然后方法集由$emit分發(fā)到父組件,由父組件處理數(shù)據(jù)狀態(tài)的變更邏輯。

// ./app.vue
<template>
    <counter
        :count="count"
        @increment="increment"
        @decrement="decrement">
    </counter>
</template>

<script>
import Counter from './Counter'
export default {
    name: 'app',
    data() {
        return {
            count: 0
        }
    },
    methods: {
        increment() {
            this.count++
        },
        decrement() {
            this.count--
        }
    },
    components: {
        Counter
    }
};
</script>

這樣做的好處可以讓UI層的組件不需要處理狀態(tài)的管理墓阀,只負(fù)責(zé)UI渲染即可毡惜,將揉合在起的數(shù)據(jù)結(jié)構(gòu)從功能層面上分離開(kāi)來(lái),達(dá)到了基本的顯示與邏輯分離斯撮。傳到子組件的數(shù)據(jù)经伙,需要全部屬性都得傳入,會(huì)增加很多的樣板代碼勿锅。觸發(fā)事件$emit會(huì)將對(duì)應(yīng)的方法傳到父組件帕膜,讓父組件來(lái)處理相應(yīng)的事件方法。不過(guò)溢十,如果子組件觸發(fā)的事件邏輯非常之多垮刹,并且都帶著負(fù)載對(duì)象參數(shù)什么的話,我們的組件邏輯就會(huì)寫得非常龐大张弛,并且難以維護(hù)荒典。

vuex引入

基于狀態(tài)管理的問(wèn)題,我們使用vue很難去維護(hù)吞鸭。官方推薦使用vuex進(jìn)行管理种蝶。我們可以通過(guò)vuex提供的store進(jìn)行管理我們的數(shù)據(jù)。而vue只負(fù)責(zé)UI渲染的問(wèn)題瞒大。數(shù)據(jù)的狀態(tài)變更螃征,由vuex來(lái)接管。
我們這樣大體上將vue與vuex作一個(gè)對(duì)比透敌,可以理解這樣的一個(gè)概念盯滚,state對(duì)應(yīng)的是data數(shù)據(jù)結(jié)構(gòu),而mutations對(duì)應(yīng)的是methods方法集酗电。

store魄藕、state

先定義一個(gè)store“數(shù)據(jù)庫(kù)”,將其掛載到app根節(jié)點(diǎn)上撵术”陈剩可以達(dá)到管控整個(gè)應(yīng)用的所有數(shù)據(jù)層。

// ./main.js
import Vue from 'vue';
import Vuex from 'vuex';
import App from './app';

Vue.use(Vuex)

const store = new Vuex.Store({
    state: {
        count: 0
    }
})

new Vue({
    el: '#app',
    store,
    render: h => h(App)
});

實(shí)際上Vuex.Store()方法接收的是一個(gè)對(duì)象作為參數(shù)嫩与。而對(duì)象包含state,mutations,actions,getters四個(gè)屬性寝姿。而我們使用state來(lái)初始化count的狀態(tài)值。
我們的靜態(tài)組件不需要調(diào)整划滋,只需要將父組件中的狀態(tài)處理邏輯交由store接管即可饵筑。

<template>
    <counter
        :count="$store.state.count"
        @increment="increment"
        @decrement="decrement">
    </counter>
</template>

<script>
import Counter from './Counter'

export default {
    name: 'app',
    methods: {
        increment() {
            this.$store.state.count++
        },
        decrement() {
            this.$store.state.count--
        }
    },
    components: {
        Counter
    }
};
</script>

如此達(dá)到了數(shù)據(jù)層與UI層的分離,我們的業(yè)務(wù)處理則可以寫到父給件上处坪,由$store對(duì)象處理我們的狀態(tài)根资。不過(guò)架专,這種寫法并不是很友好,也是多此一舉的做法玄帕〔拷牛可以將事件邏輯給另一個(gè)參數(shù)mutations來(lái)接管

mutations

state是初始化狀態(tài)值,而狀態(tài)的變化管理方法裤纹,可以交由mutations來(lái)處理睛低。

// ./main.js
import Vue from 'vue';
import Vuex from 'vuex';
import App from './app';

Vue.use(Vuex)

const store = new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        increment(state) {
            state.count++
        },
        decrement(state) {
            state.count--
        }
    }
})

new Vue({
    el: '#app',
    store,
    render: h => h(App)
});

而對(duì)應(yīng)的組件,則可以直接在傳入?yún)?shù)上添加對(duì)應(yīng)的處理方法服傍,皆由$store對(duì)象提供钱雷。

// ./app.vue
<template>
    <counter
        :count="$store.state.count"
        @increment="$store.commit('increment')"
        @decrement="$store.commit('decrement')">
    </counter>
</template>

<script>
import Counter from './Counter'

export default {
    name: 'app',
    components: {
        Counter
    }
};
</script>

不過(guò)vuex還提供了更為便捷的方式讓我們更方便處理這樣的數(shù)據(jù)接管。那就是vuex提供的輔助函數(shù)吹零。

mapState罩抗、mapMutations

mapState、mapMutations就相當(dāng)于連接vuex狀態(tài)屬性與vue組件之間的工具函數(shù)灿椅。他們將對(duì)應(yīng)的屬性與方法分別映射到相應(yīng)組件上去套蒂,使組件更專注于處理UI,而vuex更專注于管理狀態(tài)茫蛹,相互之間的聯(lián)系操刀,完全交由他們?nèi)マD(zhuǎn)化。

// ./app.vue
<template>
    <counter
        :count="count"
        @increment="increment"
        @decrement="decrement">
    </counter>
</template>

<script>
import { mapState, mapMutations } from 'vuex'
import Counter from './Counter'

export default {
    name: 'app',
    computed: mapState({ count: state => state.count }),
    methods: mapMutations(['increment','decrement']),
    components: {
        Counter
    }
};
</script>

mapState只能給computed賦值婴洼,因?yàn)閙apState返回的是一個(gè)函數(shù)集骨坑,如果賦值給data,則會(huì)報(bào)錯(cuò)柬采。

到目前為此欢唾,功能已經(jīng)實(shí)現(xiàn)了UI、狀態(tài)分管粉捻。也可以很好的維護(hù)了礁遣。有時(shí)候我們需要從 store 中的 state 中派生出一些狀態(tài),例如:
現(xiàn)在需要新增一個(gè)需求:添加一個(gè)顯示當(dāng)前計(jì)數(shù)是“奇數(shù)”還是“偶數(shù)”的提示肩刃。

getters祟霍、mapGetters

因?yàn)轱@示當(dāng)前計(jì)數(shù)是否“奇偶“,這個(gè)狀態(tài)值盈包,并非存在于原始state里面沸呐,而是由store派生出來(lái)的。

// ./main.js
import Vue from 'vue';
import Vuex from 'vuex';
import App from './app';

Vue.use(Vuex)

const store = new Vuex.Store({
    state: {
        count: 0
    },
    getters: {
        isEvenOrOdd(state) {
            return state.count % 2 === 0 ? 'even' : 'odd'
        }
    },
    mutations: {
        increment(state) {
            state.count++
        },
        decrement(state) {
            state.count--
        }
    }
})

new Vue({
    el: '#app',
    store,
    render: h => h(App)
});

同樣续语,添加上mapGetters對(duì)應(yīng)的映射關(guān)系垂谢。

// ./app.vue
<template>
    <counter
        :count="count"
        :isEvenOrOdd="isEvenOrOdd"
        @increment="increment"
        @decrement="decrement">
    </counter>
</template>

<script>
import { mapState, mapMutations, mapGetters } from 'vuex'
import Counter from './Counter'

console.log(mapState({ count: state => state.count }));

export default {
    name: 'app',
    computed:{
        ...mapState({ count: state => state.count }),
        ...mapGetters(['isEvenOrOdd'])
    },
    methods: mapMutations(['increment','decrement']),
    components: {
        Counter
    }
};
</script>


// ./components/Counter.vue
<template>
    <div>
        <div>{{ count }},this value is {{ isEvenOrOdd }}</div>
        <button @click="$emit('increment')">+</button>
        <button @click="$emit('decrement')">-</button>
    </div>
</template>
<script>
export default {
    props: {
        count: Number,
        isEvenOrOdd: String
    }
}
</script>

絕大多時(shí),我們的應(yīng)用其實(shí)都不是居于同步的基礎(chǔ)上的疮茄。還有很多是異步的應(yīng)用滥朱。也就是我們與服務(wù)端進(jìn)行交互。而我們使用vuex能處理的狀態(tài)力试,目前為此徙邻,都是在同步基礎(chǔ)上執(zhí)行的。為了解決異步問(wèn)題畸裳。我們需要使用到actions進(jìn)行處理異步邏輯缰犁。
上面的邏輯都是基于同步的操作。假設(shè)又新增了需求:新增一個(gè)異步點(diǎn)擊按扭“async+”怖糊,當(dāng)點(diǎn)擊時(shí)帅容,等1秒后執(zhí)行。

actions伍伤、mapActions

Action 類似于 mutation并徘,不同在于:

  • Action 提交的是 mutation,而不是直接變更狀態(tài)扰魂。
  • Action 可以包含任意異步操作麦乞。

Action 函數(shù)接受一個(gè)與 store 實(shí)例具有相同方法和屬性的 context 對(duì)象,因此你可以調(diào)用 context.commit 提交一個(gè) mutation劝评。實(shí)踐中姐直,我們會(huì)經(jīng)常會(huì)用到 ES2015 的 參數(shù)解構(gòu) 來(lái)簡(jiǎn)化代碼。

// ./main.js
...
const store = new Vuex.Store({
    state: {
        count: 0
    },
    getters: {
        isEvenOrOdd(state) {
            return state.count % 2 === 0 ? 'even' : 'odd'
        }
    },
    actions: {
        incrementIfAsync({ commit }) {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    commit('increment')
                    resolve()
                }, 1000)
            });
        }
    },
    mutations: {
        increment(state) {
            state.count++
        },
        decrement(state) {
            state.count--
        }
    }
})
...

我們?cè)诋惒教幚砗瘮?shù)中蒋畜,返回的是一個(gè)Promise声畏,在Promise里面執(zhí)行increment的提交。
實(shí)際上姻成,我們還有更方便的寫法砰识,那就是async/await寫異步函數(shù),那樣可以寫出干凈整潔的代碼佣渴。

...
const getData = time => new Promise((resolve, reject) => {
    setTimeout(() => { resolve() }, time)
});

const store = new Vuex.Store({
    state: {
        count: 0
    },
    getters: {
        isEvenOrOdd(state) {
            return state.count % 2 === 0 ? 'even' : 'odd'
        }
    },
    actions: {
        async incrementIfAsync({ commit }) {
            commit('increment', await getData(1000))
        }
    },
    mutations: {
        increment(state) {
            state.count++
        },
        decrement(state) {
            state.count--
        }
    }
})
...

這里需要注意一下辫狼,await的參數(shù)只能是Promise對(duì)象。

// ./app.vue
<template>
    <counter
        :count="count"
        :isEvenOrOdd="isEvenOrOdd"
        @increment="increment"
        @decrement="decrement"
        @incrementIfAsync="incrementIfAsync">
    </counter>
</template>

<script>
import { mapState, mapMutations, mapGetters, mapActions } from 'vuex'
import Counter from './Counter'

console.log(mapState({ count: state => state.count }));

export default {
    name: 'app',
    computed:{
        ...mapState({ count: state => state.count }),
        ...mapGetters(['isEvenOrOdd'])
    },
    methods: {
        ...mapMutations(['increment','decrement']),
        ...mapActions(['incrementIfAsync'])
    },
    components: {
        Counter
    }
};
</script>

// ./components/Counter.vue
<template>
    <div>
        <div>{{ count }},this value is {{ isEvenOrOdd }}</div>
        <button @click="$emit('increment')">+</button>
        <button @click="$emit('incrementIfAsync')">async+</button>
        <button @click="$emit('decrement')">-</button>
    </div>
</template>
<script>
export default {
    props: {
        count: Number,
        isEvenOrOdd: String
    }
}
</script>

有時(shí)辛润,當(dāng)前膨处,我們所有的狀態(tài)管理邏輯都是寫在main.js里面。但在大型應(yīng)用開(kāi)發(fā)的過(guò)程中砂竖,往往都將store集中寫到一個(gè)文件夾store里面真椿。

store文件夾

store
    |-- index.js
    |-- modules
        |-- counter.js
    |-- getters.js
    |-- actions.js
    |-- mutation-types.js

將其拆開(kāi)為各個(gè)文件的目的就是可以讓狀態(tài)管理更具體。

// ./store/modules/counter.js

// async(or ajax) function
const getData = time => new Promise((resolve, reject) => {
    setTimeout(() => { resolve() }, time)
});

// init state
const state = { count: 0 }

// mutations
const mutations = {
    [types.INCREMENT](state) {
        state.count++
    },
    [types.DECREMENT](state) {
        state.count--
    }
}

// actons
const actions = {
    increment: ({ commit }) => commit(types.INCREMENT),
    decrement: ({ commit }) => commit(types.DECREMENT),
    async incrementIfAsync({ commit }) {
        commit(types.INCREMENT, await getData(1000))
    }
}

// getters
const getters = {
    isEvenOrOdd(state) {
        return state.count % 2 === 0 ? 'even' : 'odd'
    }
}

export default {
    state,
    getters,
    actions,
    mutations
}

然后其它文件如下:

// ./store/getters.js
export {}

// ./store/actions.js
export {}

// ./store/mutations.js
export {}

// ./store/mutation-types.js
export const INCREMENT = 'INCREMENT'
export const DECREMENT = 'DECREMENT'

// ./store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import * as actions from './actions'
import * as getters from './getters'
import * as mutations from './mutations'
import counter from './modules/counter'
Vue.use(Vuex)
export default new Vuex.Store({
    actions,
    getters,
    mutations,
    modules: {
        counter
    }
})

事實(shí)上乎澄,我們已經(jīng)將所有狀態(tài)管理邏輯都按照state,getters,actions,mutations,modules的模式構(gòu)建突硝。而modules里面的每一個(gè)子模塊,也有自己?jiǎn)为?dú)的state,getters,actions,mutations置济。他們是在自己獨(dú)立的命名空間內(nèi)工作解恰,與外不影響锋八。如果要取得父結(jié)構(gòu)的狀態(tài),則可以通過(guò)參數(shù)rootState取得护盈。
如此挟纱,在大型應(yīng)用的開(kāi)發(fā)中,可以很方便找到對(duì)應(yīng)的模塊腐宋,處理單獨(dú)子模塊內(nèi)的狀態(tài)管理紊服。關(guān)于vuex狀態(tài)管理更多的內(nèi)容,可以查看文檔
這時(shí)胸竞,入口文件main.js可以以固定格式書寫

import Vue from 'vue';
import store from './store'
import App from './app';

new Vue({
    el: '#app',
    store,
    render: h => h(App)
});

總結(jié)

從Counter計(jì)數(shù)器的實(shí)現(xiàn)過(guò)程欺嗤,我一直在變換著寫法。實(shí)際上我的目的就是把vue從單純的組件把功能與數(shù)據(jù)揉合捆綁卫枝,一步一步地進(jìn)行拆解煎饼,并且給他裝上vuex方案,以達(dá)到組件+狀態(tài)分離剃盾。實(shí)現(xiàn)了UI與數(shù)據(jù)的完美組合腺占。
而vue與vuex的對(duì)應(yīng)關(guān)系,我理解成這樣的結(jié)構(gòu):

// 整體就是一個(gè)應(yīng)用痒谴,則整個(gè)應(yīng)用的數(shù)據(jù)狀態(tài)都?xì)wstore管控
UI —— Store //渲染層UI組件與store對(duì)象之間是存在著一種形象的“樹(shù)型結(jié)構(gòu)”
data —— state
computed —— actions衰伯、getters
methods —— mutations
components —— modules

通過(guò)如此的對(duì)應(yīng)關(guān)系,就可以很方便地將應(yīng)用的狀態(tài)邏輯狀態(tài)交由store去處理积蔚。如此意鲸,vue負(fù)責(zé)UI渲染,而vuex負(fù)責(zé)數(shù)據(jù)變更尽爆,達(dá)到完美組合怎顾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市漱贱,隨后出現(xiàn)的幾起案子槐雾,更是在濱河造成了極大的恐慌,老刑警劉巖幅狮,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件募强,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡崇摄,警方通過(guò)查閱死者的電腦和手機(jī)擎值,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)逐抑,“玉大人鸠儿,你說(shuō)我怎么就攤上這事〔薨保” “怎么了进每?”我有些...
    開(kāi)封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵汹粤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我品追,道長(zhǎng)玄括,這世上最難降的妖魔是什么冯丙? 我笑而不...
    開(kāi)封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任肉瓦,我火速辦了婚禮,結(jié)果婚禮上胃惜,老公的妹妹穿的比我還像新娘泞莉。我一直安慰自己,他們只是感情好船殉,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布鲫趁。 她就那樣靜靜地躺著,像睡著了一般利虫。 火紅的嫁衣襯著肌膚如雪挨厚。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天糠惫,我揣著相機(jī)與錄音疫剃,去河邊找鬼。 笑死硼讽,一個(gè)胖子當(dāng)著我的面吹牛巢价,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播固阁,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼壤躲,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了备燃?” 一聲冷哼從身側(cè)響起碉克,我...
    開(kāi)封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎并齐,沒(méi)想到半個(gè)月后漏麦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡冀膝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年唁奢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窝剖。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡麻掸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出赐纱,到底是詐尸還是另有隱情脊奋,我是刑警寧澤熬北,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站诚隙,受9級(jí)特大地震影響讶隐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜久又,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一巫延、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧地消,春花似錦炉峰、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至半夷,卻和暖如春婆廊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背巫橄。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工淘邻, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人嗦随。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓列荔,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親枚尼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贴浙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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