Vuex是什么?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,为了更客观的了解,下面是一个简单的流程图
这个状态自管理应用包含以下几个部分:
state,驱动应用的数据源;
view,以声明方式将 state 映射到视图;
actions,响应在 view 上的用户输入导致的状态变化。
用户发送一个actions然后修改state,修改后的state数据发生变化,视图发生了变化
为什么要使用Vuex?
当我们遇到多个组件共享状态时,多层组件的传值非常繁琐,不利于维护,因此我们把组件的共享状态抽取出来,以一个单例模式管理,在这种模式下,不管在哪个组件都可以获取。
如何使用Vuex?
下载vuex
cnpm i vuex -g
模块化引入vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex) // 必须调用此函数来注入 Vuex
定义全局使用Vuex
使用Vuex之前你应该有所了解
<1>每一个Vuex应用的核心就是store(仓库),它包含着应用中大部分的状态(state),store是内存机制,而不是缓存机制,当前页面一旦刷新挥着通过路由跳转亦或是关闭,都会导致store初始化。
<2>Vuex的核心概念分别是:
(1)State: 存放基本数据 ----辅助函数mapState: 当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键。
(2)getters:是从store中的state派生出来的状态,专门来计算state中的数据,相当于state中数据的计算属性 ---辅助函数mapGetters辅助函数: mapGetters 辅助函数仅仅是将 store 中的 getters 映射到局部计算属性,与state类似
(3)actions: 是专门操作异步请求的数据和业务逻辑的地方,它不能直接变更state中的状态,而是通过commit来调用mutations里的方法来改变state里的数据。 ---辅助函数mapActions 将组建的methods映射为store.dispath调用
(4)mutations:提交mutions是更改Vuex中的状态的唯一方法。mutations必须是同步的,如果要异步需要使用actions。每一个mutations都有一个字符串作为第一个参数,提交载荷作为第二个参数。 ---辅助函数mapMutations 将组建中的methods映射为store.commit调用。
(5)Moules:使用单一状态树,导致应用的所有状态几种到一个很大的对象,但是,当应用变得很大时,store对象会变得臃肿不堪,为了解决以上问题,Vuex允许我们将store分割到模块(modules)。每个模块拥有自己的state、mutations、avtions、grtters。
<3>当组件进行数据修改的时候我们需要调用dispatch来触发actions里面的方法。actions里面的每个方法中都会 有一个commit方法,当方法执行的时候会通过commit来触发mutations里面的方法进行数据的修改。 mutations里面的每个函数都会有一个state参数,这样就可以在mutations里面进行state的数据修改 ,当数据修改完毕后,会传导给页面。页面的数据也会发生改变。
我先来提供一个我个人项目里运用到的例子吧
需要用到的东西
1, 一个写好的组件,代码
<template>
<!-- 拖拽机器人 -->
<div
class="bilibili"
:style="{top:position.y+'px', left:position.x+'px'}"
@touchstart.stop="touchstart"
@touchmove.stop="touchmove"
@touchend.stop="touchend"
>
<img :src="bilibili1" alt />
</div>
</template>
<script>
import bilibili1 from "@/assets/images/bilibili1.png";
var dx, dy;
var screenWidth = window.screen.width;
var screenHeight = window.screen.height;
// import { mapState } from "vuex";
export default {
mounted() {},
// component: {
// ...mapState(["checked"])
// },
methods: {
touchstart() {
this.checked = true;
if(this.checked){
var touch;
if (event.touches) {
touch = event.touches[0];
} else {
touch = event;
}
}
},
touchmove(e) {
if (this.checked) {
var touch;
if (event.touches) {
touch = event.touches[0];
} else {
touch = event;
}
var maxw = document.querySelector(".bilibili").offsetWidth / 2;
// 定位滑块的位置
this.position.x = touch.clientX - maxw;
this.position.y = touch.clientY - maxw;
// 限制滑块超出页面
// console.log('屏幕大小', screenWidth, screenHeight )
if (this.position.x < 0) {
this.position.x = 0;
} else if (this.position.x > screenWidth - touch.target.clientWidth) {
this.position.x = screenWidth - touch.target.clientWidth;
}
if (this.position.y < 0) {
this.position.y = 0;
} else if (this.position.y > screenHeight - touch.target.clientHeight) {
this.position.y = screenHeight - touch.target.clientHeight;
}
if (this.position.x > screenWidth) {
this.position.x = screenWidth;
} else if (this.position.x > screenWidth - touch.target.clientWidth) {
this.position.x = screenWidth - touch.target.clientWidth;
}
if (this.position.y > screenHeight) {
this.position.y = screenHeight;
} else if (this.position.y > screenHeight - touch.target.clientHeight) {
this.position.y = screenHeight - touch.target.clientHeight;
}
//阻止页面的滑动默认事件
document.addEventListener("touchmove", function() {
event.preventDefault();
});
}
},
touchend(e) {
this.x = this.position.x;
this.y = this.position.y;
// console.log(this.x,this.y)
}
},
updated() {
this.x = this.position.x;
this.y = this.position.y;
},
data() {
return {
bilibili1,
position: {
x: this.x,
y: this.x
}
};
}
};
</script>
<style scoped>
.bilibili {
height: 0.7rem;
width: 0.7rem;
z-index: 990;
position: fixed;
top: 50%;
right: 50%;
border-radius: 50%;
}
.bilibili img {
width: 100%;
height: 100%;
}
</style>
2,把和这个注册成为全局组件,在main.js文件下注册,然后引用你想用到的页面就行了
import Bilibili from "@/components/Bilibili.vue"
Vue.component("Bilibili", Bilibili)
点击之前的效果
点击之后的效果
这个悬浮球是我设置的一个开关 默认是关闭的 点击后会在Vuex里面的仓库(Store)下面的State找到checked的值把false修改成true
这就是一个简单的修改state里面的状态来更新视图,它是怎么实现的呢,首先,
上面说了,我在Store仓库下面的state对象下存了一个数据checked,来当做开关是否开启的状态,
组件的信息配置 ,绑定了一个点击事件
<van-cell-group>
<van-cell-group>
<van-switch-cell
:icon="bilibili"
v-model="checked"
@click="changecheched"
title="bilibili悬浮球"
/>
computed: {
// 悬浮机器人的开启状态
checked: {
get() {
return this.$store.state.checked;
},
set(newVal) {
this.$store.commit("changecheched", newVal);
}
},
...mapState(["data"])
},
methods: {
// 悬浮机器人的开关事件
changecheched() {
this.checked = this.checked;
},
}
发送的事件去哪儿了呢,我们来看看state里的代码
mutations: {
// 改变悬浮机器人的状态
changecheched(state, newVal) {
console.log(state)
state.checked = newVal
},
}
显而易见,发送的事件我们在mutations里来定义,记住一句话,想要修改仓库里的数据,必须发送一个mutation,这个事件获取到用户改变的值后,把这个新值重新赋值给checked了,那么这个开关就可以控制悬浮机器人的显示和隐藏了
多个组件共享状态
还有一个问题就是 多个组件共享状态 也变得异常简单
是不是底下的foot每个页面都可以显示 我们其实只要在你想要这个机器人显示的地方引用这个bilibili组件,然后
获取在state里面checked的状态就可以实现,就不在赘述了,有什么不足之处请指点一二,不解之处也会一一细答!希望能给您带来帮助!逆战之中大家一起加油!