自从React,Vue等前端框架在市面上大量使用之后,组件化开发逐渐成为了前端主流开发方式,今天我就在这里给大家分享一下在我们平时的开发中我们自己应该如何去封装组件。主要从以下三个方面给大家讲解:

  • 什么是组件
  • 为什么要拆分组件
  • 如何拆分组件

什么是组件

对功能、ui样式的封装,一个功能或者一个ui样式就是一个组件,导航栏,banner,页脚等等这些功能、样式都是组件。
不同的框架对组件的分类有些许差别,比如有些人对react的组件分为函数式组件、无状态组件和有状态组件、展示型组件和容器型组件等;有些人vue对组件分为全局组件、局部组件、函数式(无状态)组件、普通(有状态)组件、动态组件、普通(非动态)组件、异步组件、普通(非异步)组件、递归组件、普通(非递归)组件。但本质上都是大同小异。鉴于我们目前使用的都是vue框架,所有今天的分享也主要是针对vue的组件进行分析。

1.按组件注册方式分类:vue将组件分为全局组件和局部组件

全局组件:使用Vue.component全局注册的组件(在我们的项目中一般情况下是在utils文件中进行统一注册的)

Vue.component("my-component-name", {/****/
});

局部组件:在使用的页面通过components单独引入(,一般情况下推荐使用按需引入的方式引入组件)

2.按组件有无自己的状态分类:可以分为函数式(无状态)组件和普通(无状态)组件

函数式:用jsx语法编写的html或者template 标签上加 functional。一般是无状态 (没有响应式数据)的组件可以注册成函数式组件(它没有管理任何状态,也没有监听任何传递给它的状态,也没有生命周期方法。实际上,它只是一个接受一些 prop 的函数,所以渲染开销也低很多,在一定程度上能提高一些性能)
jsx 的语法:

<script>import OtherComponent from "./other";export default {name: "FunctionComponent",functional: true,components: {OtherComponent},props: {title: {type: String,required: true}},render(h, { props }) {const { title } = props;return (<div><p> 我是函数式组件</p><p>props {title}</p><OtherComponent otherInfo={title} title="我是函数式组件的其他组件" /></div>);}};
</script>

template 标签标记 functional:

<template functional><div>{{ props.title }}<p>otherInfo {{ props.otherInfo }}</p></div>
</template>
<script>export default {functional: true,props: {title: {default: "",type: String},otherInfo: {default: "",type: String}}};
</script>

3.按组件是否动态分类:可以分为动态组件和普通(非动态)组件
动态组件:通过component 标签加is属性(属性值为引入的组件名称)引入的组件

<template><div><component :is="currentTabComponent"></component></div>
</template>
export default {components: {DynamicComponent1},data() {return {currentTabComponent: "DynamicComponent1"};}
};

一般是需要很多组件之间切换的情况下可以使用动态组件,例如下面的代码就可以优化为动态组件:(el-tab-pane部分代码基本上是重复的知识少量数据不一样,这种时候就可以将el-tab-pane里面的数据在data中定义成一个数组型的变量,然后循环el-tab-pane,里面的组件可以更换成自定义组件)

优化后:(如果组件切换比较频繁的话,可以在components标签外面加上keep-alive标签将已失活的组件缓存起来,以便下次切换组件时不需要从新创建、挂载)

<template><el-tabs v-model="activeTab"><el-tab-pane v-for="(item) in tabList" :key="item.id" :label="item.name" :name="item.id"><component :is="item.components"></component></el-tab-pane></el-tabs>
</template>
<script>
import page1 from "@/views/example/page1";
import page2 from "@/views/example/page2";
import page3 from "@/views/example/page3";
export default {name: "tab",data() {return {activeTab: '1',tabList: [{ id: '1', name: "页面1", components: page1 },{ id: '2', name: "页面2", components: page2 },{ id: '3', name: "页面3", components: page3 }]};},
};
</script>

4.按组件是否异步分类:可以分为异步组件和普通(非异步)组件
异步组件:按需加载组件,在需要组件的时候再去加载组件(这样可以让首屏部分代码块优先加载,加快首屏渲染速度,像目前我们项目中使用的路由懒加载,以及局部这种方式引入的组件() => import(’./my-async-component’)等都是异步组件)

异步组件引入的方式:

a.通过工厂函数

Vue.component('async-example', function (resolve, reject) {resolve({template: '<div>hello vue !</div>'})
})

b.通过webpack 的 代码切割 功能一起配合使用:

Vue.component('async-wepack-example', function (resolve) {// require会告诉webpack将你的代码切割成多个包,然后通过ajax加载    require(['./my-async-component'], resolve)
})

c.通过 import()

