前面我们是将所有的逻辑放到一个App.vue中:
我们来分析一下下面代码的嵌套逻辑,假如我们将所有的代码逻辑都放到一个App.vue组件中:
- 我们会发现,将所有的代码逻辑全部放到一个组件中,代码是非常的臃肿和难以维护的。
- 并且在真实开发中,我们会有更多的内容和代码逻辑,对于扩展性和可维护性来说都是非常差的。
- 所以,在真实的开发中,我们会对组件进行拆分,拆分成一个个功能的小组件。
<template>
<div id="app">
<div>
<h2>Headerh2>
<h2>NavBarh2>
div>
<div>
<h2>Bannerh2>
<ul>
<li>商品列表1li>
<li>商品列表2li>
<li>商品列表3li>
<li>商品列表4li>
<li>商品列表5li>
ul>
div>
<div>
<h2>Footerh2>
<h2>免责声明h2>
div>
div>
template>
我们可以按照如下的方式进行拆分:
按照如上的拆分方式后,我们开发对应的逻辑只需要去对应的组件编写就可, App.vue中的代码如下 :
<template>
<div id="app">
<!-- 头部 -->
<app-header></app-header>
<!-- 内容 -->
<app-main></app-main>
<!-- 底部 -->
<app-foot></app-foot>
</div>
</template>
<script>
// 引入子组件
import AppHeader from './components/AppHeader.vue'
import AppMain from './components/AppMain.vue'
import AppFoot from './components/AppFoot.vue'
export default {
// 注册组件
components: {
AppHeader,
AppMain,
AppFoot
}
}
</script>
上面的嵌套逻辑如下,它们存在如下关系:
在开发过程中,我们会经常遇到需要组件之间相互进行通信:
总之,在一个Vue项目中,组件之间的通信是非常重要的环节,所以接下来我们就具体学习一下组件之间是如何相互之间传递数据的;
父子组件之间如何进行通信呢?
在开发中很常见的就是父子组件之间通信,比如父组件有一些数据,需要子组件来进行展示:
什么是Props呢?
Props有两种常见的用法:
例如我们有如下的一个根组件, 用于展示用户信息, 但是由于子组件中的数据时固定的, 我们展示的两个信息是相同的
<template>
<div class="app">
<show-info name="chenyq" age="18" height="1.88" />
<show-info name="kaisa" age="19" height="1.85" />
div>
template>
<script>
import ShowInfo from "./ShowInfo.vue"
export default {
components: {
ShowInfo
}
}
script>
<template>
<div class="infos">
<h2>姓名: {{ name }}h2>
<h2>年龄: {{ age }}h2>
<h2>身高: {{ height }}h2>
div>
template>
<script>
export default {
// props数组的方式接收父组件数据
props: ["name", "age", "height"]
}
script>
数组用法中我们只能说明传入的attribute的名称,并不能对其进行任何形式的限制,接下来我们来看一下对象的写法是如何让我们的props变得更加完善的。
在开发中, 我们使用更多的是对象的方法
当使用对象语法的时候,我们可以对传入的内容限制更多:
例如父组件中, 我们再展示一个信息, 这个信息不传递任何数据
<template>
<div class="app">
<show-info name="chenyq" :age="18" :height="1.88" />
<show-info name="kaisa" :age="19" :height="1.85" />
<show-info />
div>
template>
子组件中使用对象的方式接收父组件传递的数据
<template>
<div class="infos">
<h2>姓名: {{ name }}h2>
<h2>年龄: {{ age }}h2>
<h2>身高: {{ height }}h2>
div>
template>
<script>
export default {
// 2.props对象的方式接收父组件数据
props: {
name: {
// 指定传入的类型
type: String,
// 指定是否必传项
require: false,
// 指定传入默认值
default: "我是默认名字"
},
age: {
type: Number,
require: false,
default: 10
},
height: {
type: Number,
require: false,
default: 1.5
}
}
}
script>
展示效果如下图, 如果父组件没有传递数据, 那么会使用默认数据
补充一 : type可以指定如下类型 :
补充二: 对象类型其他写法
export default {
props: {
// 1.如果是一个对象类型, 必须通过函数返回一个对象
friend: {
type: Object,
default() {
return { name: "aaa", age: 18, height: 1.88 }
}
},
// 2.多个可能的类型
propA: {
type: [String, Number]
}
}
}
什么情况下子组件需要传递内容到父组件呢?
我们如何完成上面的操作呢?
例如我们做一个计数器:
<template>
<div class="add">
<button @click="btnClick(1)">+1button>
<button @click="btnClick(5)">+5button>
<button @click="btnClick(10)">+10button>
div>
template>
<script>
export default {
methods: {
btnClick(count) {
// 发送自定义事件
// 第一个参数, 自定义的事件名, 第二个参数, 是要传递的参数
this.$emit("add", count)
}
},
}
script>
<template>
<div class="sub">
<button @click="btnClick(1)">-1button>
<button @click="btnClick(5)">-5button>
<button @click="btnClick(10)">-10button>
div>
template>
<script>
export default {
methods: {
btnClick(count) {
// 发送自定义事件
// 第一个参数, 发送的自定义事件名, 第二个参数, 发送的参数
this.$emit("sub", count)
}
},
}
script>
<template>
<div class="app">
<h2>当前计数: {{ counter }}h2>
<add-counter @add="addBtnClick" />
<sub-counter @sub="subBtnClick" />
div>
template>
<script>
import AddCounter from "./AddCounter.vue"
import SubCounter from "./SubCounter.vue"
export default {
components: {
AddCounter,
SubCounter
},
data() {
return {
counter: 0
}
},
methods: {
addBtnClick(count) {
this.counter += count
},
subBtnClick(count) {
this.counter -= count
}
},
}
script>
在项目开发中, 有可能子组件发送自定义事件的开发者, 和监听自定义事件的开发者不是同一个人 :
export default {
emits: ["sub", "add"]
}