我们通常在开发页面的时候,希望能够将页面中每个部分都单独分离成小切片,每个切片都有自己的视图结构、样式和逻辑。而每个切片形成的视图结构、样式和逻辑的整体我们就称之为组件。
组件有什么好处呢?
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 数据)MyLogoMyNav (传递了 navData 数据)NavItem (传递了 navData、item 数据)MyUser
这样的结构我们就称之为组件树,这样的设计就是「组件化」设计。
:::info
💡 提示
组件在封装的时候要想尽量的扁平化,没有必要把所有的内容全部拆分为组件,这样就会导致层层嵌套!不好进行维护,导致组件相互的依赖度太高。
:::
