vuex 要點 -- 原創

frontend/vuejs/vuex/vuex_banner

vuex是一個狀態管理模式,通過用戶的actions觸發事件,然后通過mutations去更改數據(你也可以說狀態啦 -> state),最后通過getters對狀態進行獲取,更改頁面展示的內容。哈哈 ?? ,詳細的內容請接著往下看,如有不妥請文末留言啊。原創文章,轉載請注明出處。

原文請戳傳送門

注意 ?? 文章中涉及到項目代碼是使用Vue官方提供的腳手架vue-cli進行搭建的,如果看者感興趣,可以自行用vue-cli搭建項目,并進行代碼的驗證。

Vuex是什么

官網介紹:Vuex是一個專門為Vuejs應用程序開發的狀態管理模式。(類似react的redux)。Vuex采用集中式存儲管理應用的所有組件的狀態,并以相應的規則保證狀態以一種可預測的方式發生變化。Vuex在構建中大型的應用比較適用,小型的應用用組件之間的通信就可以了,小型應用用上Vuex就顯得比較臃腫了。

Vuex的安裝

因為自己是使用npm來輔助開發的,所以我也只說下通過npm安裝Vuex的方法。其他的安裝方法,請戳傳送門

進入你項目的根目錄,然后執行:

$ npm install vuex --save 
或
$ npm install vuex --save-dev

然后在store主入口的javascript文件,一般是store/index.js中通過use進行引用,前提是你已經安裝了vue :

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

為了方便在各個組件中使用store,需要在程序的根組件中將其注入到每個子組件。我們需要在實例化Vue的時候將store引入(實例化Vue的文件一般是main.js主入口文件)。

import Vue from 'vue'
import store from '/path/to/store/index.js'

const initApp =new Vue({
        store: store
    }).$mount('#app')

核心概念

在使用Vuex進行開發的過程中,你可以理解核心的概念只有StateActionMutation三個,就像本文章開篇給出的截圖流程那樣簡單明了。但是,我們使用Vuex開發一個應用,肯定是想要方便管理等等。這里自己按照五個核心概念來談談,五個核心概念也是官網推薦使用的。Vuex的五個核心概念除了上面指出的三個之外,還包括GetterModule兩個。先一句話來概括下它們 :

  • State : 數據源的存放地

  • Getter : store的計算屬性

  • Mutation : 處理數據邏輯,使得數據和視圖分離(同步)

  • Action : 類似Mutation(異步),改變狀態的話,還得觸發Mutation

  • Module : 將store分解成模塊

下面來詳細講解各個核心概念咯 ??

State

Vuex是使用單一狀態樹,一個對象就包含了全部的應用層級狀態。這也就表明,一個應用僅僅包含一個store的實例。

狀態State對應于Vue對象中的data,因為兩者是對應的關系,所以在這里可以稱狀態==數據的。如下代碼指出:

<script>
    export default {
        name: '',
        data() { // state對應的地方
            return {
                ...
            }
        }
    }
</script>

State里面存放的數據是響應式的,Vue組件從store中讀取數據,若是store中的數據發生改變,依賴這個數據的組件也會發生更新。也就是說數據和視圖是同步的。

局部狀態

雖然說VuexStore倉庫讓我們統一管理數據變得更加方便,但是代碼一多也會變得冗長和不直觀。有些組件的數據是自己嚴格使用,我們可以將state放在組件自身,作為局部數據,專供此組件使用。比如現在只想在一個組件中使用emotion: happiness,那就不必要在storestate中進行定義了,只在本組件初始化就行了:

data () {
    return {
        emotion: 'happiness'
    }
}

獲取狀態

Vue組件中獲取store中的數據(狀態),最直接的就是通過計算屬性獲取。因為在上面我將store注冊到根組件上了,所以在這里直接通過this.$store就可以調用了。比如我獲取狀態(state)中的count: 100 :

computed: {
    count: function (){
        return this.$store.state.count;
    }
}

mapState輔助函數

mapState輔助函數把全局的State映射到當前組件computed計算屬性中,即是幫助我們生成計算屬性。簡化我們的代碼操作,不需要使用this.$store.state獲取了。以上面狀態(state)中的count: 100為例子 :

