一、相邻组件传值(父子之间)
这是组件之间传值中最基础也是最直接的传值关系
1.第一种方法是父组件通过props的方式向子组件传递数据,子组件通过**$emit的方式向父组件进行传递,在父组件用v-on**方法接收
例如下面这个例子:
首先是父组件:
<template>
<div>这是父组件的div
<son v-bind:something="something">这是子组件的自定义组件</son> // 绑定前者是自定义名称便于子组件调用,后者要传递数据名
</div>
</template>
<script>
import Son from "./son.vue" //这里首先引入子组件
export default {
name: Father,
data() {
return {
something: "good", //这是要传给子组件的数据
}
},
components: {
"son": Son, //这里是在引入子组件后相当于实例化的操作
}
}
</script>
<style>
</style>
然后是子组件:
<template>
<div>
这是子组件的div
</div>
</template>
<script>
export default {
name: Son,
// 这里首先要写好props
props: {
// props里面就是需要使用的父组件的数据,字段名要和父组件定义的保持一致
something: {
type: String,
required: true,
}
},
data() {
}
}
</script>
<style>
</style>
上面是父组件向子组件进行传值,接下来就是子组件向父组件传值,相对操作会更多一些
这次首先看子组件:
<template>
<div>
这是子组件的div
<button @click="transfData">点击我触发发送数据</button>
</div>
</template>
<script>
export default {
name: Son,
// 这里首先要写好props
props: {
// props里面就是需要使用的父组件的数据,字段名要和父组件定义的保持一致
something: {
type: String,
required: true,
},
},
data() {
return {
otherthing: "nice", //这个是需要传给父组件的数据
};
},
methods: {
transfData() {
this.$emit("trans", this.otherthing);
},
},
};
</script>
<style>
</style>
然后看父组件:
<template>
<div>这是父组件的div
<son
:trans="trans"
> // 采用v-on方式对子组件提交的数据进行绑定,这里的等号前的名字都要和子组件emit() 里面传的第一个值保持一致, 然后等号后是在methods进行处理的方法名
这是子组件的自定义组件</son>
</div>
</template>
<script>
import Son from "./son.vue" //这里首先引入子组件
export default {
name: Father,
data() {
return {
something: "good", //这是要传给子组件的数据
}
},
components: {
"son": Son, //这里是在引入子组件后相当于实例化的操作
},
methods: {
// 这里的方法名同样要和绑定的一致,参数val就是子组件emit() 里面传过来的第二个参数
trans(val) {
console.log(val);
}
}
}
</script>
<style>
</style>
2.第二种方法是采用ref:如果在普通的DOM元素上使用,引用指向的就是DOM元素;如果用在子组件上,引用就指向组件实例,使用后可以直接得到组件实例,使用后可以直接调用组件的方法或访问数据。
举个例子先看父组件:
<template>
<div>这是父组件的div
<son
ref="son"
></son>
</div>
</template>
<script>
import Son from "./son.vue" //这里首先引入子组件
export default {
name: Father,
mounted() {
let otherthing = this.$refs.son //这里用ref实例化一个对象
console.log(otherthing.say); //直接用实例化对象调用子组件的属性和方法
console.log(otherthing.transfData);
}
}
</script>
<style>
</style>
然后看子组件:
<template>
<div>
这是子组件的div
</div>
</template>
<script>
export default {
name: Son,
data() {
return {
say: "nice", //这个是需要传给父组件的数据
};
},
methods: {
transfData() {
console.log("数据传送成功");
},
},
};
</script>
<style>
</style>
这种方法只能在父子组件之间通信,无法跨组件进行通信
二、祖孙组件之间数据传递
1.使用\$attrs和$listeners方法可以进行祖孙组件相互传值
例如,先看祖组件:
<template>
<div>这是父组件的div
<son
:a="a"
:b="b"
></son>
</div>
</template>
<script>
import Son from "./son.vue" //这里首先引入子组件
export default {
name: Father,
data: {
a: 1,
b: 2,
},
components: {
"son": Son,
}
}
</script>
<style>
</style>
然后看子组件:
<template>
<div>
<div>{{$attrs}}</div>
</div>
</template>
<script>
export default {
mounted() {
console.log(this.$attrs); //{"a":1,"b":2}
}
}
</script>
<style>
</style>
我理解的是这是对于props的一种简捷写法,因为$attrs可以将父组件v-bind的所有属性打包成一个对象传给自己,不需要再单独写props进行接收和实例化
2.还有一种是使用ref写法,这种组件之间主要适用于祖先组件和子孙后代组件之间,不论组件层次有多深,在上下游关系成立的时间里始终生效,但是不适用于兄弟组件这种非直接关系的组件之间。
比如先看祖组件:
<template>
<div>
这是祖组件的div
<son
ref="son"
></son>
</div>
</template>
<script>
import Son from "./son.vue" //这里首先引入子组件
export default {
inject: ['something'],
mounted () {
console.log(this.something); // good
},
components: {
"son": Son
}
}
</script>
<style>
</style>
然后再看子组件:
<template>
<div>这是子孙组件的div
</div>
</template>
<script>
export default {
provide: {
something: 'good'
}
}
</script>
<style>
</style>
这种方法类似于父子组件之间通信用的props,在祖组件里面,我们设置一个provide属性,并且设置了一个值,目的就是将这个值传递给所有子孙组件,然后子孙组件通过inject注入祖组件提供的值,然后子孙组件用this.属性名就可以直接获取使用祖组件的值。
但是provide和inject传值并不是响应式的,除了所传递的是一个可监听对象以外,也就是说如果子孙组件接受并使用的祖组件的值,但是之后祖组件这个值发生变化之后子孙组件不会随之变化,如果要使用响应式的传递,最优方法是使用Vue.observable 优化响应式 provide,这个已经是有人在网上讲解过的了,因为我自己还没有用到这个高阶用法,这里就先不做讲述
三、跨组件或非直接关系组件传值
所以目前情况下,在这种需要响应式的跨组件传值以及非直接关系的组件之间传值,我一般使用vuex,接下来讲一下基本的vuex的使用方法以及步骤:
首先在项目目录下找到src\sotre目录:
目录里面的几个文件含义大概是:
state (类似存储全局变量的数据)
getters (提供用来获取state数据的方法)
actions (提供跟后台接口打交道的方法,并调用mutations提供的方法)
mutations (提供存储设置state数据的方法)
一般情况下,我们需要使用的是getters.js,mutations.js和state.js
首先要在state.js里面定义我们需要传递的字段:
export const state = {
something: '', // 定义所要进行传值的字段
}
紧接着去mutation.js里面进行设置字段属性值的方法:
export const mutations = {
setSomething(state, data) {
state.something = data
}
最后去getter.js里面设置获取字段属性值的方法:
export const something = (state) => {
return state.something
}
个人理解总结:
父子之间传值:$emit()方法或者ref绑定
祖孙之间传值:$attrs()方法更加便捷和实用
跨组件传值:vuex适用范围更广而且实用性更高