当前位置:   article > 正文

vue状态管理

vue状态管理

vue 状态管理(一)

状态就是数据。父子组件之间往往使用props和 $emit 实现数据共享,任意组件可通过bus(一个vue实例)作为桥梁,实现数据共享。当项目中组件越来越多时,组件之间的数据共享变得复杂,难以维护。使用 Vuex 可集中管理组件之间的数据(状态),使组件之间的数据共享变得简单。

父子组件间通信

父→(props)子组件;

子→($emit)父组件,即子组件自定义一个事件,在父组件中监听该事件。

自定义输入组件:

  1. <template>
  2. <input @input="handleInput" :value="value" :placeholder="placeholder" />
  3. </template>
  4. <script>
  5. export default {
  6. name: "CustomInput",
  7. //props 接收父组件传递过来的数据
  8. props: {
  9. value: {
  10. type: [Number, String],
  11. required: true,
  12. default: ""
  13. },
  14. placeholder: {
  15. type: String,
  16. default: "提示文本"
  17. }
  18. },
  19. methods: {
  20. handleInput(event) {
  21. let val = event.target.value;
  22. // 子组件的事件监听函数中触发一个自定义事件,通知父组件
  23. this.$emit("customInput", val);
  24. }
  25. }
  26. };
  27. </script>

使用组件:

  1. <template>
  2. <div class="store">
  3. <!-- props 传递值 -->
  4. <custom-input :value="value" @customInput="handleInput" :placeholder="placeholder" />
  5. <p v-text="value"></p>
  6. </div>
  7. </template>
  8. <script>
  9. import CustomInput from '_c/CustomInput.vue'
  10. export default {
  11. name: 'Store',
  12. components: {
  13. CustomInput
  14. },
  15. data() {
  16. return {
  17. value: '',
  18. placeholder: '自定义事件传递值'
  19. }
  20. },
  21. methods: {
  22. // 自定义事件处理器
  23. handleInput(val) {
  24. this.value = val
  25. }
  26. }
  27. }
  28. </script>

因为 v-model 指令是双向绑定的,我们也可以用其来实现值的传递:

  1. <template>
  2. <div class="store">
  3. <custom-input v-model="inputValue" :placeholder="placeholder" />
  4. <p v-text="inputValue"></p>
  5. </div>
  6. </template>
  7. <script>
  8. import CustomInput from '_c/CustomInput.vue'
  9. export default {
  10. name: 'Store',
  11. components: {
  12. CustomInput
  13. },
  14. data() {
  15. return {
  16. inputValue: '',
  17. placeholder: 'v-mode 传递值'
  18. }
  19. }
  20. }
  21. </script>

bus 任意组件通信

创建一个空的 vue 实例,然后将该实例添加到 vue 的原型上,通过该实例触发事件监听事件来在不同组件之间共享数据。

  1. //bus.js
  2. import Vue from "vue";
  3. let Bus = new Vue();
  4. export default Bus;

在 main.js 中添加原型属性:

  1. import Bus from './lib/bus'
  2. // 通过 bus 实现任意组件传递参数
  3. Vue.prototype.$bus=bus
  4. //ChildPage.vue
  5. <template>
  6. <div id="child-page">
  7. <h1>{{ msg }}</h1>
  8. <h3 v-text="data"></h3>
  9. </div>
  10. </template>
  11. <script>
  12. export default {
  13. name: "ChildPage",
  14. data() {
  15. return {
  16. msg: "I am child",
  17. data: ""
  18. };
  19. },
  20. mounted() {
  21. // 在挂载声明周期函数中监听自定义事件
  22. this.$bus.$on("customEvent", data => {
  23. this.data = data;
  24. });
  25. }
  26. };
  27. </script>
  28. <template>
  29. <div id="app">
  30. <button @click="sendData">给child传递数据</button>
  31. <p v-text="num"></p>
  32. </div>
  33. </template>
  34. <script>
  35. export default {
  36. name: "App",
  37. data() {
  38. return { num: 0 }
  39. },
  40. methods: {
  41. sendData(data) {
  42. // 由 bus 触发一个事件,在接收数据的组件中监听该事件
  43. this.$bus.$emit('customEvent', ++this.num);
  44. }
  45. }
  46. };
  47. </script>

Vuex 状态管理

随着组件的增加,通过以上方式共享数据,会越来越复杂,vue 提供了状态管理插件 Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式; 集中存储和管理应用的所有组件状态。

理解:

  • 状态数据,相当于组件内部的data 的返回值,Vue 是数据驱动的,数据变化往往会表现在视图层;
  • 集中存储Vue 只关注视图层,Vuex 提供了一个仓库(store)来保存数据,使得数据和视图分离;
  • 管理处理保存数据,还可计算、处理数据;
  • 所有组件状态:所有组件都可获取仓库中的数据,即一个项目只有一个数据源

Vuex 文档中说:

通过定义和 隔离状态管理中的各种概念并通过强制规则维持视图和状态间的 独立性,我们的代码将会变得更结构化且易维护。

