详细讲解vue.js里的父子组件通信(props和$emit)
在进入这个话题之前,首先我们先来想一下在vue里,如何写一个父子组件。为了简单起见,下面的代码我都没用脚手架来构建项目,直接在html文件里引入vue.js来作为例子。父子组件的写法如下:
<div id="app">
<parent></parent>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
let childNode = {
template: `<div>childNode</div>`
}
let parentNode = {
template: `
<div>
<child></child>
</div>
`,
components: {
child: childNode
}
}
new Vue({
el: '#app',
components: {
parent: parentNode
}
})
</script>
在这个代码里,template表示的是模板,components表示的是组件。子组件先要在父组件里显示就要通过components把组件对应的模板引擎(childNode对象)给挂载到父组件的components上去。然后子组件就会在父组件上得以显示。
在父子组件中,如果想要父组件的变量传递到子组件中,则需要通过props属性来进行传递。props有静态的也有动态的,下面来介绍静态的写法:
<script>
let childNode = {
template: `<div>{{message}}</div>`,
props: ['message']
}
let parentNode = {
template: `
<div>
<child message="child"></child>
</div>
`,
components: {
child: childNode
}
}
new Vue({
el: '#app',
components: {
parent: parentNode
}
})
</script>
在这里,子组件通过在props里写入想要获取的父组件的某个属性值,在父组件里,通过父组件在子组件里的占位符添加属性的方式来传值。在这里有一个命名规范,在子组件里,如果props里的参数由多个词组成则应该用驼峰命名的写法;而在父组件中则用横线做分隔符的写法。如:
<script>
let childNode = {
template: `<div>{{myMessage}}</div>`,
props: ['myMessage']
}
let parentNode = {
template: `
<div>
<child my-message="child"></child>
</div>
`,
components: {
child: childNode
}
}
new Vue({
el: '#app',
components: {
parent: parentNode
}
})
</script>
而动态props的用法是将占位符进行绑定,将父组件的数据绑定到子组件的props中,可以实现父组件的数据发生改变的时候子组件的数据也会发生改变的动态效果。如:
<script>
let childNode = {
template: `<div>{{myMessage}}</div>`,
props: ['myMessage']
}
let parentNode = {
template: `
<div>
<input type="text" v-model="myData">
<div>
<child :my-message="child"></child>
</div>
</div>
`,
components: {
child: childNode
},
data(){
return {
child: '',
myData: ''
}
},
watch: {
myData(newValue, oldValue){
this.child = newValue
}
}
}
new Vue({
el: '#app',
components: {
parent: parentNode
}
})
</script>
在这里,我通过利用v-model和watch来实现输入框发生变化的时候父组件数据动态修改后子组件的数据跟着改变。为什么这里不用computed而用watch呢?这里其实也涉及到watch和computed的区别,在vue里,这两个方法都能监听数据的变化,不同的是computed是只能读取不能写入,而watch可以读取也可以写入。当父组件的myData这个值发生改变的时候就将myData的值不断赋值给child,由于对占位符进行了绑定,所以子组件能够接收到父组件的改变。
动态props和静态props除了上面的区别以外还有一个区别,就是传递参数的时候数据类型发生变化。如下面的静态props里
<script>
let childNode = {
template: `<div>{{myMessage}}的类型是{{type}}</div>`,
props: ['myMessage'],
computed: {
type() {
return typeof this.myMessage
}
}
}
let parentNode = {
template: `
<div>
<div>
<child my-message="1"></child>
</div>
</div>
`,
components: {
child: childNode
}
}
new Vue({
el: '#app',
components: {
parent: parentNode
}
})
</script>
我们传的1在子组件里却是string类型,而如果是加入了绑定变成动态props:
<div>
<child :my-message="1"></child>
</div>
则会变成nunber,这种情况除了在数字类型发生以外,其他类型也会发生,需要注意。
在props里,我们可以验证父组件传过来的参数是否有问题,下面的例子主要是验证父组件传过来的数据是否是Number类型,如果不是的话则会在控制台里看到报错。在用这个方法的时候不要引用vue.min.js而要引用vue.js,因为vue.min.js会省略掉相应的报错提示,不利于开发的时候查看:
<script>
let childNode = {
template: `<div>{{myMessage}}</div>`,
props: {
myMessage: Number
}
}
let parentNode = {
template: `
<div>
<input type="text" v-model="myData">
<div>
<child :my-message="child"></child>
</div>
</div>
`,
components: {
child: childNode
},
data() {
return {
child: 123,
myData: ''
}
},
watch: {
myData(newValue, oldValue) {
if (/^[0-9]*$/.test(newValue)) {
this.child = parseInt(newValue)
} else {
this.child = '输入的数据不是number类型'
}
}
}
}
new Vue({
el: '#app',
components: {
parent: parentNode
}
})
</script>
可以看到我是在props里添加了一个对象,该对象里的myMessage属性里有属性值Number,表示验证数字类型,当myMessage的值不是数字类型的时候就会报错。除了Number的验证规则以外还有String、Boolean、Function、Object、Array和Symbol等验证规则,同时也可以写成这样来验证多种类型:
props: {
myMessage: [Number, String]
}
或者可以通过一个自定义一个工厂函数来进行匹配,如:
props: {
myMessage: {
validator: function (value) {
return value > 10
}
}
}
当然,在props对象里面,还有另外三个属性,一个是default属性,表示的是父组件传入值的时候子组件默认的值,另一个是require,表示的是该值是否要传入,而type则表示的是验证规则。如:
<script>
let childNode = {
template: `<div>{{myMessage}}</div>`,
props: {
myMessage: {
type: Number,
// required: true,
default: 321
}
}
};
let parentNode = {
template: `
<div>
<div>
<child></child>
</div>
</div>
`,
components: {
child: childNode
},
data() {
return {
child: 123
}
}
};
new Vue({
el: '#app',
components: {
parent: parentNode
}
})
</script>
一般来说,当props里的require表示为true的时候,则父组件要加上占位符,因为父组件有传值过来,所以default的值被覆盖了,如:
<script>
let childNode = {
template: `<div>{{myMessage}}</div>`,
props: {
myMessage: {
type: Number,
required: true,
default: 321
}
}
};
let parentNode = {
template: `
<div>
<div>
<child :my-message="child"></child>
</div>
</div>
`,
components: {
child: childNode
},
data() {
return {
child: 123
}
}
};
new Vue({
el: '#app',
components: {
parent: parentNode
}
})
</script>
由于props是单向数据流,所以父组件传过来的数据子组件修改了也不会修改到父组件的数据,而父组件一修改了则会修改到子组件的数据。所以想要反过来将子组件的数据传到给父组件则要换一种方法。用的比较多的是自定义一个事件,如:
<script>
let childNode = {
template: `
<div>
<button @click="toParent">子传父</button>
</div>
`,
methods: {
toParent() {
this.$emit('myParent', 'hello')
}
}
};
let parentNode = {
template: `
<child @myParent="change" :message="message"></child>
`,
components: {
'child': childNode
},
methods: {
change(data) {
console.log(data)
}
}
};
new Vue({
el: '#app',
components: {
parent: parentNode
}
})
</script>
在这里,子组件通过比如点击事件来触发一个自定义事件,该事件里有this.$emit的处理函数,第一个参数表示的是父组件里负责监听的函数名,第二个参数表示的传递的数值。在父组件里,通过在子组件占位符绑定一个子组件this.$emit定义的方法名即可监听得到传入的参数。
详细讲解vue.js里的父子组件通信(props和$emit)的更多相关文章
- 三大前端框架(react、vue、angular2+)父子组件通信总结
公司业务需要,react.vue.angular都有接触[\无奈脸].虽然说可以拓展知识广度,但是在深度上很让人头疼.最近没事的时候回忆各框架父子组件通信,发现很模糊,于是乎稍微做了一下功课,记录于此 ...
- vue 父子组件通信props/emit
props 1.父组件传递数据给子组件 父组件: <parent> <child :childMsg="msg"></child>//这里必须要 ...
- vue 父子组件通信-props
父组件:引用了ComBack组件 ComBack组件:引用了BasicInfor组件 先使用props获取父组件的headInfo这个对象,这里注意(default)默认返回值要用工厂形式返回 Bas ...
- vue 父子组件通信
算是初学vue,整理一下父子组件通信笔记. 父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息. 一.父组件向子组件下发数据: 1.在子组件中显式地用props选项声明它预期的数据 ...
- Vue 非父子组件通信
组件是Vue核心的一块内容,组件之间的通信也是很基本的开发需求.组件通信又包括父组件向子组件传数据,子组件向父组件传数据,非父子组件间的通信.前两种通信Vue的文档都说的很清楚,但是第三种文档上确只有 ...
- Vue 非父子组件通信方案
Vue 非父子组件通信方案 概述 在 Vue 中模块间的通信很普遍 如果是单纯的父子组件间传递信息,父组件可以使用 props 将数据向下传递到子组件,而在子组件中可以使用 events (父组件需要 ...
- vue 父子组件通信详解
这是一篇详细讲解vue父子组件之间通信的文章,初始学习vue的时候,总是搞不清楚几个情况 通过props在父子组件传值时,v-bind:data="data",props接收的到底 ...
- Vue.JS快速上手(组件间的通信)
前言 Vue采用的是组件化思想,那么这些组件间是如何通信的呢?下面详细介绍一下. 所谓组件间通信,不单单是我们字面上理解的相互传递数据,这里还包括一个组件访问另一个组件的实例方法等,如父组件通过ref ...
- 总结Vue第二天:自定义子组件、父子组件通信、插槽
总结Vue第二天:自定义子组件.父子组件通信.插槽 一.组件: 组件目录 1.注册组件(全局组件.局部组件和小demo) 2.组件数据存放 3.父子组件通信(父级向子级传递数据.子级向父级传递数据) ...
随机推荐
- Java常用命令:jps、jstack、jmap、jstat(带有实例教程)
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u013310517/article/details/80990924 查看Java进程:jps ...
- (4)Spring Boot Web开发---静态资源
文章目录 对静态资源的映射规则 模板引擎 Thymeleaf 使用 & 语法 使用之前将的快速创建项目的方法,勾选我们需要的场景,这里我需要 web --> web.sql --> ...
- 织梦/dedecms采集怎么去除a标签
dedecms采集去除a标签代码 DedeCMS采集规则-过滤-替换-技巧2009-01-14 15:491.采集去除链接[Copy to clipboard]CODE:{dede:trim}]*)& ...
- python学习-60 面向对象设计
面向对象设计 1.三大编程范式 --面向过程编程 --函数式编程 --面向对象编程 2.编程进化论 --编程最开始就是无组织无结构,从简单控制流中按步写指令 --从上述的指令中提取重复的代码快或逻辑, ...
- PAT(B) 1072 开学寄语(Java)统计
题目链接:1072 开学寄语 (20 point(s)) 题目描述 下图是上海某校的新学期开学寄语:天将降大任于斯人也,必先删其微博,卸其 QQ,封其电脑,夺其手机,收其 ipad,断其 wifi,使 ...
- C++中的构造函数与析构函数及组合类的调用
// 构造函数与析构函数及类的组合 #include "stdafx.h"#include <iostream>using namespace std; //枚举enu ...
- AS3动画效果常用公式
缓动公式: sprite.x += (targetX – sprite.x) * easing;//easing为缓动系数变量 sprite.y += (targetY – sprite.y) * e ...
- C#方法(用法,参数)
方法:是一种用于实现可以由对象或类执行的计算或操作的成员,是一个已命名的语句集.方法就是把一些相关的语句组织到一起,用来执行一个任务的语句块.比如每个C#程序至少带一个main函数 1.格式:修饰符 ...
- ASP.NET Core利用拦截器 IActionFilter实现权限控制
“麦荻网教系统”采用了前后端代码分离的架构,即“Miidy.Cloud.Console”站与“Miidy.Cloud.Manage”站(两个前端站)同时通过web api的方式调用“Miidy.Clo ...
- vue单页面应用加入百度统计
版权声明:本文为CSDN博主「钟文辉」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/qq_39753974/a ...