在下面代码中cpn2是父组件,cpn1是子组件
父子组件错误用法:以子标签的形式在Vue实例中使用
因为当子组件注册到父组件的components时,Vue会编译好父组件的模块
该模块的内容已经决定了父组件将要渲染的HTML(相当于父组件中已经有了子组件的内容了)
cpn1是只能在cpn2中被识别的,写在div里是会被浏览器忽略的
<div id="app">
<cpn2></cpn2>
</div>
<script>
//创建第一个组件构造器
const cpnC1=Vue.extend({
template:`
<div>
<h2>我是标题1</h2>
<p>我是内容1</p>
</div>`,
})
//创建第二个组件构造器
const cpnC2=Vue.extend({
template:`
<div>
<h2>我是标题2</h2>
<p>我是内容2</p>
<cpn1></cpn1>
</div>`,
components:{
cpn1:cpnC1
}
})
const app=new Vue({
el:"#app",
data:{
message:'hello'
},
components:{
cpn2:cpnC2
}
})
</script>
父组件给子组件传值,子组件通过props接收数据
props的值有两种方式:
方式一:字符串数组,数组中的字符就是传递时的名称
方式二:对象,对象可以设置传递时的类型,也可以设置默认值等等
注意:如果props传递的名称为驼峰命名法例cInfo,则在自定义组件绑定此名称的时候不能用驼峰命名法会报错,要使用-连接,例如c-info
<div id="app">
<cpn :cmovies="movies"></cpn>
</div>
<template id="cpn">
<div>
<h2>{{cmessage}}</h2>
{{cmovies}}
</div>
</template>
<script>
const cpn={
template:'#cpn',
//方式一
//props:['cmovies'],
//方式二
props:{
//1.类型限制
cmovies:Array,
//2.提供一些默认值,不需要进行绑定,绑定的话就显示data下的数据了
cmessage:{
type:String,
default:'aaaaaaaa'
}
}
}
const app=new Vue({
el:"#app",
data:{
message:'hello',
movies:[
'海贼王','大耳朵图图','熊出没'
]
},
components:{
cpn
}
})
</script>
上图是props的值方式一的例图
子组件给父组件传值:通过自定义事件
自定义事件的流程:
在子组件中,通过$emit()来触发事件
在父组件中,通过v-on来监听子组件事件
<!-- 父组件模板 -->
<div id="app">
<cpn v-on:itemclick="cpnClick"></cpn>
</div>
<!-- 子组件模板 -->
<template id="cpn">
<div>
<button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
</div>
</template>
<script>
//子组件
const cpn={
template:'#cpn',
data(){
return {
categories:[
{id:'a',name:'热门推荐'},
{id:'b',name:'手机数码'},
{id:'c',name:'家用家电'},
{id:'d',name:'电脑办公'},
]
}
},
methods: {
btnClick(item){
//发射事件:自定义事件(自定义事件名称,自定义事件参数)
this.$emit('itemclick',item)
}
},
}
//父组件
const app=new Vue({
el:"#app",
data:{
message:'hello',
},
components:{
cpn
},
methods:{
cpnClick(item){
console.log("cpnClick",item)
}
}
})
</script>