前言
最近在用Vue+echarts+d3做一个项目,网上大多数是零散的,我把项目中遇到 的问题都总结起来,放在博客下,便于日后查看以及分享一下爬坑经验。
我所遇到的困难在网上大多数可以找到,但比较零散,且不好找,这是Vue项目的第四篇博客,因为也是初次使用Vue,所以多详细记录一下。
这篇博客主要分享的知识点是Vue中父组件传以及echarts鼠标事件中的父组件传值,还解决了一个在父组件传值的过程中div被加载了两次的问题。
1.Vue子组件向父组件传值
二话不说,先上代码。
子组件代码:
<template>
<div class="child">
<button @click="sendMsg">给父组件发送数据</button>
</div>
</template>
<script>
export default {
name:'child',
methods:{
sendMsg(){
//this.$emit()是向父组件发送数据的函数
//参数1:规定必须父组件使用的事件类型,
//参数2: 向父组件发射的数据
//getData: 是父组件指定的传数据绑定的函数,在父组件中引入子组件标签时定义
//"老爹,我来啦":子组件给父组件传递的数据
this.$emit('getData', "老爹,我来啦")
}
}
}
</script>
父组件代码:
<template>
<div class="parent">
<--第三步,child为引入子组件的名字,@getData为指定数据绑定的函数,在子组件中的this.$emit()给这个函数发送数据,getMsgFormSon为父组件接收子组件传值过来的函数,用于接收数据-->
<child @getData="getMsgFormSon"></child>
</div>
</template>
<script>
import child from './child.vue'//第一步,先在这里导入子组件文件,并指名为child
export default {
components:{
child,//第二步,把子组件引入到父组件中,如果不写这个,在第三步的时候会报错,说child没有注册
},
methods:{
getMsgFormSon(data){
console.log(data)//当点击按钮的时候,父组件就会打印"老爹,我来啦"
}
}
}
</script>
2.Vue父组件向子组件传值
在本系统中设定APP.vue是唯一的父组件,其他所有的组件都是他的子组件
参考文档博客文章 https://blog.csdn.net/qq_42376617/article/details/106193508
子组件代码:
<template>
<div class="child"></div>
</template>
<script>
export default {
name:'child',
props: ['getCityName'],//getCityName是父组件中定义的,一定要有这行,表明从父组件中获取到这个值
watch: {//监听事件,父组件值发生变化,就会传给子组件
getCityName(data) {
console.log(data)//这里的data就是父组件穿过来的数据
}
},
}
</script>
父组件代码:
父组件传值用到的是“v-bind:”。
<template>
<div class="parent">
<button v-bind:getCityName="CityName">给子组件发送数据</button>
</div>
</template>
<script>
import child from './child.vue'//第一步,先在这里导入子组件文件,并指名为child
export default {
data(){
return{
CityName:'china'//在父组件中给CityName复制,把这个值传给子组件,可以在下面的代码中对CityName进行动态复制,只要只一改变,子组件就会监听到,数据就传送过去了。
}
}
components:{
child,//把子组件引入到父组件中,如果不写这个,在第三步的时候会报错,说child没有注册
},
}
</script>
3.Vue兄弟组件传值
兄弟组件之间传值是需要一个中转站的,也就是要借助于事件车, 通过事件车的方式传递数据 。也就是说让各兄弟同用一个事件机制( 创建一个Vue的实例 )。
传递数据方,通过一个事件触发eventVue. e m i t ( 方 法 名 , 传 递 的 数 据 ) 。 接 收 数 据 方 , 通 过 m o u n t e d ( ) 触 发 e v e n t V u e . emit(方法名,传递的数据)。 接收数据方,通过mounted(){}触发eventVue. emit(方法名,传递的数据)。接收数据方,通过mounted()触发eventVue.on(方法名,function(接收数据的参数){用该组件的数据接收传递过来的数据}),此时函数中的this已经发生了改变,可以使用箭头函数。
先创建一个js文件夹,文件夹下面创建 eventVue.js ,内容为
import Vue from 'vue'
export default new Vue
父组件引入两个子组件(路由方法):
<router-view name="main" />
<router-view name="bottom" />
子组件bottom(传递方):
<template>
<div class="child">
<button @click="sendMsg">给父组件发送数据</button>
</div>
</template>
<script>
import eventVue from '../js/eventVue.js'
export default {
name:'app',
sendMsg(){
eventVue.$emit('getData', "大哥,弟弟bottom来啦")
}
</script>
子组件main(接收方):
<script>
import eventVue from '../js/eventVue.js'
export default {
name:'app',
mounted: function () {
this.getMsg();
},
methods: {
getMsg() {
eventVue.$on("getData", (data) => { //这里最好用箭头函数,不然this指向有问题
console.log(data)
})
},
}
</script>
当点击按钮时,组件main就会打印"大哥,弟弟bottom来啦"。这就实现了兄弟间传值
另外一种放方式就是通过父组件来转发,子组件A先把值传给父组件,父组件再传给子组件B,这样就完成了兄弟组件的通信。
4.Vue传值导致div覆盖问题
我在完成子组件向父组件传值后,发现有两个按钮,一个按钮可以发送数据,也就是有点击事件,另外一个按钮没有点击事件,也就是不可以发送数据。后来我看了一下我的echarts图,也被画了两次,也就是说我的子组件被调用了两次,所以才会发生重画div的问题。
解决办法是,因为我先做的是多个组件合成一个页面,也就是Vue的多组件问题,我在之前调用组件的时候就已经调用过一次子组件,在APP.vue的文件中写了 这行代码掉用子组件,但我们在传值的时候又在父组件中写了<child @getData=“getMsgFormSon”>,这就导致子组件被调用两次,所以div也就被绘制两次,我们把APP.vue文件中的 去掉就好了。
5.echarts鼠标事件给组件传值
上面讲的子组件向父组件传值是通过按钮来传的,但我们画echarts时并不是用按钮来传值的,而是通过给图形绑定on事件来获取图形中的值,所以我们就要当点击图形的时候给父组件传值,d3传值也一样。如果我们直接在点击函数中写
this.$emit('getData', "老爹,我来啦")
会报一个错误,说 TypeError: this.$emit is not a function,这时我们只需要进行一步操作即可解决这个问题。发现是this指向的问题,先把this保存下来即可。看示例代码:
<script>
export default {
methods: {
LineChart(divid) {
let that = this;//把this赋给变量that
myChart.on("click", function (param) {
that.$emit('getData', param['name']);//用that.$emit即可解决传值问题
})
},
}
}
</script>