vuex
核心目标:
(1)vuex的基本使用步骤
(2)vuex的核心概念
(3)vuex实现常见的业务开发功能
vuex的概念:组件间共享数据的一种方式
父传子:v-bind属性绑定(拓展1)
子传父:v-on事件绑定(拓展2)
兄弟组件间的数据共享:EventBus(事件总线)(拓展3)
任意组件通信:vuex
vuex是实现集中式状态、数据管理的一个vue插件,多个组件共享状态进行集中式的管理(读、写)
思路
- 1.npm i vuex
- 2.Vue.ues(Vuex)
- 3.store(创建)
- 4.vc==>store(让组件看得见store)
组件仍然保有局部状态
使用 Vuex 并不意味着你需要将所有的状态放入 Vuex。虽然将所有的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态。你应该根据你的应用开发需要进行权衡和确定。
1.搭建vuex的开发环境(全局配置store)
全局配置$store
实现思路
- 在
main.js中引入vuex插件,挂载vuex,作用:创建vm时就可以传入store配置项进去,这样就可以全局使用$store了(store提供dispatch和commit方法)import最先被解析,无论它在何位置。所以将Vue.ues(vuex)放到src->store->index.js中去解析
1.创建文件:src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
name:"博博"
},
mutations: {
},
actions: {
}
});
2.在main.js中创建vm时传入store配置项
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import './plugins/element'
import './assets/css/global.css'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
store,
}).$mount('#app')
2.基本使用
用一个组件与vuex的一次完整数据共享作为其他组件实现的示例,其他组件使用vuex同理可得
实现思路
- 实现基础sum++组件
- 将组件中的需要共享的数据放到index,js(vuex中)
- 将组件中使用的方法,使用
$store与index.js进行数据交互实现数据的共享
前提条件:vue2
准备components组件如下,以及上面配置好的两个(main.js与store(index.js))
//components组件 作用:实现基础sum++
<template>
<div>
<div>sum:{{ sum }}</div>
<button @click="addSum">sum++</button>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
n:2
sum:0
}
},
methods: {
addSum() {
this.sum+=this.n
}
},
mounted() {
console.log('APP',this);
}
}
</script>
1.初始化数据、配置actions、配置mutations,操作文件store.js
......
//准备actions对象——响应组件中用户的动作
const actions = {
//每一个事件都默认可以接收2个参数
jia(context,value) {
// console.log(context, value);
//commit向下传递('事件名称',值)
context.commit('JIA', value)
}
}
//准备mutations对象——修改state中的数据
const mutations = {
JIA(state,value) {
// console.log(this);
//处理数据,此时共享的store中的sum值也随之改变
state.sum += value
}
}
//准备state对象——保存具体的数据
const state = {
sum:0
}
......
如何使用
- 组件中读取vuex中的数据:
$store.state.sum- 组件中修改vuex中的数据:
$store.dispatch('action中的方法名',数据)或$store.commit('mutations中的方法名',数据)
备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写
dispatch,直接编写commit
......
<div>
<!-- 实现store数据共享 -->
<div>sum:{{ this.$store.state.sum }}</div>
<button @click="addSum">sum++</button>
</div>
......
methods: {
addSum() {
//调用dispatch传递(事件名称,需要传递的值)
this.$store.dispatch('jia',this.n);
}
},
......
-----现在点击页面上的按钮,简单的数据共享成功了----
3.getter
当state中的数据需要经过加工后再使用时,可以使用getters加工。
使用场景:逻辑复杂且想复用
如何使用
- 组件中读取数据:
$store.getters.bigSum例如:{{$store.getters.bigSum}}
,展示的就时getter中的bigSum值
1.在store.js中追加getters配置
......
const getters = {
bigSum(state){
return state.sum * 10
}
}
//创建并暴露store
export default new Vuex.Store({
......
getters
})
//在本例中的使用
......
getters: {
bigSum(state) {
return state.sum*10
}
},
4.mapstate,mapgetter
mapState方法: 用于帮助我们映射state中的数据为计算属性
mapGetters方法: 用于帮助我们映射getters中的数据为计算属性
通常放在computed里面
将填入的字段自动映射为一个计算属性;这是vuex已经封装好的方法直接用在需要的组件中即可(全局挂载过vuex),mapgetter同样用法。
在组件中引入mapstate
数组写法(常用)
mapState(['likes','friends','token','userInfo'])
等价于下面的代码
userInfo(){
return this.$store.state.userInfo
},
token(){
return this.$store.state.token
},
friends(){
return this.$store.state.friends
},
likes(){
return this.$store.state.likes
}
当方法名与属性名不一致时可使用(对象写法)
mapState({xihuan:'likes',penyou:'friends',miyao:'token',yhxx:'userInfo'})
5.mapaction,mapmutations
mapActions方法: 用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数
mapMutations方法: 用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数
通常放在methods里面
vuex封装的mapmutations样式,借助maputation生成对应的方法,方法会调用commit去联系mutation(store中的)
increment(value){
this.$store.commit('JIA',value)
},
在组件中引入mapmutations
对象写法(常用)
Mapmutations({increment:'JIA',decrement:'JIAN'})
等价于下面的代码
increment(){
this.$store.commit('JIA',this.n)
},
decrement(){
this.$store.commit('JIAN',this,n)
}
数组写法
Mapmutations(['JIA','JIAN'])
<button @click="JIA(n)"></button>
注意
在组件中使用increment,decrement方法时需要传参
<button @click="increment(n)"></button>
另外的写法见(拓展5)
2.mapaction(使用方法同上)
方法会去调用dispatch与vuex中的action联系
incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
}
完整实现:图二创建在src->store文件夹->count.js
总结
相同点:mapxxxx的使用方法都一样,对象或者数组样式
区别:1.mapstate与mapgetter放组件的computed里面,另外两个放methods里面
2.mapaction与mapmutation在使用时,绑定参数时需要传参(原因见上面mapaction,mapmutation详细介绍)
备注:mapActions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象。
拓展
-------------------------------纸上得来终觉浅,绝知此事要躬行。-------------------------------
总结: 在通信中,无论是子组件向父组件传值还是父组件向子组件传值,他们都有一个共同点就是有 中间介质,子向父的介质是自定义事件,父向子的介质是props中的属性。抓准这两点对于父子通信就好理解了
1.父传子:v-bind属性绑定
父组件通过import + component写入子组件,然后v-bind绑定数据,子组件通过props接收
思路
- 父:自定义属性名 + 数据(要传递)=> v-bind:value="数据"
- 子:props ["父组件上的自定义属性名"] => 进行数据接收
实现思路
- 父组件中通过
import-components-< />三部曲 注册子组件- 子组件在
props对象中创建一个属性prop- 父组件在注册的子组件标签中添加
prop属性,即prop="value"- 父组件可以通过
v-bind:prop(:prop)实现数据双向绑定
图解记忆法:
2.子传父:v-on事件绑定
子组件click设置点击事件,$emit设置通道后传参,父组件在methods接收
思路
- 子:this.$emit('自定义事件名称', 数据) 子组件标签上绑定@自定义事件名称 = '回调函数'
- 父:methods: { 回调函数() { //逻辑处理 } }
实现思路
- 子组件中需要以某种方式的方法来触发一个自定义事件(例如点击事件)
- 子组件使用
this.$emit方法,第一个参数为父组件定义的方法名称event,第二个参数为传递的值- 在父组件中注册子组件并在子组件标签上绑定对自定义事件的监听(
event="Event"),Event(data)可以接收传过来的参数
图解记忆法:
3.兄弟组件间的数据共享:EventBus(事件总线)
兄click设置点击事件,用$emit设置通道传参给中转站,弟通过$on接收来自中转站的参数
思路
- 通过中转站 let bus = new Vue()
- A:methods :{ 函数{bus.$emit(‘自定义事件名’,数据)} 发送
- B:created (){bus.$on(‘A发送过来的自定义事件名’,函数)} 进行数据接受
中转站文件
创建 bus.js 做为中转站文件
bus.js 内容为
child1.vue
child2.vue
总结
- 兄组件通过
click设置点击事件- 兄组件通过
$emit设置通道传参给中转站- 弟组件通过
$on接收来自中转站的参数
涉及到很多组件共享会比较麻烦,庞大的项目多组件共享使用vuex实现(全局事件总线需要多次使用on,数据庞大且冗余)
4.计算属性:
5.mapmutations的另外写法(只是看看,平时都不这样写)
methods:{
increment(){
this.atguiguJia(this.n)
}
...mapmutations({atguiguJia:'JIA'})
}
<button @click="increment"></button>
作者:清风夜半 链接:juejin.cn/post/696955… 来源:稀土掘金
转载:作者:ALKAOUA 链接:juejin.cn/post/696506… 来源:稀土掘金