组件的通信
父子组件之间通信的方式
父组件传递给子组件
Props的数组用法
Props的对象用法
细节一:type的类型都可以是哪些呢?
细节二:对象类型的其他写法
细节三:Prop 的大小写命名
非Prop的Attribute
禁用Attribute继承和多根节点
App.vue
<template>
<div>
<show-message id="abc" class="why" title="哈哈哈" content="我是哈哈哈哈" message-info=""></show-message>
<show-message title="呵呵呵" content="我是呵呵呵呵"></show-message>
<show-message :title="title" :content="content"></show-message>
<show-message :title="message.title" :content="message.content"></show-message>
<show-message v-bind="message"></show-message>
<multi-root-element id="aaaa"></multi-root-element>
<!-- 补充 -->
<!-- 写成小驼峰personalInfo 也是可以的 -->
<!-- <show-message :personalInfo="personalInfo"></show-message> -->
<!-- <show-message :personal-info="personalInfo"></show-message> -->
</div>
</template>
<script>
import ShowMessage from './ShowMessage.vue';
import MultiRootElement from './MultiRootElement.vue';
export default {
components: {
ShowMessage,
MultiRootElement
},
data() {
return {
title: "嘻嘻嘻",
content: "我是嘻嘻嘻嘻",
message: {
title: "嘿嘿嘿",
content: "我是嘿嘿嘿"
}
}
}
}
console.log()
</script>
<style scoped>
</style>
ShowMessage.vue
<template>
<div>
<h2 v-bind="$attrs">{{title}}</h2>
<p>{{content}}</p>
</div>
</template>
<script>
export default {
// props: ['title', 'content']
inheritAttrs: false,
props: {
title: String,
content: {
type: String,
required: true,
default: "123"
},
counter: {
type: Number
},
info: {
type: Object,
default() {
return {name: "why"}
}
},
messageInfo: {
type: String
}
}
}
</script>
<style scoped>
</style>
MultiRootElement.vue
<template>
<h2>MultiRootElement</h2>
<h2>MultiRootElement</h2>
<!-- 【如果子组件是多个根元素,那么就要明确指定哪个根元素用到了父组件传递的属性。】 -->
<!-- 【如果子组只有一个根元素,那么根元素会自动接收父组件传递的属性。也可以明确指定根元素的子元素接收,此时根元素和子元素就同时接收了。】 -->
<h2 :id="$attrs.id">MultiRootElement</h2>
</template>
<script>
export default {
}
</script>
<style scoped>
</style>
子组件传递给父组件
自定义事件的流程
自定义事件的参数和验证
App.vue
<template>
<div>
<h2>当前计数: {{ counter }}</h2>
<counter-operation @add="addOne" @sub="subOne" @addN="addNNum"></counter-operation>
</div>
</template>
<script>
import CounterOperation from './CounterOperation.vue';
export default {
components: {
CounterOperation
},
data() {
return {
counter: 0
}
},
methods: {
addOne() {
this.counter++
},
subOne() {
this.counter--
},
addNNum(num, name, age) {
console.log(name, age);
this.counter += num;
}
}
}
</script>
<style scoped>
</style>
CounterOperation.vue
<template>
<div>
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
<hr>
<input type="text" v-model.number="num">
<button @click="incrementN">+n</button>
</div>
</template>
<script>
export default {
// 先注册
emits: ["add", "sub", "addN"],
// 对象写法的目的是为了进行参数的验证
// emits: {
// add: null, // null表示不需要验证
// sub: null,
// addN: (num, name, age) => {
// console.log(num, name, age);
// if (num > 10) {
// return true
// }
// return false;
// }
// },
data() {
return {
num: 0
}
},
methods: {
increment() {
console.log("+1");
this.$emit("add");
},
decrement() {
console.log("-1");
this.$emit("sub");
},
incrementN() {
this.$emit('addN', this.num, "why", 18);
}
}
}
new Array()
</script>
<style scoped>
/* CEBE8C D8BE88 CEBE8E */
</style>
组件间通信案例练习
App.vue
<template>
<div>
<tab-control :titles="titles" @titleClick="titleClick"></tab-control>
<h2>{{contents[currentIndex]}}</h2>
</div>
</template>
<script>
import TabControl from './TabControl.vue';
export default {
components: {
TabControl
},
data() {
return {
titles: ["衣服", "鞋子", "裤子"],
contents: ["衣服页面", "鞋子页面", "裤子页面"],
currentIndex: 0
}
},
methods: {
titleClick(index) {
this.currentIndex = index;
}
}
}
</script>
<style scoped>
</style>
TabControl.vue
<template>
<div class="tab-control">
<div class="tab-control-item"
:class="{active: currentIndex === index}"
v-for="(title, index) in titles"
:key="title"
@click="itemClick(index)">
<span>{{title}}</span>
</div>
</div>
</template>
<script>
const
export default {
emits: ["titleClick"],
props: {
titles: {
type: Array,
default() {
return []
}
}
},
data() {
return {
currentIndex: 0
}
},
methods: {
itemClick(index) {
this.currentIndex = index;
this.$emit("titleClick", index);
}
}
}
</script>
<style scoped>
.tab-control {
display: flex;
}
.tab-control-item {
flex: 1;
text-align: center;
}
.tab-control-item.active {
color: red;
}
.tab-control-item.active span {
border-bottom: 3px solid red;
padding: 5px 10px;
}
</style>