【Vue】Re20 VueX 第一部分(共享数据,Getters)

一、概述

专门为VueJS应用程序开发的状态管理模式

集中式存储管理应用的所有组件的状态,按照相应的规则保证状态以一种可预测的方式发生变化

VueX也集成到了官方调试工具devtools extension中

状态共享问题:

类似JavaWeb中的Session,每一个资源共同需要的变量

二、案例演示

首先需要安装VueX,CLI2的安装是没有提供VueX的

npm install vuex --save

App.vue

<template>
  <div id="app">
    <h3>{{message}}</h3>
    <p>
      <button @click="$store.state.count --"> - </button>
      <span>{{$store.state.count}}</span>
      <button @click="$store.state.count ++"> + </button>
    </p>
    <vuex-comp></vuex-comp>
  </div>
</template>
<!-- Actions行为 + View视图 + State状态 -->
<script>
import VueXComp from "./components/VueX";
export default {
  name: 'App',
  data () {
    return {
      message : 'sss',
      // count : 0
    }
  },
  components : {
    vuexComp : VueXComp
  },

}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

VueX.vue

<template>
  <div>
    <h3>VueX Component</h3>
    <p>{{$store.state.count}}</p>
  </div>
</template>

<script>

export default {
  name: "VueX"

}
</script>

<style scoped>

</style>

store目录的Index.js

import Vue from 'vue';
import VueX from 'vuex';

/* 安装VueX */
Vue.use(VueX);

const store = new VueX.Store({
  state : { /* 状态保存,存放所有组件共享的对象 */
    count : 0
  },
  mutations : {

  },
  actions : {

  },
  modules : {

  }
});

export default store;

main.js引入VueX的初始化:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import Store from './store';

Vue.config.productionTip = false

// Vue.use(VueX);

/* eslint-disable no-new */

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

两个组件是共用store中的state属性的count

变量引用依靠$store

$store.state.定义的属性

但是官方不推荐使用上面这样的直接引用获取

因为在devtools的调试插件中可以发现这样的问题:

在界面中的点击,共享的count数据更新了,但是在调试插件中的vuex属性状态栏中,

数据是没有发生变化的。

使用mutations实现,并且可以被devtools跟踪

至少使用先使用mutations调用,如果还有请求的操作,那还需要actions中调用

store/index.js

import Vue from 'vue';
import VueX from 'vuex';

/* 安装VueX */
Vue.use(VueX);

const store = new VueX.Store({
  state : { /* 状态保存,存放所有组件共享的对象 */
    count : 0
  },
  mutations : { /*  */
    increment (state) {
      state.count ++
    },
    decrement (state) {
      state.count --
    }
  },
  actions : {

  },
  modules : {

  }
});

export default store;

首页App.vue

<template>
  <div id="app">
    <h3>{{message}}</h3>
    <p>
<!--      <button @click="$store.state.count &#45;&#45;"> - </button>-->
      <button @click="aaa"> - </button>
      <span>{{$store.state.count}}</span>
      <button @click="bbb"> + </button>
<!--      <button @click="$store.state.count ++"> + </button>-->
    </p>
    <vuex-comp></vuex-comp>
  </div>
</template>
<!-- Actions行为 + View视图 + State状态 -->
<script>
import VueXComp from "./components/VueX";
export default {
  name: 'App',
  data () {
    return {
      message : 'sss',
      // count : 0
    }
  },
  methods : {
    aaa () {
      this.$store.commit('decrement');
    },
    bbb () {
      this.$store.commit('increment');
    }
  },
  components : {
    vuexComp : VueXComp
  },

}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

修改预览的效果可以跟踪Mutations的方法执行

但是state变量不知道为什么对不上值:

三、使用Getters计算复杂的需求

现在Store中多了一组学生信息,需求是获取某一属性的某一范围的所有学生信息

例如年龄大于20或者小于20

store/index.js

import Vue from 'vue';
import VueX from 'vuex';

/* 安装VueX */
Vue.use(VueX);

const store = new VueX.Store({
  state : { /* 状态保存,存放所有组件共享的对象 */
    count : 0,
    str : 'sss',
    students : [
      { id : 110, name : '学生110', age : 28, gender : true, },
      { id : 111, name : '学生111', age : 18, gender : true, },
      { id : 112, name : '学生112', age : 38, gender : false, },
      { id : 113, name : '学生113', age : 14, gender : true, },
      { id : 114, name : '学生114', age : 44, gender : false, },
      { id : 115, name : '学生115', age : 10, gender : true, },
    ]
  },
  mutations : { /*  */
    increment (state) {
      state.count ++
    },
    decrement (state) {
      state.count --
    },
  },
  actions : {

  },
  modules : {

  },
  getters : {
    getStringJoin (state) {
      return state.str + 'saa';
    },
    getCount (state) {
      return state.count;
    },
    large20Age (state) {
      return state.students.filter(student => student.age > 20);
    }
  }
});

