初识VUEX

一、vuex用来做什么

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。其实就是vue的内存持久化的管理。

    首先我们需要来通过npm安装vuex

npm install vuex --save

安装完成以后,在进行全局的注册这样使用起来会更方便, 如果不注册这样也不会影响任何东西,只是这样更简便。

// main.js

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'  // 引入store

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  store,  // 进行注册,这样就能通过this.$store进行调用到
  components: { App },
  template: '<App/>'
})

ps:  使用vuex好还是localstorage好?

两者应用场景不同。vuex是当前vue项目的全局状态对象,存放在内存中,一旦当前vue项目刷新,vuex的数据也将恢复默认值;而localstorage是当前域下可以永久存放在浏览器中的对象,即使刷新数据也仍然存在,只要在当前域中即可获取到存放在localStorage中的数据。

二、vuex重要的五个属性

  • state,用于存放状态,就是store对象的全部属性。
  • mutations ,每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。只能通过mutation来修改state的属性。
  • actions,用于存放异步操作,Action 提交的是 mutation,而不是直接变更状态。
  • getters , 加工state成员给外界,可以在这里进行对数据的组装等操作。
  • modules ,模块化管理,解决了store属性太多导致的臃肿问题。

三、如何使用vuex

1. state

import Vue from 'vue'
import Vuex from 'vuex'  // 导入vuex

// 显示的声明使用vuex
Vue.use(Vuex)

const store = new Vuex.Store({
  // state用于存放状态
  state: {
    count: 0
  }
})

// 对外暴露store对象
export default store

为了方便使用store变量的一些属性,vuex提供了混入变量的语法 

<template>
  <div>
    <div>{{msg}}</div>
  </div>
</template>

<script>
import store from '../store'
// mapState在computed里面去使用里面的参数是state中的变量名称,...是混入到当前变量中也就是可以在当前组件相当于data中的直接使用
import { mapState } from 'vuex'
export default {
  name: 'start',
  data () {
    return {
      msg: store.state.count, // 获取store对象的属性
    }
  },
  computed: {
     ...mapState(['name', 'des'])  // 在这里就将当前的state的属性进行了导入
  }
}
</script>

增加和删除state中的成员变量

Vue.set(state,"age",15)   // Vue.set 为某个对象设置成员的值,若不存在则新增

Vue.delete(state,'age')   // Vue.delete 删除成员

2. mutations

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

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0
  },
  // 通过mutations来修改state的状态,这个里面必须都是同步函数
  mutations: {
    increment (state) {
      state.count++
      console.log(state.count)
    }
  }
})

export default store

在mutations里面的函数只能是同步函数不能是异步的

<template>
  <div>
    <div>{{msg}}</div>
    <button @click="incr">click me</button>
    <!-- 当点击button以后触发函数,对state的状态进行了修改,就会触发count进行重新读取值 -->
    <h1>{{count}}</h1>
    <!-- 如果mutation的函数需要入参必须在这里进行传递 -->
    <button @click="clicked(2)">clicked</button>
  </div>
</template>

<script>
import store from '../store'
import {mapMutations} from 'vuex'
export default {
  name: 'start',
  data () {
    return {
      msg: store.state.count,
    }
  },
  methods: {
    incr: function () {
      // 通过提交触发increment进行变量的修改
      store.commit('increment')
    }
  },
  // 在这里重新计算值
  computed: {
    count () {
      return this.$store.state.count
    },
    ...mapMutations(['clicked'])  // // 在这里就将当前的mutation的属性进行了导入
  }
}
</script>

3. getters

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

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0,
    todos: [
      { id: 1, text: '刘硕是我儿', done: true },
      { id: 2, text: '我是刘硕爹', done: false }
    ]
  },
  // getter 加工state给外界
  getters: {
    // 在这个箭头函数的参数里可以进行传递参数,
    dochange: (state) => {
      // 在这里是返回了item.done为true的元素
      return state.todos.filter(item => item.done)
    },
    // 这个id是传进来的参数
    getChange: (state) => (id) => {
      // 在这里是返回了item.done为true的元素
      return state.todos.find(item => item.id === id)
    }
  }
})

