Vue——组件传值2:子向父传值(利用组件的自定义事件进行反向传值)

281 阅读1分钟

2.子向父传值使用“$emit”

由于是子组件传值给父组件,我们可以回忆上一次的子组件==>父组件通信方式就是组件的自定义事件

参考:juejin.cn/post/714031…

事件的三要素:

事件源target、事件类型type、监听器hander

组件的自定义事件:

就是自己创建的事件,包含事件名,事件回调等,定义好之后去给组件使用。也是一种组件间的通信方式,适用于子组件==>父组件。这里我们通过传值去讲述自定义事件如何使用。

  1. 在根组件中给子组件标签绑定自定义事件( <Box1 v-on:myevent="fn1"></Box1>),创建一个方法(监听器:fn1),在自定义事件触发后调用这个函数。
  2. 在子组件内部定义事件类型,当满足事件触发的条件(条件是自己定义的)后,就去触发组件内的事件(this.$emit("自定义事件名",传值给根组件内定义的方法)),然后监听器就会去做处理。

使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:

  • 使用 $on(eventName) 监听事件
  • 使用 $emit(eventName) 触发事件
  1. 通过在子组件上定义自定义事件,在子组件中通过$emit 来触发事件;

  2. 子组件的事件被触发并传参,事件处理函数可以接收到子组件的数据;

  3. 事件绑定的事件处理函数在父节点上,故可在事件处理函数中用到子组件的数据值来修改父节点的数据。

补充:

页面刷新:this.$set(修改的值,数据的下标,修改的值)

案例:算商品总价:

前端:

父组件:

        <template>
  <div>
<!-- 父向子传值 :使用props属性进行传值title,price,count,index-->
<!-- 子向父传值:使用组件的自定义事件传值给父组件 在子组件中this.$emit()触发父组件中的自定义事件,将子组件中值传给父组件 -->
   <Box v-for="(el,i) in arr" :key="i" 
:title="el.title"
:price="el.price"
:count="el.count"
@ment="change2"
:index="i"></Box>
<div>总价:{{total}}</div>
<button @click="change">修改父组件的值</button>
 </div>
</template>

<script>
import Box from './components/Box.vue';
 export default {
 data(){  
   return {
    msg:"hello",
    arr:[]
}
},
 async mounted() {
 //做网络请求
let res=await this.$axios("/good")
console.log(res)
//将请求的数据赋值给数组arr
this.arr=res.data
 },
 methods:{
 //方法
change(){
  this.arr[0].count=100
  // 更改数据后,刷新页面
  this.$set(this.arr,0,this.arr[0])
},
change2(arg,arg2){
  // 接收子组件传来的值
  // 实参arg就是子组件传过来的值n
  console.log(arg);
  // 实参arg2就是子组件传来的每个组件相对应的下标
  // 用于区分每个子组件
  console.log(arg2)

  this.arr[arg2].count=arg
  // 刷新页面
  this.$set(this.arr,arg2,this.arr[arg2])

}
 },
 components:{
 //注册组件
   Box
 },
 computed:{
 //计算属性
   total(){
  return this.arr.reduce((n1,n2)=>{
    return n1+n2.price*n2.count
  },0)
}
 }
}
</script>

子组件:

       <template>
 <div>
<div>{{title}}----{{price}}元
数量:
<button>-</button>
<span>{{count}}</span>
 <button @click="add">+</button>
</div>
 </div>
</template>

<script>
export default {
props:["title","price","count","index"],
methods:{
    add(){
        // console.log(this.count)
        // this.count++
        let n=this.count+1
        // 为什么要传一个下标给父组件呢?
        // 是因为子组件循环,不易区分每一个组件,不易明确改变哪个组件的count值,所以传一个下标,区分一下
        // this.$emit()触发父组件中的事件
        this.$emit("ment",n,this.index)
    }
}

}
</script>

main.js文件:

image.png

vue.config.js文件:

image.png

后端代码(egg框架):

image.png