Vuex学习之——初识Vuex

Vuex

来自官网
Vuex是一个专为Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex也集成到Vue的官方调试工具devtools extension。

什么是状态管理模式

一个简单的Vue计数应用

// 状态管理应用包含以下几个部分:
new Vue({
  // state,驱动应用的数据源
  data () {
    return {
      count: 0
    }
  },
  // view,以声明方式将state映射到视图
  template: `
    <div>{{ count }}</div>
  `,
  // actions,响应在view上的用户输入导致的状态变化
  methods: {
    increment () {
      this.count++
    }
  }
})

单项数据流
在这里插入图片描述
上面是单向数据流的简单示意,但是,当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:

  • 多个视图依赖同一状态
  • 来自不同视图的行为需要变更同一状态

什么情况下应该使用Vuex?

Vuex可以帮助我们管理共享状态,并附带了更多的概念和框架。
构建一个中大型单页项目,很可能会考虑如何更好地在组件外部管理状态,Vuex将会成为自然而然的选择。

Vuex 安装

npm install vuex --save

在一个模块化的打包系统中,您必须显式地通过Vue.use()来安装Vuex

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

核心 —— store

每一个Vuex应用的核心就是store(仓库)。'store’基本上就是一个容器,它包含着你的应用中的大部分的状态(state)。Vuex和单纯的全局对象有以下两点不同:

  1. Vuex的状态存储是响应式的。当Vue组件从store中读取状态的时候,若store中的状态发生变化,那么响应的组件也会相应地得到高效更新。
  2. 你不能直接改变store中的状态。改变store中的状态的唯一途径就是显式地提交(commit)mutation。这样使得我们可以方便地跟踪每一个状态的变化。从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

一个简单的store

安装Vuex之后,让我们来创建一个store。仅需提供一个初始化state对象和一些mutation:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
	state:{
		count:0
	},
	mutations:{
		increment(state){
			state.count++
		}
	}
})

现在,你可以通过 store.state来获取状态对象,以及通过store.commit方法触发状态变更。

store.commit('increment')
console.log(store.state.count) //1

为了在Vue组件中访问 this.$store property,你需要为Vue实例提供创建好的store。Vuex提供了一个从跟组件向所有子组件,以store选项的方式注入该store的机制:

new Vue({
  el: '#app',
  store: store,
})

提示:如果使用ES6,你也可以以ES6对象的property简写(用在对象某个property的key和被传入的变量同名时)

new Vue({
	el: '#app',
	store
})

现在,我们可以从组建的方法提交一个变更。

methods:{
	increment(){
		this.$store.commit('increment')
		 //强调!!我们通过提交mutation的方式,而非直接改变 ` store.state.count`,是因为我们想要更明确地追踪到状态的变化。
		console.log(this.$store.state.count)
	}
}

由于store中的状态是响应式的,在组件中调用store中的状态简单到仅需要在计算属性中返回即可。触发变化也仅仅是在组件中的methods中提交mutation。

核心概念(有5个)

State 单一状态树

Vuex使用单一状态树——用一个对象就包含了全部的应用层级状态。至此,它便作为一个‘唯一数据源’而存在。
这也意味着,每个应用将仅仅包含一个store实例。单一状态树让我们能够直接地定位任一特定片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
存储在Vuex中的数据和Vue实例中的data遵循相同的规则,例如状态对象必须是纯粹(plain)的。

在Vue组件中获得Vuex状态。

由于Vuex的状态存储是响应式的,从store中读取状态最简单的方法就是在计算属性(computed)中返回某个状态。
创建一个Counter组件

//创建一个Counter 组件
const Counter = {
	template:`<div>{{count}}</div>`
	computed:{
		count(){
			return store.state.count
			//每当 store.state.count变化的时候,都会重新求取计算属性,并且触发更新相关联的DOM
		}
	}
}

但是,这种模式导致组件依赖全局状态单例。在模块化的构建系统中,在每个需要使用state的组件中需要频繁的导入,并且在测试组件时需要模拟状态。

