zoukankan      html  css  js  c++  java
  • VueX入门

    VueX入门

    VueX是什么?

    Vuex 是用于集中管理组件之间数据的一个组件,通过Vue可以完成父子、子父、兄弟等任何复杂关系的组件之间数据传递问题。

    • VueX可以集中管理共享数据,易于开发和后期维护。
    • 能够高效的实现组件之间的数据共享,提高开发效率
    • 存储在VueX中的数据都是响应式的,能够时时保持数据与页面的同步

    什么样的数据适合存放在VueX中

    一般情况下,只有组件之间共享的数据,才有必要存储在VueX中,对于组件中私有的数据,依旧存放在自身的data中即可。

    VueX的使用

    1、安装依赖包

    npm install vuex --save
    

    2、导入vuex包

    这一步一般我们会在src下创建一个名为store的文件夹,在其内创建一个index.js(安装好vuex插件后,一般都会默认创建了。)

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    

    3、创建store对象

    这一步同样是在src/store/index.js中创建的

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
      },
      mutations: {
      },
      actions: {
      },
      modules: {
      }
    })
    

    4、将store对象挂载到vue实例中

    这一步一般在main.js中进行全局配置,别忘了引入store

    import store from './store'
    ...
    
    new Vue({
      router,
      store,//ES6语法引入
      render: function (h) { return h(App) }
    }).$mount('#app')
    

    state

    Vue中的store是用于统一存放数据的仓库,用于组件之间的参数传递。可以理解为所有组件中共有参数的公共容器。store中的属性默认是只读的,如果要操作,需要使用mutations。(vuex如果没有开启严格模式的话是可以直接修改state中的值的但是强烈不推荐这样做)

    state数据的创建

    在state中创建属性:以下内容引用自src/store/index.js

    export default new Vuex.Store({
      state: {
          count: 0
      }
        ...
    })
    

    state数据的访问

    组件内访问

    this.$store.state.全局数据名称
    

    如果是在html元素组件之间调用,则可以省略this

    <span>{{$store.stat.全局数据名称}}</span>
    

    mapState辅助函数

    mapState访问

    通过mapState辅助函数方式,实现组件访问State中数据的第二种方式关于mapsState的详细讲解

    // 1. 从vuex中按需导入mapState函数
    import { mapState } from 'vuex'
    

    通过刚才导入的mapState函数,将当前组件需要的全局数据,映射为当前的computed计算属性:(注意这里的...必须要加,不是代表省略其他代码的意思)

    // 2. 将全局数据映射为当前组件的计算属性
    computed: {
        // ...表示展开映射,意思就是将全局属性映射为当前组件的计算属性
        ...mapState(['count'])
    }
    

    直接在调用获取组件属性

    <span>{{count}}</span>
    

    使用了mapState后,值可以进行watch监听。

    import { mapState } from 'vuex'
    export default {
        name:"VueXPage",
        components:{
    
        },
        methods:{
            test(){
                this.$store.state.count++;
            }
        },
        computed:{
            ...mapState(['count'])
        },
        watch:{
            count(oVal,nVal){
                console.log(oVal + "," + nVal);
            }
        }
    }
    

    Mutations

    VueX中的mutations是用于变更Store中的数据。

    在VueX中,只能通过mutations变更store数据,不可以直接操作store中的数据。虽然通过mutations的方式操作数据,虽然繁琐了一些,但是可以集中监控所有数据的变化。

    例如要让全局数据自增1,则可以通过如下的方式在mutations中定义(以下代码来自/src/store/index.js)

    export default new Vuex.Store({
      state: {
          count: 0
      },
      mutations:{
          increment(state){
              //修改state
              state.count++;
          }
      }
    })
    

    定义完mutations之后,我们介绍以下如何在组件中触发~

    方式1、通过$store.commit()函数触发mutations

    组件代码:在组件中创建一个函数,然后通过@click等事件触发机制来调用

    methods: {
        handle1 () {
            // 触发mutations的第一种方式
            this.$store.commit('increment')
        }
    }
    

    带参数的调用:

    export default new Vuex.Store({
      state: {
          count: 0
      },
      mutations:{
          increment(state){
              //修改state
              state.count++;
          },
          incrementVal(state,num){
              //增加具体的值
              state.count += num;
          }
      }
    })
    

    在组件中是使用:

    methods: {
        handler2: {
            this.$store.commit('incrementVal', 5);
        }
    }
    

    方式2:通过mapMutations辅助函数触发

    上面我们介绍了mapState,Mutations中同样提供了辅助函数来简化操作。

    // 1. 从vuex中按需导入mapMutations函数
    import { mapMutations } from 'vuex'
    
    ...
    
    // 2. 将制定的mutations函数映射为当前组件的methods函数
    methods: {
        // 将add和addN方法映射为methods中的函数,拱当前组件使用。
        ...mapMutations(['increment','incrementVal']),
        handleAdd() {
            this.increment();
        },
        handleAddN(n) {
            this.incrementVal(n);
        }
        // 或者直接在标签元素中直接@click=add()
    }
    

    对于mutations来说,只能够实现同步操作,不可以执行异步操作的。

    Actions

    从vuex官网中可以了解到,Actions类似于mutations,不同之处在于:

    • Actions 提交的是 mutation,而不是直接变更状态。
    • Actions 可以包含任意异步操作。

    可以得出一个结论就是,如果通过异步操作变更数据,必须通过Actions,而不能使用Mutations,但是在Actions中还是要通过触发Mutations的方式间接变更数据。

    定义actions

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        count:0
      },
      mutations: {
        increment(state){
          state.count++;
        },
        incrementVal(state,num){
          state.count += num;
        }
      },
      actions: {
        incrSync(context){
          setTimeout(()=>{
            context.commit('increment');
          },1000);
        },
        incrValSync(context,num){
          setTimeout(()=>{
            context.commit("increment",num);
          },1000);
        }
      },
      modules: {
      }
    })
    
    

    需要再次强调的是,只有通过mutations中定义的函数,才有权利去修改state中的数据,因此actions最终还是要调用mutations。

    触发Actions

        methods:{
            ...mapMutations({increment:'increment',incrementVal:'incrementVal'}),
            test(){
                this.$store.state.count++;
            },
            incr(){
                this.increment();
            },
            incrVal(num){
                this.incrementVal(5);
            },
            syncIncr(){
                this.$store.dispatch('incrSync');
            },
            syncIncrVal(num){
                this.$store.dispatch('incrValSync',num);
            }
        }
    

    触发Actions的第二种方式

    Actions同样拥有辅助函数,mapActions。

    // 1. 从vuex中按需导入mapActions函数
    import { mapActions } from 'vuex'
    
    ...
    
    // 2. 将指定的actions函数,映射为当前组件的methos函数
    methods: {
        ...mapActions(['incrSync', 'incrValSync']),
        handleAddAsync() {
            this.addAsync();
        },
        handleAddNAsync(n) {
            this.addNAsync(n);
        }
    }
    

    Getter

    在Vuex官网中,用到了派生这一词来介绍Getter,在这里可以理解为就是用于对Store中的数据进行加工处理,形成新的数据,类似Vue的计算属性。Getter的数据是基于Store中的数据的,所以当Store中数据发生变化时,Getter中的数据也会随之变化。

    定义Getter

    例如state中存有todos计划项,其对象有一个done状态表示完成与否。

    const store = new Vuex.Store({
      state: {
        todos: [
          { id: 1, text: '...', done: true },
          { id: 2, text: '...', done: false }
        ]
      },
      getters: {
        // 这里通过getters定义的doneTodos方法来过滤已完成的todo项
        doneTodos: state => {
          return state.todos.filter(todo => todo.done);
        },
        // 这里还可以通过传入getters对象来获取其他方法
        doneTodosCount: (state, getters) => {
            return getters.doneTools.length;
        },
        // 传入参数
        getTodoById: (state) => (id) => {
            return state.todos.find(todo => todo.id == id);
        }
      }
    })
    
    

    触发Getter定义函数的第一种方法**

    this.$store.getters.doneTodos // -> [{id: 1, text: '...', done: true}]
    this.$store.getters.doneTodosCount // -> 1
    

    触发Getter定义函数的第二种方法**

    通过mapGetters来触发Getter中定义的函数

    // 1. 导入mapGetters辅助函数
    import { mapGetters } from 'vuex'
    
    ...
    
    // 2. 将制定的Getters函数映射为当前组件的函数
    methods: {
        ...mapGetters(['doneTodos', 'doneTodosCount']),
        handleDoneTodos() {
            this.doneTodos();
        }
    }
    
    
    

    Modules

    当Store中存放了非常多非常大的共享数据对象时,应用会变的非常的复杂,Store对象也会非常臃肿,所以Vuex提供了一个Module模块来分隔Store。通过对Vuex中的Store分隔,分隔成一个一个的Module模块,每个Module模块都拥有自己的state、mutation、actions和getters。

    const moduleA = {
      state: () => ({ ... }),
      mutations: { ... },
      actions: { ... },
      getters: { ... }
    }
    
    const moduleB = {
      state: () => ({ ... }),
      mutations: { ... },
      actions: { ... }
    }
    
    const store = new Vuex.Store({
      modules: {
        a: moduleA,
        b: moduleB
      }
    })
    
    store.state.a // -> moduleA 的状态
    store.state.b // -> moduleB 的状态
    
    

    对于模块中的mutations和getters,传入的第一个参数规定为state,而actions则依旧是context参数。如下:

    const moduleA = {
      state: {
         count: 0
      },
      mutations: {
        increment (state) {
          // 这里的 `state` 对象是模块的局部状态
          state.count++
        }
      },
    
      getters: {
        doubleCount (state) {
          return state.count * 2
        }
      },
      actions: {
      	// context对象其实包含了 state、commit、rootState。
      	incrementIfOddRootsum (context) {
    		if ((context.state.count + context.rootState.count) % 2 === 1) {
            // 调用mutations
            commit('increment')
          }
      	}
      }
    }
    
    

    第一种调用方式

    在module中通过mapState、mapGetters、mapActions和mapMutations等辅助函数来绑定要触发的函数**

    methods: {
    	...mapActions([
    		'some/nested/module/foo',
    		'some/nested/module/bar'
    	])
    }
    
    

    在vuex中,可以为导入的state、getters、actions以及mutations命名别名,,这样可以方便调用

    methods: {
    	...mapActions([
    		'foo': 'some/nested/module/foo',
    		'bar': 'some/nested/module/bar'
    	])
    }
    
    

    第二种调用方式

    对于这种情况,你可以将模块的空间名称字符串作为第一个参数传递给上述函数,这样所有绑定都会自动将该模块作为上下文。于是上面的例子可以简化为:

    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 {
      methods: {
        // 在 `some/nested/module` 中查找
        ...mapActions([
          'foo',
          'bar'
        ])
      }
    }
    

    总结

    1. Vuex主要用于管理Vue组件中共享的数据。
    2. Vuex中有state、mutation、action、getter等核心概念。
    3. 获取state可以通过this.$store.state.xx或者是通过定义mapState来获取。
    4. 修改state中的变量需要通过mutation函数实现,而mutation的触发由两种方式,一种是通过this.$store.commit()函数,另外一种就是通过mapMutations来实现。
    5. mutation只能用于修改数据,而Actions可以实现异步操作。
    6. 通过Actions的异步操作+mutation的修改数据,可以实现异步修改数据。调用Actions有两种方式,第一种是通过this.$store.dispatch来调用,另外一种方式是通过mapActions来调用。
    7. Getters函数用于对Store中数据进行加工,不会修改原本Store中的数据;Getters中的数据会受Store中数据进行影响。
  • 相关阅读:
    HDU 2116 Has the sum exceeded
    HDU 1233 还是畅通工程
    HDU 1234 开门人和关门人
    HDU 1283 最简单的计算机
    HDU 2552 三足鼎立
    HDU 1202 The calculation of GPA
    HDU 1248 寒冰王座
    HDU 1863 畅通工程
    HDU 1879 继续畅通工程
    颜色对话框CColorDialog,字体对话框CFontDialog使用实例
  • 原文地址:https://www.cnblogs.com/zhangruifeng/p/14334550.html
Copyright © 2011-2022 走看看