export default store;

App.vue

<template>
  <div id="app">
    <h3>{{message}}</h3>
    <p>
<!--      <button @click="$store.state.count &#45;&#45;"> - </button>-->
      <button @click="aaa"> - </button>
      <!--<span>{{$store.state.count}}</span>-->
      <strong>{{$store.getters.getCount}}</strong>
      <button @click="bbb"> + </button>
<!--      <button @click="$store.state.count ++"> + </button>-->
    </p>

    <ul> <!-- 使用store的getters属性调用 -->
      <li v-for="student in $store.getters.large20Age">
        {{student.id}} | {{student.name}} | {{student.age}} | {{student.gender}}
      </li>
    </ul>

    <ul> <!-- 使用当前组件computed属性调用 -->
      <li v-for="student in largeThan20Age">
        {{student.id}} | {{student.name}} | {{student.age}} | {{student.gender}}
      </li>
    </ul>

    <p>
      {{$store.getters.getStringJoin}}
    </p>
    <vuex-comp></vuex-comp>
  </div>
</template>
<!-- Actions行为 + View视图 + State状态 -->
<script>
import VueXComp from "./components/VueX";
export default {
  name: 'App',
  data () {
    return {
      message : 'sss',
      // count : 0
    }
  },
  methods : {
    aaa () {
      this.$store.commit('decrement');
    },
    bbb () {
      this.$store.commit('increment');
    }
  },
  computed : {
    // largeThan20Age () {
    //   return this.$store.state.students.filter(student => {
    //     return student.age >= 20;
    //   });
    // }

    largeThan20Age () {
      return this.$store.state.students.filter(student => student.age >= 20);
    }

  },
  components : {
    vuexComp : VueXComp
  },

}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

getters属性支持内嵌式调用,提高了其他getters方法的可重用性

  getters : {
    getStringJoin (state) {
      return state.str + 'saa';
    },
    getCount (state) {
      return state.count;
    },
    large20Age (state) {
      return state.students.filter(student => student.age > 20);
    },
    large20AgeLength (state, getters) {
      return getters.large20Age.length;
    }
  }

年龄限制条件交给参数决定,更灵活的需求:

getters方法无法自定义我们希望的参数【已经固定了参数格式,第一state、第二getters】

解决方案是先返回一个函数,在这个函数的形参就可以获取了,然后里面再写需求逻辑

    largeAgeBy (state) {
      return age => {
        return state.students.filter(student => student.age > age);
      }
    }

App.vue调用

<template>
  <div id="app">
    <h3>{{message}}</h3>
    <p>
<!--      <button @click="$store.state.count &#45;&#45;"> - </button>-->
      <button @click="aaa"> - </button>
      <!--<span>{{$store.state.count}}</span>-->
      <strong>{{$store.getters.getCount}}</strong>
      <button @click="bbb"> + </button>
<!--      <button @click="$store.state.count ++"> + </button>-->
    </p>

    <ul> <!-- 使用store的getters属性调用 -->
      <li v-for="student in $store.getters.large20Age">
        {{student.id}} | {{student.name}} | {{student.age}} | {{student.gender}}
      </li>
    </ul>

    <ul> <!-- 使用当前组件computed属性调用 -->
      <li v-for="student in largeThan20Age">
        {{student.id}} | {{student.name}} | {{student.age}} | {{student.gender}}
      </li>
    </ul>

    <p>{{$store.getters.large20AgeLength}}</p>

    <p>
      {{$store.getters.getStringJoin}}
    </p>

    <ul>
      <li v-for="student in $store.getters.largeAgeBy(0)">
        {{student.id}} {{student.name}} {{student.age}} {{student.gender}}
      </li>
    </ul>

    <vuex-comp></vuex-comp>
  </div>
</template>
<!-- Actions行为 + View视图 + State状态 -->
<script>
import VueXComp from "./components/VueX";
export default {
  name: 'App',
  data () {
    return {
      message : 'sss',
      // count : 0
    }
  },
  methods : {
    aaa () {
      this.$store.commit('decrement');
    },
    bbb () {
      this.$store.commit('increment');
    }
  },
  computed : {
    // largeThan20Age () {
    //   return this.$store.state.students.filter(student => {
    //     return student.age >= 20;
    //   });
    // }

    largeThan20Age () {
      return this.$store.state.students.filter(student => student.age >= 20);
    }

  },
  components : {
    vuexComp : VueXComp
  },

}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

 

posted @ 2020-11-02 14:42  emdzz  阅读(149)  评论(0编辑  收藏  举报