首页 > 其他 > 详细

vue学习之vuex

时间:2019-02-11 18:33:50      阅读:236      评论:0      收藏:0      [点我收藏+]

 

父组件通过props传数据到子组件,子组件通过事件回传数据给父组件,那么几个不相关的组件想共享一个数据,那么就可以用到vuex。

概念

state

存放要共享的数据。在组件中,state的属性没有直接放在组件的data部分,一般是在computed里,依赖于state属性的改变而更新页面数据。

mutations

定义操作state属性的方法。组件不能直接操作state的属性,需要通过mutations操作。

actions

通过actions里各方法的commit(‘mutations方法名’),与mutations里的方法关联起来。

页面接收到用户的交互行为分发事件到actions的时候,执行对应的mutations里的方法改变state,,从而更新页面使用到的state数据部分

技术分享图片

 

实践

大概过程就是:创建一个管理state的文件——导出vuex实例——根实例中注册实例——在组件中使用实例

 

安装vuex:npm install vuex --save

创建一个store.js文件

import Vue from ‘vue‘
import Vuex from ‘vuex‘

Vue.use(Vuex)
//声明state
const state={
  count:1
}
//声明mutations,定义方法操作state的属性 const mutations
={ add(state){ state.count++ }, reduce(state){ state.count-- } } //声明actions,通过commit与mutations的方法关联起来 const actions={ onAdd:({commit})=>{//通过解构的形式,使用对应的commit方法 commit(‘add‘); }, onReduce:({commit})=>{ commit(‘reduce‘); } } //导出模块 export default new Vuex.Store({state,mutations,actions})

 

在组件中使用state

在main.js里引入模块

import Vue from ‘vue‘
import App from ‘./App‘
import router from ‘./router‘
import store from ‘./store‘

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: ‘#app‘,
  router,
  store,
  components: { App },
  template: ‘<App/>‘
})

创建一个使用state数据的组件count.vue

<template lang="html">
  <div class="count">
    {{$store.state.count}}
    <button type="button" name="button" @click="onAdd"></button><!--onAdd:methods里的方法-->
    <button type="button" name="button" @click="onReduce"></button>
  </div>
</template>
<script>
  import {mapActions} from ‘vuex‘

    export default{
      methods:mapActions([
        ‘onAdd‘,//和store.js中action里的increment关联起来
        ‘onReduce‘
      ])
    }
</script>
<style lang="css">
</style>

部分解说:

1、在组件中分发action:可以使用 this.$store.dispatch(‘actions里的方法名称‘) 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store

上面代码中,事件使用的都是methods里的方法,直接写method的方法是没法和action关联上的,这里通过mapActions使它的onAdd和action里的onAdd关联了起来。、


 2、{{$store.state.count}}中$store来自于main里引入的store。

前面提到过state的属性没有直接放在组件的data部分,一般是在computed里,每当 store.state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。

要是对每个属性进行计算,下面这样的写法就不方便了

const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}

 

使用mapState函数,mapState 函数返回的是一个对象

当映射的计算属性的名称与 state 的子节点名称相同时,可以给 mapState 传一个字符串数组。
computed: mapState([
  // 映射 this.count 为 store.state.count
  ‘count‘
])

 

或使用对象展开符混合mapSate的对象到computed里:

computed: {
  localComputed () { /* ... */ },
  // 使用对象展开运算符将此对象混入到外部对象中
  ...mapState({
    // ...
  })
}

 

在App.vue中引入这个组件

<template>
  <div id="app">
     <count/>
     <router-view></router-view>
  </div>
</template>

<script>
  import count from ‘components/count.vue‘
export default {
  name: ‘App‘,
  components:{
    count
  }
}
</script>

 

state应用再更复杂的场景

比如a,b,c三个页面,a页面由多个组件构成,这些组件共享一个state。b页面也由多个组件构成,这些组件又共享一个state。此时如果只有一个state去管理a和b页面的所有state属性,可能会导致命名冲突或者操作失误,也不方便管理。这个时候就想要他们管理各自的state。

创建一个store目录

技术分享图片

 

a和b.js里面声明各自的state,mutations,actions

//a.js和b.js的代码
const state = { money: 1
//money:10 b的money初始值
} const mutations = { add(state){ state.money++ }, reduce(state){ state.money-- } } const actions = { onAdd: ({commit})=> { commit(‘add‘); }, onReduce: ({commit})=> { commit(‘reduce‘); } } export default { namespaced:true,//开启命名空间 state, mutations, actions }

 

在index.js中引入a和b再通过modules导出

import Vue from ‘vue‘
import Vuex from ‘vuex‘
import moneya  from ‘./modules/a‘
import moneyb from ‘./modules/b‘

Vue.use(Vuex)

export default new Vuex.Store({
 modules:{
   moneya,
   moneyb
 }
})

 

在main.js中引入index.js

import Vue from ‘vue‘
import App from ‘./App‘
import router from ‘./router‘
import store from ‘./store/index‘

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: ‘#app‘,
  router,
  store,
  components: { App },
  template: ‘<App/>‘
})

在a.vue和b.vue中使用各自的state

a.vue

<template lang="html">
  <div>
    pagea:{{$store.state.moneya.money}}//$store.state和index.js中的modules对应
  </div>
</template>
<script>
    export default{}
</script>
<style lang="css">
</style>

b.vue

<template lang="html">
  <div>
    pagea:{{$store.state.moneyb.money}}
  </div>
</template>
<script>
    export default{}
</script>
<style lang="css">
</style>

 

在App.vue中加载a和b组件

<template>
  <div id="app">
     <pagea></pagea>
     <pageb></pageb>

  </div>
</template>

<script>

import pagea from "./components/a.vue"
import pageb from "./components/b.vue"
export default {
  name: ‘App‘,
  components:{
    pagea,
    pageb
  }
}
</script>

结果如下:

技术分享图片

 

 

那么a和b组件在交互方面怎么样呢?

 以a.vue为例,增加两个按钮操作a.js里的money

<template lang="html">
  <div>
    pagea:{{$store.state.moneya.money}}
     <button type="button" name="button" @click="onAdd">增加</button>
     <button type="button" name="button" @click="onReduce">减少</button>
  </div>
</template>
<script>
  import {mapActions} from ‘vuex‘
    export default{
      methods:mapActions(moneya‘,["onAdd","onReduce"])//注意这里的写法
    }
</script>
<style lang="css">
</style>

 

点击a组件的按钮,b的money不受影响

技术分享图片

 

补充

给mutations传参

从交互的地方触发action的时候传进来参数。以a.vue和a.js为例

<template lang="html">
  <div>
    pagea:{{$store.state.moneya.money}}
     <button type="button" name="button" @click="onAdd(2)">增加</button>
     <button type="button" name="button" @click="onReduce">减少</button>
  </div>
</template>
<script>
  import {mapActions} from ‘vuex‘
    export default{
      methods:mapActions(‘moneya‘,["onAdd","onReduce"])
    }
</script>

a.js中

const mutations = {
  add(state,params){
    console.log(params);
    state.money++
  },
  reduce(state){

state.money
-- } } const actions = { onAdd: ({commit},params)=> { commit(‘add‘,params);//接收参数 }, onReduce: ({commit})=> { commit(‘reduce‘); } }

 结果,点击增加按钮,输出2

技术分享图片

 

vue学习之vuex

原文:https://www.cnblogs.com/yaoyao-sun/p/10361351.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!