通过发布订阅模式子传父
传父发布订阅注册方法:基于自定义事件,把父组件中的某一个方法注册到任务队列中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.min.css">
<title>Document</title>
<style>
.container {
box-sizing: border-box;
margin: 20px auto;
padding: 0 10px;
border: 1px solid #AAA;
width: 300px;
}
.container h3 {
font-size: 16px;
line-height: 40px;
border-bottom: 1px dashed #AAA;
font-weight: bold;
}
.red {
color: red !important;
}
</style>
</head>
<body>
<!-- 基于自定义事件,把父组件中的某一个方法注册到任务队列中
-->
<div id="app">
<my-vote v-for="item in voteList" :title="item.title"></my-vote>
</div>
<template id="MyVoteTemplate">
<div class="container">
<h3><span v-text='title'> </span>(<span v-text='num'></span>)</h3>
<vote-content></vote-content>
<!-- 子传父发布订阅注册方法:基于自定义事件,把父组件中的某一个方法注册到任务队列中 -->
<!-- @changeparent自定义事件必须是小写的 -->
<vote-button @changeparent='changeParent'></vote-button>
</div>
</template>
<template id="VoteContentTemplate">
<div class="content">
<p>支持人数:<span>0</span> </p>
<p>反对人数:<span>0</span> </p>
<p>支持率:<span>0%</span> </p>
</div>
</template>
<template id="VoteButtonTemplate">
<div class="footer">
<button type="button" class="btn btn-primary" @click="handle('support')">支持</button>
<button type="button" class="btn btn-danger" @click="handle('oppose')">反对</button>
</div>
</template>
<script src="../node_modules/vue/dist/vue.min.js"></script>
<script>
//=>注册组件
//=>在组件中调取渲染使用
const VoteContent = {
template: '#VoteContentTemplate',
data() {
return {
}
}
};
const VoteButton = {
template: '#VoteButtonTemplate',
data() {
return {
}
},
methods:{
handle(type){
//=>通知任务队列中changeParent这个自定义事件执行:第一个参数是自定义事件类型changeParent,第二个参数(后面的参数都是通知方法执行的时候,给方法传递的参数)
this.$emit('changeparent',type)
}
}
};
const MyVote = {
template: '#MyVoteTemplate',
//=>子组件设置props用来接收父组件基于属性传递进来的信息: 在props中注册的属性和data一样,会挂载在当前实例上 this.title/{{title}}
//1.父组件传递的属性名是kebab-cese格式,子组件在注册时候应该按照camelCase/PasalCase格式来接收和使用:属性名传递的是大写的,其实也是按照小写的来传递,所以props中注册和使用的时候都按照小写的来处理即可
//props :["title","aaa"],
//2.注册属性的校验
// props :{
// title:String,
// aaa:[Number,Array]
// },
props: {
title: {
type: String,
//设置默认值,当 <my-vote></my-vote>中为空,设置默认default数据
default: '我是设定的属性默认值',
},
aaa: {
//=>数据格式
type: [Number, Array],
//=>是否为必传,TRUE必须传递
//required:true
//=>自定义验证规则 val传递的属性值,在函数中,根据自己的规则,返回true和false来验证传递的值是否符合规则
validator(val) {
return val >= 0;
}
}
},
data() {
return {
num:0
}
},
components: {
VoteContent,
VoteButton
},
methods:{
changeParent(type){
//=>this.$emit通知执行的时候传递的参数信息
this.num++;
}
}
};
let vm = new Vue({
el: '#app',
components: {
MyVote
},
data: {
voteList: [{
id: 1,
title: '前端细化'
}, {
id: 2,
title: '人工智能'
}
]
},
})
</script>
</body>
</html>
运行效果如下: