uvex快速入门 Vue.js 应用程序开发的状态管理模式 + 库

参考视频
vue参考文档

在这里插入图片描述

VueX 大型项目 管理公共数据的工具

作用: 独立与组件系统之外的,状态管理工具,采用集中式存储管理所有的组件状态,解决多组件数据通信(跨组件通信 A组件修改数据其他组件都能收到), 数据变化是可预测的 响应式

主要内容三个: state 保存公共数据 (类似于data) mutations 修改数据 actions 异步请求
次要的 : getters 计算属性 (类似于computed) moudules 拆分模块

请添加图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

项目中使用两种情况

1.老项目 先额外安装vuex包,在配置
2.新项目 在配置vue-cli中创建项目时,就可以选中vuex项,这样就不用配置了(脚手架会自动帮助我们完成.)
在这里插入图片描述

旧项目中使用vuex

在这里插入图片描述

//vue2对应官网npm上面的vuex 下载[email protected]最好
npm install vuex@3.6.2
开发依赖 : npm i xxxx --save-dev ;  npm i xxxx -D ;
生产依赖: npm i xxxx --save ;            npm i xxxx -S;     npm i xxxx

在这里插入图片描述
创建index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
    
    
  state(){
    
    
    return {
    
    
      // 就是公共的数据,所有的组件都可以直接使用
      count: 100
    }
  }
})
export default store

main.js

 // 省略其他
// 1. 导入store
import store from './store' 

new Vue({
    
    
  // 省略其他...
  store // 2. 注入Vue实例
})

在任意组件中,通过this.$store.state 来获取公共数据。

state定义公共数据

new Vuex.store({
    
    
  state() {
    
    
    return {
    
    
       属性名: 属性值 
    }
  }
})

1.在组件中,通过this.KaTeX parse error: Expected '}', got 'EOF' at end of input: …省略this而直接写成: { { store.state.属性名}}

在这里插入图片描述
下载如图插件
在这里插入图片描述

Vuex-用mutations修改公共数据

vue组件 ---->修改公共数据 ---->{vuex: mutations用来修改公共数据 —>state用来保存公共数据} ---->读取公共数据—>vue组件
1.定义格式

new Vue.store({
    
    
  // 省略其他...
  mutations:{
    
    
    // 每一项都是一个函数,可以声明两个形参
  	mutation名1function(state [, 载荷]) {
    
    
  
    },
    mutation名2function(state [, 载荷]) {
    
    
  
    }
	}
})

● 第一个参数是必须的,表示当前的state。在使用时不需要传入
● 第二个参数是可选的,表示载荷,是可选的。在使用时要传入的数据
2.调用格式

//commit是固定的方法
this.$store.commit('mutation名', 实参)

在这里插入图片描述
**
1.mutations的中文含义是:变异。 它是Vuex中用来修改公共数据的唯一入口。
2.在定义时:它的第一个参数是state,第二个参数是载荷
3.在调用时:用 this.$store.commit(‘mutation名’, 载荷) 来调用
**

Vuex-mutaions拓展理解

问:为啥是 s t o r e . c o m m i t ( ′ m u t a t i o n s 的 名 字 ′ ) 而 不 是 store.commit('mutations的名字')而不是 store.commit(mutations)store.mutations的名字()?

答:Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。

问:数据不可以该在组件内部直接修改吗?

答:不能。虽然语法上不报错,也有响应式的特点。但是不推荐。特别是在严格模式下会报错。若将vue创建 store 的时候传入 strict: true, 开启严格模式,那么任何修改state的操作,只要不经过 mutation的函数,vue就会报错

问:可以传递多个数据吗?

答:参数只能有一个

this.$store.commit('setUrl', url, host) // host这个参数将无法被接收到
//如果希望传递复杂的数据,第二个参数可以是对象,例如下面的写法
this.$store.commit('setUrl', {
    
     url, host} )
等价写法 this.$store.commit({
    
    type: 'mutations的名字'})

组件created钩子函数中:

组件


//渲染数据
<div style="flex: 1 1 auto; border:1px solid #ccc;">
        书目
        <p v-for="(book, idx) in $store.state.books" :key="idx">
          {
    
    {
    
    book.name}}, {
    
    {
    
    book.price}}
        </p>
  		  总价为:XX元
      </div>
      //用法
created(){
    
    
    // console.log(this.$store.state.count)
    this.loadData()
  },
  methods: {
    
    
    async loadData(){
    
    
      // 1. 发请求拿数据
      const res = await axios.get('http://www.liulongbin.top:3009/api/getbooks')
      console.log(res.data.data)
      // 2. 把数据保存到vuex(state)

      this.$store.commit('initBooks', res.data.data)

    }
  },

