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的组件通讯对比的更多相关文章

  1. 盘点Vue2和Vue3的10种组件通信方式(值得收藏)

    Vue中组件通信方式有很多,其中Vue2和Vue3实现起来也会有很多差异:本文将通过选项式API 组合式API以及setup三种不同实现方式全面介绍Vue2和Vue3的组件通信方式.其中将要实现的通信 ...

  2. vue2升级vue3:Vue Demij打通vue2与vue3壁垒,构建通用组件

    如果你的vue2代码之前是使用vue-class-component 类组件模式写的.选择可以使用 https://github.com/facing-dev/vue-facing-decorator ...

  3. vue2.0中eventBus实现兄弟组件通讯

    我们知道,在vue中父子组件的通讯是通过props和自定义事件搞定的,简单那的非父子组件通讯用bus(一个空的Vue实例),针对中大型的项目会选择vuex,然而小项目的话,便捷的解决方案就是event ...

  4. Vue2和Vue3技术整理1 - 入门篇 - 更新完毕

    Vue2 0.前言 首先说明:要直接上手简单得很,看官网熟悉大概有哪些东西.怎么用的,然后简单练一下就可以做出程序来了,最多两天,无论Vue2还是Vue3,就都完全可以了,Vue3就是比Vue2多了一 ...

  5. vue2和vue3生命周期的区别

    概念 首先,我们了解一下"生命周期"这个词.通俗的来说,生命周期就是一个事务从出生到消失的过程.例如,一个人从出生到去世.在vue中,vue的生命周期是指,从创建vue对象到销毁v ...

  6. vue2.x入坑总结—回顾对比angularJS/React的一统

    从感性的角度讲,我是不屑于用VUE,觉得react套件用起来更顺手,但是vue现在越来火,所以也不得入vue(杂烩汤)的坑.vue/anguarJS/React,三者对关系现在就是: https:// ...

  7. Vue3 父组件调用子组件的方法

    Vue3 父组件调用子组件的方法 // 父组件 <template> <div> 父页面 <son-com ref="sonRef"/> < ...

  8. vue2升级vue3:vue2 vue-i18n 升级到vue3搭配VueI18n v9

    项目从vue2 升级vue3,VueI18n需要做适当的调整.主要是Vue I18n v8.x 到Vue I18n v9 or later 的变化,其中初始化: 具体可以参看:https://vue- ...

  9. vue2升级vue3指南(二)—— 语法warning&error篇

    本文总结了vue2升级vue3可能会遇到的语法警告和错误,如果想知道怎样升级,可以查看我的上一篇文章:vue2升级vue3指南(一)-- 环境准备和构建篇 Warning 1.deep /deep/和 ...

随机推荐

  1. [loj3315]抽卡

    令$S$表示对于某一种抽卡顺序中某一段长度为$k$的段全部被抽到的时间(这里没有期望)所构成的集合,根据$min-max$容斥的公式,有$E(\min(S))=\sum_{T\subseteq S}( ...

  2. 史上最简单的手写Promise,仅17行代码即可实现Promise链式调用

    Promise的使用相比大家已经孰能生巧了,我这里就不赘述了 先说说我写的Promise的问题吧,无法实现宏任务和微任务里的正确执行(也就是在Promise里面写setTimeout,setInter ...

  3. C/C++ Qt TreeWidget 嵌套节点操作技巧

    在上一篇博文<C/C++ Qt TreeWidget 单层树形组件应用>中给大家演示了如何使用TreeWidget组件创建单层树形结构,并给这个树形组件增加了右键菜单功能,接下来将继续延申 ...

  4. pm2 重启策略(restart strategies)

    使用 PM2 启动应用程序 时,应用程序会在自动退出.事件循环为空 (node.js) 或应用程序崩溃时自动重新启动. 但您也可以配置额外的重启策略,例如: 使用定时任务重新启动应用程序 文件更改后重 ...

  5. CF1610F F. Mashtali: a Space Oddysey

    我们首先发现有如下性质: 我们不妨先随机定向边,那么我们发现无论我们如何翻转边. 都会对其两端的点,造成 \(2 / 4\) 的影响,所以我们发现如果一个点其和他相连的所有边权和为偶数,则我们不能调整 ...

  6. 洛谷 P5299 - [PKUWC2018]Slay the Spire(组合数学+dp)

    题面传送门 hot tea 啊--这种风格及难度的题放在省选 D2T1 左右还是挺喜闻乐见的罢 首先考虑对于固定的 \(m\) 张牌怎样求出最优的打牌策略,假设我们抽到了 \(p\) 张强化牌,攻击力 ...

  7. Atcoder Grand Contest 038 E - Gachapon(Min-Max 容斥+背包)

    Atcoder 题面传送门 & 洛谷题面传送门 我竟然能独立做出 Ag 的 AGC E,incredible!更新了 Atcoder 做题难度上限( 首先按照套路 Min-Max 容斥,\(a ...

  8. P3438 [POI2006]ZAB-Frogs

    P3438 [POI2006]ZAB-Frogs 给出一个不一样的解法.不需要用到斜率优化等高级算法. 下文记 \(n=w_x,m=w_y\). 首先,答案显然满足可二分性,因此二分答案 \(d\in ...

  9. [R]在dplyr基础上编写函数-(1)eval

    tidyverse系列的R包虽然解放了大家的双手,但同时也束缚了我们重新编写函数的能力.在这一套语法中,要实现作为函数参数的字符串和变量之间的相互转换困难重重,但只要掌握了其中原理后,也就能够游刃有余 ...

  10. python包之drmaa:集群任务管理

    目录 1. drmaa简介 2. 安装和配置 3. 示例 3.1 开始和终止会话 3.2 运行工作 3.3 等待工作 3.4 控制工作 3.5 查询工作状态 4. 应用 4.1 写一个简单应用 4.2 ...