前提,这是一篇笔记,
在使用vue脚手架构建项目后,第一个想到的就是它了——vuex,用来处理非常恶心的组件传值功能,新建的项目还不算是很大,但是一层又一层的组件关系犹如一团乱麻,在vm/vc上不停得找节点也无济于事,后来干脆用vuex来代理。但是不怎么使用的技能又在使用中出了一些问题,所以,写一篇博客来记录相关问题和方法:
这里忽略一些基础配置(路由啊,vuex等的下载问题,一般来说较于vue2版本,只要不装太高版本的插件基本都能用,具体步骤推荐去官网看文档直接复制)
首先就是传值问题:
1. 父子间传值(父组件与子组件)
父传子:使用props:
//子组件内容
<template>
<div id="app">
<div>姓名:{{ name }}</div>
<div>年龄:{{ age }}</div>
</div>
</template>
<script>
export default {
props: ["name", "age"],
};
</script>
<template>
<son1 :name="newname" :age="newage" @son1data="getdata"></son1>
</template>
<script>
export default {
data(){
return {
newname:'李雷',
newage:15
}
}
}
</script>
原理就是通过props设置,绑定父级组件上的两个属性作为子组件的属性进行使用,但是尝试修改后会报错,因此需要使用中间键过渡一下
//子组件
data(){
return {
myname:this.name
}
}
子传父:
//子组件
<template>
<div id="app">
<div>姓名:{{ name }}</div>
<div>年龄:{{ age }}</div>
<div>姓名1:{{ myname }}</div>
<div>年龄1:{{ myage }}</div>
<button @click="son1emit">点击发送数据</button>
</div>
</template>
export default {
data() {
return {
myname: "李四",
myage: 23,
};
},
props: ["name", "age"],
methods: {
son1emit() {
this.$emit("son1data", { name: this.myname, age: this.myage });
},
},
};
</script>
//父组件
//模板
<son1 :name="newname" :age="newage" @son1data="getdata"></son1>
//方法
methods: {
getdata(val) {
this.son1_name = val.name;
this.son1_age = val.age;
}
},
//属性
data() {
return {
newname: "张三",
newage: 22,
son1_name: "",
son1_age: "",
};
},
该方法原理是通过子组件的$emit,将第二个参数的值传出去,再由父组件的$on事件进行监听,从而获取相关数据。
另外可用的方法还有vc身上的$children,$parent属性,一直点就好了。
祖传孙(中间层断开):
//provide选项可以定义数据给其他后代组件使用
provide() {
return {
address: this.address,
};
},
data() {
return {
address: "南京雨花台",
};
},
上面是祖组件的导出内容,下面是孙组件的内容:
<template>
<div>
<p>地址:{{ myaddress }}</p>
</div>
</template>
<script>
export default {
data() {
return {
myaddress: this.address,
};
},
//通过注入的方式拿到主组件的数据
inject: ["address"],
};
</script>
兄弟组件之间的传值:
//在main.js中往vue的原型上添加一条自定义属性
Vue.prototype.$bus = new Vue()
<template>
<div class="son3">
车名:{{ carname }} -- 车价:{{ carprice }} --
<button @click="pemit">点击发送数据</button>
</div>
</template>
<script>
export default {
data() {
return {
carname: "保时捷",
carprice: "80W",
};
},
methods: {
pemit() {
this.$bus.$emit("cardata", {
carname: this.carname,
carprice: this.carprice,
});
},
},
};
</script>
//同时在两个兄弟组件中调用这个原型属性,一个传值,一个接收值
<template>
<div class="son4">carname: {{ carname4 }} -- carprice:{{ carprice4 }}</div>
</template>
<script>
export default {
data() {
return {
carname4: "",
carprice4: "",
};
},
mounted() {
//这里用方法时this指向会发生改变,尝试修改this指向
let that = this;
this.$bus.$on("cardata", function (e) {
that.carname4 = e.carname;
that.carprice4 = e.carprice;
});
},
};
</script>
因为组件一旦切换,this就会发生变化,所以为了this的指向同一,所以在原型上做做手脚,同理可以将axios设置在原型上,就不用一直引入调用了。
vuex:
首先,如上,具体安装导入推荐去官网看API,里面有详细的内容可以复制,vue2就别装vuex3以上的版本了,防止报错。
基本的5个钩子:
state:状态,通俗的讲就是数据的掌管,你可以放所有你想要在全局使用的数据,后面直接调用即可,调用方法:$store.state.value.key,后面value.key就是存在state里的数据内容,
getters:相当于计算属性computed钩子:里面用于存放计算相关的数据使用,方法类似计算属性,通过形参state拿到全局状态state并计算返回
mutations:定义操作状态的方法,用于接收commit传来的方法名和值的并单纯地进行赋值操作,比如:
//子组件
methods:{
send(){
this.$store.commit('changename','王二蛋')
}
}
//vuex里面的store里面的index.js
mutations:{
changename(state,val){
state.name = val
}
官方推荐mutations里面最好只做一些简单的赋值操作,不要有太多计算相关的内容,所以这里按照官方来,
actions: 就是一系列动作,刚刚上文描述的关于解决传值后要经过计算,值才能被使用的问题,在组件中由组件发出dispatch请求后,actions里设置监听事件,在actions里对数据进行处理(计算啊,异步请求啊啥的),然后再由actions发出commit,由mutations监听,这就是官方推荐的一系列流程,就像:
//组件
methods:{
send(){
this.$store.dispatch("updataname", "lisa");
}
}
//actions
updataname(context,val){
setTimeOut(()=>{
context.commit('updatatname', val)
},1000)
}
//mutations
updataname(state, val) {
state.name = val
},
//最后这个val就是我们传过来的lisa了!
,最后还有个modules:是用来管理分支模块的,一个主模块下可能会有几十上百条state甚至更多,用起来极不方便,为此,可以单独的将某些用法功能相似的内容打包作为index.js的模块分离出去,使用方法大致相同:分离出去的模块结构一致,也有state getters mutations actions modules这5块,内容用法和index.js大致相同:
避坑点:
分离出去的模块在使用的时候,其state下的内容会被打包成一个以模块名为名的对象,因此在调用该模块下的state数据时需按名使用:
//比如现在store下有一个主代理index.js和一个代理模块hotel.js
//第一步,在index.js里导入hotel,js
export default{
import hotel from './hotel.js';
//...
modules:{
hotel,
}
//第二步,在hotel.js模块里写入一份数据
...
state:{
name:'张三'
...
}
//第三步,在组件中使用这份数据
<div>
{{$store.state.hotel.name}}
</div>
其次就是,模块代理后会将所有模块(包括主代理和各个模块代理)的commit和dispatch事件都会合并在一起,因此,在为这些事件起名的时候最好不要起重复的名,当整个项目中有重名事件后,将会抛出错误,因此,起名需谨慎(可以尝试死亡数组递增命名,事件a,事件b,事件c...),另外一个就是在监听这些事件时,需要在事件名前加上组件名/,
比如我有个组件代理叫hotel(迷hotel),那么我在commit或dispatch的时候第一个参数就是
“ hotel/updataname ",依次类推。
好了,总结一下,
组件间传值:
父传子:props,
子传父:$emit ,
祖传孙:provide==>inject,
孙传祖:$parent,或者provide里传递一个方法(function),直接传递,
兄弟间互传:设置中间键或给Vue原型上加公共属性,
什么是VUEX
Vuex的相关钩子,
Vuex的模块化代理,
一些Vuex模块化代理的误区