index.js

state: {
    
    
  // 省略其他...
  books: [] // 用来保存书
},
mutations: {
    
    
  // 省略其他...
  
  // 用来设置数据
  initBooks(state, books) {
    
    
     state.books = books
  }
}

在这里插入图片描述

Vuex-用getters的派生状态

定义格式

//state 就是义的公共数据state
new Vuex.store({
    
    
  // 省略其他...
  getters: {
    
    
    // state 就是上边定义的公共数据state
    getter的名字1: function(state) {
    
    
      return 要返回的值
    }
  }
})

在组件中通过:$store.getters.getter的名字 来访问
它的作用是从已有公共数据项中派生出新的数据项,类似于computed

Vuex-state-mutation-getters 小结

  1. 定义数据:
  2. 提供获取/修改数据的方法

在这里插入图片描述

Vuex-actions-发异步请求

  1. 组件内部发ajax
  2. ajax回来之后,去调用mutations来保存到vuex中
    actions是vuex的一个配置项
    作用:发异步请求获取数据,调用mutations来保存数据,将整个ajax操作封装到Vuex的内部
    ● 要点:

    ○ action 内部可以发异步请求操作
    ○ action是间接修改state的:是通过调用 mutation来修改state

定义格式

new Vuex.store({
    
    
  // 省略其他...
  actions: {
    
    
    // context对象会自动传入,它与store实例具有相同的方法和属性
    action的名字: function(context, 载荷) {
    
    
      // 1. 发异步请求, 请求数据
      
      // 2. commit调用mutation来修改数据
      
      // context.commit('mutation名', 载荷)
    }
  }
})

在组件中通过this.$store.dispatch(‘actions的名字’, 参数)来调用action

在这里插入图片描述

// 发ajax请求,从后端获取数据,再来去修改state中的数据
    actions: {
    
    
      getBooks (context) {
    
    
        // 1. 发异步请求
        axios({
    
    
          url: 'https://www.fastmock.site/mock/37d3b9f13a48d528a9339fbed1b81bd5/book/api/books',
          method: 'GET'
        }).then(res => {
    
    
          console.log(res)
          // 2. 调用mutation
          context.commit('setBooks', res.data.data)
        })
      }
    },

在这里插入图片描述

将ajax请求放在actions中有两个好处:

  1. 代码得到了进一步封装。将发ajax和保存数据到vuex绑定在一起。
  2. 逻辑更通顺。如果数据需要保存在Vuex的state中,那从接口处获取数据的操作就定义在Vuex的actions中。在这里插入图片描述

Vuex-用modules来拆分复杂业务

随着项目越来越大,需要放在vuex中的数据越来越多,整个store/index.js中代码会越来越长,怎么办呢?
modules的作用,拆分模块,把复杂的场景按模块来拆开

格式:

export default new Vuex.Store({
    
    
  // state: 用来保存所有的公共数据
  state: {
    
    },
  getters: {
    
    },
  mutations: {
    
    },
  actions: {
    
    },
  modules: {
    
    
  	模块名1{
    
    
    		// namespaced为true,则在使用mutations时,就必须要加上模块名
      	namespaced: true, 
  		  state: {
    
    },
  			getters: {
    
    },
  			mutations: {
    
    },
  			actions: {
    
    },
  			modules: {
    
    }
  	},
    模块名2{
    
    
        // namespaced不写,默认为false,则在使用mutations时,不需要加模块名
  		  state: {
    
    },
  			getters: {
    
    },
  			mutations: {
    
    },
  			actions: {
    
    },
         modules: {
    
    }
  	}  
  }
})

在这里插入图片描述

访问数据和修改数据的调整 namespaced为true

获取数据项:  {
    
    {
    
    $store.state.模块名.数据项名}}
获取getters: {
    
    {
    
    $store.getters['模块名/getters名']}}

● 访问模块中的mutations/actions:
○ 如果namespaced为true,则需要额外去补充模块名
○ 如果namespaced为false,则不需要额外补充模块名

$store.commit('mutations名')        // namespaced为false
$store.commit('模块名/mutations名')  // namespaced为true

$store.dispatch('actions名')        // namespaced为false
$store.dispatch('模块名/actions名')  // namespaced为true

使用了modules之后,在访问数据时就要额外添加modules的名字了。
结论: 在使用modules时,建议都给加上namespaced!

