一:介绍
在vue项目开发中,很多模块复用性很高,于是我们会将这些模块封装成组件,以便于减少代码的重复率,同时提高代码的可维护性和阅读性。
那么在组件中如果需要一些数据该怎么办呢?这就涉及到了组件之间的传值,组件中传值一共有六种传值方法,分别是父传子,子传父,兄弟组件(平级传递),vuex存储公共数据,使用provide和inject监控祖孙之间传递,$parent和$chiildren传值。那么接下来让我们来看一下这六种传值方式该如何实现吧。
二:传值的六种方法
1.父传子
父传子是目前vue开发中较为常见的一种方式,通常有接口的情况下,为了提高项目的效率,我们会传递一个ID值过去,通过ID获取数据。父传子的主要方式是通过props进行传值,如图:
父页面
<template>
<div>
<son-component :id='id'></son-component>
</div>
</template><script>
import sonComponent from './components/sonComponent.vue'
export default {
components:{
sonComponent
},
data() {
return {
id: 1
}
}
}
</script>
子组件
<template>
<div>
子组件的值:{{id}}
</div>
</template><script>
export default{
props:['id']
}
</script>
2.子传父
在vue开发中,子传父的使用频率不低于父传子。通常是在子组件中处理一些数据(比如子组件是个表单),在用户操作完成后需要保存这些数据,通常为了方便我们是不会在子组件中进行调用保存接口的,这样容易写出死组件,即失去了应有的模块化,所以我们通过this.$emit()进行传值到父页面中,在父页面进行保存。如图所示:
父页面代码
<template>
<div>
<son-component :id='id' @success='successMethod'></son-component>
</div>
</template><script>
import sonComponent from './components/sonComponent.vue'
export default {
components:{
sonComponent
},
data() {
return {
id: 1
}
},
methods:{
//子组件成功的回调函数
successMethod(val){
console.log(val)
}
}
}
</script>
子组件代码
<template>
<div>
子组件的值:{{id}}
<ul>
<li>
我的id是:{{dataItem.id}}
</li>
<li>
我的名字是:{{dataItem.name}}
</li>
<li>
我的年龄是:{{dataItem.age}}
</li>
</ul>
<el-button @click="onHandleUpdata">修改</el-button>
</div>
</template><script>
export default {
props: ['id'],
data() {
return {
//模拟数据库里的数据
dataList: [{
id:0,
name: '张三',
age: 18
}, {
id:1,
name: '李四',
age: 21
}, {
id:2,
name: '王五',
age: 16
}],
dataItem:{}
}
},
created() {
this.getData()
},
methods:{
getData(){
this.dataItem=this.dataList.find((val,index,arr)=>{
if(val.id==this.id) return val
})
console.log(this.dataItem)
},
onHandleUpdata(){
this.dataItem.age=25
//前面是父组件中调用的方法,后面是传的值
this.$emit('success',this.dataItem)
}
}
}
</script>
效果图:
上图是子组件获取到的原值,通过点击修改后年龄变为25并传给父页面如下图
3.兄弟组件(平级传递)
兄弟组件的传值和子传父组价类似,都是通过emit()进行传值。主要是通过暴露一个事件总线,两个兄弟组件同时引入该总线,传值方使用this.$emit(),接收值的一方使用this.$on()
比如事件总线(eventBus.js)代码如下
import Vue from 'vue';
export default new Vue;
兄弟组件的接收和发送数据代码如下:
<script>
import bus from '../../common/config/bus';
export default {
components: {},
data() {
return {
myList: [],
};
},
mounted() {
},
methods: {
getData(){
//接收别的组件传过来的数据
bus.$on('sendList', data => {
this.myList = data;
})
},
sendData() {
//发送数据
this.myList=[];
bus.$emit('sendList', this.myList);
},
},
}
</script>
4. vuex存储公共数据
每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:
-
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
-
你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
创建@/store/omdex.js目录,文件内容如下:
import Vue from 'vue'
import Vuex from 'vuex'
//1.安装插件
Vue.use(Vuex)
//2.创建对象
const store = new Vuex.Store({
state:{
count:0
},
mutations:{
addCount(state){
state.count++
},
subCount(state){
state.count--
}
},
actions:{
aAddCount(context,payload){
setTimeout(() => {
context.commit('addCount')
console.log(payload);
}, 500);
}
},
getters:{
},
modules:{
}
})
//3.导出使用
export default store
在main.js添加以下代码
import store from './store'
// 创建vm
new Vue({
// 指定容器
el: '#app',
// 解析App模板
render: h => h(App),
store
})
子组件一的代码
<template>
<div>
当前的值是:{{$store.state.count}}
<button @click="onSubClick">+1</button>
</div>
</template><script>
export default{
data(){
return{
}
},
methods:{
onSubClick(){
// this.$store.commit('addCount')
this.$store.dispatch('aAddCount')
}
}
}
</script><style>
</style>
子组件二的代码
<template>
<div>
当前的值是:{{$store.state.count}}
<button @click="onSubClick">-1</button>
</div>
</template><script>
export default{
methods:{
onSubClick(){
this.$store.commit('subCount')
},
}
}
</script><style>
</style>
父组件引入两个子组件
<template>
<div>
<div>vuex(状态管理)的使用如下:</div>
<AddCount></AddCount>
------------------------------
<SubCount></SubCount>
</div>
</template><script>
import AddCount from './components/AddCount.vue'
import SubCount from './components/SubCount.vue'
export default {
// 组测组件
components: {
AddCount,
SubCount
},
methods: {
},
};
</script>
运行效果,当点击任意一个按钮时,会改变vuex里的值,其余组件会自动同步
5.provide和inject注入
在父子组件传递数据时,通常使用的是 props 和 emit,父传子时,使用的是 props,如果是父组件传孙组件时,就需要先传给子组件,子组件再传给孙组件,如果多个子组件或多个孙组件使用时,就需要传很多次,会很麻烦。
像这种情况,可以使用 provide 和 inject 解决这种问题,不论组件嵌套多深,父组件都可以为所有子组件或孙组件提供数据,父组件使用 provide 提供数据,子组件或孙组件 inject 注入数据。同时兄弟组件之间传值更方便。
父组件
<script> export default { // 父组件通过provide将自己的数据以对象形式传出去 provide(){ return { msg:'一条信息' } } }; </script>
子孙组件
<script> export default { // inject:["msg"], // 使用一个注入的值作为数据入口 inject:{ //或者写成对象 // 使用一个默认值使其变成可选项 msg: { // 键名 from: 'msg', // 来源 default: '' // 默认值 } } } </script>
6.$parent和$chiildren传值
在开发中该方法使用频率没有那么高,因此在本文中不做详细解释,只做概括。
(1)父传子
this.
$children[index]
需要指定子组件的下标(第几个子组件)
this.$children[0].name = '张三';//将子组件的name值设置为'张三'
(2)子传父
this.$parent 不需要指定下标
this.$parent.name = "李四";//将父组件的name属性设置为'李四'
三:尾记
目前开发中,比较常见的传值方法是父传子,子传父,vuex存储,provide和inject监控(至少我在项目中很少使用到第三个和第六个)。当然传值的方法还有很多,比如缓存等,但这些容易导致浏览器缓存过多而加载慢,甚至导致浏览器未响应关闭等,同时会占用电脑大量内存,因此我在这里不做介绍与推荐。好啦,希望各位小伙伴通过本篇章能够学到一点东西,这就是对博主的最大支持啦~