前端开发那些事儿vue

谈谈对vuex的理解

2021-02-03  本文已影响0人  赵Wayne

首先我们先抛出三个问题
(1)有了vuex我们是不是就不需要组件之间传参?
(2)vuex和localstorage啥区别?
(3)vuex里面直接修改state为什么还要有专门的修改方法mutation?
先把3个问题的答案放出来:
(1)vuex是多个组件,共享同一个数据的状态管理工具。只是父子之间的数据传递没必要使用vuex,小型项目官方都不推荐使用vuex,只会增加项目的负担,大型的项目并且是多个组件共享的用vuex更好
(2)vuex和localstorage两者应用场景不同。vuex是当前vue项目的全局状态对象,存放在内存中,一旦当前vue项目刷新,vuex的数据也将恢复默认值;而localstorage是存放在浏览器中的对象,即使刷新数据也仍然存在。
(3)对于这个问题,在创建 store 的时候传入 strict: true, 开启严格模式,那么任何修改state的操作,只要不经过mutation的函数,vue就会 throw error

const store = new Vuex.Store({
   state,
   strict:true
   //开启严格模式后,只能通过mutation来改变状态(不支持异步)否则会报错
})
//下面的开启严格模式就会报错,不开启是可行的
  console.log(store.state.count) //0
  store.state.count = 3;
  console.log(store.state.count)  //3

注意:发布环境下不要开启严格模式,严格模式会深度监测状态树来检测不合规的状态变化,造成不必要的性能损失
但是真正原因是:
Vuex的state是响应式的,响应式就是状态改变页面组件也实时更新。但是要实现响应式必须通过提交mutation去改变state,并且还需要遵守一定的规则

image.png

下面从是什么,为什么,怎么用的角度来谈对vuex的理解

【1】vuex是什么

多个组件,共享,同一个数据的状态管理工具
vuex适用于大型单页应用,简单的应用使用 Vuex 可能是繁琐冗余的

【2】为什么

当在开发大型单页应用时,会出现多个视图组件依赖同一个状态,来自不同视图的行为需要变更同一个状态。如登录状态、加入购物车、音乐播放等。
或许你认为可以用传参的方法解决组件之间互相传值的问题。但是传参的方法对于多层嵌套的组件将会变得很繁琐,并且对于兄弟组件间的传递无能为力。所以vuex出现了,相当于一个“前端的数据库”。
Vuex主要用于解决组件之间同一状态的共享问题,它能把组件的共享状态抽取出来,当做一个全局单例模式进行管理。 这样不管你在何处改变状态,都会通知使用该状态的组件做出相应修改。即Vuex采用集中式存储管理应用的所有组件的状态 这里的关键在于集中式存储管理。 这意味着本来需要共享状态的更新是需要组件之间的通讯,而现在有了Vuex,组件就都和store通讯了

【3】怎么用

安装使用步骤
1.安装
sudo cnpm install vuex -S
2.引入状态管理工具vuex
import vuex from 'vuex'
import store from './vuex/store'
3.main.js里面实例化
new Vue({
  el: '#app',
  router, :style="{ 'left': leftnum + 'px' }"  
  store,
  components: { App },
  template: '<App/>'
})
4.在src里面和views同级创建vuex文件里面store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
  // 定义状态
  state: {
    //动态路由的数组
    keepAlive:[],
    //全局域名
    domainName:"",
  }
})
export default store

5.使用:this.$store.state.名字

使用方法核心内容

(1)state 存放状态
(2)mutations 美[mjuːˈtion] 同步的,唯一更改state的方法是提交 mutation。
(3)getters 加工state成员给外界类似于计算属性
(4)actions 异步的,然后提交mutation去操作state
(5)modules 模块化状态管理


image.png
(1)state 存放状态
const store = new Vuex.store({
    state:{
        name:'jack'
    },
})
//页面调用
this.$store.state
(2)mutations同步的对state操作的集合,比如对该数据的修改、增加、删除等等。里面的函数有两个默认形参([state] [payload])