在这里插入图片描述
在这里插入图片描述

Vuex-辅助函数mapState来使用公共数据

掌握mapState的用法,将state中的变量映射到当前的组件中使用;

问题当访问某个数据项嵌套太深了,能不能优化一下访问的方式?
用mapState把公共数据(vuex.store) 映射 到本组件内部的计算属性中

mapState的使用步骤 映射

// 1. 导入辅助函数mapState,它是在vuex中定义的一个工具函数。
//  es6 按需导入 import { mapState } from 'vuex' 
import {
    
     mapState } from 'vuex'

computed: {
    
    
   // 说明1: ...对象 是把对象展开,合并到computed
   // 说明2: mapState是一个函数 
   //  ['数据项1', '数据项2']
   ...mapState(['xxx'])...mapState({
    
    '新名字': 'xxx'})
}

使用

this.xxx
{
    
    {
    
    xxx}}
// 步骤
// 1. 导入辅助函数mapState,它是在vuex中定义的一个工具函数。
//  es6 按需导入 import { mapState } from 'vuex' 
import {
    
     mapState } from 'vuex'

// 2. 在computed中使用 ...mapState(['books'])
// const res = mapState(['books'])
// res的结果是一个对象: { books: function() {}}
// console.log('mapState', res)

export default {
    
    
  computed: {
    
    
    c1 () {
    
    
      return 'c1'
    },
    // books: function() {}
    // ..res: 把res这个对象合并到computed对象中
    // ...res
    ...mapState(['books'])
  }
}
</script>

1. mapState是辅助函数,将vuex中的数据投射到组件内部;
2. computed:{ …mapState() } 这里的…是对象的展开运算符,整体来看是对象的合并

Vuex-辅助函数mapState对数据重命名

掌握mapState对数据重命名的用法。 vuex中的数据与本组件内的数据名相同

...mapState({
    
    '新名字': 'xxx'})

Vuex-map函数用法汇总

在这里插入图片描述

如何使用全局state

● 直接使用: this.$store.state.xxx;
● map辅助函数:

computed: {
    
     
  ...mapState(['xxx']), 
  ...mapState({
    
    '新名字': 'xxx'})
}

如何使用modules中的state

● 直接使用: this.$store.state.模块名.xxx;
● map辅助函数:

computed: {
    
     
  ...mapState('模块名', ['xxx']), 
  ...mapState('模块名', {
    
    '新名字': 'xxx'})
}

如何使用全局getters

● 直接使用:this.$store.getters.xxx
● map辅助函数:

computed: {
    
     
  ...mapGetters(['xxx']), 
  ...mapGetters({
    
    '新名字': 'xxx'})
}

如何使用modules中的getters

直接使用: this.$store.getters.模块名.xxx
map辅助函数:

computed: {
    
     

  ...mapGetters('模块名', ['xxx']), 

  ...mapGetters('模块名',{
    
    '新名字': 'xxx'})

}

如何使用全局mutations

直接使用:this.$store.commit('mutation名', 参数)
map辅助函数:

methods: {
    
     

  ...mapMutations(['mutation名']), 

  ...mapMutations({
    
    '新名字': 'mutation名'})

}

如何使用modules中的mutations(namespaced:true)

直接使用: this.$store.commit('模块名/mutation名', 参数)
map辅助函数:

methods: {
    
     

  ...mapMutations('模块名', ['xxx']), 

  ...mapMutations('模块名',{
    
    '新名字': 'xxx'})

}

如何使用全局actions

直接使用:this.$store.dispatch('action名', 参数)
map辅助函数:

methods: {
    
     

  ...mapActions(['actions名']), 

  ...mapActions({
    
    '新名字': 'actions名'})

}

如何使用modules中的actions(namespaced:true)

直接使用: this.$store.dispatch('模块名/action名', 参数)
map辅助函数:

methods: {
    
     

  ...mapActions('模块名', ['xxx']), 

  ...mapActions('模块名',{
    
    '新名字': 'xxx'})

}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

画画画

在这里插入图片描述

在这里插入图片描述

本地储存

watch: {
    
     //监听list改变时把数据存储在本地上
    // 'list'
    // this.数据
    // this.计算属性
    // this.$route // this.$route.qeury.xxx

    '$store.state.list': {
    
    
      deep:true,
      handler(newVal){
    
    
        localStorage.setItem('tododd',JSON.stringify(newVal))
      }
    }
  }

猜你喜欢

转载自blog.csdn.net/qq_43944285/article/details/124723411