Vuex随笔

news/2024/7/10 0:30:48 标签: vue, vue.js, javascript, 前端

Vuex

  1. 本质上使用Vuex的原因其实是组件之间的数据交互过于复杂,重点在于当组件过多时,数据的传递就会不可控,所以引入 Vuex 是一个专门为 Vue.js 应用程序开发的状态管理模式。它采用集中式管理应用的所有组件的状态,并以相应 的规则保证状态以一种可预测的方式发生变化。

  2. 回顾数据传递方式:props , 自定义事件$emit(.sync) , EventBus , $parent , $root,vuex 。
    组件较少的情况下传递数据可以使用EventBus ; 组件特别多,而且对数据要求可预测改变就应该使用Vuex。开发大型单页面应用时用Vuex,简单的SPA不要使用。

  3. 代码执行流程:

    1. 创建store
    2. 创建state
    3. 创建mutations
    4. 创建actions
    5. 创建modules
  4. 操作store

    1. 读取state
      快捷方案:computed --> state getter
    2. 设置state(修改)
      快捷方案:methods -->mutations actions
  5. 表单相关
    表单操作:
    1. 使用 v-model 解决方案:get 和 set
    2. 不使用 v-model 解决方案:通过事件

  6. 边缘化操作

    1. 项目结构
    2. 插件
    3. 严格模式 =》安全的操作方式
    4. 热重载:方便开发人员调试

Vuex核心知识点

Store(仓库):一个项目只能有一个store仓库
State(状态):数据
Mutation(计算方式):只能通过此方法修改state状态
Action(动作):异步操作的核心
Getter(读取数据的方案):可选项,读取的容错方式
Module(模块):分解state,避免state过多引起臃肿

Vuex执行流程:VueComponent —dispatch—> Actions —commit—> Mutations —mutate—> state —render—> VueComponent

安装并引入

javascript">npm install --save es6-promise(Vuex依赖于es-promise)
npm install --save vuex

import 'es6-promise/auto'
import Vuex from 'vuex'
Vue.use(Vuex)

Vuex和全局对象的区别

全局对象:Vue.prototype.$api = api ; //此时给两个页面分别通过
this.$api 都使用一次,然后改变其中一个页面的$api的值,另一个组件的值不会改变。
Vuex : this.$store.state.对象名.key 如果其中一个改变则另外一个响应的也改变。

创建仓库

javascript">创建一个store文件夹,创建index.js并配置
const store = new Vuex.Store({
	      state : {
	      		obj : {
					name : "apple",
					pic : 0
	      		}
	       }
	})
然后挂载到 new Vue({     //主入口文件main.js
		     render : h => h(App),
		     store
		}).$mount('#app')

显示 :产品:{{ this.$store.state.obj.name }}
	   价格:{{ this.$store.state.obj.pic }}

分离 store文件:src下创建一个 store,里边创建 index.js引入配置导出,main.js引入使用。

State快捷读取方法

mapState辅助函数:

javascript">import { mapState } from 'vuex'
	写法1 :computed : mapState({
		     msg : state => state.obj
		})
	写法2:computed : {
		     ...mapState(["obj","...",,,]) //必须是字符串
		}

Mutation

更改 Vuex 中的 store 中的状态的唯一方法是提交 mutation。

