Vue2与Vue3的组件通讯对比

vue

vue2">Vue2

父传子

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

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

    <Child :childData=\'pMsg\'/>

    <!-- 也可以写死 -->

    <Child childData=\'123\'/>

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

    props: ["childData"]

  3. 子在template中或其他地方任意使用接受到的数据

    <h2>我得到了{{childData}}</h2>

列出完整例子:

<!--@html-start-->

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<meta http-equiv="X-UA-Compatible" content="ie=edge" />

<title>title</title>

</style>

</head>

<body>

<div id="app">{{ message }}</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

</body>

</html>

<!--@html-end-->

<!--@css-start-->

fieldset {

margin-top: 30px;

}

<!--@css-end-->

<!--@javascript-start-->

Vue.component("Parent", {

data() {

return {

pMsg: "小楼昨夜又东风",

};

},

//步骤一

template: `<div><fieldset><legend>父组件</legend><input type="text" v-model="pMsg"/><Child :childData=\'pMsg\'/></fieldset></div>`,

});

Vue.component("Child", {

//步骤三

template: `<div><fieldset><legend>子组件</legend>来自父组件的数据: {{ childData }}</fieldset></div>`,

//步骤二

props: ["childData"],

});

var vm = new Vue({

el: "#app",

data() {

return {

msg: "往input中输入东西试试",

};

},

template: `<div><fieldset><legend>App组件</legend>{{ msg }}<Parent/></fieldset></div>`,

});

<!--@javascript-end-->