import { mapState } from 'vuex' // 注意別漏了引入
export default {
    computed: 
    mapState({
        count: state => state.count
    }),
}

Getter

上面的state中我們了解到,在store倉庫里,state是用來存儲數據的。在多個組件中要進行使用同一種狀態的話,對數據進行簡單操作,我們可以通過在組件的computed中進行獲取this.$store.state.theDataName。簡單操作沒問題,但是,我們進行其他的操作,比如過濾操作,我們就得寫一堆的代碼 :

computed: {
    filterData: function () {
        this.$store.state.theDataName.filter(function(item){
            // do something ...
        })
    }
}

然后在每個組件中復制這一大堆的代碼,或者你單獨新建一個文件把代碼寫進入,每個組件都引入(如果你不覺得很麻煩的話)。

Getter可以把組件中共享狀態抽取出來,這也是Getter存在的意義。我們可以認為,GetterStore的計算屬性。

如何使用Getter

為了方便管理,需要一個單獨的getters.js的文件,假如已經有對數據進行過濾的函數了:

export default {
    filterDatas (state,getter,rootState) {
        // do something ...
    }
}

那么只要在相關的組件的computed中引入就可以了,是不是很方便啊 :

computed: {
   filterItems: function () {
       return this.$store.getters.filterDatas;
   }
}

mapGetters輔助函數

mapGetters輔助函數僅僅是將store中的getter映射到局部計算屬性,看情況使用,類似mapState。下面使用mapGetter改寫上面的filterItems

import { mapGetters } from 'vuex' // 記得引入
export default {
    computed: 
        mapGetters({
            filterItems: 'filterDatas'
        })
}

Mutation

Vuex的中文官網中明確指出更改Vuex的store中的狀態(state)的唯一的方法是提交mutation

Mutation可以理解為:在Mutation里面裝著一些改變數據方法的集合。即把處理數據邏輯方法全部放在Mutation里面,使得數據和視圖分離。

使用Mutation

Mutation的結構:每個mutation都有一個字符串的事件類型(type)和一個回調函數(handler)也可以理解為{type:handler()},這和訂閱發布有點類似。先是注冊事件,當觸發響應類型的時候調用handle(),調用type的時候需要用到store.commit('typeName')方法。比如我想在要觸發mutations.js中的INCREASE處理函數:

// mutations.js
const INCREASE = 'INCREASE'; // 不能漏
export default {
    [INCREASE](state,data){
        // change the state ...
    }
}

因為我注冊了store到根組件,那么在.vue組件中就可以通過this.$store.commit('INCREASE')觸發這個改變相關狀態的處理函數了。如果在actions.js中調用,直接使用提供的commit參數進行commit('INCREASE')觸發處理函數。

提交載荷(Payload)

可以向store.commit傳入額外的參數,參數一般為object類型。我這里接著上面的示例,組件觸發的時候傳入一個100的數字到data里面 :

methods:{
    increase: function (){
        this.$store.commit('INCREASE',100);
    }
}

使用mutation-types.js

使用mutation-types.js(名稱可根據愛好隨便取)是為了方便管理項目mutation的類型。我在知乎上也回答過為什么要使用mutation-types.js,當然你完全沒必要使用它,不過我自己喜歡使用它。將使用mutation內容中的mutations.js代碼拆分為兩部分,一部分是mutation-types.js,另一部分是mutations.js,示范如下 :

// mutation-types.js
export const INCREASE = 'INCREASE';

// mutations.js
import {INCREASE} from '/path/to/mutation-type.js'
export default {
    [INCREASE](state,data){
        // change the state ...
    }
}

mapMutations輔助函數

為了簡化你的代碼量,使得代碼看起來逼格更高點,你可以使用mapMutations輔助函數將組件中的methods映射為store.commit調用(需要在根節點注入store哦)。demo來映射上面的increase

import {mapMutations} from 'vuex' // 不能漏哦
export default {
    methods: {
        ...mapMutations([
            'INCREASE'
        ])
    }
}

Action

Action 類似于 Mutation,不同點是 :

  • Action提交的是 mutation,而不是直接變更狀態

  • Action是異步的,而Mutation是同步的

詳細的相似點可以回滾看Mutation的啦,或者直接戳vue官網Store

