Vuex组件数据共享

组件之间共享数据的方式

  • 1.父向子传值 v:bind绑定数据, props接收
  • 2.子向父传值 :父组件 v-on事件绑定,子组件用this.$emit()接受
  • 3.兄弟之间共享数据 全局的EventBus,挂载 vue的原型上 $emit发送数据的那个组件,$on接收数据的那个组件
  • 4.祖先和后代相互传参 :祖先要使用provide方法传参,后代使用inject属性接受祖先中的参数,
  • 5.vue实例属性传参(parent、children[n]、root、refs)
  •  +$parent 获取父元素的数据/方法  获取父元素的整个vm实例
  •  +$children  获取子元素的数据/方法(mounted钩子函数,要有下标)
  • +$root获取根组件的数据/方法
  • $refs:this的子元素中需要定义ref属性:比如ref=

 如果ref定义在DOM标签中==:this.$refs.xxx获取的是DOM对象

 如果ref定义在子组件标签中==:this.$refs.xxx获取的是子组件的vm实例

Vuex是什么?

Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的共享

Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源“而存在。这也意味着,每个应用将仅仅包含一个 store 实例

使用Vuex统一管理的好处?

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

什么样的数据适合存储在vuex中?

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

vuex的作用?

1、vuex是专为Vue.js应用程序开发的状态管理模式(集中式存储)--->公共仓库

2、缓存 keep-aliv

  • vuex:不刷新,不关闭页面,就会保存以前的数据,刷新就不存在数据
  • sessionStorage:会话存储,刷新有数据、关闭页面没有数据
  • localStorage:本地存储,刷新有数据、数据永久

vuex:“单向数据流”理念

  • state,驱动应用的数据源;
  • view,以声明方式将 state 映射到视图;
  • actions,响应在 view 上的用户输入导致的状态变化

 vuex的异步函数执行的过程:

vuex的基本使用

1.安装vuex依赖包

npm install vuex --save

2.导入vuex包

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

3.创建store对象

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)
//state存放全局共享数据
export default new Vuex.Store({
  state: {},    //相当于vue中的data存放数据
  getters: {},  //相当于vue中的compute计算属性
  mutations: {},//相当于vue中的methods方法(==同步==) 
  actions: {},  //相当于vue中的methods方法(==异步)==
  modules: {}  //模块
})

4.将store挂载到vue实例中

new Vue({
  //将创建的共享数据对象,挂载到vue实例中
  //所有的组件,就可以直接从store中获取到全局数据了
  store,
  render: h => h(App)
}).$mount('#app')

vuex的五个核心属性

  • state:相当于vue中的data
  • mutations:相当于vue中的methods(==同步==)
  • actions:相当于vue中的methods(==异步)==
  • getters:相当于vue中的computed
  • Modules:模块

1.state  相当于vue中的data

state:提供唯一的公共数据源,所有的公共数据要统一放到Store的State中进行存储,

仓库中

const store = new Vuex.Store({
  	//在大仓库中存放一个count为0
   state: {
    count: 0
  }
})

组件访问State中的数据

第一种方式:this. $store.state.具体的数据名称
  <h3>当前的count值为: {{ $store.state.count }}</h3>
注意:在template模板中使用this可以省略,直接沿着原型链调用(不推荐没缓存)
//--------------
第二种方式: 辅助函数
1.//从vuex中按需导入mapState函数
import {mapState} from 'vuex';
2.通过刚才导入的mapState函数,将当前组件需要的全局数据,映射为当前组件的computed计算属性
注意:计算属性展示到页面使用插值表达式(小胡子语法)推荐,有缓存
数组形式:
  computed: {
    ...mapState(['count']),
  },