state是当前VueX对象中的state
payload是该方法在被调用时传递参数使用的

//index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.store({
    state:{
        name:'jack'
    },
    mutations:{
        //es6语法,等同edit:funcion(){...}
        //编辑
        edit(state,payload){
            //(1)直接调用
            state.name = 'wayne'
            //(2)传值调用
            state.name = payload
            //(3)传值对象调用
            state.name = payload.name
        },
        //新增
        myadd(state,payload){
            //新增逻辑
            Vue.set(state,"name1","dawei")
        },
        //删除  
        mydel(state,payload){
            //删除逻辑
            Vue.delete(state,"name1")
        },
    }
})
export default store
//页面通过this.$store.commit调用
//(1)直接调用
this.$store.commit('edit')
//(2)传值调用
this.$store.commit('edit','wayne')
//(3)传值对象调用
this.$store.commit('edit',{name:'wayne',sex:'男'})
//还可以这么写
this.$store.commit({
    type:'edit',
    payload:{
        name:'wayne',
        sex:'男'
    }
})
image.png

新增和删除不能使用xx.xx = xx,delete state.info.age这种原来的模式因为不是响应式的,响应式规定新增和删除有自己的方法,这样才能自动更新到组件上面去;
新增用Vue.set(state,"name1","dawei"),
删除用Vue.delete(state,"name1")

(3)getters 加工state成员给外界类似于计算属性

可以对state中的成员加工后传递给外界,Getters中的方法有两个默认参数
state 当前VueX对象中的状态对象
getters 当前getters对象

//index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.store({
    state:{
        name:'jack',
        age:'15'
    },
    mutations:{
        //编辑
        edit(state,payload){
        }
    },
    getters:{
       nameInfo(state){
           return "姓名:"+state.name
       },
       fullInfo(state,getters){
           return getters.nameInfo+'年龄:'+state.age
        }  
  }
})
export default store
// 调用
this.$store.getters.fullInfo//姓名:jack 年龄:15
(4)actions 专门放置异步操作,然后提交mutation去操作state

注意:Action 提交的是 mutation,而不是直接改变state,只有mutation能改变state。
至于是在页面组件中等异步操作(如axious请求接口改变state)完成后去commit调用mutation;还是直接action去做异步axious,根据不同的业务场景有不同的选择,也有不同的好处体现出来。
比如多次遇到的异步(如axious请求接口改变state)那就直接放在action里面,需要的时候页面组件直接使用this.$store.dispatch就可以不用重复写axious,所以vuex只是为了更灵活使开发者多一个选择,让代码尽可能的变动优雅。
Actions中的方法有两个默认参数
context 上下文(相当于箭头函数中的this)对象
payload 挂载参数

//index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.store({
    state:{
        name:'jack'
    },
    mutations:{
        //es6语法,等同edit:funcion(){...}
        //编辑
        edit(state,payload){
            //(2)传值调用
            state.name = payload
        }
    },
    actions:{
        Edit(context,payload){
            //异步操作
            setTimeout(()=>{
                //提交mutations方法,修改state
                context.commit('edit',payload)
            },2000)
        }
      }
})
export default store

//在页面组件中调用:
this.$store.dispatch('Edit','wayne')
(5)modules 模块化状态管理

当项目庞大,状态非常多时,可以采用模块化管理模式。Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。

const store = new Vuex.Store({
models:{
    a:{
        state:{},
        getters:{},
        ....
    },
     b:{
        state:{},
        getters:{},
        ....
    },
}
})
//调用
this.$store.state.a
//而提交或者dispatch某个方法和以前一样,会自动执行所有模块内的对应type的方法:
this.$store.commit('editKey')
this.$store.dispatch('aEditKey')
上一篇下一篇

猜你喜欢

热点阅读