vuex使用

Vuex 状态管理模式     

一、是什么?   

vue官方的一个插件 npm包      作用:实现组件之间的数据共享

是个全局变量   像个数据池 大范围的数据共享

在哪需要它?

大项目  适合中大型单页应用

二、怎么使用

怎么使用 :看官网文档

1.安装

(vue2 要安装vuex@3, vue3 要安装vuex@4)

vue2

npm i vuex@3 -S

vue3

yarn add vuex  或  npm install vuex --save

2.配置  实例化store

新建store文件->index.js, 实例化store对象   导出store对象

在store的index里new了一个实例对象赋值给store , export default导出去了

// 1.引入 Vue 和 Vuex 包
import Vue from 'vue'
import Vuex from 'vuex'



(类似于data(){return {a:1, b:2,xxxxxx}})

 // 2.向vue中注册vuex 让 vue 使用 Vuex
Vue.use(Vuex)


 // 3. new Vuex.Store() 实例化store对象,并设置state数据池和mutations方法集
const store = new Vuex.Store({

  state: {   //存所有数据,相当于data(){return {num:1, uname:'aaa'}

  num:1
  uname:'aaa'

  },
  getters: { // vuex中的计算属性
  },
  
  mutations: { //同步方法,操作state方法
     addNum(state){
      state.num++     //同步方法每次加1
    },
  },
 
  actions: {   // 异步方法, 操作mutation
  },
  modules: {  // 模块
  },

// 4.导出store对象
export default store

3. main.js中,将 store 实例对象导入注入到Vue根组件 

进行引入store,在所有组件中就可以使用了(因为new的是vue是根实例)

(作用:把state里的所有变量都 变成vue内部变量 ,这样的话 computed的依赖更
新就生效了
理解:

从main.js导入 store 注入进 Vue根实例,注入之后 vue身上就多了 store ,

import Vue from 'vue'               // Vue 是一个构造函数   所以要大写
import App from './App.vue'
import router from './router'
import store from './store'   // 这里就省略了index.js 


new Vue({

// 挂载实例对象
  router,
  store,
  render: h => h(App)
}).$mount('#app')

拓展1.import引入

./ 开头, webpack会把这个当成我们自己的组件来加载,在自己当前的文件里找

没有./,则webpack会把这个当成第三方包来加载

如果引入index取名的文件可以省略不写,写上也没有任何问题。

拓展2:

要渲染到public文件夹下面的index.html里的id="app"两种方式 一种el

new Vue({

  el:'#app'

})

// 完全等价于下面写法

new Vue({

}).$mount('#app')

4.state的使用  ,定义公共数据格式,可以在任何组件中进行调用


export default new Vuex.Store({
  // 存所有的数据,相当于data

  state: {

    num:1
  },

})

state是响应式的:如果修改了数据,相应的在视图上的值也会变化.

每次敲完代码,记得去网页中使用vue-devtool调试工具查看

三、核心概念

vuex分为五个大块 使用

state: 统一定义公共数据(类似于data(){return {a:1, b:2,xxxxxx}})

mutations : 使用它来修改数据(类似于methods) 

getters: 类似于computed(计算属性,对现有的状态进行计算得到新的数据-------派生 )

actions: 发起异步请求

modules: 模块拆分

5.1   State

组件访问 State 数据    使用公共数据

1>{{$store.state.属性名}} 在标签中直接使用,可以省略this,

{{$store.state.属性名}}             {{$store.state.num}}

2>this.$store.state.属性名      组件js里通过this.$store就能访问到

this.$store.state.属性名        this.$store.state.num

在组件中通过 computed 使用 vuex 数据池里的变量,

(不能写在data里 一旦写在data里 my_num不会变化

一定要写在computed里

data() 里的变量是死的 num赋值给my_num 你不主动修改my_num 它是不会变的)

5.2  Mutation  里面的方法一般全大写

addNum 需要替换成  ADD_NUM

(1) 用mutations修改公共数据   在store/index.js里

特点:要修改State 的数据,只能调用Mutation 方法,Vuex中修改公共数据的唯一入口。

好处:能够确保修改来源的唯一性,方便调试和后期维护。

mutations: { //同步方法,操作state方法
     addNum(state){
      state.num++     //同步方法每次加1
    },

改变数据池里的数据只能通过commit触发mutations里的某个函数)修改state里的数据,否则生不成快照

间接改变vuex数据池里的数据(极力推荐)
在methods里,
     通过commit()方法触发   mutations同步获取数据 
 this.$store.commit('mutations里的函数名')

    通过dispatch()方法触发   actions异步获取数据

this.$store.dispatch('actions里的函数名')

methods: {
    add() {
      // commit()的第一个参数是mutations里的函数名
      // 调用addNum方法 改变数据 用commit()     this.$store.commit('mutations里的函数名')
      this.$store.commit("addNum");

      // 但是强烈不推荐这么写!!!
      // this.$store.state.num++;
    },
  },

拓展: 开启严格模式

数据不能在组件内直接修改   强烈不推荐这么写!!!       // this.$store.state.num++;

一定通过mutations去改变数据池里的数据,虽然不会报错,但这样不能生成数据快照.

dev-tools只监听mutations里函数的执行情况.函数执行一次就生成一个数据快照)

作为项目经理,为了防止底下的人私自使用这种错误方法,可以在vuex中写上:

 vue创建 store 的时候传入 strict : true, 开启严格模式,

那么任何修改state的操作,只要不经过 mutation处理的函数,vue就会报错;

  // 判断现在是开发环境还是生产环境,如果是开发环境就开启严格模式,否则关闭

  strict: process.env.NODE_ENV !== 'production',

  (2)简写

如果一个组件是需要使用很多vuex中的数据或方法就可以集体导入

第一步、引入...mapState   和   ...mapMutations 方法 从展示页面的js代码中

import { mapState, mapMutations } from "vuex";

        

第二步、集体导入数据和方法

...mapState方法  在computed   集体导入vuex中的state里的数据

...mapMutations方法  在methods    集体导入mutations里的方法

...mapMutations(["addNum"])

 // 等价于下面写法

    // addNum(state) {

    //   state.num++;

    // },

方法可以互相使用    既然上面已经引入addNum()方法 还可以用this调用 实现

  // myAddNum() {

    //   this.addNum();

    // },

  myAddNum() {
      this.addNum();
    },

第三步、在html代码里直接使用vuex里mutations方法集的方法

 <h3>Right 组件{{num}} {{$store.state.num}}</h3>

 <p>{{uname}}</p>

<button @click="myAddNum">加1</button>

 <button @click="addNum">+1</button>

(3) 传参数

第一种:

调用mutations可以传值

不是加1        每次加2

main.js

  mutations:{

    // 固定 第一个参数永远是state,第二个参数永远是调用者传进来的值

    addNum(state,val){    // 接收第二个参数 

      // state.num++

      state.num+=val 

    },

 第一种 用commit去写

<h3>Right 组件{{num}} {{$store.state.num}}</h3> 

 <button @click="add">加2</button> 



methods:

add() {

this.$store.commit("addNum",2);

},

第二种:

<h3>Right 组件{{num}} {{$store.state.num}}</h3>
  
 <button @click="myAddNum">加2</button>



import { mapState, mapMutations } from "vuex";




  methods: {

    ...mapMutations(["addNum"),

    myAddNum() {

      this.addNum(2);  // 只加了这里

    },

5.3 actions-发异步请求

如果在Mutations里执行异步函数,devtools 一旦监听到Mutations被执行了,就立马生成一个数
据快照,但是此时数据还没更新,所以生成的快照里数据是旧的
所以vuex 规定:
1. Mutation里必须是同步事务
2. 所有异步事务交给Actions去执行

Action 本质上是 JavaScript 函数,专门用来处理 Vuex 中的异步操作

使用Actions是个方法集 来处理异步操作后,devtools就可以 正常追踪数据
数据快照依赖mutations
   // commit 是专门用来触发moutations里的函数
      // this.$store.commit('add')
      // dispatch 是专门用来触发sctions里的函数
     //this.$store.dispatch("add");
在页面methods用dispatch触发(actions里的函数)
<p>{{$store.state.num}}</p>
<button @click="add">+1</button>


 methods: {
    add() {
      this.$store.dispatch("add");
    },
  },

main.js     

actions里 调用commit触发触发mutations里的函数,显示快照

 注意 actions里方法的第一个参数是store不是state

 mutations:{
    //  mutations里的方法建议全大写
    ADD_NUM(state,payload){
      state.num++
    }
    },
  actions:{
    // 注意 actions里方法的第一个参数是store不是state
      add(store){
        // 千万不要在Mutations中异步代码的变更,devtools无法监视到数据变化
        setTimeout(()=>{
          // store.state.num++
          // actions不显示快照
          // 所以要调用commit触发触发mutations里的函数,显示快照
          store.commit('ADD_NUM')
        },3000)
    }
  }

简写

...mapActions(["add"]),

...mapActions方法  在methods    集体导入actions里的方法

  methods: {
    ...mapActions(["add"]),
    // 等价于下面
    // add() {
    //   // dispatch 是专门用来触发actions里的函数
    //   this.$store.dispatch("add");
    // },
  },

5.4  getters   是vuex里的计算属性

计算属性的本质是属性 不是方法  是变量  只是写成了方法的样子

vue里computed 里的方法 实际是计算属性 可以后台打印看this       打印结果是属性my_num:3

和data里的变量的唯一的区别,它的值是通过别的变量计算得到的,如果别的数据发生变化,它也跟着变化

computed计算属性的变量  是来自于data的变量  

   <p>{{num}}</p>          // 1
    <p>{{my_num}}</p>      // 6
    <p>{{your_num()}}</p> 



   return {
      // 普通属性   是固定的 不会变的属性
      num: 1,
      a: 3,
    };
  },
  computed: {
    // 计算属性   是计算得来的属性  不是函数方法  上面可以直接{{my_num}}显示
    // my_num 是依据return的数值变化而变化的
    my_num() {
      return this.a+3;
    },

  methods: {
    // 方法里的函数 上面显示需要带上() {{ your_num()}}
    your_num() {
      return 3;
    },

解决办法 写一遍在getters里 共享计算属性     每个组件可以直接调用

 Getters 是 Vuex 中的计算属性。当数据源发生变化时,Getters 的值会自动更新

getters的变量来自于state的变量

state的变量是有根的

getters的变量是没有根的 依赖于state的变量

...mapGetters(["isAllDone"]),

...mapGetters方法  在computed    集体导入acitions里的方法

 汇总简写方法:

...mapState方法  在computed   集体导入vuex中的state里的数据

...mapGetters方法  在computed  集体导入acitions里的计算属性

...mapMutations方法  在methods 集体导入mutations里的同步方法

...mapActions方法      在methods    集体导入actions里的异步方法

5.5 modules模块化

Modules 按照 模块化 的开发思想,把 不同业务 的数据和方法,封装到不同的模块中。
第一步:定义模块
每个模块都是 彼此独立 的,拥有自己的 state、mutations、actions、getters
全局的都是 :

new Vuex.Store({ 

state: { 

num: 1 

},

})

局部的 省略大括号的箭头函数

new Vuex.Store({ 

namespaced: true,  // 开启命名空间变为局部

state: () => ({

    num: 3,

  }),

即state里的数据

第二步:注册模块 

 

 第三步:使用模块中的数据和方法

 Modules – 命名空间    防止多个module之间变量名或方法名冲突

里面的total变量和changeTotal方法都一样,调用的时候成员名称冲突

namespaced(命名空间)

第一步:开启命名空间

l 作用: 可以解决不同模块之间 成员名称冲突的问题 。在实际项目开发中, 强烈建议 为每个 Module 模块都开启命名空间!

 

第二步:在组件中使用带有命名空间的module

两种访问方式:
  mapXXX(' 模块的注册名称 ', [ /* 要映射的成员名称 */ ])
  mapXXX(‘ 模块的注册名称 ’, {新的变量名: ’模块中的变量名’})

 也可以把模块内state里所有的变量都map出来

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值