对象形式:可以自定义接收 调用的时候用自定义的名
 computed: {
    ...mapState({
      n: 'count',
    }),
//-------------
第三种方式:放到computed计算属性中使用
注意:这里要加this
  computed: {
    count() {
      return this.$store.state.count
    },
},

2.Mutaion  当于vue中的methods(==同步==)

用于变更Store中的数据

  • 1.只能通过mutation变更Store数据,不可以直接操作Store中的数据
  • 2.mutations中的函数必须是同步的,不能放异步方法
  • 3.通过这种方式,操作起来虽然稍微繁琐一些但是可以监控所有数据变化

参数

  • state:【默认参数】指向当前vuex实例store的state对象
  • payload:载荷,用来接收组件传给函数的参数,一般情况下载荷应该是一个对象
  • ...params:第二个及以后的参数,组件调用方法时向方法传递的参数

仓库中

//定义状态
const store = new Vuex.Store({
state: {
    count: 0
  },
  mutations: {
  //变更状态 同步
    add(state,payload) {
      state.count++
      state.count += payload//接收组件传递过来的参数,可以是对象
    }
})

组件中

 //触发mutation的第一种方式
注意:使用store.commit方法可直接调用
 methods: {
    handlel() {
    //commit的作用,就是调用某个mutation函数
      this.$store.commit('add', 100)//可以携带参数
    },
  },
//触发mutation的第二种方式-------------------------
import {mapMutations} mapMutations from 'vuex';
2.通过刚才导入的mapMutations函数,将当前组件需要的全局数据,映射为当前组件的methods方法
数组形式:
  methods: {
    ...mapMutations(['sub']),
  },
对象形式:可以自定义事件句柄
  ...mapMutations({
      s: 'sub',
    }),
在调用时传递参数
 <button @click="s(3)">-1</button>

3.Action 相当于vue中的methods(==异步)==

  • Action 用于处理异步任务
  • 如果通过异步操作变更数据必须通过Action ,而不能使用Mutaion ,但是Active中还是要通过触发Mutaion的方式间接变更数据
  • context:【默认参数】指向vuex的实例store大仓库

仓库中

const store = new Vuex.Store({
   state: {
    count: 0
  },
  mutations: {
    add(state,payload) {
      state.count++
      state.count += payload      
    }
  },
  actions: {
    addAsync(context,payload) {
      setTimeout(() => {
        //在 action 中不能直接修改 state 中的数据,
        //必需通过 context.commit 触发某个mutations 才行
        context.commit('add',payload)
      }, 1000);
    }
  },
})

组件中

//第一种方法-----------------
  methods: {
    //异步的让count自增+1
    btnhandlel() {
      //这里的 dispatch 函数专门触发 Action
      this.$store.dispatch('addAsync',100)
    },
  },
//触发actions的第二种方式-------------------------
import {mapActions} mapMutations from 'vuex';
2.通过刚才导入的mapActions函数,将当前组件需要的全局数据,映射为当前组件的methods方法
数组的形式
 methods: {
    ...mapActions(['addAsync']),
  },
对象形式:可以自定义事件句柄
  ...mapMutations({
      a: 'addAsync',
    }),
在调用时传递参数
 <button @click="a(3)">-1</button>

触发Action异步任务时携带参数的步骤?

  • 1.组件调用时传入一个参数
  • 2.actions方法里接受外界传递过来的参数
  • 3.触发mutatios时把参数传到mutatios里
  • 4.mutatios的方法里接收传递过来的参数,并实现对数据的修改

4.Getter 相当于vue中的computed

  • Getter用于Stroe中的数据进行加工处理形成新的数据,类似vue的计算属性
  • store中的数据发生改变Getteer中的数据也会跟着变化
  • state:【默认参数】指向的是vuex的实例store里的state
  • getters:【默认参数】指向的是vuex的实例store里的getters,可以根据它,获得getters中其他属性的信息

仓库中

//定义Getter
const store = new Vuex.Store({
   state: {
     arr: [10, 20, 30]
  },
    getters: {
    showNum(state) {
      return state.arr.filter(item => {
        return item > 10
      })
    }
  },
})

组件中

第一种方式:this. $store.getters.名称
 {{ $store.getters.showNum }}
注意:在template模板中使用this可以省略,直接沿着原型链调用(不推荐没缓存)
//--------------
第二种方式: 辅助函数
1.//从vuex中按需导入mapGetters函数
import {mapGetters} from 'vuex';
2.通过刚才导入的mapGetters函数,将当前组件需要的全局数据,映射为当前组件的computed计算属性
注意:计算属性展示到页面使用插值表达式(小胡子语法)推荐,有缓存
数组形式:
  computed: {
    ...mapGetters(['showNum']),
  },
对象形式:可以自定义接收 调用的时候用自定义的名
 computed: {
     g: 'showNum',
    }),
//-------------
第三种方式:放到computed计算属性中使用
注意:这里要加this
  computed: {
    snum() {
      return this.$store.getters.showNum
    },
},

5.modules 模块

  • 作用:减少单一状态树的shore对象存放数据导致的臃肿,将整个sotre对象拆分为多个模块module,每个模块都存在自己局部的state、getters、mutations、actions、namespaced,甚至仍然将这个模块继续向下拆分
  • namespaced:默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。
  • 如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
  • 我们在...mapGetters("moduleA",["msg"]),寻找的是moduleA模块中的msg状态值,如果没有写moduleA的话,它会直接去全局的store中找状态值msg

第一步:需要创建一个独立的模块:

const moduleA = {
    state: { 
    msg: '我是moduleA',
    arr: [1, 2, 3, 4, 5, 6]
 },
    getters: {
      donearr: state => {
            return state.arr.filter(item => {
                return item % 2 == 0
            })
        }
},
    mutatios: {},
    actions: {},
    modules: {}
}
export default moduleA

第二步:在store实例中导入并挂载:

重点: store挂载moduleA之后: moduleA中的state对象会挂载到store的state对象上

           moduleA中的mutations、getters、actions对象会挂载到store的对应对象上

import moduleA from './moduleA'
const store = new Vuex.Store({
  namespaced: true,//命名空间
  modules: {
    moduleA
  },
})

第三步:在vue组件中调用vuex的modules:

//方式一:通过$store导入
	$store.state.moduleA.msg //获取moduleA模块中的属性
    {{ $store.getters['moduleA/donearr'] }};//获取方法或计算属性
//方式二写在computed计算属性中----------------------
----------------获取属性-----------
 computed: {
    msg() {
      return this.$store.state.moduleA.msg
    },
-----------获取方法-----------------
  computed: {
    donearr() {
      return this.$store.getters['moduleA/donearr']
    },
//方式三 辅助函数 注意加命名空间------------------
----------获取属性-------------
import { mapState } from 'vuex'
 computed: {
 ...mapState('moduleA', ['msg']),
}
-------------获取方法和计算属性--------------
import { mapGetters } from 'vuex'
 computed: {
 ...mapGetters({
      donearr: 'moduleA/donearr',
    }),
    },
辅助函数第二种方法--------------
import { createNamespacedHelpers } from 'vuex'
const { mapState } = createNamespacedHelpers('moduleA')
----------------获取属性------------
computed: {
  ...mapState(['msg']),
}
--------------获取方法和计算属性----------------
computed: {
...mapGetters(['donearr']),
}
  

辅助函数

  • ==mapState()获取的是大仓库state属性中的状态值==
  • ==mapGetters()获取的是大仓库getters属性中的状态值==
  • ==mapMutations()获取的是大仓库mutations属性中的方法==
  • ==mapActions)获取的是大仓库actions属性中的方法==

vuex中的缓存

  • ==问题==:没有用缓存之前,我们每次打开页面都会发送请求
  • ==目标==:应用vuex实现缓存,只要页面不刷新,不关闭,数据如果是null,我就发送请求,如果不是null就从vuex的缓存中拿数据

第一步:创建异步方法获取服务器数据,并把数据赋值给状态值

import Vue from 'vue'
import Vuex from 'vuex'
import api from "@/api/index.js"

Vue.use(Vuex)

const store = new Vuex.Store({
// 第一步:list专门存放数据
  state: {
    list: null
  },
  getters: {
  },
  // 第二步:payload 接收传递过来的数据,修改list的值,如果请求成功就不为null了
  mutations: {
    setlist(state, payload) {
      state.list = payload
    }
  },
//第三步:异步函数需要写在actions中
  actions: {
    async getData(context) {
      let result = await api.getTaskList()
      if (result.code == 0) {//返回数据成功
  //异步函数想修改state状态值,必须经过mutationscommit执行setlist 传递数据
        context.commit("setlist", result.list);
      } else {
        context.commit("setlist", []);
      }
    }
  },

})


export default store;

第二步:在页面加载之前,先判断是否有缓存,如果有直接用

<template>
  <div class="three">
    {{ list }}
  </div>
</template>

<script>
export default {
  name: "Three",
  data() {
    return {};
  },
  computed: {
    //仓库中存放的list数据
    list() {
      return this.$store.state.list;
    },
  },
    //创建之后的生命函数执行仓库的异步函数getData
  created() {
    if (this.list == null) {
      this.$store.dispatch("getData");
    }
  },
};
</script>

<style>
</style>

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值