在开发中,往往一些数据确实需要从上层传递到下层:
- 比如在一个页面中,我们从服务器请求到了很多的数据;
- 其中一部分数据,并不是使用整个页面大组件来展示,而是需要下面的子组件
- 这个时候,并不会在让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)。
如何进行父子组件间的通信呢?Vue官方提到两种方法:
- 通过props向子组件传递数据
- 通过事件向父组件发送消息
在下面的代码中,我直接将Vue实例当做父组件,并且其中包含子组件来简化代码。
通过 props 父组件向子组件传递数据
方式一:字符串数组,数组中的字符串就是传递时的名称。
方式二:对象,对象可以设置传递时的类型,也可以i设置默认等。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--父组件的 html 模板-->
<div id="vue">
<!--父组件数据 绑定给 子组件的数据定义-->
<cpn :cmovies ="movies" :cmessage="message"></cpn>
</div>
<!--子组件html模板-->
<template id="childrenHtml">
<div>
<ul><li v-for="item in cmovies">{{item}}</li></ul>
<h2>{{cmessage}}</h2>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//特别注意:当子组件需要引入父组件时,
// 子组件需要先定义在父组件之前
// 父传子:props
// props数据格式:1:字符串数组 2:对象
const cpnChildren = {
template: '#childrenHtml',
props: ['cmovies',"cmessage"],
data() {
// 必须 return 一个实例,当然可以 return 一个空
return{}
},
methods: {
}
}
// 父组件
// 通过 props 向子组件传递数据
const app = new Vue({
el: '#vue',
data: {
movies: ['java', 'c++', 'python', 'javaScript'],
message: '你好!华为'
},
// 局部注册子组件
components: {
cpn :cpnChildren
}
});
</script>
</body>
</html>
props写法
// props写法总结
props: {
// 基础的类型检查('null',匹配任何类型)
propA:Number,
// 多个可能的类型
propB:[String,Number],
// 必填的字符串
propC:{
type:Number,
required:true
},
// 带有默认值的数字
propD:{
type:Object,
// 对象或数组默认值必须从一个工厂函数获取
default:function () {
return {
message: 'hello'
}
}
},
// 自定义验证函数
propF:{
validator:function (value) {
//这个值必须是匹配下列字符串中的一个
return['success','warning','danger'].indexOf(value) !== -1
}
}
},
通过 $emit 父组件向子组件传递参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--父组件模板-->
<div id ="vue">
<!--其中这个v-on 不仅可以监听默认事件,还可以监听子组件事件-->
<!--v-on 可以用来@代替-->
<!--有的不支持驼峰:如果在script中定义了childrenCpn,在html中要用‘-’代替,不然渲染不出来-->
<!--需要注意的是:组件通信中,@子组件=父组件 -->
<children-cpn @itemclick="parentclick"></children-cpn>
<p>{{message}}</p>
</div>
<!--子组件模板-->
<template id="children">
<div>
<button v-for="item in categories" @click="itemclick(item)">
{{item.name}}
</button>
</div>
</template>
<!-- 引入vue.js 文件-->
<script src="../js/vue.js"></script>
<script>
//子组件
const childrenCpn = {
template:'#children',
data(){
return{
categories:[
{id:'aaa',name:'热门推荐'},
{id:'bbb',name:'手机数码'},
{id:'ccc',name:'家用家电'},
{id:'ddd',name:'电脑办公'},
{id:'eee',name:'市场营销'}
]
}
},
methods:{
itemclick(item){
// 子组件发射:自定义事件
this.$emit('itemclick',item)
}
}
};
// 父组件
const vue = new Vue({
el:'#vue',
data:{
message:'你好啊,华为'
},
components: {
childrenCpn
},
methods: {
parentclick(item){
console.log(item)
}
}
});
</script>
</body>
</html>