通过props通信(父传子)
基本准备
使用vue脚手架创建个vue项目,然后整理目录结构如下:
其中各个文件内容如下:
父组件Father.vue
<template>
<div>
<h2>我是父组件</h2>
</div>
</template>
<script>
</script>
<style>
</style>
子组件Child.vue
<template>
<div>
<h2>我是子组件</h2>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
index.js文件中设置路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import Father from '../components/Father.vue'
import Child from '../components/Child.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Father',
component: Father
},
{
path: '/father',
component: Father
},
{
path: '/child',
component: Child
}
]
const router = new VueRouter({
routes
})
export default router
App.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
<style>
</style>
main.js注册Child为全局组件
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import Child from './components/Child.vue'
Vue.config.productionTip = false
Vue.component('child', Child)
new Vue({
router,
render: h => h(App)
}).$mount('#app')
通过props父子组件传值
子组件的props选项能够接收来自父组件数据。仅仅只能接收,props是单向绑定的,即只能父组件向子组件传递,不能反向。而传递的方式也分为两种:静态传递和动态传递。
静态传递
子组件通过props选项来声明一个自定义的属性,然后父组件就可以在嵌套标签的时候,通过这个属性往子组件传递数据了。
静态传递就是直接在属性中设置要传递的数据信息。
在父组件中通过<child></child>调用子组件,其中info是自定义的属性,即该属性名可以任意自定义命名,而双引号内的内容是传递给子组件的信息,这个数据是规定死的,不能修改,因此叫做静态传递。
在子组件通过props来接收父组件的信息,props是规定的关键字,而通过一个数组来存放接收的父组件信息,其中'info'是父组件的属性名。
父组件Father.vue
<template>
<div>
<h2>我是父组件</h2>
<child info="我是传递给子组件的信息"></child>
</div>
</template>
<script>
</script>
<style>
</style>
子组件Child.vue
<template>
<div>
{{info}}
</div>
</template>
<script>
export default {
props: ['info']
}
</script>
<style>
</style>
效果
动态传递
可以用 v-bind 来实现。通过v-bind绑定props的自定义的属性,传递去过的就不是静态的字符串了,它可以是一个表达式、布尔值、对象等等任何类型的值。
动态传递是通过v-bind绑定属性自定义的属性,然后在data中传递不同类型的数据,而不只是字符串。
父组件通过v-bind动态绑定属性来动态传递数据信息到子组件,其中传递的数据可以是字符串、布尔值、数组和对象等。其中v-bind后面的info是自定义的属性名,而双引号内的是在data中声明的数据对象,以便达到动态更新数据的目的。
在子组件通过props来接收父组件的信息,props是规定的关键字,而通过一个数组来存放接收的父组件信息,其中'info'是父组件的属性名。
父组件Father.vue
<template>
<div>
<h2>我是父组件</h2>
<child v-bind:info="stringInfo"></child>
<child v-bind:info="boolInfo"></child>
<child v-bind:info="arrayInfo"></child>
<child v-bind:info="objectInfo"></child>
</div>
</template>
<script>
export default {
data () {
return {
stringInfo: '我是传递给子组件的string信息',
boolInfo: true,
arrayInfo: ['唐僧', '孙悟空', '猪八戒', '沙僧'],
objectInfo: { name: '李四', age: 15 }
}
}
}
</script>
<style>
</style>
子组件Child.vue
<template>
<div>
{{info}}
</div>
</template>
<script>
export default {
props: ['info']
}
</script>
<style>
</style>
浏览器查看效果
通过$ref 实现通信(父传子)
概述
查看官网
(1)ref如果用到DOM上,指向该DOM元素,通过this.$refs可以获取到该DOM的属性集合,访问到DOM元素,作用与选择器类似。
例如:
<template>
<div>
<h2 ref="title">我是父组件</h2>
</div>
</template>
<script>
export default {
data () {
return {
}
},
created () {
console.log(this.$refs)
}
}
</script>
<style>
</style>
解释说明:
- 要使用ref必须先在元素或组件上设置一个ref属性,如ref="title"。
- 可以通过this.$refs获取绑定元素的属性。
查看控制台打印的结果,可以看到绑定DOM元素的属性,其中title表示名称,而h2表示绑定的DOM元素,是一个对象。
如果设置多个ref,是一个对象,打印出不同的元素
存在多个ref属性时,打印指定名称的对象
可以通过this.$refs.age.innerText打印里面的属性值。
甚至可以更改属性值
this.$refs.age.innerHTML = "<h2 style='background:red'>我的年龄是15</h2>"
(2)如果ref用在子组件上,指向的是组件实例,可以理解为对子组件的索引,通过$refs可能获取到在子组件里定义的属性和方法。
示例:
Father.vue
<template>
<div>
<h2 ref="name">我是父组件</h2>
<child info="我是传给子组件的信息" ref="child"></child>
<button @click="printRef">打印Ref</button>
</div>
</template>
<script>
export default {
data () {
return {
}
},
methods: {
printRef () {
console.log(this.$refs.child)
}
}
}
</script>
<style>
</style>
解释说明:
- 本例中ref是绑定在子组件child中的
- 可以通过this.$refs来打印绑定子组件的信息,并可以在其后(如this.$refs.child.info)获取具体属性,操作方法。
就可以看到与DOM元素打印结果不一样
可以通过this.$refs.child.info来打印info属性的值
如果使用this.$refs.child.info = '我是通过ref修改后传给子组件的信息'来修改就会报错了
通信传值
父组件Father.vue
<template>
<div>
<h2>我是父组件</h2>
<child ref="info"></child>
</div>
</template>
<script>
export default {
data () {
return {
}
},
methods: {
},
mounted: function () {
console.log(this.$refs.info)
this.$refs.info.getInfo('我是子组件')
}
}
</script>
<style>
</style>
子组件Child.vue
<template>
<div>
{{info}}
</div>
</template>
<script>
export default {
data () {
return {
info: ''
}
},
methods: {
getInfo (m) {
this.info = m
}
}
}
</script>
<style>
</style>
解释说明:
先看看控制台打印出来的
具体过程如下
prop和$ref之间的区别
- prop 着重于数据的传递,它并不能调用子组件里的属性和方法。像创建文章组件时,自定义标题和内容这样的使用场景,最适合使用prop。
- $ref 着重于索引,主要用来调用子组件里的属性和方法,其实并不擅长数据传递。而且ref用在dom元素的时候,能起到选择器的作用,这个功能比作为索引更常有用到。
通过$emit 实现通信(子传父)
概述
基本语法如下:
vm.$emit( event, arg )
$emit 绑定一个自定义事件event,当这个这个语句被执行到的时候,就会将参数arg传递给父组件,父组件通过@event监听并接收参数。
上面两种示例主要都是父组件向子组件通信,而$emit 实现子组件向父组件通信。
实现
子组件Child.vue
<template>
<div>
<h2>我是子组件</h2>
</div>
</template>
<script>
export default {
data () {
return {}
},
methods: {},
mounted: function () {
this.$emit('getInfo', '我是父组件')
}
}
</script>
<style>
</style>
父组件Father.vue
<template>
<div>
<h2>{{info}}</h2>
<child @getInfo="showInfo"></child>
</div>
</template>
<script>
export default {
data () {
return {
info: ''
}
},
methods: {
showInfo (val) {
this.info = val
}
}
}
</script>
<style>
</style>
解释说明:
- 子组件Child.vue通过this.$emit('getInfo', '内容')来向父组件传递数据,其中this.$emit(event, params)是固定语法,其中event即'getInfo'是自定义的函数名,也是要在父组件中被触发监听的函数,而params即'内容'是getInfo函数的参数,要传递到父组件的内容。
- 父组件Father.vue在调用的子组件<child></child>中绑定该事件,并且有一个参数。