在进入这个话题之前,首先我们先来想一下在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)的更多相关文章

  1. 三大前端框架(react、vue、angular2+)父子组件通信总结

    公司业务需要,react.vue.angular都有接触[\无奈脸].虽然说可以拓展知识广度,但是在深度上很让人头疼.最近没事的时候回忆各框架父子组件通信,发现很模糊,于是乎稍微做了一下功课,记录于此 ...

  2. vue 父子组件通信props/emit

    props 1.父组件传递数据给子组件 父组件: <parent> <child :childMsg="msg"></child>//这里必须要 ...

  3. vue 父子组件通信-props

    父组件:引用了ComBack组件 ComBack组件:引用了BasicInfor组件 先使用props获取父组件的headInfo这个对象,这里注意(default)默认返回值要用工厂形式返回 Bas ...

  4. vue 父子组件通信

    算是初学vue,整理一下父子组件通信笔记. 父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息. 一.父组件向子组件下发数据: 1.在子组件中显式地用props选项声明它预期的数据 ...

  5. Vue 非父子组件通信

    组件是Vue核心的一块内容,组件之间的通信也是很基本的开发需求.组件通信又包括父组件向子组件传数据,子组件向父组件传数据,非父子组件间的通信.前两种通信Vue的文档都说的很清楚,但是第三种文档上确只有 ...

  6. Vue 非父子组件通信方案

    Vue 非父子组件通信方案 概述 在 Vue 中模块间的通信很普遍 如果是单纯的父子组件间传递信息,父组件可以使用 props 将数据向下传递到子组件,而在子组件中可以使用 events (父组件需要 ...

  7. vue 父子组件通信详解

    这是一篇详细讲解vue父子组件之间通信的文章,初始学习vue的时候,总是搞不清楚几个情况 通过props在父子组件传值时,v-bind:data="data",props接收的到底 ...

  8. Vue.JS快速上手(组件间的通信)

    前言 Vue采用的是组件化思想,那么这些组件间是如何通信的呢?下面详细介绍一下. 所谓组件间通信,不单单是我们字面上理解的相互传递数据,这里还包括一个组件访问另一个组件的实例方法等,如父组件通过ref ...

  9. 总结Vue第二天:自定义子组件、父子组件通信、插槽

    总结Vue第二天:自定义子组件.父子组件通信.插槽 一.组件: 组件目录 1.注册组件(全局组件.局部组件和小demo) 2.组件数据存放 3.父子组件通信(父级向子级传递数据.子级向父级传递数据) ...

随机推荐

  1. 如何解决mac brew遇到无法下载的依赖?

    使用brew安装软件时,需要下载依赖包,但是如果依赖包特别大的时候,就很容易失败:brew本身不支持断点续传:但是可以使用wget -c的方式断点续传的下载依赖:下载完如何给brew安装使用呢?参考: ...

  2. mysql索引 多个单列索引和联合索引的区别详解

    背景: 为了提高数据库效率,建索引是家常便饭:那么当查询条件为2个及以上时,我们是创建多个单列索引还是创建一个联合索引好呢?他们之间的区别是什么?哪个效率高呢?我在这里详细测试分析下. 一.联合索引测 ...

  3. Http 请求到后端过程

    描述下网页一个 Http 请求,到后端的整个请求过程 评注:基础题,感觉属于常识题!必会! 回答: 利用DNS进行域名解析 -------> 发起TCP的3次握手 --------> 建立 ...

  4. (3)Spring Boot日志

    文章目录 选择哪一种日志框架 日志的使用 Spring Boot 日志使用 选择哪一种日志框架 市面上日志门面有: JCL(Jakart Commons Logging) .SLF4J(Simple ...

  5. Ubuntu 18.04 LTS 设置代理(系统代理;http 代理;sock5 代理;apt 代理 ...)

    1. 设置系统代理 1.1 设置 http 代理 1.1.1 只在当前 shell 生效 export http_proxy="http://<user>:<passwor ...

  6. PAT(B) 1049 数列的片段和(C)规律

    题目链接:1049 数列的片段和 (20 point(s)) 题目描述 给定一个正数数列,我们可以从中截取任意的连续的几个数,称为片段.例如,给定数列 { 0.1, 0.2, 0.3, 0.4 },我 ...

  7. 【Qt】Qt5.12编译MySQl5.7驱动(亲自测试成功)

    目录 00. 目录 01. 安装Qt5.12 02. 打开MySQL源码项目 03. 编译MySQL驱动代码 04. 修改mysql.pro文件 05. 编译之后得到对应的库 06. 拷贝动态库到指定 ...

  8. 跟我一起学docker

    一.认识 1.什么是docker Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目.它基于 Google 公司推出的 Go 语言实现. 项目后来加 ...

  9. springcloud 1.5 与 springcloud 2.0 配置区别

    eureka配置区别: 1.5:${spring.cloud.client.ipAddress}:${server.port} 2.0:${spring.cloud.client.ip-address ...

  10. 开源微信小程序商城测评

    1. Java版 1)微同商城 减少重复造轮子,开源微信小程序商城 .快速搭建一个属于自己的微信小程序商城. 官网地址:https://fly2you.cn 开源地址:https://gitee.co ...