先简单说一下Vue中的组件,Vue中的组件为了能够在模板中使用,必须要先注册以便Vue能够识别到这个组件.组件注册分为两种类型:全局注册和局部注册.
有了组件,就会有或者涉及到组件之间的传值.总的来说,Vue组件之间的传值,主要分为3种类型或情况下的传值:
- 简单的父子组件之间的传值
- 同属于同一个父组件之间兄弟组件之间的传值
- 好不相关的组件之间的传值
简单的父子组件传值和同属于同一个父组件的兄弟组件之间的传值,Vue提供了方法可以直接进行传值,不需要Vuex.
简单父子组件之间的传值
为了看起来简单,文中的demo都写的非常简单,就是为了看起来简单,就是篇幅长了些.
父组件向子组件传值
父组件cmp.vue
<template>
<div class="parent">
{{msg}}
<ComponentChild :parentToChildData="parentData"></ComponentChild>
</div>
</template>
<script>
import ComponentChild from './cmpc'
export default {
name:"componentP",
components:{
ComponentChild
},
data() {
return {
msg:"Hello, ComponentP",
parentData:"我是来自父组件的数据"
}
}
}
</script>
子组件cmpc .vue
<template>
<div class="componentA">
<div>{{parentToChildData}}</div>
<div>{{msg}}</div>
</div>
</template>
<script>
export default {
name:"componentA",
data() {
return {
msg: "我是子组件的数据"
}
},
props:["parentToChildData"]
}
</script>
我们先看父组件文件cmp.vue.
父组件中引入并注册了子组件ComponentChild,并通过props的方式向子组件传递了一个值:parentToChildData.然后子组件通过props方式接收到了从父组件传递过来的值.页面数据的渲染效果如下:
子组件向父组件传值
父组件cmp.vue
<template>
<div class="parent">
<p>{{msg}}</p>
<p>{{data1}}</p>
<!--
@dataFromParent:父组件中定一的事件,可以简单的理解为就是和click、hover一样的事件,只不过不是内置的事件类型,而是一个自定义的事件名称;目的:在子组件中调用该方法,实现从子组件向父组件的值的传递
dataFromChildToParent:事件响应函数,会在当前的组件中有具体实现
-->
<ComponentChild :parentToChildData="parentData" @dataFromParent="dataFromChildToParent"></ComponentChild>
</div>
</template>
<script>
import ComponentChild from './cmpc'
export default {
name:"componentP",
components:{
ComponentChild
},
data() {
return {
msg:"Hello, ComponentP",
parentData:"我是来自父组件的数据",
data1:""
}
},
methods: {
dataFromChildToParent(data){ //从子组件传递过来的数据
this.data1 = data;
}
},
}
</script>
子组件cmpc.vue
<template>
<div class="componentA">
<h3>我是子组件</h3>
<div>{{parentToChildData}}</div>
<div>{{msg}}</div>
<button @click="dataToParent">向父组件传递数据</button>
</div>
</template>
<script>
export default {
name:"componentA",
data() {
return {
msg: "我是子组件的数据",
childFromData:"新来的子组件数据"
}
},
props:["parentToChildData"],
methods: {
dataToParent(){
this.$emit("dataFromParent",this.childFromData);//dataFromParent:父组件中的方法;this.childFromData这个参数为子组件要向父组件传递的数据
}
},
}
</script>
这里就不演示效果了,如果有读者比较期待效果,可以直接将上面的代码复制到自己的项目中,然后建个路由就可以看效果了.
父组件通过props向子组件传递数据.我们需要注意,组件中数据共有3种形式的数据,即组件模板中的数据的来源有3个:data、props、computed.
data:就是组件初始化时的data函数了;
props:父组件传递过来的数据
compoted:模板中一些数据的展示依赖于data中一些属性的变化自动计算的值,来源时通过compoted计算的来的,本质上还是data.
对于这3点解释,是个人的一点见解,没有什么官方的说法,这就仁者见仁智者见智了.看怎么好理解就怎么理解了.
这个时候我们也许会想,我们直不把子组件中的数据上传给父组件了,而直接把子组件中的数据渲染到页面元素中不也可以吗?因为我把数据传递给了父组件,父组件也是会再通过props将这些数据通过子组件的元素来展示.从道理上来说是可以直接将自元素的新数据不传递给父组件,而仅在子组件本身处理这些数据,但这里又会涉及到一个问题,就是数据的整合问题,包括数据的遍历、循环等,会把数据的处理搞的很复杂,不如直接将子组件数据传递给父组件再通过props传递回来处理简单.
同属于一个父组件的兄弟节点之间的传值
其实这个比较好理解,及时在一个模板文件中,同时引用了多个子组件,那么这子组件中的一个有数值的变化了,其他子组件也会有相关的值的变化.这里并没有技术难点,就是把前面我们介绍过的父子组件之间的传值综合利用了起来.先将子组件A的值传递给父组件,然后父组件再通过props将从组件A获取到的数据传递给子组件B,这样实现了兄弟组件之间值的传递.
看个例子:
父组件componentP.vue
<template>
<div>
<div class="cmp1">
{{msg}}
<ComponentA @cmpAToParent="cmpASendDataToParent" :cmaData="cmadata"></ComponentA>
</div>
<div class="cmp2">
<ComponentB :msgfromP="msg"></ComponentB>
</div>
</div>
</template>
<script>
import ComponentA from './componentA'
import ComponentB from './componentB'
export default {
name: "ComponentBrother",
data() {
return {
msg:"",
cmadata:"父组件传递给组件A测试数据"
}
},
components: {
ComponentA, ComponentB
},
methods: {
cmpASendDataToParent(data) {
this.msg = data;
}
},
}
</script>
子组件A:componentA.vue
<template>
<div class="cmp-a">
<p>{{msg}}</p>
<p>{{cmaData}}</p>
<input type="text" class="ipt" v-model="username">
<button class="btn" @click="comASendDataToParent">组件A向父组件传递数据</button>
</div>
</template>
<script>
export default {
name:'ComponentA',
data(){
return {
msg:"组件A",
username:""
}
},
props:["cmaData"],
methods: {
comASendDataToParent(){
this.$emit("cmpAToParent",this.username);
}
},
}
</script>
子组件B:componentB.vue
<template>
<div>
<p>{{msg}}</p>
<p>A组件的变化,引起的B的变化:{{msgfromP}}</p>
<button class="btn" @click="sentDataToParent">sendDataToParent</button>
</div>
</template>
<script>
export default {
name:'ComponentB',
data(){
return {
msg:"组件B"
}
},
props:["msgfromP"],
methods: {
sentDataToParent(){
console.log("组件B中点击一下按钮");
}
},
}
</script>
demo中只实现了子组件A向子组件B的传值,没有做子组件B向子组件A传值的实现,道理是一样的.
兄弟节点之间的传值,除了上面的先子组件传递给父组件然后父组件再传递给子组件外,还有另外一种通过程序化的事件侦听器(也叫中央事件总线)来监听.
到此为止,有规律的组件之间的传值已经介绍完了,还有一种无规定关系组件之间的传值了.这种关系的组件之间的传值就不能通过上面介绍的方式来实现了,可以借助vuex来实现.
不相关组件之间的值的传递