我们通常在开发页面的时候,希望能够将页面中每个部分都单独分离成小切片,每个切片都有自己的视图结构、样式和逻辑。而每个切片形成的视图结构、样式和逻辑的整体我们就称之为组件。
组件有什么好处呢?
1、复用性,每个组件都是独立的块,可以在任意的地方进行多次使用。
2、独立使用决定了组件的维护性高。
3、配置度高,虽然是独立但提供了接口,让开发者可以传入一些属性使其配置度高。
例如在 Vue 中想要使用组件进行相互嵌套:
const MyHeader = {
template: `
<header style="border: 1px solid #333;">
<my-logo />
<my-nav :nav-data="navData" />
<my-user />
</header>`,
// 注册数据属性
props: ["navData"],
components: {
MyLogo,
MyNav,
MyUser
}
};
以上代码,我们定义了一个MyHeader
的父组件,MyHeader
下面又引入包含了myLogo
、myNav
、myUser
这些子组件,所以父子组件是一种包含关系。
Vue 中如果你要使用组件就必须要通过components
进行局部注册(当然也有全局注册,这个我们后面在讨论):
const myHeader = {
// ...
components: {
MyLogo,
MyNav,
MyUser
}
}
myHeader
组件通过props
属性来注入父组件传递来的数据,然后又把navData
数据传递给了myNav
组件,像这样一层层的数据传递我们就称之为「单向数据流」!
const App = {
template: `
<div>
<!-- 使用组件 -->
<!-- 父组件给子组件传递数据 -->
<my-header :nav-data="navData" />
<!-- 复用组件,相互独立 -->
<my-header :nav-data="navData" />
</div>`,
components: {
// 注册组件,这样的方式叫做局部注册
// 局部注册:在组件内部的局部注册另外一个组件,只供当前组件使用
MyHeader
},
data() {
return {
navData: [
{
id: 1,
title: "百度",
link: "https:www.baidu.com"
},
{
id: 2,
title: "谷歌",
link: "https:www.google.com"
},
{
id: 3,
title: "必应",
link: "https:www.bing.com"
}
]
};
}
};
createApp(App).mount("#app");
const MyHeader = {
// ...
// 注册数据属性
props: ["navData"],
};
const MyNav = {
// ...
// 注册数据属性
props: ["navData"]
};
子组件不能直接更改父组件传递过来的props
数据,只能通过emit
去向父组件发送事件,然后让父组件去更改props
的数据:
const MyNav = {
template: `<button @click="onClickBtn">更改数据</button>`,
// 注册数据属性
props: ["navData"],
methods:{
onClickBtn(){
// 不要这样做!!!
this.navData.reverse()
}
}
};
const MyNav = {
template: `<button @click="onClickBtn">更改数据</button>`,
// 注册数据属性
props: ["navData"],
methods:{
onClickBtn(){
// 应该这样做!!!
this.$emit("updateData")
}
}
};
const MyHeader = {
template: `
<header style="border: 1px solid #333;">
<my-logo />
<my-nav :nav-data="myNavData" @update-data="updateData" />
<my-user />
</header>`,
// 注册数据属性
props: ["navData"],
components: {
MyLogo,
MyNav,
MyUser
},
data(){
return{
// 初始化的时候进行赋值
myNavData: this.navData
}
},
methods:{
updateData(){
this.myNavData.reverse()
}
}
};
回到组件的概念,我们发现上面的组件形成了这样的一种结构:
App (传递了 navData 数据)
MyHeader (传递了 navData 数据)
MyLogo
MyNav (传递了 navData 数据)
NavItem (传递了 navData、item 数据)
MyUser
这样的结构我们就称之为组件树,这样的设计就是「组件化」设计。
:::info
💡 提示
组件在封装的时候要想尽量的扁平化,没有必要把所有的内容全部拆分为组件,这样就会导致层层嵌套!不好进行维护,导致组件相互的依赖度太高。
:::