Vue2与Vue3的组件通讯对比


Vue2

父传子

父传子比较简单, 主要通过以下步骤实现

  1. 父在template中为子绑定属性

    
    
    
    
  2. 子用props接收数据, props的值可以是数组或对象

    props: ["childData"]
    
  3. 子在template中或其他地方任意使用接受到的数据

    我得到了{{childData}}

列出完整例子:




  
    
    
    
    title
    
  
  
    
{{ message }}
fieldset { margin-top: 30px; } Vue.component("Parent", { data() { return { pMsg: "小楼昨夜又东风", }; }, //步骤一 template: `
父组件
`, }); Vue.component("Child", { //步骤三 template: `
子组件来自父组件的数据: {{ childData }}
`, //步骤二 props: ["childData"], }); var vm = new Vue({ el: "#app", data() { return { msg: "往input中输入东西试试", }; }, template: `
App组件{{ msg }}
`, });

子传父

  1. 父组件中为子组件绑定一个自定义事件

    `
  2. 父组件中为自定义事件写函数,形参为要接收的值,假如要加到this中的话,最好在data中预留一个key
    methods: {
    	childHandler(val) {
    		this.ChildData = val
    	}
    }
    
  3. 子组件中绑定一个原生事件
    @input="change(data)"
    
    再在方法中使用$emit调用父组件中的方法
    this.$emit("childHandler", val)
    
    触发父组件中的自定义事件

    $emit: 触发当前实例上的事件。附加参数都会传给监听器回调

完整例子:




  
    
    
    
    title
  
  
    
{{ message }}
fieldset { margin-top: 30px; } Vue.component("Parent", { data() { return { ChildData: "", }; }, //步骤一 template: `
父组件

来自子组件的数据: {{ ChildData }}

`, // 步骤二 methods: { // 处理从子组件中获取的数据 childHandler(val) { this.ChildData = val; }, }, }); Vue.component("Child", { data() { return { data: "故国不堪回首月明中", }; }, //步骤三 template: `
子组件
`, methods: { // 调用$emit方法 change(val) { this.$emit("childHandler", val); }, }, }); var vm = new Vue({ el: "#app", data() { return { msg: "在input中输入东西试试", }; }, template: `
App组件{{msg}}
`, });

父传孙

父组件里使用provide, 子组件里使用inject
完整例子




  
    
    
    
    title
  
  
    
{{ message }}
Vue.component("Parent", { data() { return { data: "小楼昨夜又东风" }; }, template: `
父组件

父组件数据: {{ data }}

`, // 步骤一 provide() { return { data: this.data, }; }, }); Vue.component("Child", { template: `
子组件
`, }); Vue.component("GrandSon", { // 步骤二 // 接收祖辈的数据 data inject: ["data"], data() { return { // 通过this.x取值 parentData: this.data, }; }, template: `
孙组件

祖辈的数据: {{ parentData }}

`, }); var vm = new Vue({ el: "#app", data() { return { msg: "观察组件的数据", }; }, template: `
App组件

{{ msg }}

`, }); fieldset { margin-top: 30px; }

注意, 这种方法传值不是响应数据
你可以把数据变为object类型, 让其可以同步修改

兄弟之间互传

  1. 在Vue的原型对象向上添加一个属性叫$bus
    该属性是一个Vue实例对象
  2. 发送端, 调用this.$bus.$emit
  3. 接收端, 监听对应事件, 处理数据

完整例子:




  
    
    
    
    title
  
  
    
{{ message }}
// 步骤一 添加$bus属性 Vue.prototype.$bus = new Vue(); Vue.component("Child1", { data() { return { data: "小楼昨夜又东风" }; }, methods: { update() { // 步骤二 使用$emit触发自定义事件, 传入数据 this.$bus.$emit("handlerData", this.data); }, }, template: `
子组件

子组件发送的数据:

`, }); Vue.component("Child2", { data() { return { data: "", }; }, mounted() { // 步骤三 处理传过来的数据 this.$bus.$on("handlerData", (val) => { this.data = val; }); }, template: `
子组件

子组件接收的数据: {{ data }}

` }); var vm = new Vue({ el: "#app", data() { return { msg: "往input中输入数据试试", }; }, template: `
App组件

{{msg}}

`, }); fieldset { margin-top: 30px; }

Vue3

由于vue3vue2的选项变为了组合API, 而且把datamethods集合到了setup中, 故而使用起来有所区别, 但也大差不差

父传子

  1. 父组件使用refreactive将数据变为响应数据
  2. 子组件使用props接收

    关于props见: props

  3. 要在setup中使用, 使用如下方法:
    props: ["data"],
    setup(props, context) {
      props.data
    }
    

完整例子




  
    
    
    
    title
  
  
    
app组件 {{ data }}
const AttributeBindingApp = { name: "App", setup() { const data = "往input中输入东西试试"; return { data, }; }, }; const app = Vue.createApp(AttributeBindingApp); app.component("Parent", { setup() { // 变为响应数据 const parentData = Vue.ref("故国不堪回首月明中"); return { parentData, }; }, template: `
父组件
`, }); app.component("Child", { props: ["parentData"], setup() { const childData = "childData"; return { childData, }; }, template: `
子组件{{ parentData }}
`, }); app.mount("#app"); fieldset { margin-top: 30px; }

子传父

  1. 父组件中定义接收数据的方法
  2. template中为子组件绑定自定义事件
  3. 在子组件中触发自定义事件, 执行context.emit方法
  4. 传给父组件使用

总的来说, 原理与Vue2差不多, 但由于要在setup中获取值, 故要使用参数接收




  
    
    
    
    title
  
  
    
app组件 {{ data }}
const AttributeBindingApp = { name: "App", setup() { const data = "往input中输入东西试试"; return { data, }; }, }; const app = Vue.createApp(AttributeBindingApp); app.component("Parent", { setup(props, context) { const childData = Vue.ref(""); // 步骤一 定义处理接收数据的方法 const receive = (e) => { // 处理从子组件中传来的数据 childData.value = e; }; return { receive, childData, }; }, // 步骤二 自定义事件 触发处理接收数据的方法 template: `
父组件

子组件中的数据: {{ childData }}

`, }); app.component("Child", { props: ["parentData"], setup(props, context) { const data = Vue.ref("小楼昨夜又东风"); // 步骤四 调用context.emit const toParent = () => { // input时调用 // 调用inputText事件 context.emit("inputText", data.value); }; return { data, toParent, }; }, // 步骤三 触发事件 template: `
子组件
`, }); app.mount("#app"); fieldset { margin-top: 30px; }

父传孙

和vue2一样, 同样使用provideinject
但不同的是, 我们可以使用refreactive将数据转换为响应式数据




  
    
    
    
    title
  
  
    
app组件 {{ data }}
const AttributeBindingApp = { name: "App", setup() { const data = "往两个input中都输入试试"; return { data, }; }, }; const app = Vue.createApp(AttributeBindingApp); app.component("Parent", { setup() { // 响应的数据 const data = Vue.ref(""); // 步骤一 使用provide // 把data 标记为 "parentData" Vue.provide("parentData", data); return { data, }; }, template: `
父组件从子孙辈中获取的数据:
`, }); app.component("Child", { template: `
子组件
`, }); app.component("GrandSon", { setup() { // 步骤二 接收数据 // 接收 parentData const data = Vue.inject("parentData"); return { data, }; }, template: `
孙组件

从父辈中获取的数据:

`, }); app.mount("#app"); fieldset { margin-top: 30px; }