export default store

vuex对getters也提供了辅助函数

<template>
  <div>
    <h1>{{doTodosByAttr}}</h1>
    <h1>{{doTodosByMethod}}</h1>
  </div>
</template>

<script>
import store from '../store'
import { mapGetters } from 'vuex'

export default {
  name: 'start',
  data () {
    return {
      msg: store.state.count,
    }
  },
  methods: {
    incr: function () {
      store.commit('increment')
    }
  },
  // 在这里重新计算值
  computed: {
    // 去调用getters方法,这种是相当于属性去调用getters,会被缓存
    doTodosByAttr () {
      return this.$store.getters.dochange
    },
    // 这种是相当于方法去调用getters,不会被缓存
    doTodosByMethod () {
      return this.$store.getters.getChange(2)
    },
    ...mapGetters(['dochange']),
  }
}
</script>

4. actions

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

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0,
    todos: [
      { id: 1, text: '刘硕是我儿', done: true },
      { id: 2, text: '我是刘硕爹', done: false }
    ]
  },
  mutations: {
    increment (state) {
      state.count++
      console.log(state.count)
    },
    docrazy (state) {
      console.log('****')
    },
    docry (state) {
      console.log('I am Crying')
    }
  },
  // actions 异步操作 提交的是 mutation,而不是直接变更状态。
  actions: {
    // context 是一个和store拥有相同方法和属性的一个对象,但是并不是store的实例
    increment (context) {
      context.commit('increment')
    },
    // 进行分发以后会返回一个promise对象
    incrementAsync ({commit}) {
      // 在这里去提交mutations
      commit('docrazy')
    },
    // 通过promise可以,这是正确处理异步的方式
    actionA ({commit}) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          commit('docry')
          resolve()
        }, 1000)
      })
    }
  }
})

export default store
<template>
  <div>
    <h1>{{doCrazy}}</h1>
    <h1>{{doActionA}}</h1>
  </div>
</template>

<script>
import store from '../store'
import {mapActions} from 'vuex'
export default {
  name: 'start',
  data () {
    return {
      msg: store.state.count,
    }
  },
  computed: {
    // 进行action的分发
    doCrazy () {
      this.$store.dispatch('incrementAsync')
    },
    doActionA () {
      // 通过promise进行任务的返回
      this.$store.dispatch('actionA').then(() => {
        console.log('执行成功')
      })
    },
    ...mapActions(['clicked'])  // 快速对actions进行导入
  }
}
</script>

※:使用mapMutations、mapActions暴露的函数,需要手动传值,否则传入默认的事件对象。

5. modules:

import Vuex from 'vuex'

const moduleA = {
  namespaced: true,  // 开启命名空间,这样才能获取
  state: {name: 'my name is liushuo'},
  actions:{},
  mutations:{},
  getters:{}
}
const moduleB = {
  namespaced: true,
  state: {name: 'liushuo sha bi'},
  actions:{},
  mutations:{},
  getters:{}
}

// 可以将每个属性定义成为好几个模块这样解决了非常臃肿的问题
const self = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})
export default self


// 提交或者dispatch某个方法和以前一样,会自动执行所有模块内的对应type的方法
this.$store.commit('editKey')
this.$store.dispatch('aEditKey')

// 模块中mutations和getters中的方法接受的第一个参数是自身局部模块内部的state
// getters中方法的第三个参数是根节点状态
// actions中方法获取局部模块状态是context.state,根节点状态是context.rootState

此时通过快速获取的方式不会变:

computed:{
  // 可以指定哪个模块下的某个state
  ...mapState('b', ['message']),
  ...mapMutations('b', ['clicked']),
  ...mapActions('b', ['doThink']),
  ...mapGetters('b', ['getThink']),
}

通过$store方式获取就会出现问题

$store.state.b.message   // 多指定一层是哪个module
$store.getters['a/getThink']   // 需要通过中括号进行获取,因为含有斜杠
this.$store.commit("a/doThink")    
this.$store.dispatch("a/makeThink")

※:为什么会有斜杠的出现:因为定义就是带斜杠的。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值