vuex的理解和使用,vuex是怎么实现的
本文详细解释了Vuex及其用法,并通过示例代码详细介绍。对大家的学习或者工作都有一定的参考价值,有需要的朋友可以参考一下。
目录
一、什么是Vuex二、运行机制三、创建项目1、使用脚手架构建Vue项目2、安装Vuex3、启动项目4、配置使用Vuex4.1、创建存储文件夹4.2、配置全局使用存储对象四、Vuex核心概念1、状态2、变异3、Getter3.1、按属性访问3.2、辅助函数访问4、动作4.1、调度触发4.2、辅助函数触发5、模块5、摘要1、核心概念2
一、什么是Vuex
官网解释如下:
Vuex是专门为Vue.js应用开发的状态管理模式。它采用集中存储来管理应用程序所有组件的状态,并确保状态以可预测的方式随相应的规则变化。Vuex还集成到了Vue的官方调试工具devtools extension中,提供了零配置的穿越调试、状态快照的导入导出等高级调试功能。
那么什么是“国家管理模式”呢?
状态自我管理的应用包括以下几个部分:
状态:驱动应用程序的数据源;视图:以声明方式将状态映射到视图;动作:响应由视图上的用户输入引起的状态改变;请看下面显示“单向数据流”概念的简单图表:
从上图可以看出,整个系统的数据流是单向的:数据(即状态)驱动视图的更新,用户对视图进行一些操作来触发动作,通过动作而不是视图直接更新状态来更新状态。
二、运行机制
我们来看看官网上的一张Vuex运行机制图:
从图中可以看出,Vuex不再与组件有很强的相关性。运行机制:Vuex提供数据(状态)驱动视图(这里指的是Vue组件),视图通过dispatch调度动作。在动作中可以进一步做一些异步操作(比如通过ajax请求后端接口数据),然后通过Commit提交给突变,突变最终会改变状态。那么为什么要经历突变呢?这是因为我们需要记录Vue调试工具(Devtools)中的数据变化,以便通过插件进一步调试。所以突变只能是纯粹的同步操作。如果有异步操作,需要在动作中处理。如果没有异步操作,那么提交操作突变可以由组件直接执行。如下图所示:
三、创建项目
1、使用脚手架搭建Vue项目
在命令行中输入以下命令来创建Vue项目:
vue初始化web pack vuex-演示
如下图所示:
然后按enter安装,并选择默认配置。如下界面显示创建成功:
2、安装Vuex
默认情况下,Vuex不会安装在新项目中。如果要使用Vuex,需要手动安装。输入以下命令:
npm安装vuex -保存
如下图所示:
注意:- save表示全局安装。
3、启动项目
在第一步中创建成功的项目后,将最终提示您如何启动项目,如下所示:
这两行命令意味着您可以通过首先输入项目的根目录,然后输入npm run dev命令来启动项目,如下图所示:
在浏览器窗口中输入:http://localhost:8080浏览:
4、配置使用Vuex
4.1、创建store文件夹
在src目录下创建一个Store文件夹,用来存储所有与状态管理相关的文件,然后创建一个index.js文件。store对象写在index.js文件中,代码如下:
//介绍Vue
从“vue”导入Vue
//介绍Vuex
从“vuex”导入Vuex
//添加全局引用
vue . use(Vuex);
//创建一个存储对象
const store=new Vuex。商店({
})
//导出创建的存储对象
导出默认存储;
4.2、配置全局使用store对象
在main.js中配置全局使用存储对象:
//要用“import”命令加载的Vue构建版本
//(仅运行时或独立)已在webpack.base.conf中用别名设置。
从“vue”导入Vue
从导入应用程序。/App
从导入路由器。/路由器
//引入index.js文件
从导入存储。/存储/索引
Vue.config.productionTip=false
/* eslint-禁用no-new */
新Vue({
埃尔: #app ,
路由器,
Store,//配置存储对象的全局使用
组件:{ App },
模板:“应用程序/”
})
到目前为止,已经创建了一个Vuex项目,并且安装了Vuex。现在您可以使用这个项目来演示如何使用Vuex进行状态管理。
四、Vuex核心概念
1、state
使用以下代码在index.js文件中添加状态:
//介绍Vue
从“vue”导入Vue
//介绍Vuex
从“vuex”导入Vuex
//添加全局引用
vue . use(Vuex);
//创建状态
常量状态={
//定义num属性并将初始值设置为1
数字:1
}
//创建一个存储对象
const store=new Vuex。商店({
//添加状态导出
状态
})
//导出创建的存储对象
导出默认存储;
使用test.vue中的显示初始值:
模板
p初始值:{{this。$store.state.num}}/p
/模板
脚本
导出默认值{
名称:“测试”
}
/脚本
页面效果:
注意:您也可以通过计算属性来获得num的值:
模板
差异
p初始值:{{this。$store.state.num}}/p
p通过计算属性获取初始值:{{count}}/p
/div
/模板
脚本
导出默认值{
名称:“测试”,
//计算属性
计算值:{
计数(){
归还这个。$ store . state . num;
}
}
}
/脚本
效果如图所示:
2、mutations
属性的值可以用上面的state得到,那么如何修改state中属性的值呢?这时我们需要突变。官网解释如下:
改变Vuex商店状态的唯一方法是提交一个突变。Vuex中的突变与事件非常相似:每个突变都有一个字符串和回调函数(处理程序)的事件类型。这个回调函数是我们实际进行状态更改的地方,它将接受状态作为第一个参数。以上面为例。
修改index.js文件并添加突变:
//介绍Vue
从“vue”导入Vue
//介绍Vuex
从“vuex”导入Vuex
//添加全局引用
vue . use(Vuex);
//创建状态
常量状态={
//定义num属性并将初始值设置为1
数字:1
}
//通过提交更改状态
var突变={
//状态作为第一个参数
ChangeState(状态){
//自动递增1
state.num
}
}
//创建一个存储对象
const store=new Vuex。商店({
//添加状态
状态,
//导出突变
突变
})
//导出创建的存储对象
导出默认存储;
修改test.vue文件:
模板
差异
p初始值:{{this。$store.state.num}}/p
p通过计算属性获取初始值:{{count}}/p
button @ click= $ store . commit( changestate )更改属性值/button
/div
/模板
脚本
导出默认值{
名称:“测试”,
//计算属性
计算值:{
计数(){
归还这个。$ store . state . num;
}
}
}
/脚本
效果:
注意:更改状态也可以通过传递参数来修改。请参见以下示例:
修改index.js文件,如下所示:
//介绍Vue
从“vue”导入Vue
//介绍Vuex
从“vuex”导入Vuex
//添加全局引用
vue . use(Vuex);
//创建状态
常量状态={
//定义num属性并将初始值设置为1
数字:1
}
//通过提交更改状态
var突变={
//状态作为第一个参数
ChangeState(状态){
//自动递增1
state.num
},
//state作为第一个参数,para作为第二个参数
ChangeStateWithPara(state,para){
//自动递增1
state.num=para
}
}
//创建一个存储对象
const store=new Vuex。商店({
//添加状态
状态,
//导出突变
突变
})
//导出创建的存储对象
导出默认存储;
Test.vue修改如下:
模板
差异
p初始值:{{this。$store.state.num}}/p
p通过计算属性获取初始值:{{count}}/p
button @ click= $ store . commit( changestate )更改属性值/button
button @ click= $ store . commit( changestatewithpara ,5)传递参数以更改属性值/button
/div
/模板
脚本
导出默认值{
名称:“测试”,
//计算属性
计算值:{
计数(){
归还这个。$ store . state . num;
}
}
}
/脚本
效果:
3、Getter
有时候我们需要从存储中的状态派生出一些状态,比如根据num的值返回基数或者偶数。如果有多个组件需要使用这个状态,那么我们需要在每个组件中定义一个重复的函数,或者定义为一个常用函数,然后在多个组件中导入。两种方式都不理想。这时候就需要用getter了。官网解释如下:
Vuex允许我们在商店中定义“getter”(可以认为是商店的计算属性)。就像计算属性一样,getter的返回值会根据其依赖关系进行缓存,只有当其依赖关系值发生变化时才会重新计算。类似地,Getter接受状态作为第一个参数。请看下面的例子:
修改index.js文件,如下所示:
//介绍Vue
从“vue”导入Vue
//介绍Vuex
从“vuex”导入Vuex
//添加全局引用
vue . use(Vuex);
//创建状态
常量状态={
//定义num属性并将初始值设置为1
数字:1
}
//通过提交更改状态
var突变={
//状态作为第一个参数
ChangeState(状态){
//自动递增1
state.num
},
//state作为第一个参数,para作为第二个参数
ChangeStateWithPara(state,para){
//自动递增1
state.num=para
}
}
//Getter,相当于存储中的计算属性。
var getters={
IsOddOrEven(州){
返回state.num % 2==0?偶数:奇数
}
}
//创建一个存储对象
const store=new Vuex。商店({
//添加状态
状态,
//导出突变
突变,
//导出getter
吸气剂
})
//导出创建的存储对象
导出默认存储;
那么如何访问getters呢?您可以通过以下方式访问它:
3.1、通过属性进行访问
将test.vue修改如下:
模板
差异
p初始值:{{this。$store.state.num}}/p
p通过计算属性获取初始值:{{count}}/p
button @ click= $ store . commit( changestate )更改属性值/button
button @ click= $ store . commit( changestatewithpara ,5)传递参数以更改属性值/button
!-通过属性访问getters
p通过属性访问getters:{ { $ store . getters . isolated } }/p
/div
/模板
脚本
导出默认值{
名称:“测试”,
//计算属性
计算值:{
计数(){
归还这个。$ store . state . num;
}
}
}
/脚本
效果:
3.2、通过辅助函数进行访问
vuex中提供了MapGetters辅助函数,该函数只将存储中的getter映射到本地计算属性:
修改text.vue,如下所示:
模板
差异
p初始值:{{this。$store.state.num}}/p
p通过计算属性获取初始值:{{count}}/p
button @ click= $ store . commit( changestate )更改属性值/button
button @ click= $ store . commit( changestatewithpara ,5)传递参数以更改属性值/button
!-通过属性访问getters
p通过属性访问getters:{ { $ store . getters . isolated } }/p
!-通过辅助功能访问getters -
p通过辅助函数访问getter:{ { ISODDOREVEN } }/p
/div
/模板
脚本
//导入辅助功能
从“vuex”导入{mapGetters}
导出默认值{
名称:“测试”,
//计算属性
计算值:{
计数(){
归还这个。$ store . state . num;
},
//使用对象扩展运算符将getters混合到计算对象中。数组内部是getters中定义的方法名。如果有一个以上
//在数组中添加多个。
.mapGetters([IsOddOrEven])
}
}
/脚本
效果:
可以看出,通过属性访问和辅助功能访问达到的效果是一样的。
4、Action
Vuex官方网站对行动的解释如下:
动作类似于突变,但它们之间的区别是:
行动提交的是突变,而不是直接变更状态。也就是说行动是用来管理变化的,执行顺序是先执行行动,然后通过行动来触发突变,最后在通过变化来变更状态100 .行动中可以包含异步操作,突变中只能包含同步操作。看下面的例子:
修改索引。射流研究…如下:
//引入某视频剪辑软件
从“vue”导入某视频剪辑软件
//引入状态管理
从" vuex "导入状态管理
//添加全局引用
vue。使用(Vuex);
//创建状态
常量状态={
//定义数字属性并赋初始值为一
数字:1
}
//改变状态,通过犯罪
定义变量突变={
//状态作为第一个参数
变更状态(状态){
//自增一
状态编号
},
//状态作为第一个参数,第10段作为第二个参数
ChangeStateWithPara(state,para){
//自增一
state.num=para
}
}
//Getter,相当于商店里面的计算属性
var getters={
IsOddOrEven(州){
返回state.num % 2==0?偶数:奇数
}
}
//用来管理突变
定义变量操作={
ExecChangeState({commit}){
//执行突变里面定义的变更状态方法
提交(“ChangeState”);
}
}
//创建商店对象
const store=new Vuex .商店({
//添加状态
状态,
//导出突变
突变,
//导出吸气剂
吸气剂,
//导出行动
行动
})
//导出创建的商店对象
导出默认存储;
4.1、通过dispatch触发
修改测试。某视频剪辑软件如下:
模板
差异
p初始值:{ {这个. store.state.num}}/p
p通过计算属性获取初始值:{{count}}/p
button @ click= $ store。提交( ChangeState )改变属性值/按钮
button @ click= $ store。commit( ChangeStateWithPara ,5)传递参数改变属性值/按钮
!-通过属性访问吸气器-
p通过属性访问getters:{ { $ store。吸气剂。iso ddoreven } }/p
!-通过辅助函数访问吸气器-
p通过辅助函数访问getter:{ { IsOddOrEven } }/p
!-演示行动
差异
p属性值:{{count}}/p
按钮@click=添加通过行为改变属性值/按钮
/div
/div
/模板
脚本
//导入辅助函数
从" vuex "导入{mapGetters}
导出默认值{
名称:"测试",
//计算属性
计算值:{
计数(){
归还这个100美元商店。状态。num
},
//使用对象展开运算符将吸气剂混入计算对象中,数组里面是在吸气剂里面定义的方法名称,如果有多个
//则在数组里面添加多个即可
.mapGetters([IsOddOrEven])
},
方法:{
add(){
//通过派遣触发行动里面的ExecChangeState
这个100美元商店。分派( ExecChangeState );
}
}
}
/脚本
效果:
下面看一下执行顺序:
分别在add()、ExecChangeState()、ChangeState()里面添加一句console.log()来查看执行顺序:
索引。射流研究…修改如下:
//引入某视频剪辑软件
从“vue”导入某视频剪辑软件
//引入状态管理
从" vuex "导入状态管理
//添加全局引用
vue。使用(Vuex);
//创建状态
常量状态={
//定义数字属性并赋初始值为一
数字:1
}
//改变状态,通过犯罪
定义变量突变={
//状态作为第一个参数
变更状态(状态){
console.log("突变");
//自增一
状态编号
},
//状态作为第一个参数,第10段作为第二个参数
ChangeStateWithPara(state,para){
//自增一
state.num=para
}
}
//Getter,相当于商店里面的计算属性
var getters={
IsOddOrEven(州){
返回state.num % 2==0?偶数:奇数
}
}
//用来管理突变
定义变量操作={
ExecChangeState({commit}){
//执行突变里面定义的变更状态方法
console.log("操作");
提交(“ChangeState”);
}
}
//创建商店对象
const store=new Vuex .商店({
//添加状态
状态,
//导出突变
突变,
//导出吸气剂
吸气剂,
//导出行动
行动
})
//导出创建的商店对象
导出默认存储;
Test.vue修改如下:
模板
差异
p初始值:{{this。$store.state.num}}/p
p通过计算属性获取初始值:{{count}}/p
button @ click= $ store . commit( changestate )更改属性值/button
button @ click= $ store . commit( changestatewithpara ,5)传递参数以更改属性值/button
!-通过属性访问getters
p通过属性访问getters:{ { $ store . getters . isolated } }/p
!-通过辅助功能访问getters -
p通过辅助函数访问getter:{ { ISODDOREVEN } }/p
!-示范动作-
差异
p属性值:{{count}}/p
Button @click=add 通过操作/button更改属性值
/div
/div
/模板
脚本
//导入辅助功能
从“vuex”导入{mapGetters}
导出默认值{
名称:“测试”,
//计算属性
计算值:{
计数(){
归还这个。$ store . state . num;
},
//使用对象扩展运算符将getters混合到计算对象中。数组内部是getters中定义的方法名。如果有一个以上
//在数组中添加多个。
.mapGetters([IsOddOrEven])
},
方法:{
add(){
//通过调度在操作中触发ExecChangeState
console . log( Trigger add());
这个。$ store . dispatch( ExecChangeState );
}
}
}
/脚本
效果:
从上图可以看出,执行顺序是:先执行组件中的方法,再执行动作,最后执行突变,最后通过突变更新状态。
4.2、通过辅助函数触发
除了使用dispatch()触发操作之外,还可以使用辅助函数mapActions,它将组件中的方法映射到store.dispatch Modify test.vue,如下所示:
模板
差异
p初始值:{{this。$store.state.num}}/p
p通过计算属性获取初始值:{{count}}/p
button @ click= $ store . commit( changestate )更改属性值/button
button @ click= $ store . commit( changestatewithpara ,5)传递参数以更改属性值/button
!-通过属性访问getters
p通过属性访问getters:{ { $ store . getters . isolated } }/p
!-通过辅助功能访问getters -
p通过辅助函数访问getter:{ { ISODDOREVEN } }/p
!-示范动作-
差异
p属性值:{{count}}/p
Button @click=add 通过操作/button更改属性值
/div
!-触发动作-通过辅助功能-
差异
p属性值:{{count}}/p
Button @click=ExecChangeState 通过辅助函数/按钮更改属性值
/div
/div
/模板
脚本
//导入辅助功能
从“vuex”导入{mapGetters,mapActions}
导出默认值{
名称:“测试”,
//计算属性
计算值:{
计数(){
归还这个。$ store . state . num;
},
//使用对象扩展运算符将getters混合到计算对象中。数组内部是getters中定义的方法名。如果有一个以上
//在数组中添加多个。
.mapGetters([IsOddOrEven])
},
方法:{
add(){
//通过调度在操作中触发ExecChangeState
console . log( Trigger add());
这个。$ store . dispatch( ExecChangeState );
},
//辅助函数mapActions辅助函数将组件中的方法映射到store.dispatch
//这意味着映射 This。“ExecChangeState”到“this . store . dispatch( ExecChangeState )”
.mapActions([ExecChangeState])
}
}
/脚本
效果:
此时,有人可能会问:用动作管理突变比直接使用突变更复杂。你为什么要这么做?其实并不是这样的。突变只能执行同步方法,动作不受此限制。我们可以在动作内部执行异步方法。请参见以下示例:
使用以下代码修改index.js并添加一个异步方法:
//介绍Vue
从“vue”导入Vue
//介绍Vuex
从“vuex”导入Vuex
//添加全局引用
vue . use(Vuex);
//创建状态
常量状态={
//定义num属性并将初始值设置为1
数字:1
}
//通过提交更改状态
var突变={
//状态作为第一个参数
ChangeState(状态){
console.log(“突变”);
//自动递增1
state.num
},
//state作为第一个参数,para作为第二个参数
ChangeStateWithPara(state,para){
//自动递增1
state.num=para
}
}
//Getter,相当于存储中的计算属性。
var getters={
IsOddOrEven(州){
返回state.num % 2==0?偶数:奇数
}
}
//用于管理突变
var操作={
ExecChangeState({commit}){
//执行在突变中定义的ChangeState方法。
console.log(“操作”);
提交(“ChangeState”);
},
//执行异步方法:在更改属性值之前,单击按钮5秒钟。
execchangestatasync({ commit }){
setTimeout(()={
提交(“ChangeState”)
}, 5000);
}
}
//创建一个存储对象
const store=new Vuex。商店({
//添加状态
状态,
//导出突变
突变,
//导出getter
吸气剂,
//导出操作
行动
})
//导出创建的存储对象
导出默认存储;
修改test.vue文件:
模板
差异
p初始值:{{this。$store.state.num}}/p
p通过计算属性获取初始值:{{count}}/p
button @ click= $ store . commit( changestate )更改属性值/button
button @ click= $ store . commit( changestatewithpara ,5)传递参数以更改属性值/button
!-通过属性访问getters
p通过属性访问getters:{ { $ store . getters . isolated } }/p
!-通过辅助功能访问getters -
p通过辅助函数访问getter:{ { ISODDOREVEN } }/p
!-示范动作-
差异
p属性值:{{count}}/p
Button @click=add 通过操作/button更改属性值
/div
!-触发动作-通过辅助功能-
差异
p属性值:{{count}}/p
Button @click=ExecChangeState 通过辅助函数/按钮更改属性值
/div
!-执行异步操作-
差异
p属性值:{{count}}/p
button @ click= ExecChangeStateAsync 通过异步方法更改属性值/button
/div
/div
/模板
脚本
//导入辅助功能
从“vuex”导入{mapGetters,mapActions}
导出默认值{
名称:“测试”,
//计算属性
计算值:{
计数(){
归还这个。$ store . state . num;
},
//使用对象扩展运算符将getters混合到计算对象中。数组内部是getters中定义的方法名。如果有一个以上
//在数组中添加多个。
.mapGetters([IsOddOrEven])
},
方法:{
add(){
//通过调度在操作中触发ExecChangeState
console . log( Trigger add());
这个。$ store . dispatch( ExecChangeState );
},
//辅助函数mapActions辅助函数将组件中的方法映射到store.dispatch
//这意味着映射 This。“ExecChangeState”到“this . store . dispatch( ExecChangeState )”
//这意味着映射 This。ExecChangeStateAsync to this。$ store . dispatch( ExecChangeStateasync )
.mapActions([ExecChangeState , ExecChangeStateAsync])
}
}
/脚本
效果:
5、Module
由于使用了单个状态树,应用程序的所有状态都将集中在一个相对较大的对象中。当应用程序变得非常复杂时,store对象可能会变得非常臃肿。为了解决上述问题,Vuex允许我们将商店分成模块。每个模块都有自己的状态、变异、动作和getter。
五、总结
通过以上的基本解释,我们知道了Vuex的一些基本用法。Vuex便于状态管理,但不代表Vue项目一定要用Vuex,没有Vuex也可以用。我们来总结一下Vuex中的核心概念和底层原理。
1、核心概念
州:州:这个。$store.state.xxx Getter: Getter:这个。$store.getters.xxx突变:这个。$ store.commit (xxx )通过赋值来更改状态。您只能调用同步方法action: this。$ store.dispatch (xxx )来赋值,但不能直接更改状态。最后,你必须承诺。模块:模块
2、底层原理
状态:提供响应数据;Getter: cache是利用Vue的computed属性实现的;突变:改变状态状态;动作:触发变异法;模块:Vue.set动态地将状态添加到响应数据中;关于Vuex的详细介绍和使用方法的文章到此为止。希望对大家的学习有帮助,也希望大家多多支持。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。