組件內分發Action

因為我在全局組件中掛載了store,所以引用就可以這樣寫 -> this.$store.dispatch('dispatchEvent'),當然你可以傳參過去啦。比如:this.$store.dispatch('dispatchEvent',param),param一般是obj類型的。

mapActions輔助

為了簡化操作,Action像Mutaion一樣有一個映射的函數mapActions。使用方法也類似Mutation,demo如下 :

import {mapActions} from 'vuex' // 不能漏哦
export default {
    methods: {
        ...mapActions([
            'INCREASE'
        ])
        或
        ...mapActions([
            increase: 'INCREASE'
        ])
    }
}

Module

由于vue中使用單一的狀態樹,當管理的項目中大型的時候,所有的狀態都集中在一個對象中會變得比較復雜,難以管理,顯得項目比較臃腫。為了解決這些問題,我們可以使用vuex提供的Module功能,將store分割成模塊。每個模塊都有自己的state、mutation、action、getter。現在假設你的應用的功能包括登錄和音樂兩個功能模塊頁面,那么store的結構可以這樣寫:


- module
    - music
        actions.js
        getters.js
        index.js    // music module 的入口文件
        mutations.js
        state.js
    - user
        actions.js
        getters.js
        index.js    // user module的入口文件
        mutations.js
        state.js
actions.js
index.js    // store 的入口文件
mutation-types.js   // 管理所有的mutations
mutations.js
state.js
        

模塊的局部狀態

對于模塊內部的mutation,接收的第一個參數是state,也就是接收本模塊的局部狀態,比如上面的music模塊,我在其state.js中寫上 :

export default {
    music: {
        list: [],
        total: 100
    }
}

我在同級的mutations.js中有 :

import * as types from '../../mutation-types'
export default {
    [types.UPDATE_MUSIC](state,data){
        console.log(state.music.total); // 打印出100
        ...other handle
    }
}

命名空間

默認情況下,模塊內部的action、mutation 和 getter是注冊在全局命名空間的 -> 這樣使得多個模塊能夠對mutation和action作出響應。

如果看者希望你寫的模塊具有更高的封裝度和復用性,你可以通過添加namespaced:true的方式使其成為命名空間模塊。當模塊被注冊后,它的所有 getter、action 及 mutation 都會自動根據模塊注冊的路徑調整命名。比如上面的music模塊 :

import state from './state'     //state
import getters from './getters' //getters
import * as actions from './actions'    //actions
import mutations from './mutations'     //mutations

//modules
export default {
    namespaced: true, // 添加命名空間
    state,
    getters,
    actions,
    mutations
}

詳細的情況請戳vuex官網modules

store結構

vuex的官網談項目結構,我這里談store結構,因為我覺得每個人的項目的結構布局有所不同,但是vuex可以是一個模版化的使用。當然,這模版化的使用遵循了官網所定的規則:

  • 應用層級的狀態應該集中在單個 store對象中

  • 提交mutation是更改狀態(state)的唯一方法,并且這個過程是同步的

  • 異步邏輯都應該封裝到action里面

整理的store結構如下:

.
├── ...
│
└── store
    ├── actions.js  // 根級別的 action
    ├── index.js        // 我們組裝模塊并導出 store 的地方
    ├── mutation-types.js   // store所有mutations管理
    ├── mutations.js        // 根級別的 mutation
    ├── state.js        // 根級別的 state
    └── modules
        ├── moduleA
        ├── moduleB
        └── moduleC
            ├── actions.js  // moduleC 的 action
            ├── getters.js  // moduleC 的 getter
            ├── index.js        // moduleC 的 入口
            ├── mutations.js        // moduleC 的 mutation
            └── state.js        // moduleC 的 state

上面的結構比較通用,模版化,我在接下來的完整小項目中就是使用上面的store結構來管理啦 ??

完整小項目

自己在上面講了一大推的<del>廢話</del>,嗯哈,為了證明那不是<del>廢話</del>,下面就結合上面講的知識點來一個綜合的min-demo吧,歡迎指正啊! @~@

是什么項目呢

思來想去,自己還是覺得做一個簡單版本的todo項目好點,理由如下:

  • 個人時間精力郵箱(main reason)

  • todo項目 -> 麻雀雖小,五臟俱全