Vuex通过store选项,提供了一种机制将状态从根组件注入到每一个子组件中(需要调用 Vue.use(Vuex)

const app = new Vue({
	el:'#app',
	//把store对象提供给 store 选项,这可以吧 store 的实例注入到所有的子组件
	store,
	components:{Counter},
	template:`
		<div> <counter></counter> </div>
	`
})

通过根实例中注册 store选项,该store实例会注入到根组件下的所有子组件中,且子组件能通过this.store访问到。
更新一下Counter的实现

//创建一个Counter 组件
const Counter = {
	template:`<div>{{count}}</div>`
	computed:{
		count(){
			return this.$store.state.count
			//变成了this.$store
		}
	}
}
mapState 辅助函数

当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余,为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性。

示例代码:

// 在单独构建的版本中辅助函数为Vuex.mapState
import { mapState } from 'vuex'
export default {
	//...
	computed:mapState({
	// 传入了state,返回了state.count
	count:state=>state.count,
	//传字符串参数 'count' 等同于 `state=>state.count`
	countAlias:'count',
	// 为了能够使用 this 获取局部状态,必须使用常规函数
	countPlusLocalState(state){
		return state.count + this.localCount
	}
	})
}

当银蛇的计算属性的名称与 state 的子节点名称相同时,我们也可以给mapState传一个字符串数组。

computed:mapState([
	//映射 this.count 为 store.state.count
	'count'
])

对象展开运算符
mapState 函数返回的是一个对象。那么我们如何将它与局部计算属性混合使用呢?通常,我们需要使用一个工具函数将多个对象合并为一个,以使我们可以将最终对象传给 computed 属性。使用对象展开运算符,简化写法。

computed:{
	localComputed(){},
	//使用对象展开运算符将此对象混入到外部对象中
	...mapState({
	//...
	})
}

组件仍然保有局部状态
使用Vuex并不意味着你需要将所有的状态放入Vuex。虽然将所有的状态放入Vuex会使状态变化更显式和易调试,但也会使代码变的冗余和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态。

Getter 计算属性

有时我们需要从store中的state中派生出一些状态,例如对列表进行过滤并计数。

computed: {
  doneTodosCount () {
    return this.$store.state.todos.filter(todo => todo.done).length
  }
}

如果有多个组件需要用到此属性,我们可以复制这个函数,或者抽取到一个共享函数,然后在多处导入它,都不理想。
Vuex允许我们在store中定义‘getter’(可以认为是store的计算属性)。就像计算属性一样,getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
Getter 接受 state 作为其第一个参数:

const store = new Vuex.Store({
	state:{
		todos:[
			{id:1,text:'...',done:true},
			{id:1,text:'...',done:true},
		]
	},
	getters:{
		doneTodos:state=>{
		return state.todos.filter(todo=>todo.done)
		}
	}
})
通过属性访问

Getter 会暴露为 store.getters对象,你可以以属性的形式访问这些值:

store.getters.doneTodes // [{id:1,text:'...',done:true}]

Getter 也可以接受其他getter作为第二个参数

getters: {
  // ...
  doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
  }
}
store.getters.doneTodosCount // -> 1

我们很容易在任何组件中使用它

computed: {
  doneTodosCount () {
    return this.$store.getters.doneTodosCount
  }
}

注意,getter在通过属性访问时是作为Vue的响应式系统的一部分缓存其中的。

通过方法访问

你也可以通过让getter返回一个函数,来实现给getter传参。在对store里的数组进行查询时非常有用。

getters: {
  // ...
  getTodoById: (state) => (id) => {
    return state.todos.find(todo => todo.id === id)
  }
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }

注意,getter在通过方法访问时,每次都会去进行调用,而不会缓存结果。

mapGetters 辅助函数

mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:

import { mapGetters } from 'vuex'
export default {
  // ...
  computed: {
  // 使用对象展开运算符将 getter 混入 computed 对象中
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}

如果想将一个getter属性另取一个名字,使用对象形式

...mapGetters({
  // 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
  doneCount: 'doneTodosCount'
})

module 模块

mutation 同步

action? 异步

创建Vuex项目

在这里插入图片描述

如何之间获取到数据??

如何通过辅助函数获取到数据??

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
想在Hello上获取数据。
在这里插入图片描述
把实例打印出来,看有什么,仓库里面有什么?就有state上的user_id
在这里插入图片描述
state里的数据映射到本地
用在计算属性上
在这里插入图片描述
实际上是做了下面的事。
在这里插入图片描述

在界面上就拿到了
在这里插入图片描述

上面是Vuex的父子间通信

还有跨组件通信,这是啥???

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值