javascript">在 index.js 中配置, 和 state 同级配置:
	mutations:{
	          increment(state){    //参数state指的就是同级的state
    	             state.obj.pic++
    	          },
        	       decrement(state){   
            		state.obj.pic --
        	        }
javascript">在组件中配置:
	<button @click="addHandle">增加</button>
    <button @click="minHandle">减少</button>
	addHandle(){
            	this.$store.commit("increment") 
       	 },
    minHandle(){
            	this.$store.commit("decrement")
       	 }

提交载荷(Payload)

javascript">在index.js中配置, 和 state 同级配置:
	mutations:{
	       //     increment(state,n){   //写法1
    	       //         state.obj.pic+=n
    	       //     },
        	       increment(state,payload){   //写法2
            		state.obj.pic += payload.num
        	       },
        	       decrement(state,{ num }){   //写法3:es6解构赋值
            		state.obj.pic -= num
      }

javascript">在组件中配置:
	<button @click="addHandle">增加</button>
        	<button @click="minHandle">减少</button>
        	<input placeholder="请输入" type="text" v-model="num">

	methods:{
        	       addHandle(){
         		// this.$store.commit("increment",parseInt(this.num))  //写法1
            		this.$store.commit("increment",{    //写法2
                		num : parseInt(this.num)
            		})
		this.$store.commit({   //写法3
                		type:"increment",
                		num : parseInt(this.num)
            		})
        	        },
        	        minHandle(){
            		// this.$store.commit("decrement",parseInt(this.num))
            		this.$store.commit("decrement",{
                		num : parseInt(this.num)
            		})
        	         }
    	}

Mutation遵循Vue的响应规则

就和数组,对象的更新检测一个意思
例如:需求要给state仓库添加一个值,同时页面也要显示

javascript">在vuex.js中配置, 和 state 同级配置:
	mutatios : {
	        xiangying(state,payload){
            		// state.obj.aa = payload.msg;//仓库加进去了但是页面不显示,和数组对象更新检测同理
            		Vue.set(state.obj,"aa",payload.msg);//成功
        	         }
	  }
javascript">在组件中配置:
	aa:{{ this.$store.state.obj.aa }}
	data(){ return{ msg : "我是新添加的产品" }}
	methods:{
	         tianjia(){
            		this.$store.commit("xiangying",{
                	            msg : this.msg
            	                })
        	          }
	  }
  1. 以新对象替换老对象
    利用对象展开运算符我们可以这样写:
    state.obj = { …state.obj, newProp: 123 }

  2. 使用常量替代 Mutation 事件类型
    vuex文件夹下创建一个 mutation-type.js 文件,导出
    export const INCREMENT = “INCREMENT”;
    export const DECREMENT = “DECRMENT”;
    随后在vue.js和组件使用vuex的地方,引入并把字符串“increment”"decrement"替换掉
    import { INCREMENT,DECREMENT } from ‘./mutation-type’

Mutation必须是同步函数(重点)

待补充。。。

在组件中提交Mutation(快捷方案)

javascript">import { mapMutations } from 'vuex'

        methods:{
        ...mapMutations([INCREMENT,DECREMENT,"xiangying"]),//...是es6高级语法,这里的这个包 core-js 经常丢包,重装一下就行。
        addHandle(){
            
            // this.$store.commit({   //写法3
            //     type:INCREMENT,
            //     num : parseInt(this.num)
            // })

            this[INCREMENT]({ num : parseInt(this.num) })  //写法4
        },
        minHandle(){

            // this.$store.commit(DECREMENT,{
            //     num : parseInt(this.num)
            // })

            this[DECREMENT]({ num : parseInt(this.num) })
        },
        tianjia(){

            // this.$store.commit("xiangying",{
            //     msg : this.msg
            // })

            this.xiangying({ msg:this.msg })
        }
    }

Action

Action 类似于 mutation,不同在于:Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作,有异步操作时action才有意义。

javascript">index.js中配置
	const store = new Vuex.Store({
	         state : {
		banner : { }   //定义一个存储仓库
	         },
	         mutations : {
		setBanner(state,payload){
          		          //异步请求数据
          		          state.banner = payload.banner; //把参数的值赋值到仓库
        		}
	         },
	         actions : { 
		asyncBanner(context,url){      //定义一个异步请求方法,参数context固定,url地址
        		        axios.get(url).then(res=>{
          			context.commit("setBanner",res.data);//通过context.commit提交一个mutation
        		         })
      		}
	         }
	})
javascript">组件中配置:
	<button @click="asyncAction">action提交异步请求</button>
        	<ul>
            	        <li v-for="(item,index) in banner" :key="index">{{item.title}}</li>
        	</ul>
	import { mapState } from 'vuex'
	 computed:mapState({
        	         banner : state => state.banner   //将仓库中的banner存放到变量banner中
	         //...mapState([ "banner" ])   //写法2
    	}),
    	methods:{
        	         asyncAction(){   //定义一个方法
            		this.$store.dispatch("asyncBanner","http://iwenwiki.com/api/blueberrypai/getIndexBanner.php");  //通过dispatch分发action
        	         }
    	}

在组件中分发action

javascript"> 组件中配置:
	import { mapState,mapActions } from 'vuex'   
	 methods:{
        	         ...mapActions(["asyncBanner"]), //写法2
        	         asyncAction(){
            		// this.$store.dispatch("asyncBanner","http://iwenwiki.com/api/blueberrypai/getIndexBanner.php");//写法1
            		this.asyncBanner("http://iwenwiki.com/api/blueberrypai/getIndexBanner.php"); //写法2
        	         }
    	}

Getter

对store中的state的状态的验证修改

  1. 需求:假设产品价格最高不超过100,最低不低于1
javascript">index.js配置:
	const store = new Vuex.Store({
	          getters:{
      		getPic(state){
        		      if(state.obj.pic > 100 || state.obj.pic <= 0){
          			return "价格出错了"
        		         }else{
          			return state.obj.pic;
        		         }
     		 }
   	          }
  	})

在组件中读取 :{{ this.$store.getters.getPic }}
  1. 通过属性访问
javascript">index.js配置:
	const store = new Vuex.Store({
	     getters:{
	          getPic(state,getter){
        		console.log(getter);
        		if(state.obj.pic > 100 || state.obj.pic <= 0){
          			// return "价格出错了";    //方法1
          			return getter.getHello;    //方法2
        		}else{
          			return state.obj.pic;
        		}
      	           },
      	          getHello(){
        		return "价格出错了";
      	          }
	      }
  	})
  1. 通过方法访问
  2. mapGetters 辅助函数
javascript">组件读取:
	import { mapGetters  } from 'vuex'
	computed : mapState({
        	         ...mapGetters(["getPic"])
    	})
    	
	<div> 价格:{{ getPic }} </div>

项目结构

├── index.html
├── main.js
├── api
│ └── … # 抽取出API请求
├── components
│ ├── App.vue
│ └── …
└── store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── cart.js # 购物车模块
└── products.js # 产品模块

Module

Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。

javascript">// 创建Store仓库
const store = new Vuex.Store({
    state : defaultStore,
    mutations : defaultMutations,
    actions : defaultActions,
    getters : defaultGetters,
    modules:{
      //拥有完整的vuex结构
      moduleA : {
        namespaced : true,  //命名空间
        state : {
          msg : "我是moduleA的"
        },
        mutations : {

        },
        actions : {

        },
        getters : {

        }
      },
      moduleB : {
        namespaced:true,
        state : {
          msg : "我是moduleB的"
        },
       .....
      },
      // moduleC....
    }
  })
javascript"> 读取moduleA 和 moduleB 的值:
	方式1直接读取 : {{ this.$store.state.moduleA.msg }}
	读取方式2{{ msg }}--{{str}}
	import { mapState } from 'vuex'
	computed:{  //计算属性
        	        ...mapState("moduleA",{   //这种读取方式必需设置命名空间 namespaced:true 才能读到
            		msg : state => state.msg
        	          }),
        	        ...mapState("moduleB",{
            		str : state => state.msg
       	          })
    	  }

Vuex动态模块

可以使用 store.registerModule 动态创建,使用 store.unregisterModule(模块名) 来动态卸载模块,使用 store.hasModule(moduleName) 方法检查该模块是否已经被注册到 store。

插件

Vuex 的 store 接受 plugins 选项,这个选项暴露出每次 mutation 的钩子。Vuex 插件就是一个函数,它接收 store 作为唯一参数:

javascript">在index.js中配置:
	const myPlugin = store =>{
  	        //当store初始化后调用
  	         store.subscribe((mutation,state)=>{
    		console.log( mutation , state);
 	          })
	}
	
	// 在Store仓库引用
	const store = new Vuex.Store({
	         plugins : [myPlugin , ......],
	})

严格模式

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。然而在mounted生命周期函数中和标签中直接用 = 赋值,都可以改变它的值。为了解决这个问题,严格模式由此而生,仅需在创建 store 的时候传入 strict : true ,在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。

javascript">const store = new Vuex.Store({
  	          strict : true
		// ...
	})