Vuex 就是通过隔离数据、拆分改变数据的方式使得数据和视图独立,数据被组件数共享。

虚线内部的三个部分组成了一个Store,组件的数据保存在 State 中,用户和组件交互时,通过组件内的方法分发(dispatch)一个动作(action,有点像事件),动作会提交(Commit)一个更改(Mutation,也类似事件),改变 State 中的数据,然后获取数据渲染到视图上。

  • actions 可以是 异步操作,故可在action中调用后台接口获取新的数据
  • mutations 只能是 同步操作
  • mutations 和 actions 都可直接更改 state,但是当 action 含有异步操作时,会使得数据变化混乱,难以跟踪,使得调试困难;
  • 基于以上原因,Vuex 规定只能是 mutations 来改变 state
  • 在开发工具中也可提交 mutations。

使用 vuex

  1. //main.js
  2. import Vue from 'vue';
  3. import Vuex from 'vuex';
  4. Vue.use(Vuex);// Vuex 是 Vue 的插件
  5. let store = new Vuex.Store({
  6. state: { //放置state的值
  7. count: 0,
  8. str:"abcd234"
  9. },
  10. getters: { //放置getters方法
  11. strLen: state => state.str.length
  12. },
  13. // mutations只能是同步操作
  14. mutations: { //放置mutations方法
  15. increment(state, payload) {
  16. //在这里改变state中的数据
  17. state.count = payload.number;
  18. }
  19. },
  20. // actions可以是异步操作
  21. actions: { //放置actions方法
  22. actionName({ commit }) {
  23. //dosomething
  24. commit('mutationName')
  25. },
  26. getSong ({commit}, id) {
  27. //请求后台数据
  28. api.getMusicUrlResource(id).then(res => {
  29. let url = res.data.data[0].url;
  30. }).catch((error) => { // 错误处理
  31. console.log(error);
  32. });
  33. }
  34. }
  35. });
  36. new Vue({
  37. el: '#app',
  38. store // 通过 this.store 访问 store
  39. });

我们看看 Vuex 和 store 是什么?

Vuex:

Vuex 它实际上是一个对象,里面包含了Store这一构造函数,还有几个mapActions、mapGetters、mapMutations、mapState、install 方法

store:

store 是 Vuex 的实例(废话)。

实际项目中往往将 store 单独放置的一个文件夹在,mutations 、getters、actions 等属性各自用一个文件保存。

state

state 对象的属性时 Vuex 管理的状态,类似单个组建的 data

访问 getters:

  1. this.$store.state
  2. 使用 mapState 映射成计算属性推荐
  1. //state.js
  2. export default {
  3. count: 100,
  4. name: 'Jack*Zhou',
  5. firstName: 'Jack',
  6. lastName: 'Zhou',
  7. age: 24,
  8. profession: 'web deveploper',
  9. company: 'Baidu'
  10. }

组件:

  1. import {mapState} from 'vuex'
  2. export default {
  3. data(){
  4. return {
  5. localCount:0
  6. }
  7. },
  8. computed: {
  9. localCount() {
  10. return this.$store.state.count + 1;
  11. },
  12. //计算属性名和 state 属性名相同:传入数组
  13. // ...mapState(['count','name']),
  14. // 计算属性名和 state 属性不同,传入对象
  15. ...mapState({
  16. name: state => state.name,
  17. count: state => state.count,
  18. countAlias: 'count',
  19. //为了使用 this 不能使用箭头函数
  20. countPlusLocalCount(state) {
  21. return state.count + this.localCount;
  22. }
  23. })
  24. },
  25. }

getters

getters 是对 state 的加工,类似于组件中的 data 和计算属性的关系。getters 的返回值会被缓存起来,只有当它的依赖改变,才会重新计算。

访问 getters:

  1. this.$store.getters
  2. 使用 mapGetters 将 getters 映射成计算属性推荐
  3. 方法访问,不会缓存。
  1. // getters.js
  2. export default {
  3. fullName: state => state.firstName + ' ' + state.lastName,
  4. //在getters 中访问 getters
  5. info: (state, getters) => {
  6. return state.age + ',' + getters.fullName;
  7. },
  8. //为了传递参数,返回一个函数,
  9. personInfo: (state, getters) => (city) => {
  10. return {
  11. name: getters.fullName,
  12. age: state.age,
  13. company: state.company,
  14. city
  15. }
  16. }
  17. }

使用 getters:

  1. import { mapGetters } from 'vuex'
  2. export default {
  3. name: 'Store',
  4. computed: {
  5. ...mapGetters(['fullName', 'info', 'personInfo']),
  6. myInfo() { return this.personInfo('杭州') },
  7. ...mapGetters({
  8. fullNameAlias1: 'fullName',
  9. //不能写成函数
  10. // fullNameAlias2(state){
  11. // return state.name+',你好'+this.$store.getters.fullName;
  12. // }
  13. })
  14. },
  15. mounted() {
  16. console.log(this.personInfo('成都'))
  17. console.log(this.myInfo)
  18. }
  19. }

参考

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/391465
推荐阅读
相关标签
  

闽ICP备14008679号