vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue父子组件传值&自定义事件

Vue父子组件传值&自定义事件方式

作者:白桃味稠鱼烧

这篇文章主要介绍了Vue父子组件传值&自定义事件方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

Vue 父子组件传值&自定义事件

因为vue 的数据是单向流动的,这是为了避免数据污染。

在官方文档中也说到:所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。

这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

大致归纳一下:父传子--传值、子传父--传事件

父传子:父组件可以传递任何类型的数据给子组件

如果传递的数据是对象格式的,那么在子组件 内部监听 watch 的时候,需要使用深度监听,也就是添加 deep : true ,也就是下面的子组件的监听方式,如果是别的格式的,例如,字符串、数字、布尔值、 数组格式等,那就是普通监听就好了

父组件代码

在父组件中 通过 v-bind 的缩写形式 :listData='listData' 绑定了data 内部的数据,第一个 listData 只是一个名字,为了方便辨认,所以写的相同。 第二个 listData 则是 data 内部的数据

<template>
  <div>
    <h3>我是father</h3>
    <Children :listData='listData' :xxx='xxx' :listObj='listObj'></Children> 
    //子组件传递了一个数组、一个字符串、一个对象
  </div>
</template>

<script>
import Children from './children'  //引入子组件
export default {
  data () {
    return {
      xxx:'123',
      listData: [{
          id: 1,
          name: "TCL彩电",
          price: 1000,
          num: 1,
          img: "../../../assets/a.jpg"
        }],
      listObj: {
          name: "aaa",
          age: 18
      }
    }
  },
  components : {
    Children //注册子组件
  },
}
</script>

子组件代码

1、通过 props 接收父组件传递过来的数据,规范要求写出数据的类型以及默认值,如果数据是数组或对象形式的,需要使用函数返回,不然控制台会报错。

2、props 接收数据之后,需要使用数据,这个时候需要用到 watch 监听器。对象监听需要用到 deep 深度监听,如果需要组件第一次进来之后就开始监听数据,那么需要 添加 immediate: true

<template>
  <div>
    <h3>我是children</h3>
  </div>
</template>

<script>
export default {
  props: {
    listData: {
      type: Array,
      default: () => []
    },
    xxx:{
      type:String,
      default : ''
    },
    listObj:{
      type: Object,
      default: () => {}
    }
  },
  watch: {
    listData:{
      handler(n,o) {
        console.log(n,o)
      }
    },
    xxx:{
      handler(n) {
        console.log(n)
      }
    },
    listObj:{
      handler(n,o) {
        console.log(n,o)
      },
      deep: true,
      immediate: true,
    },
  }
};
</script>

子传父--传事件:子组件传递数据给父组件时存在三种方式,但是都是通过事件传递

1、父组件传递 函数类型的props 给子组件,实现子组件向父组件传递数据

在父组件中引入子组件,向子组件中 通过 v-bind( 简写为 : ) 绑定一个 test 属性 ,该 test 属性对应的值则是 methods 中定义的方法。

<template>
  <div id="app">
    <School :test="test"/>
  </div>
</template>

methods: {
  test(val) {
    console.log(val,'这是子组件传递过来的数据')
  },
},

定义子组件,以及子组件事件

<template>
  <div>
    <p class="demo" @click="goto">School组件</p>
  </div>
</template>

在子组件中接收该 test 属性,定义数据,定义组件方法。其实props 可以直接写成一个数组,不去定义类型,默认值以及是否必传,但是推荐还是写全一点,这样编译的时候会校验,提高代码质量

export default ({
  // props:['test'],
  props: {
    test: {
      type: Function,
      default: () => {},
      required: true,
    }
  },
  data() {
    return {
      msg:'子组件数据'
    }
  },
  methods: {
    goto() {
      this.test(this.msg)
    }
  },
})

点击触发 goto 事件,找到当前 props 中接收的 test 函数 ( props 接收的参数,都被Vue 底层处理过之后放在了 当前组件实例对象上,所以可以直接通过 this.xxx 拿到 )

控制台上打印了子组件数据。可以看到子组件传递的数据被打印了,表示父组件中绑定的 test 事件被执行了

2、通过 v-on( @ ) 与 $emit 实现子组件向父组件传递数据

App 组件中引入 School 子组件,且绑定 自定义事件 test。

<School @test="test"/>

test(val) {
    console.log(val,'这是子组件传递过来的数据')
},

子组件模板、数据、样式不变,只是 goto 方法内部逻辑变更

methods: {
  goto() {
    this.$emit('test',this.msg)
  }
},

点击触发 goto 事件,通过 $emit 触发 test 事件,根据名称找到 父组件中的 test 属性对应的方法,执行该方法。结果与 props 传递函数参数一致

3、通过 ref 以及 $on、$emit 三个 api 实现 父组件通过 自定义事件接收子组件参数

App 组件中引入 Schoo 组件,且给 School 子组件添加了 ref 属性,定义 test 函数

<School ref='student'/>

test(val) {
    console.log(val,'这是子组件传递过来的数据')
},

如果想使用这个方法去获取子组件数据,就需要用到 $on() 这个方法。现在假设,当父组件挂载时,我就要获取到子组件的值,我就应该在 父组件 的 mounted 生命周期中 使用 this.$refs.xxx来获取当前组件的实例对象,至于 $on() 这个方法,则是 挂载到 Vue 实例对象的原型上的,所以 组件实例对象 和 Vue 实例对象 都能使用 $on() 。

在这里就是 通过 $on 注册或者叫创建了一个 qwe 的自定义事件,且该自定义事件的回调函数是写在 methods 中的 getname

mounted() {
  this.$refs.student.$on('qwe', this.test)
}

父组件的工作已经完了,现在该看看子组件了。子组件更简单了,和上面 第二种方法一样,通过 $emit() 这个方法来触发父组件定义的 qwe 方法,且将子组件 数据传递出去。

goto() {
   this.$emit('test',this.msg)
}

当我点击 School 组件时,执行 goto 方法,通过 $emit 触发父组件自定义的 qwe 方法,且将参数传递给父组件。

父组件通过 $on 监听 qwe 方法,发现被触发了,执行其回调函数 this.test,且 $emit 传递的参数,都会当做形参传递到回调函数中

$on 和 v-on 的区别

这么一看哈,其实我在子组件上使用 v-on( @ ) 和我使用 $on 做到的事情是一样的啊,那为啥还要来个 $on 这个玩意。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文