vuex了解一下?

Vuex

一个专为 Vue.js,应用程序开发的状态管理模式。它采用集中式存储管理应用的全部组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。vue

vuex流程图

组件触发事件dispatch;
actions调用后端接口;
调用commit,来触发mutations;
改变state的状态;
最后渲染组件;

使用vuex

安装模块
npm install vuex --saveios

// store.js
import Vue from 'vue'  
import Vuex from 'vuex'  

Vue.use(Vuex)
let store = new Vuex.Store({
    state:{
        count:100
    },
    getters:{
        // 可传递 getter 做为第二个参数
        filter(state){
            return state.count >= 120 ? 120 : state.count;
        }
    },
    mutaitons:{
        add(state,n,m){
            state.count= state.count + n + m;
        },
        de(state,payload){
            state.count-=payload.n;
        }
    },
    actions:{
        add(context){
            setTimeout( ()=>{
                context.commit('add', {n:5} )
            }, 1000)
        }
    }
})

export default store
复制代码

读取state的属性

this.$store.state.count;  
复制代码

读取getters的属性

this.$store.getters.filter;  
复制代码

commit同步改变state

// 多个参数
this.$store.commit('add',5,3);   
// 对象参数
this.$store.commit('de',{
    n:5
});  
// 直接使用包含 type 属性的对象  
this.$store.commit({
    type:'de',
    de:5
});   
复制代码

dispatch异步改变state

this.$store.dispatch('add')  
复制代码

vuex辅助函数

mapState
mapGetters
mapMutations
mapActions
createNamespacedHelpers
以上方法都接收一个参数,返回对象;vuex

import {mapState,mapGetters,mapActions,mapMutations} from 'vuex'
export default {
  computed: {
    ...mapGetters({
      num: 'filterCount'
    }),
    ...mapState(['count']),
  },
  methods: {
    ...mapActions({
      addHandle: 'addAction'
    }),
    ...mapMutations({
      deHandle:'deIncrement'
    })
  }
}

/*
多种写法
computed: {
    ...mapGetters({
        num: state => state.count,
        num: 'count',
        num(state) {
            return state.count+100
        },
        count: 'count'
    })
},
computed: mapGetters(['count']),
*/
复制代码

如需传参能够直接写在绑定事件上:npm

<input type="button" value="-" @click="deHandle({de:5})" />
复制代码

vuex模块

// 定义模块
let selectModule = {
  state:{
    title:'hello123',
    list: []
  },
  getters:{
        // 接受 getter 做为第二个参数
        // 接受 rootStare 根state 做为第三个参数
        filter(state){
            return state.count >= 120 ? 120 : state.count;
        }
    },
  mutations:{
    changeTitle(state, payload){
      state.title = payload.title
    },
    changeList(state, list){
      state.list = list;
    }
  },
  actions:{
    getListAction({state, commit, rootState}){
      // 发送请求
      axios.get('http://easy-mock.com/mock/594f5d4b9adc231f3569be76/list/list')
        .then((data)=>{
          commit("changeList", data.data);  // 拿到数据后,提交mutations,改变状态
        })
        .catch((error)=>{
          conso.log(error)
        })
    }
  }
};

let store = new Vuex.Store({
    modules:{
      selectModule
    }
})
复制代码

state里的属性须要以下访问,其余的不变;axios

this.$store.state.selectModule.title  
this.$store.commit('changeTitle',5,3);  
this.$store.dispatch('getListAction',5,3);  
复制代码

插件

Vuex 的 store 接受 plugins 选项,这个选项暴露出每次 mutation 的钩子。Vuex 插件就是一个函数,它接收 store 做为惟一参数(洗澡睡觉 明天补充 1562083121584 这是啥)后端

// 定义插件
const myPlugin = store => {
  // 当 store 初始化后调用
  store.subscribe((mutation, state) => {
    // 每次 mutation 以后调用
    // mutation 的格式为 { type, payload }
  })
}
// 使用
const store = new Vuex.Store({
  // ...
  plugins: [myPlugin]
})
复制代码

严格模式

在严格模式下,不管什么时候发生了状态变动且不是由 mutation 函数引发的,将会抛出错误。这能保证全部的状态变动都能被调试工具跟踪到。bash

const store = new Vuex.Store({
  // ...
  strict: true
})
复制代码

devtools

为某个特定的 Vuex 实例打开或关闭 devtools。异步

{
  devtools: false
}
复制代码

module命名空间

默认状况下,模块内部的 action、mutation 和 getter是注册在全局命名空间的——这样使得多个模块可以对同一 mutation 或 action 做出响应。函数

经过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的全部 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。工具

带命名空间的模块内访问全局内容

  • 但愿使用全局 state 和 getter,rootState 和 rootGetter 会做为第三和第四参数传入 getter,dispatch也会经过 context 对象的属性传入 action。
  • 若须要在全局命名空间内分发 action 或提交 mutation,将 { root: true } 做为第三参数传给 dispatch 或 commit 便可。
