组件通信与访问
组件通信
父传子——props
在每个组件中使用 v-bind:cmovies=“movies” movies为父组件数据 ,传给子组件cmovies表示,通过props来向子子组件传递
props可以是一个数组,可以是一个对象(做类型限制,提供默认值)
类型限制包含:String,Number,Boolean,Array,Object,Date,Function,Symbol
<body>
<div id="app">
<cpn v-bind:cmovies="movies" :cmessage="message"></cpn>
</div>
<template id="cpn">
<div>
<h2>{{cmovies}}</h2>
<h3>{{cmessage}}</h3>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
Vue.component('cpn',{
template: "#cpn",
//父传子
props:["cmovies","cmessage"],
})
const app = new Vue({
el:'#app',
data:{
message:"你好",
movies:["12","13","14"]
},
component:{
cpn
}
})
</script>
</body>
做类型限制
//做类型限制
props:{
cmovies:Array,
cmessage:String,
}
提供默认值(设置默认值,数组和对象必须是函数)
//提供一下默认值
props:{
cmovies:{
type:Array,
default(){
return []
},//设置默认值,数组和对象必须是函数,其他的可以直接写
required:false,//true表示传值必须传,否者报错
},
cmessage:{
type:String,
default:"aaa",//设置默认值
required:false,//true表示传值必须传,否者报错
},
}
validator定义验证函数
props:{
cmessage:{
type:String,
default:"aaa",//设置默认值
required:true,//true表示传值必须传,否者报错
validator:function (value) {
//这个值必须匹配下列字符串的一个
return ['success','warning','danger'].valueOf(value)!==-1
}
},
}
子传父(自定义事件)
在子组件中通过this.$emit()来触发事件,在父组件中v-on来监听子组件事件
如下:在子组件中发生点击事件,发出 this.$emit(“itemclick”,item) 发射事件itemclick,item表示传递的参数,在父组件中监听事@itemclick=“cpnClick”,监听了itemclick事件,响应了cpnClick函数
<body>
<!--父组件模板-->
<div id="app">
<!-- 监听事件,默认传输子组件的传输参数-->
<cpn @itemclick="cpnClick"></cpn>
</div>
<!--子组件模板-->
<template id="cpn">
<div>
<button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template:'#cpn',
data(){
return {
categories:[
{
id:'1',
name:"家用家电"
},
{
id:'2',
name:"手机数码"
},
{
id:'3',
name:"热门推荐"
},
{
id:'4',
name:"电脑办公"
},
]
};
},
methods:{
btnClick(item){
//发射事件,item表示传递的参数
this.$emit("itemclick",item)
}
}
}
const app = new Vue({
el:'#app',
data:{
message:"你好"
},
components:{
cpn
},
methods:{
cpnClick(item){
console.log(item);
}
}
})
</script>
</body>
双向传递
通过v-bind和v-on结合实现双向传递
(event.target.value来获取input中的值)
(双向绑定v-model不能绑定props的值,否则会报错)
<body>
<div id="app">
<h1>{{num1}}</h1>
<h1>{{num2}}</h1>
<cpn
:number1="num1"
:number2="num2"
@num1change="num1appchange"
@num2change="num2appchange"></cpn>
</div>
<template id="cpn">
<div>
<h1>{{dnumber1}}</h1>
<input type="text" :value="dnumber1" @input="num1inputchange">
<h1>{{dnumber2}}</h1>
<input type="text" :value="dnumber2" @input="num2inputchange">
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn={
template:'#cpn',
props:{
number1:{
type:Number,
},
number2:{
type:Number,
}
},
data(){
return {
dnumber1:this.number1,
dnumber2:this.number2,
}
},
methods:{
num1inputchange(event){
this.dnumber1=event.target.value;
this.$emit("num1change",this.dnumber1);
},
num2inputchange(event){
this.dnumber2=event.target.value;
this.$emit("num2change",this.dnumber2);
}
}
}
const app = new Vue({
el:'#app',
data:{
num1:1,
num2:2,
},
components:{
cpn
},
methods: {
num1appchange(value){
this.num1=parseInt(value);
},
num2appchange(value){
this.num2=parseInt(value);
}
}
})
</script>
</body>
通过watch实现
watch能够监听某个属性的改变,名称为属性名,参数为newValue和oldValue
<body>
<div id="app">
<h1>{{num1}}</h1>
<h1>{{num2}}</h1>
<cpn :number1="num1"
:number2="num2"
@num1change="num1appchange"
@num2change="num2appchange"></cpn>
</div>
<template id="cpn">
<div>
<h1>{{dnumber1}}</h1>
<input type="text" v-model="dnumber1">
<h1>{{dnumber2}}</h1>
<input type="text" v-model="dnumber2">
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn={
template:'#cpn',
props:{
number1:{
type:Number,
},
number2:{
type:Number,
}
},
data(){
return {
dnumber1:this.number1,
dnumber2:this.number2,
}
},
//监听属性值的改变
watch:{
dnumber1(newValue){
this.$emit("num1change",newValue);
},
dnumber2(newValue){
this.$emit("num2change",newValue);
},
},
}
const app = new Vue({
el:'#app',
data:{
num1:1,
num2:2,
},
components:{
cpn
},
methods: {
num1appchange(value){
this.num1=parseInt(value);
},
num2appchange(value){
this.num2=parseInt(value);
}
}
})
</script>
</body>
组件访问
父访问子($children)
拿到所有子组件用$children,this. $children是一个数组类型,包含了所有子组件对象,
<body>
<div id="app">
<cpn></cpn>
<cpn></cpn>
<button @click="btnClick">按钮</button>
</div>
<template id="cpn">
<div>我是子组件</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:"你好"
},
components:{
cpn:{
template:'#cpn',
methods:{
showMessage(){
console.log("showMessage!");
}
},
data(){
return {
name:"我是子组件的name"
}
}
}
},
methods:{
btnClick(){
// $children
for(let c of this.$children){
console.log(c.name);
}
}
}
})
</script>
</body>
打印两个 “我是子组件的name”
父访问子($refs)
拿到特定的子组件用$refs,在组件中定义ref,来通过 $refs来实现
<body>
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn ref="aaa"></cpn>
<button @click="btnClick">按钮</button>
</div>
<template id="cpn">
<div>我是子组件</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:"你好"
},
components:{
cpn:{
template:'#cpn',
methods:{
showMessage(){
console.log("showMessage!");
}
},
data(){
return {
name:"我是子组件的name"
}
}
}
},
methods:{
btnClick(){
//$refs(reference) 对象类型,默认为空的对象,必须再组件上加 ref=“123”
console.log(this.$refs);
console.log(this.$refs.aaa.name);
}
}
})
</script>
</body>
子访问父($parent —— $root)
访问父组件用$parent ,访问根组件用 $root
<body>
<div id="app">
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>我是cpn组件</h2>
<ccpn></ccpn>
</div>
</template>
<template id="ccpn">
<div>
<h2>我是子组件</h2>
<button @click="btnClick">按钮</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:"你好"
},
components:{
cpn:{
template:'#cpn',
data(){
return {
name:"我是中间组件的name",
}
},
components: {
ccpn:{
template: '#ccpn',
methods:{
btnClick(){
//访问父组件
// console.log(this.$parent.name);
//访问根组件
console.log(this.$root.message);
}
},
}
}
}
},
})
</script>
</body>