項目包含一個簡單的登錄頁面,然后跳轉到todo小項目的頁面。如圖所示:

frontend/vuejs/vuex/min-demo-login
frontend/vuejs/vuex/min-demo-todo

在登錄頁面,會要求你填寫非空的內容進入,我這里填了自己的名字啦。在todo頁面,你就需要在輸入框輸入你要做的事情啦,事情的添加默認是未做的狀態。當然,允許進行時間的狀態進行設置和事件的刪除啦。成品可查看下面最終的效果gif動效,就醬 @~@

項目的初始化

?? 本項目在mac系統上使用vue-cli的基礎上搭建(搭建日期2018.01.14)的小項目,其完整的覆蓋了vue的全家桶了 -> 使用的vue版本是^2.5.2,vuex的版本是^3.0.1,vue-router的版本也是^3.0.1。如果你使用低版本,請參考低版本的相關說明。

# 全局安裝 vue-cli
$ npm install --global vue-cli
# 進入桌面
$ cd desktop
# 初始化項目min-demo
$ vue init webpack min-demo

? Project name min-demo     # 項目名稱
? Project description A Vue.js project  # 項目描述
? Author reng99   # 項目作者
? Vue build standalone
? Install vue-router? Yes   # 是否使用路由
? Use ESLint to lint your code? No  # 是否啟動語法檢查
? Set up unit tests No      # 是否配置單元測試
? Setup e2e tests with Nightwatch? No   # 是否配置集成測試
? Should we run `npm install` for you after the project has been created? (recom
mended) npm # 選擇那種包管理工具進行安裝依賴,共三種選擇:npm,yarn,no thanks 我選擇了npm

   vue-cli · Generated "min-demo".
# 等待安裝依賴的完成
...
# 進入項目
$ cd min-demo
# 啟動項目
$ npm run dev

# 如果一切正常,就會在瀏覽器的http://localhost:8080的地址頁面有相關的vue界面展示出來

當然,使用腳手架搭建的項目,沒有自動集成vuex,這就需要你進入項目的根目錄,執行npm install vuex --save命令來安裝啦。

項目的實現

嗯嗯,下面我將改寫在vue-cli搭建的項目,以符合我自己期望。改寫的代碼就不全給出來了啊,關鍵的項目代碼還是會貼一下的。??

這個項目的結構如下:

.
├── build/  #webpack 的配置項
│   └── ...
├── config/
│   ├── index.js        # 項目的主要配置
│   └── ...
├── node_modules/   # 相關依賴
│   └── ...
├── src/
│   ├── main.js     # 應用的主入口
│   ├── App.vue     # 引用的根組件
│   ├── components/ 
│   │   ├── Login.vue       # 登錄組件
│   │   └── Todo.vue        # todo組件
│   ├── store/ 
│   │   ├── modules/        # todo組件
│   │   │     └── todo
│   │   │         ├── actions.js    # todo的actions
│   │   │         ├── getters.js    # todo的getters
│   │   │         ├── index.js      # todo的入口
│   │   │         ├── mutations.js      # todo的mutations
│   │   │         └── state.js      # todo的狀態
│   │   ├── actions.js      # 根actions
│   │   ├── index.js        # store入口文件
│   │   ├── mutation-types.js       # 整個store中的mutation的管理
│   │   ├── mutations.js        # 根mutations
│   │   └── state.js        # 根的狀態
│   ├── router/ 
│   │   └── index.js        # 路由文件
│   └── assets/     #  模塊的資源
│       └── ...
├── static/  # 靜態資源存放的地方
│   └── ...
├── .babelrc                    # 語法轉換babel的相關配置
├── .editorconfig               # 編輯器IDE的相關配置
├── .gitignore                  # 提交到github忽略的內容配置
├── .postcssrc.js               # css的處理配置postcssrc
├── index.html                  # index html模版
├── package.json                # 相關的執行命令和依賴配置
└── README.md                   # 項目的說明文件

?? 項目重點在src文件夾內

/src/components/Login.vue

<template>
  <div id="login">
    <div class='login'>
      <div class='login-title'>簡單模擬登錄</div>
      <div class='login-body'>
        <div class='hint' v-show='hintFlag'>輸入的文字不能為空</div>
        <input placeholder='請輸入任意文字...' type='text' v-model='loginTxt'/>
        <div class="btn" @click='login'>登錄</div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Login',
  data () {
    return {
      hintFlag: false,
      loginTxt: ''
    }
  },
  methods: {
    login () {
      var vm = this;
      if(vm.loginTxt.trim()==''){
        vm.hintFlag = true;
      }else{
        // 進入todo的頁面
        vm.hintFlag = false;
        // 觸發獲取登錄名
        vm.$store.dispatch('createUsername',vm.loginTxt);
        vm.$router.push('/todo');
      }
    }
  },
  watch:{
    loginTxt(curVal){
      var vm = this;
      if(curVal.trim()==''){
        vm.hintFlag = true;
      }else{
        vm.hintFlag = false;
      }
    }
  }
}
</script>

<style scoped lang='less'>
  #login{
    margin-top: 100px;
    .login{
      width: 400px;
      margin: 0 auto;
      &-title{
        color: #999;
        font-size: 22px;
        text-align: center;
        margin-bottom: 20px;
      }
      &-body{
        width: 360px;
        padding: 40px 20px 60px 20px;
        background: #ededed;
        input{
          width: 100%;
          display: block;
          height: 40px;
          text-indent: 10px;
        }
        .btn{
          width: 100%;
          text-align: center;
          height: 40px;
          line-height: 40px;
          background: #09c7d1;
          color: #fff;
          margin-top: 20px;
          cursor: pointer;
        }
        .hint{
          color: red;
          font-size: 12px;
          text-align: center;
          padding-bottom: 10px;
        }
      }
    }
  }
</style>

在上面的組件中,自己原封不動的將里面的代碼復制過來了,你應該可以看出,這個.vue文件中結合了三塊的東西,分別是html的模版、javascript代碼和運用less預處理器編寫的css代碼。

/src/components/Todo.vue組件的結構依舊是這樣:

<template>
  <div id="todo">
    <div class='username'>歡迎您!<span>{{username}}</span></div>
    <div class="main">
      <div class="input">
        <input placeholder='請輸入要做的事情...' type='text' v-model='eventTxt'/>
        <button @click="addEvent">增加</button>
      </div>
      ...
    </div>
  </div>
</template>

<script>
export default {
  name: 'ToDo',
  data () {
    return {
      noDataFlag: true,
      ...
    }
  },
  created(){
    var vm = this;
    if(vm.username == ''){
      vm.$router.push('/');
    }
  },
  computed: {
    username(){
      return this.$store.getters.username;
    },
    ...
  },
  methods: {
    delEvent (id) {
      this.$store.dispatch('delEvent',id);
    },
    ...
  },
  watch:{
    ...
  }
}
</script>

<style scoped lang='less'>
  #todo{
    margin-top: 100px;
    ...
  }
</style>

在路由的文件中,因為知識涉及了兩個頁面的路由跳轉,這里也全貼出來吧 --

import Vue from 'vue'
import Router from 'vue-router'
import Login from '@/components/Login'
import ToDo from '@/components/ToDo'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Login',
      component: Login
    },
    {
      path: '/todo',
      name: 'ToDo',
      component: ToDo
    }
  ]
})

關于store,這是一個重點,我打算詳細說啦。首先當然得從整個store的入口文件講起啦。在store/index.js中,我是這樣引用的 :

import Vue from 'vue'       // 引入vue依賴
import Vuex from 'Vuex'     // 引入vuex依賴

import state from './state'     // 引入根狀態
import * as actions from './actions'        // 引入根actions
import mutations from './mutations'     // 引入根mutations

import todo from './modules/todo/index'     // 引入todo模塊

Vue.use(Vuex)       // 引入vuex

// 初始化store
export default new Vuex.Store({
  state,
  actions,
  mutations,
  modules:{
    todo
  }
})

在根的storemutation-types.js文件中,管理著整個項目的狀態管理函數 --> 包括創建用戶名、添加要做的事情、刪除創建的事情、顯示事件的狀態(全部,已經做,沒有做)和標記事件(已經做的事件標記為未做,未做的事件標記為已經做)。代碼展示如下 :