Vue.component('async-wepack-example', () => import('./my-async-component'))
局部组件注册异步组件(这种方式为目前我们项目中常用的方式)
new Vue({components: {myComponent: () => import('./my-async-component')}
})
高级异步组件
const asyncComponent = () => ({component:import('./my-async-component.vue'),//需要加载的组件delay: 200, // 展示加载时组件的延时时间,默认200毫秒error: errorComponent, // 加载失败显示组件loading: loadingComponent, // 加载时使用组件timeout: 2000 // 超时时间,默认 Infinity(组件加载也超时后则使用加载失败时使用的组件。)
})

5.按组件是否循环引用分类:可以分为递归组件和普通(非递归)组件

递归组件:组件可以在它们自己的模板中调用自身(必须要定义name组件的值,一般用于树组件,侧边栏路由组件等)

<template><div><ul><li v-for="item in list" :key="item.name"><span>{{ item.name }}</span><recursive-component v-if="item.children" :list="item.children" /></li></ul></div>
</template>
<script>export default {name: "RecursiveComponent",props: {list: {default: () => [],type: Array}}};
</script>

6.在一般我们的开发中,组件又分为ui展示类组件(着重ui样式的展示,比如我们常用的element-ui之类的)、功能组件(不注重样式,只对功能进行封装)、业务组件等。

为什么要拆分组件

1.提高开发效率

在组件化开发之前,我们每个页面都是单独的,如果在开发一个页面的时候遇到了曾今开发过类似的部分,只能复制粘贴到当前页面,然后进行一些改动,有时参数、变量之类的丢失,页面或许还会报错,还要花费大量的时候去排查问题,组件化之后,类似的部分我们只需要引入组件即可,无需重复开发,一定程度上也减少了代码量,极大提高项目的编译速度

2.方便重复使用

一个组件可在多个地方使用

3.简化调试步骤

一个页面出现问题时,可以优先定位到某个模块,然后直接定位到某个组件,无需看完整个页面的所有代码然后排查问题

4.提升整个项目的可维护性

页面都由组件组成,模块与模块之间的耦合度降低,删除修改某个模块的功能时仅需直接修改组件

5.便于协同开发

每个组件都把对应的业务功能收敛在一个工程里,彼此互不打扰。 在多人团队里,每个人只负责自己的业务模块,对业务功能的增删改查,都只限定在自己的这个业务模块里,不会影响其他人的业务。

如何拆分组件

1.保证单一职责。

一个组件“只做好一件事”,只做好最基本的事,留出可组合的口子。尽量把更多功能外包出去。

2.开放封闭原则。

对扩展开放,对修改封闭。有新的业务需求时,首先考虑如何扩展,单个组件只实现最单纯的功能,更多通过扩展实现,而不是修改组件。

3.单个组件文件最好不超过200或400kb

追求短小精悍,有利于调试,缩小排错范围

4.避免函数有太多的参数。入口处检查参数的有效性,出口处检查返回的正确性

避免别人使用组件时传参有误,造成很多无法预料的报错。

5.松耦合,封装的组件不要依赖太多其他的组件

当所有问题都是通过堆砌一堆开源代码解決时,一是会存在冗余,二是很难调试,当其中一个模块有问题时可能会导致整个组件无法使用,复杂的依赖关系,也会发生版本冲突之类的事情。如果要依赖组件或库,要依赖稳定的也就是不经常変的。

6.无副作用:不依赖、不修改外部变量,内部操作不影响其它组件

在保证输入/输出不变的情况,可以安全的被替换。

7.提炼精华,一些无关紧要的东西,比如数据获取,数据整理或事件处理逻辑,理想情况下应该将其移入外部 js 或者放在父组件中去进行处理,组件内只负责ui展示或者功能的实现。

8.合理组件化

将大块代码变成松散耦合且可复用的组件确实是有很多优点,但是并不是所有的页面结构都需要被抽离成组件,也不是所有的逻辑部分都需要被抽出到组件外部。我们在实际进行组件抽离工作的时候,需要考虑到不要过度的组件化。那么我们在决定是否要抽离组件的时候可以根据以下几点来判断:
a.是否有足够的页面结构/逻辑来保证它?如果它只是几行代码,那么最终可能会创建更多的代码来分隔它。

b.代码重复(或可能重复)? 如果某些东西只使用一次,并且服务于一个不太可能在其他地方使用的特定用例,那么将它嵌入其中可能会更好。

c.性能是否会受到影响?更改 state/props 会导致组件重新渲染,当发生这种情况时,你需要的是 只是重新去渲染经过 diff 之后得到的相关元素节点。在较大的、关联很紧密的组件中,你可能会发现状态更改会导致在不需要它的许多地方重新呈现,这时应用的性能就可能会开始受到影响。

组件化开发之如何封装组件相关推荐

  1. Vue.js-Day02-PM【组件化开发(全局注册组件、局部注册组件、案例)、组件的配置选项、轮播图实例(左右切换按钮、底部导航栏、定时器、鼠标移入-图片静止)】

    Vue.js实训[基础理论(5天)+项目实战(5天)]博客汇总表[详细笔记] 目   录 4.组件化开发 4.1.组件的注册 全局注册 局部注册(只能在当前整个Vue实例的范围内才可以使用) 使用组件 ...

  2. 我的react组件化开发道路(二) 分页 组件开发

    2019独角兽企业重金招聘Python工程师标准>>> 上一篇文章主要写了关于react组件化开发的一些基本配置,慢慢的深入到每个组件的详细介绍中,今天我们就来分享react的分页组 ...

  3. 四、Vue组件化开发学习笔记——父子组件通信,父级向子级传值(props),子级向父级传值(自定义事件),slot插槽

    一.父子组件的通信 在上一篇博文中,我们提到了子组件是不能引用父组件或者Vue实例的数据的. 但是,在开发中,往往一些数据确实需要从上层传递到下层: 比如在一个页面中,我们从服务器请求到了很多的数据. ...

  4. 【Vue 组件化开发 三】父组件给子组件传递数据、组件通信(父传子、子传父)、父访问子(children、ref)、动态组件(is、component)

    目录 一.前言 完整内容请关注: 二.父组件给子组件传递数据 1.使用props属性,父组件向子组件传递数据 1.使用组件的props属性 2.向cmessage对象传值 2. props属性使用 1 ...

  5. Vue组件化开发 - 非常详细,不要错过哦~

    源码示例链接:https://pan.baidu.com/s/1NEYDmLl2K7nNa-AKWtJqVA 提取码:2c7a 目标 能够知道组件化开发思想 能够知道组件的注册方式 能够说出组件间的数 ...

  6. vue之购物车案例升级版、v-model之lazy、number、trim的使用、fetch和axios、计算属性、Mixins、虚拟dom与diff算法 key的作用及组件化开发

    文章目录 1.购物车案例升级版(含价格统计.全选/反选.商品增加减少) 2.v-model之lazy.number.trim的使用 3.fetch和axios 3.1.通过jquery+ajax实现v ...

  7. 组件化开发之-我们有什么必要使用组件化开发?

    原创 2016-05-19 背景介绍: 首先简单说一下为什我会写这篇文章呢? 源于今天讨论,提到这个组件化开发和以前没有多大区别,都需要合作编码,共同开发某些相同模块,本来之前都是按照模块划分来开发的 ...

  8. Vue全家桶之组件化开发

    作者 | Jeskson 掘金 | https://juejin.im/user/5a16e1f3f265da43128096cb 学习组件化开发,首先掌握组件化的开发思想,组件的注册方式,组件间的数 ...

  9. vue3组件化开发常用API

    组件化思想 为什么使用组件化开发? 当前前端比较流行的 Vue React 等框架,都会通过编写组件来完成业务需求,也就是组件化开发.包括小程序开发也会用到组件化开发的思想. 分析组件化思想开发应用程 ...

最新文章

  1. C/C++中constkeyword
  2. 用c实现跨平台异常捕获机制
  3. [原]vue实现全选,反选
  4. nyoj 715 Adjacent Bit Counts
  5. mysql格式化日期成分_MySQL格式化日期
  6. Android Makefile and build system 分析
  7. PyCharm高校固定资产管理系统django-python+vue
  8. 设置下载安装 桌面_电脑C盘快满了不要慌,别只知道清垃圾,这些设置也要改...
  9. Repeater实现批量删除
  10. HTML5 实现拼图游戏
  11. markdown删除代码空白行
  12. golang 报错 missing go.sum entry
  13. 微信开发工具无法支持vue文件
  14. 【转载】SpringBoot 接口数据加解密技巧,so easy!
  15. Excel如何隔一行或几行填充颜色
  16. Gitee生成公钥详细教程
  17. Makefile编写和使用技巧
  18. ‘step’的调用中是否存在不正确的参数数据类型或缺少参数
  19. 14.什么是响应式设计?响应式设计的基本原理是什么?如何做?
  20. 《拐点》简单选股绝招

热门文章

  1. Android OpenGLES2.0(一)OpenGLES2.0基础介绍
  2. 同济大学计算机学院杨志强,大学计算机课程论坛-同济大学计算机基础教研室.PDF...
  3. Sigcomm2017 Credit-Scheduled Delay-Bounded Congestion Control for Datacenters 论文阅读
  4. 在anaconda环境中安装tflearn模块
  5. python星星排列代码怎么写_【读码】python中的小星星*用法示例
  6. 计算机网络学习(二)物理层
  7. table动态修改表格内容
  8. 【LeetCode 3-中等】无重复字符的最长子串(高清截图)
  9. 一个有关占有而非所有的例子——帮人占座或者以物品占座的非正义性
  10. 技术更高,设计更远:华为全屋智能设计大赛的审美之跃