dispatch('actionName') // -> 'module/actionName'
dispatch('actionName', null, { root: true }) // -> 'rootStoreActionName'
commit('mutationName') // -> 'module/mutationName'
commit('mutationName', null, { root: true }) // -> 'rootStoreMutationName'
复制代码

在带命名空间的模块注册全局action

须要在带命名空间的模块注册全局 action,你可添加 root: true,并将这个 action 的定义放在函数 handler 中

modules: {
    foo: {
      namespaced: true,
      actions: {
        someAction: {
          root: true,
          handler (namespacedContext, payload) {}
        }
      }
    }
}
复制代码

带命名空间的绑定函数

computed: {
  ...mapState({
    a: state => state.some.nested.module.a,
    b: state => state.some.nested.module.b
  })
},
methods: {
  ...mapActions([
    'some/nested/module/foo', // -> this['some/nested/module/foo']()
    'some/nested/module/bar' // -> this['some/nested/module/bar']()
  ])
}
// 将模块的空间名称字符串做为第一个参数传递给辅助函数,这样全部绑定都会自动将该模块做为上下文。
computed: {
  ...mapState('some/nested/module', {
    a: state => state.a,
    b: state => state.b
  })
},
methods: {
  ...mapActions('some/nested/module', [
    'foo', // -> this.foo()
    'bar' // -> this.bar()
  ])
}
//经过使用 createNamespacedHelpers 建立基于某个命名空间辅助函数。它返回一个对象,对象里有新的绑定在给定命名空间值上的组件绑定辅助函数:
import { createNamespacedHelpers } from 'vuex'

const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')

export default {
  computed: {
    // 在 `some/nested/module` 中查找
    ...mapState({
      a: state => state.a,
      b: state => state.b
    })
  },
  methods: {
    // 在 `some/nested/module` 中查找
    ...mapActions([
      'foo',
      'bar'
    ])
  }
}
复制代码

模块动态注册

  • 在 store 建立以后,你可使用 store.registerModule 方法注册模块
  • store.unregisterModule(moduleName) 来动态卸载模块(建立 store 时声明的模块不能卸载)

保留 state

在注册一个新 module时,你颇有可能想保留过去的state,例如从一个服务端渲染的应保留 state。
你能够经过 preserveState 选项将其归档:store.registerModule('a', module, { preserveState: true })。
当设置 preserveState: true 时,该模块会被注册,action、mutation 和 getter 会被添加到 store 中,可是 state 不会。这里假设 store 的 state 已经包含了这个 module 的 state 而且你不但愿将其覆写。

其余笔记

父子组件之间改变状态

1.x版本上的:propertyName.sync传参到子组件,当子组件的属性值改变时,父组件也会变
2.0版本废除
2.3版本以后又恢复了sync;
因此使用:propertyName.sync,绑定属性时的属性值sync便可;

父组件:

<select-input :is-show.sync="listShow"></select-input>
<list v-show="listShow"></list>
复制代码

子组件:

<button @click="showListHandle"><button/>
<script>
export default {
  props:['isShow'],
  computed:{
    initShow(){
        return this.isShow
    }
  },
  methods: {
    showListHandle(){
        //触发更新,名字是is-show,值为initshow取反;
        this.$emit("update:isShow", !this.initShow)
    }
  }
}
</script>
复制代码

兄弟组件之间改变状态

须要使用父组件做为通道,父组件传入子组件自定义的事件,在子组件触发某个事件时,使用$emit来触发父组件传入的自定义事件,来改变兄弟组件的状态;

需求:
父组件的title值传入了select-input组件做为input的值;
list组件的列表项点击时须要改变title值;
以改变兄弟组件select-input的input值;

实现:
父组件传入list组件自定义事件changeTitle;
在list组件的列表项点击时,触发getTitleHandle事件处理函数,而后再来触发自定义事件changeTitle来改变父组件的title值;

父组件

<select-input :is-show.sync="listShow" :title="title"></select-input>
<list v-show="listShow" @changeTitle="titleHandle"></list>
<script>
exprot default{
    data(){
        return {
            listShow: flase;
            title:’’
        }
    },
    methods:{
        titleHeadle(title){
            this.title=title;
        }
    }
}
</script>
复制代码

select-input组件

<input @click="showListHandle" :value="this.props.title"/>
复制代码

list组件:

<template>
<ul class="list">
    <li v-for="item in data" @click="getTitleHandle(item.title)">{{item.title}}</li>
</ul>
</template>
<script>
exprot default{
    data(){},
    methods:{
        getTitleHandle(title){
            this.$emit('changeTitle',title)
        }
    }
}
</script>
复制代码
相关文章
相关标签/搜索