此篇说明了如何利用props和$emit对父子组件通信,父子组件之间的通信还有ref / $refs、provide/ inject等方式,后面继续进行说明。
单向数据流:所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
另外,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
当我看到面试题的示例,只看到父组件如何写的代码,子组件写的代码,并且尝试了运行起来看看是如何传值的,控制台会出现很多问题。下面我就总结下如何在vue里面使用父子组件通信:
方式一
// 路由文件——index.js
import Son from '../components/son.vue'
import Father from '../components/father.vue'
const routes = [
{
path: '/father',
name: 'Father',
component: Father,
redirect: '/son',
children:[
{ path: '/son',name: 'Son',component: Son}
]
},
]
方式二
{
path: '/father',
name: 'father',
component: resolve => require(['@/components/father.vue'], resolve),
children: [
{
path: '/son',
name:"son",
component: resolve => require(['@/components/son.vue'], resolve),
},
]
},
刚开始方式一相比于方式二写路由的作用在哪里并不了解,参考了其他博主的文章,作用如下:如果用import引入的话,当项目打包时路由里的所有component都会打包在一个js中,造成进入首页时,需要加载的内容过多,时间相对比较长。
当你用require这种方式引入的时候,会将你的component分别打包成不同的js,加载的时候也是按需加载,只用访问这个路由网址时才会加载这个js。
这里插入一下router-link的概念,因为当我们想在一个父组件中点击了子组件,像a链接一样跳转到指定目标地址,就可以用到router-link。
router-link组件支持用户在具有路由功能的应用中点击导航。通过to属性指定目标地址,默认渲染为带有正确连接的a标签,可以通过配置tag属性生成别的标签。另外,当目标路由成功激活时,链接元素自动设置一个表示激活的css类名
router-link组件的属性有:
to 、replace、 append、 tag、 active-class、 exact 、 event、 exact-active-class
正式说明在父组件里面怎么写:
(1)引入子组件
(2)注册子组件
(3)使用子组件,绑定父组件中的数据,可向子组件进行传值
注意:组件中的数据共有三种形式:data、props、computed。
// 父组件——father.vue
<template>
<div id="app">
<!-- 若想要将子组件具有像a链接一样,点击它之后,则跳转到指定目标地址。则可以利用router-link>
<router-link to="/father/son"> -->
<Son :fatherData="fatherData"></Son> // 3.使用子组件,并绑定父组件的数据
<!-- </router-link> -->
</div>
</template>
<script>
import Son from './son.vue'//1.引入子组件
export default {
data () {
return{
fatherData:[
{
id:1,
title:'德莱文'
},
{
id:2,
title:'辛德拉'
},
{
id:3,
title:'火男'
},
{
id:4,
title:'男刀'
},
{
id:5,
title:'女坦'
},
{
id:6,
title:'泽丽'
}
]
}
},
components: {
Son //2.注册子组件
},
}
</script>
// 子组件
<template>
<div>
<p v-for="item in fatherData" :key="item.id">{{item.title}}</p>
</div>
</template>
<script>
export default {
name:'Users',
// 使用props 来接受父组件传过来的数据
props:['fatherData'],
}
</script>
可以看到父组件里的fatherData数据传给了子组件的props,并在父组件中渲染出了子组件(p标签就是子组件里面使用的)。
Vue 3 现在提供一个 emits 选项,和现有的 props 选项类似。这个选项可以用来定义一个组件可以向其父组件触发的事件。
与上述方法类似
//子组件
<template>
<h1 @click="changeTitle">{{title}}</h1>
</template>
<script>
export default {
name:'Son',
data() {
return {
title:"我是子组件的标题"
}
},
methods:{
changeTitle(){
this.$emit("titleChanged","现在我从子组件传过来了") // 参数1:自定义事件名称;参数2:子组件向父组件传递的值“现在我从子组件传过来了”。
}
}
}
</script>
<template>
<div id="father">
<Son v-on:titleChanged="updateTitle"></Son> //3.使用子组件
<h2>{{title}}</h2>
</div>
</template>
<script>
import Son from './son.vue'//1.引入子组件
export default {
name:'father',
components:{Son},//2.注册子组件
data(){
return{
title:"我是父组件的标题"
}
},
methods:{
updateTitle(e){
this.title = e
}
}
}
</script>
可以看到刚开始父组件中title的值是“我是父组件的标题”,点击后,变成“现在我从子组件传过来了”。
参考链接
【VUE】父子组件通讯
<router-link>属性详解
vue-router嵌套路由