export const CREATE_USERNAME = 'CREATE_USERNAME'  // 創建用戶名
export const ADD_EVENT = 'ADD_EVENT'  // 添加事件
export const DEL_EVENT = 'DEL_EVENT'  // 刪除事件
export const ALL_EVENT = 'ALL_EVENT'  // 全部事件
export const UNDO_EVENT = 'UNDO_EVENT'  // 沒做事件
export const DONE_EVENT = 'DONE_EVENT'  // 已做事件
export const MARK_UNDONE = 'MARK_UNDONE' // 標記為未做
export const MARK_DONE = 'MARK_DONE' // 標記為已做

store/state.js的作用在你聽完store/todo/state.js的講解后你應該會明白。在模塊todo的state中,自己定義了此模塊的相關的數據結構,如下:

export default {
  // 事件列表
  list:[
    // {
    //   id: 0,  相關的id
    //   content:'',  // 事件的內容
    //   flag: 1 // 是否完成,1是完成,0是未完成
    // }
  ],
  allList:[],
  increase: 0,
  total: 0,
  done: 0
}

定義的這些數據結構,你可以說是狀態吧,是為了給mutation和getters進行操作。對了,你也許注意到了store根目錄中沒有getters.js文件。因為,這是分散模塊管理項目,為什么還需要呢,如果你想保留,你可以自己新建一個,按照自己的習慣進行管理項目唄。

上個段落以及前面某部分內容已經談及了mutations的作用,本項目中使用mutation就是為了改變自己在todo/state.js定義的狀態,比如改變allList:[]

import * as types from '../../mutation-types'

export default {
  // 添加事件
  [types.ADD_EVENT] (state,data){
    var obj = {
      id: state.increase++,
      content: data,
      flag: 0
    }
    state.allList.push(obj);
    state.list = state.allList;
    state.total = state.allList.length;
  },
  ...
}

todo/getter.js就是為了將vuex中的狀態獲取,方便顯示在頁面的啦,在本項目中,自己超級簡單的使用了下:

export default {
  list (state,getters,rootState) {
    return state.list;
  },
  username (state,getters,rootState) {
    return rootState.username;
  },
  ...
}

最后一個是關于todo/actions.js,這是頁面中的用戶的事件去發送事件,使得產生mutations去改變狀態(state.js),最終使得頁面展示的內容(getters)發生改變。這里以一個派遣添加事件為例子 :

import * as types from '../../mutation-types'

export const addEvent = ({commit,state,rootState},query) => {
  commit(types.ADD_EVENT,query);
}

嗯,整篇文章都說整個store是掛載在根組件上的,那么是在哪里呢?答案就是src/main.js文件啦,文件內的代碼如下 :

import Vue from 'vue'
import App from './App'
import router from './router'

import store from './store'

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

最終的效果

好吧,自己利用了一個下午搭建項目并簡單思考了相關的邏輯,簡單實現項目,其最終的效果如下gif動圖啦 :

frontend/vuejs/vuex/min-demo

嗯,項目是不是很簡單,所以就不放源碼上去了 ?? 。其實自己覺得源碼實現不夠嚴謹啦,畢竟只是花了短短一個下午和晚上從設計到實現... 逃:)

參考內容

vuex官網

( 完 @~@ )

原文請戳傳送門

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

推薦閱讀更多精彩內容

  • 安裝 npm npm install vuex --save 在一個模塊化的打包系統中,您必須顯式地通過Vue.u...
    蕭玄辭閱讀 2,960評論 0 7
  • Vuex是什么? Vuex 是一個專為 Vue.js應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件...
    蕭玄辭閱讀 3,130評論 0 6
  • Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件的狀態,并以相應...
    白水螺絲閱讀 4,678評論 7 61
  • 系列文章:Vue 2.0 升(cai)級(keng)之旅Vuex — The core of Vue applic...
    6ed7563919d4閱讀 4,562評論 2 58
  • 按照自己的閱讀安排,最近在看《少有人走的路》。雖然第一章給我很多的激勵,然而第二章似乎有些偏激,啰嗦。第二章反復在...
    松樹愛姜姜閱讀 1,015評論 1 2