逆战来临,我们谈谈Vuex

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的状态就可以实现,就不在赘述了,有什么不足之处请指点一二,不解之处也会一一细答!希望能给您带来帮助!逆战之中大家一起加油!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值