子传父

  1. 父组件中为子组件绑定一个自定义事件
    <h2> <Child @childHandler="childHandler" /></h2>`

  2. 父组件中为自定义事件写函数,形参为要接收的值,假如要加到this中的话,最好在data中预留一个key
    methods: {

    childHandler(val) {

    this.ChildData = val

    }

    }

  3. 子组件中绑定一个原生事件
    @input="change(data)"

    再在方法中使用$emit调用父组件中的方法

    this.$emit("childHandler", val)

    触发父组件中的自定义事件

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

完整例子:

<!--@html-start-->

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<meta http-equiv="X-UA-Compatible" content="ie=edge" />

<title>title</title>

</head>

<body>

<div id="app">{{ message }}</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

</body>

</html>

<!--@html-end-->

<!--@css-start-->

fieldset {

margin-top: 30px;

}

<!--@css-end-->

<!--@javascript-start-->

Vue.component("Parent", {

data() {

return {

ChildData: "",

};

},

//步骤一

template: `<div><fieldset><legend>父组件</legend><p>来自子组件的数据: {{ ChildData }}</p><Child @childHandler="childHandler" /></fieldset></div>`,

// 步骤二

methods: {

// 处理从子组件中获取的数据

childHandler(val) {

this.ChildData = val;

},

},

});

Vue.component("Child", {

data() {

return {

data: "故国不堪回首月明中",

};

},

//步骤三

template: `<div><fieldset><legend>子组件</legend><input type="text" v-model="data" @input="change(data)" /></fieldset></div>`,

methods: {

// 调用$emit方法

change(val) {

this.$emit("childHandler", val);

},

},

});

var vm = new Vue({

el: "#app",

data() {

return {

msg: "在input中输入东西试试",

};

},

template: `<div><fieldset><legend>App组件</legend>{{msg}}</h1><Parent/></fieldset></div>`,

});

<!--@javascript-end-->

父传孙

父组件里使用provide, 子组件里使用inject

完整例子

<!--@html-start-->

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<meta http-equiv="X-UA-Compatible" content="ie=edge" />

<title>title</title>

</head>

<body>

<div id="app">{{ message }}</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

</body>

</html>

<!--@html-end-->

<!--@javascript-start-->

Vue.component("Parent", {

data() {

return { data: "小楼昨夜又东风" };

},

template: `<div><fieldset><legend>父组件</legend><p>父组件数据: {{ data }}</p><Child /></fieldset></div>`,

// 步骤一

provide() {

return {

data: this.data,

};

},

});

Vue.component("Child", {

template: `<div><fieldset><legend>子组件</legend><GrandSon /></fieldset></div>`,

});

Vue.component("GrandSon", {

// 步骤二

// 接收祖辈的数据 data

inject: ["data"],

data() {

return {

// 通过this.x取值

parentData: this.data,

};

},

template: `<div><fieldset><legend>孙组件</legend><p>祖辈的数据: {{ parentData }}</p></fieldset></div>`,

});

var vm = new Vue({

el: "#app",

data() {

return {

msg: "观察组件的数据",

};

},

template: `<div><fieldset><legend>App组件</legend><p>{{ msg }}</p><Parent/></fieldset></div>`,

});

<!--@javascript-end-->

<!--@css-start-->

fieldset {

margin-top: 30px;

}

<!--@css-end-->

注意, 这种方法传值不是响应数据

你可以把数据变为object类型, 让其可以同步修改

兄弟之间互传

  1. 在Vue的原型对象向上添加一个属性叫$bus

    该属性是一个Vue实例对象

  2. 发送端, 调用this.$bus.$emit
  3. 接收端, 监听对应事件, 处理数据

完整例子:

<!--@html-start-->

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<meta http-equiv="X-UA-Compatible" content="ie=edge" />

<title>title</title>

</head>

<body>

<div id="app">{{ message }}</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

</body>

</html>

<!--@html-end-->

<!--@javascript-start-->

// 步骤一 添加$bus属性

Vue.prototype.$bus = new Vue();

Vue.component("Child1", {

data() {

return { data: "小楼昨夜又东风" };

},

methods: {

update() {

// 步骤二 使用$emit触发自定义事件, 传入数据

this.$bus.$emit("handlerData", this.data);

},

},

template: `<div><fieldset><legend>子组件</legend><p>子组件发送的数据: <input type="text" v-model="data" @input="update()"/></p></fieldset></div>`,

});

Vue.component("Child2", {

data() {

return {

data: "",

};

},

mounted() {

// 步骤三 处理传过来的数据

this.$bus.$on("handlerData", (val) => {

this.data = val;

});

},

template: `<div><fieldset><legend>子组件</legend><p>子组件接收的数据: {{ data }}</p></fieldset></div>`

});

var vm = new Vue({

el: "#app",

data() {

return {

msg: "往input中输入数据试试",

};

},

template: `<div><fieldset><legend>App组件</legend><p>{{msg}}</p><Child1 /> <Child2 /></fieldset></div>`,

});

<!--@javascript-end-->

<!--@css-start-->

fieldset {

margin-top: 30px;

}

<!--@css-end-->

Vue3

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

父传子

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

    关于props见: props

  3. 要在setup中使用, 使用如下方法:
    props: ["data"],

    setup(props, context) {

    props.data

    }

完整例子

<!--@html-start-->

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<meta http-equiv="X-UA-Compatible" content="ie=edge" />

<title>title</title>

</head>

<body>

<div id="app">

<fieldset>

<legend>app组件</legend>

{{ data }}

<!-- 使用组件 -->

<Parent />

</fieldset>

</div>

<script src="https://unpkg.com/vue@3.2.26/dist/vue.global.js"></script>

</body>

</html>

<!--@html-end-->

<!--@javascript-start-->

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: `<fieldset><legend>父组件</legend> <input type="text" v-model="parentData" /> <Child :parentData="parentData" /></fieldset>`,

});

app.component("Child", {

props: ["parentData"],

setup() {

const childData = "childData";

return {

childData,

};

},

template: `<fieldset><legend>子组件</legend>{{ parentData }}</fieldset>`,

});

app.mount("#app");

<!--@javascript-end-->

<!--@css-start-->

fieldset {

margin-top: 30px;

}

<!--@css-end-->

子传父

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

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

<!--@html-start-->

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<meta http-equiv="X-UA-Compatible" content="ie=edge" />

<title>title</title>

</head>

<body>

<div id="app">

<fieldset>

<legend>app组件</legend>

{{ data }}

<!-- 使用组件 -->

<Parent />

</fieldset>

</div>

<script src="https://unpkg.com/vue@3.2.26/dist/vue.global.js"></script>

</body>

</html>

<!--@html-end-->

<!--@javascript-start-->

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: `<fieldset><legend>父组件</legend><p>子组件中的数据: {{ childData }}</p><Child @inputText="receive" /></fieldset>`,

});

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: `<fieldset><legend>子组件</legend><input type="text" @input="toParent" v-model="data" /></fieldset>`,

});

app.mount("#app");

<!--@javascript-end-->

<!--@css-start-->

fieldset {

margin-top: 30px;

}

<!--@css-end-->

父传孙

和vue2一样, 同样使用provideinject

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

<!--@html-start-->

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<meta http-equiv="X-UA-Compatible" content="ie=edge" />

<title>title</title>

</head>

<body>

<div id="app">

<fieldset>

<legend>app组件</legend>

{{ data }}

<!-- 使用组件 -->

<Parent />

</fieldset>

</div>

<script src="https://unpkg.com/vue@3.2.26/dist/vue.global.js"></script>

</body>

</html>

<!--@html-end-->

<!--@javascript-start-->

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: `<fieldset><legend>父组件</legend>从子孙辈中获取的数据: <input type="text" v-model="data" /> <Child /></fieldset>`,

});

app.component("Child", {

template: `<fieldset><legend>子组件</legend><GrandSon /></fieldset>`,

});

app.component("GrandSon", {

setup() {

// 步骤二 接收数据

// 接收 parentData

const data = Vue.inject("parentData");

return {

data,

};

},

template: `<fieldset><legend>孙组件</legend><p>从父辈中获取的数据: <input type="text" v-model="data" /></p></fieldset>`,

});

app.mount("#app");

<!--@javascript-end-->

<!--@css-start-->

fieldset {

margin-top: 30px;

}

<!--@css-end-->

以上是 Vue2与Vue3的组件通讯对比 的全部内容, 来源链接: utcz.com/z/374782.html

回到顶部