【注意】:不要在发布环境下启用严格模式!请确保在发布环境下关闭严格模式,以避免性能损失。类似于插件,我们可以让构建工具来处理这种情况 strict : process.env.NODE_ENV !== 'production’

javascript">const store = new Vuex.Store({
  		// ...
  		//直接写这种就行,自动识别
  		strict : process.env.NODE_ENV !== 'production'  
	})

表单处理

建议使用v-model模式

Vuex热重载

方便开发阶段调试

  1. 热更新:浏览器自动刷新 webpack(我们在开发阶段在浏览器控制台添加调试的都会重置)

  2. 热重载:浏览器不刷新,但是数据要更新(不会重置)


http://www.niftyadmin.cn/n/1813814.html

相关文章

苹果推送APNS总结 (

开发状态服务器地址 gateway.sandbox.push.apple.com 2195产品状态服务器地址 gateway.push.apple.com 2195Development和Production两个版本对应的apns device token是不同的&#xff0c;前者是develop的mobileprovision下获取的。后者是production的mobileprovision获…

互联网广告的效果真实性

互联网广告投放的话呢&#xff0c;最常见的目的应该有两个 —— 品牌、效果&#xff08;真实的销售额、注册等等&#xff09;。* 我们姑且这么狭隘的定义其目标。*对于前者 - 品牌&#xff0c;曝光量的高低、广告媒介有效接触的时长与频率是优质有效与否的关键。由于这种Campai…

当Hashtable和HashMap添加自身时

今天在看Hashtable的toString()源码时&#xff0c;看到了其中有一个"key this"的判断&#xff0c;于是突发奇想&#xff0c;如果用Hashtable添加自身再做一些别的操作会怎样&#xff1f; ①&#xff0c;hashCode方法 先看代码&#xff1a; 1 public static void…

Babel随笔

Babel是一个es6转码器 项目安装 npm install -D babel/core 安装命令行工具babel/cli npm install -D babel/cli在项目根目录下创建一个.babelrc配置文件&#xff0c;配置文件&#xff1a;{"presets" : ["babel/env"],"plugins" : []}pres…

判断某个函数是否为回文数【转】

回文就是从前后读都是一样的。可以用判断入栈和出栈是否相同来实现&#xff08;比较复杂&#xff09;&#xff0c;这里利用整数逆序成另一个整数&#xff0c;通过判断两个整数是否相等来实现。 #include<stdafx.h> int IsEchoNum(int num) { int tmp0; for(nnum;n!0;n/10…

iphone开发学习,Block

基本使用&#xff1a; void (^vFun)()^(void){NSLog("void function");};vFun();//void function  //void:返回类型  //(^vFun):vFun代表函数名  //(xx):传入参数的类型,为空代表木有参数  //^(xxx):block格式&#xff0c;xxx代表传入参数 int (^iFun)(in…

HDU-4619 Warm up 2 二分匹配

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid4619 一看就知道是二分匹配题目&#xff0c;对每个点拆点建立二分图&#xff0c;最后答案除2。因为这里是稀疏图&#xff0c;用邻接表处理。。。 1 //STATUS:C_AC_31MS_480KB2 #include <functional>3 #…

js学习整理

学习最好的检验方法是测试&#xff0c;就是coding! 当然&#xff0c;理论知识不能差&#xff0c;不然没发展。 javascript呢&#xff0c;功能很强大&#xff0c;依靠浏览器本地处理优化&#xff0c;对浏览器的依赖性也比较大。 javascript 的真实名称是ECMAScript,对于js有什么…