「前端组件化」该怎么理解?

大家好,我是若川。今天分享一篇关于前端组件化」的好文。欢迎点击下方卡片关注我。

以下是正文~


这里我们一起来学习前端组件化的知识,而组件化在前端架构里面是最重要的一个部分。

讲到前端架构,其实前端架构中最热门的就有两个话题,一个就是组件化,另一个就是架构模式。组件化的概念是从开始研究如何扩展 HTML 标签开始的,最后延伸出来的一套前端架构体系。而它最重要的作用就是提高前端代码的复用性。

架构模式就是大家特别熟悉的 MVC, MVVM 等设计模式,这个话题主要关心的就是前端跟数据逻辑层之间的交互。

所以说,前端架构当中,组件化可以说是重中之重。在实际工程当中,其实组件化往往会比架构模式要更重要一些。因为组件化直接决定了一个前端团队代码的复用率,而一个好的组件化体系是可以帮助一个前端团队提升他们代码的复用率,从而也提升了团队的整体效率。

因为复用率提高了,大家重复编写的代码量就会降低,效率就会提高,从而团队中的成员的心理和心智负担就会少很多。

!! 所以学习组件化可以是说是非常重要的

这里我们先从了解什么是组件化和一个组件的基本组成部分开始。

组件的基本概念

组件都会区分为模块和对象,组件是与 UI 强相关的,所以某种意义上我们可以认为组件是特殊的模块或者是特殊的对象。

!! 组件化既是对象也是模块

组件化的特点是可以使用树形结构来进行组合,并且有一定的模版化的配置能力。这个就是我们组件的一个基本概念。

对象与组件的区别

首先我们来看对象,它有三大要素:

  1. 属性 —— Properties

  2. 方法 —— Methods

  3. 继承关系 —— Inherit

在 JavaScript 中的普通对象可以用它的属性,方法和继承关系来描述。而这里面的继承,在 JavaScript 中是使用原型继承的。

这里说的 “普通对象” 不包含复杂的函数对象或者是其他的特殊对象,而在 JavaScript 当中,属性和方法是一体的。

相对比组件,组件里面包含的语义要素会更丰富一点,组件中的要素有:

  • 属性 —— Properties

  • 方法 —— Methods

  • 继承 —— Inherit

  • 特性 —— Attribute

  • 配置与状态 —— Config & State

  • 事件 —— Event

  • 生命周期 —— Lifecycle

  • 子组件 —— Children

PropertiesAttribute 在英语的含义中是有很大的区别的,但是往往都会翻译成 “属性”。如果遇到两个单词都出现的时候,就会把 Attribute 翻译为 “特性”,把 Properties 翻译成 “属性”。这两个要素要怎么区分呢?这里在文章的后面会和大家一起详细了解。

接下来就是组件的 Config,它就是对组件的一种配置。我们经常会在一个构造函数创建一个对象的时候用到 Config ,我们传入这个构造函数的参数就叫 “ Config”(配置)。

同时组件也会有 state(状态)。当用户去操作或者是一些方法被调用的时候,一个 state 就会发生变化。这种就是组件的状态,是会随着一些行为而改变的。而 statepropertiesattributesconfig 都有可能是相识或者相同的。

event 就是 “事件” 的意识,而一个事件是组件往外传递的。我们的组件主要是用来描述 UI 这样的东西,基本上它都会有这种事件来实现它的某种类型的交互。

每一个组件都会有生命周期 lifecycle,这个一会儿在文章的后面会详细的展开学习。

组件的 children 是非常重要的一部分,children 也是组件当中一个必要的条件,因为没有 children 组件就不可能形成树形结构,那么描述界面的能力就会差很多。

之前有一些比较流行的拖拽系统,我们可以把一些写好的 UI 组件拖到页面上,从而建立我们的系统界面。但是后面发现除了可以拖拽在某些区域之外,还需要一些自动排序,组件嵌套组件的功能需求。这个时候组件与组件之间没有树形结构就不好使了。

最后组件在对象的基础上添加了很多语义相关的概念,也是这样使得组件变成了一种非常适合描述 UI 的概念。

组件 Component

我们用一张图来更深入的了解组件。

组件最直接产生变化的来源就是用户的输入和操作,比如说当一个用户在我们的选择框组件中选中了一个选项时,这个时候我们的状态 state,甚至是我们的子组件 children 都会发生变化。

图中右边的这几种情况就是组件的开发者与组件的关系。其中一种就是开发者使用了组件的标记代码 Markup Code,来对组件产生影响。其实,也就是开发者通过组件特性 Attribute 来更改组件的一些特征或者是特性。

!! Attribute 是一种声明型的语言,也是标记型代码 Markup Code。而 Markup Code 也不一定是我们的 HTML 这种 XML 类的语言。在标记语言的大生态中,其实有非常多的语言可以用来描述一个界面的结构。但是最主流的就是基于 XML 体系的。在我们 Web 领域里面最常见的就是 XML 。而 JSX 也可以理解为一种嵌入在编程语言里面的 XML 结构。

开发者除了可以用 Attribute,也可以用 Property 来影响组件。这个组件本身是有 Property (属性)的,当开发者去修改一个组件的属性时,这个组件就会发生变化。而这个就是与对象中的 属性 Property 是一样的概念。

!! Attribute 和 Property 是不是一样的呢?有的时候是,有的时候也不是,这个完全取决于组件体系的设计者。组件的实现者或者是设计者可以让 attributeproperty 统一。甚至我们把 stateconfigattributeproperty 四者都全部统一也是可以的。

然后就是 方法 method,它是用于描述一个复杂的过程,但是在 JavaScript 当中的 Property 是允许有 getset 这样的方法的,所以最终 methodproperty 两者的作用也是差不多的。

那么这里我们可以确定一个概念,使用组件的开发者会使用到 methodproperty,这些组件的要素。但是如果一个开发组件的开发者需要传递一个消息给到使用组件的程序员,这个时候就需要用到 事件 event。当一个组件内部因为某种行为或者事件触发到了变化时,组件就会给使用者发送 event 消息。所以这里的 event 的方向就是反过来的,从组件往外传输的。

通过这张图我们就可以清楚知道组件的各个要素的作用,以及他们的信息流转方向。

特性 Attribute

在所有组件的要素中,最复杂的无非就是 AttributeProperty

我们从 Attribute 这个英文单词的理解上,更多是在强调描述性。比如说我们描述一个人,头发很多、长相很帅、皮肤很白,这些都是属于 Attribute,也可以说是某一样东西的特性和特征方面的描述。

Property 更多的是一种从属关系。比如,我们在开发中经常会发现一个对象,它有一个 Property 是另外一个对象,那么大概率它们之间是有一个从属关系的,子对象是从属于父对象。但是这里也有一种特殊情况,如果我们是弱引用的话,一个对象引用了另外一个对象,这样就是完全是另一个概念了。

上面讲的就是这两个词在英文中的区别,但是在实际运用场景里面他们也是有区别的。

因为 Property 是从属关系的,所以经常会在我们面向对象里面使用。而 Attribute 最初就是在我们 XML 里面中使用。它们有些时候是相同的,有些时候又是不同的。

Attribute 对比 Property

这里我们用一些例子来看看 Attribute 和 Property 的区别。我们可以看看它们在 HTML 当中不等效的场景。

Attribute:

<my-component attribute="v" />
<script>myComponent.getAttribute('a')myComponent.setAttribute('a', value)
</script>
  • HTML 中的 Attribute 是可以通过 HTML 属性去设置的

  • 同时也可以通过 JavaScript 去设置的

Property:

myComponent.a = 'value';
  • 这里就是定义某一个元素的 a = ‘value’

  • 这个就不是 attribute 了,而是 property

!! 很多同学都认为这只是两种不同的写法,其实它们的行为是有区别的。

Class 属性

<div class="class1 class2"></div><script>var div = document.getElementByTagName('div');div.className // 输出就是 class1 class2 
</script>

早年 JavaScript 的 Class 是一个关键字,所以早期 class 作为关键词是不允许做为属性名的。但是现在这个已经被改过来了,关键字也是可以做属性名的。

为了让这个关键字可以这么用,HTML 里面就做了一个妥协的设计。在 HTML 中属性仍然叫做 class 但是在 DOM 对象中的 property 就变成了 className。但是两者还是一个互相反射的关系的,这个神奇的关系会经常让大家掉一些坑里面。

比如说在 React 里面,我们写 className它自动就把 Class 给设置了。

Style 属性

现在 JavaScript 语言中,已经没有 class 和 className 两者不一致的问题了。我们是可以使用 div.class 这样的写法的。但是 HTML 中就还是不支持 class 这个名字的,这个也就是一些历史包袱导致的问题。

有些时候 Attribute 是一个字符串,而在 Property 中就是一个字符串语义化之后的对象。最典型的就是 Style

<div class="class1 class2" style="color:blue"></div><script>var div = document.getElementByTagName('div');div.style // 这里就是一个对象
</script>

在 HTML 里面的 Style 属性他是一个字符串,同时我们可以使用 getAttribute 和 setAttribute 去取得和设置这个属性。但是如果我们用这个 Style 属性,我们就会得到一个 key 和 vaule 的结构。

Href 属性

在 HTML 中 href 的 attribute 和 property 的意思就是非常相似的。但是它的 property 是经过 resolve 过的 url。

比如我们的 href 的值输入的是 "//m.taobao.com"。这个时候前面的 http 或者是 https 协议是根据当前的页面做的,所以这里的 href 就需要编译一遍才能响应当前页面的协议。

做过 http 到 https 改造的同学应该都知道,在让我们的网站使用 https 协议的时候,我们需要把所有写死的 http 或者 https 的 url 都要改成使用 //

所以在我们 href 里面写了什么就出来什么的,就是 attribute。如果是经过 resolve 的就是我们的 property 了。

<a href="//m.taobao.com"></a>
<script>var a = document.getElementByTagName('a');// 这个获得的结果就是 "http://m.taobao.com", 这个 url 是 resolve 过的结果// 所以这个是 Propertya.href;// 而这个获得的是 "//m.taobao.com", 跟 HTML 代码中完全一致// 所以这个是 Attributea.getAttribute('href');
</script>

在上面的代码中我们也可以看到,我们可以同时访问 property 和 attribute。它们的语义虽然非常的接近,但是它们不是一样的东西。

不过如果我们更改了任何一方,都会让另外一方发生改变。这个是需要我们去注意的现象。

Input 和 value

这个是最神奇的一对,而 value 也是特别的坑。

我们很多都以为 property 和 attribute 中的 value 都是完全等效的。其实不是的,这个 attribute 中的 input 的 value 相当于一个 value 的默认值。不论是用户在 input 中输入了值,还是开发者使用 JavaScript 对 input 的 value 进行赋值,这个 input 的 attribute 是不会跟着变的。

而在 input 的显示上是会优先显示 property,所以 attribute 中的 value 值就相当于一个默认值而已。这就是一个非常著名的坑,早期同学们有使用过 JQuery 的话,我们会觉得里面的 prop 和 attr 是一样的,没想到在 value 这里就会踩坑。

所以后来 JQuery 库就出了一个叫 val 的方法,这样我们就不需要去想 attribute 还是 property 的 value,直接用它提供的 val 取值即可。

!! 这里一方面是一起增强一下 HTML 的 property 和 attribute 的知识。另一方面就是让我们认识到,就算是非常顶级的计算机专家设计的标签系统,也出现两个差不多的属性不等效的问题。那么如果让我们去设计一个标签系统,我们会让 property 和 attribute 等效还是不等效呢? 等学习完整个组件化的知识后,我们一起来回答一下这个问题。

如何设计组件状态

这里我们来分析一下,propertyattributestateconfig 在组件设计中都有什么区别。

这里 Winer 老师给我们整理了一个表格,分成了四个场景:

  • Markup set —— 用标签去设置

  • JavaScript Set —— 使用 JavaScript 代码去设置

  • JavaScript Change —— 使用 JavaScript 代码去改变

  • User Input Change —— 终端用户的输入而改变

Markup setJavaScript setJavaSscript ChangeUser Input Change
property
attribute
state
config

那么我们一个一个来讲述一下:

  • Property

    • ❌  它是不能够被 markup 这种静态的声明语言去设置的

    • ✅ 但是它是可以被 JavaScript 设置和改变的

    • ❓ 大部分情况下 property 是不应该由用户的输入去改变的,但是小数情况下,可能是来源于我们的业务逻辑,才有可能会接受用户输入的改变

  • Attribute

    • ❓ 用户的输入就不一定会改变它,与 Property 同理

    • ✅ 是可以由 markup,JavaScript 去设置的,同时也是可以被 JavaScript 所改变的

  • State

    • ❌ 状态是会由组件内部去改变的,它不会从组件的外部进行改变。如果我们想设计一个组件是从外部去改变组件的状态的话,那么我们组件内部的 state 就失控了。因为我们不知道组件外部什么时候会改变我们组件的 state,导致我们 state 的一致性无法保证。

    • ✅ 但是作为一个组件的设计者和实践者,我们一定要保证用户输入是能改变我们组件的 state 的。比如说用户点击了一个 tab,然后点中的 tab 就会被激活,这种交互一般都会用 state 去控制的。

  • Config

    • ✅ Config 在组件中是一个一次性生效的东西,它只会在我们组件构造的时候触发。所以它是不可更改的。也是因为它的不可更改性,所以我们通常会把 config 留给全局。通常每个页面都会有一份 config,然后拿着这个在页面内去使用。

组件生命周期 Lifecycle

讲到生命周期,我们最容易想到的会有两个,一个是 created 一个是 destroy。世界万物的生命必定会有 出生死亡,这两个生命周期。

那么在这两个开始与结束之间有什么生命周期呢?我们就需要想一下,一个组件在构造到销毁之间都会发生什么事情。

一个组件有一个非常重要的事情,就是它被创建之后,它有没有被显示出来。这里就涉及生命周期中的 mount,也就是组件有没有被挂載到 “屏幕的这棵树上”。这个生命周期我们可以在 React 和 Vue 里面看到,我们经常会使用这个生命周期,在组件被挂載后做一些相应的初始化操作。

有挂載那必然就会有卸载,所以组件中的 mountunmount 是一组生命周期。而这个挂載与卸载的整个生命周期是可以反复的发生的,我们可以挂上去然后卸下来,然后再挂上去,这样反复又反复的走这个生命周期。

所以在 unmount 之后,我们是可以回到 created 构建组件的这个生命周期的状态。

那么组件还会在什么时候发生状态更变呢?这里我们就有两种情况:

  • 程序员使用代码去改变或者设置这个组件的状态

  • 用户输入时影响了组件的状态

比如说我们用户点了一下按钮或者 Tab,这个时候就会触发这个组件的状态更变。同时也会产生一个组件的生命周期,而这个生命周期就是 Render 渲染或者 Update 更新。

所有这些生命周期加在一起就是我们一个组件完整的生命周期。我们看到的所谓 willMountdidMount 无非就是这个生命周期之中更细节的位置。下面我给大家附上一张完整的生命周期的图。

Children

最后我们来讲一下 Children(子组件)的概念。Children 是构建组件树最重要的一个组件特性,并且在使用中其实有两种类型的 Children:

  • Content 型 Children —— 我们有几个 Children,但是最终就能显示出来几个 Children。这种类型的 Children,它的组件树是非常简单的。

  • Template 型 Children —— 这个时候整个 Children 它充当了一个模版的作用。比如说我们设计一个 list,但是最后的结果不一定就与我们 Children 代码中写的一致。因为我们 List 肯定是用于多个列表数据的,所以 list 的表示数量是与我们传入组件的 data 数据所相关的。如果我们有 100 个实际的 children 时,我们的 list 模版就会被复制 100 份。

在设计我们的组件树的 children 的时候,一定要考虑到这两种不同的场景。比如我们在 React中,它没有 template 型的 children,但是它的 children 可以传函数,然后这个函数可以返回一个 children。这个时候它就充当了一个模版型 children 的作用了。那么在 Vue 里面当我们去做一些无尽的滚动列表的时候,这个对 Vue 的模版型 children 就有一定的要求。

结束语

这里我们就学习完了整个组件的概念和知识了,下一篇文章我们就会一起来设计和搭建一个组件系统,并且了解到它的各方各面的实践知识。我们还会用一些典型的组件和典型的功能来让大家对组件的实现有一定的了解。


最近组建了一个江西人的前端交流群,如果你也是江西人可以加我微信 ruochuan12 拉你进群。



················· 若川出品 ·················

今日话题

通常加我微信进群都会做一层验证,主要是进群打广告的太多了。问得最多的问题是:JS如何准确的判断数组?只有部分小伙伴答不上。欢迎留言评论。

一个愿景是帮助5年内前端人走向前列的公众号

后台回复“1”,可加我个人微信,长期交流学习

推荐阅读

我在阿里招前端,我该怎么帮你?(现在还能加我进模拟面试群)

如何拿下阿里巴巴 P6 的前端 Offer

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/276091.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大屏设计的视觉统一_视觉设计中的统一

大屏设计的视觉统一视觉设计的统一性是什么&#xff1f; (What is unity in visual design?) The concept of unity in visual design means a group of elements working together to create a greater whole. It means, as the clich goes: A whole that is greater than th…

跟着官方文档能学懂React Hooks就怪了

大家好&#xff0c;我是若川。今天分享一篇关于「React Hooks」的好文。欢迎点击下方卡片关注我。以下是正文~回想下你入门Hooks的过程&#xff0c;是不是经历过&#xff1a;类比ClassComponent的生命周期&#xff0c;学习Hooks的执行时机慢慢熟练以后&#xff0c;发现Hooks的执…

origin图上显示数据标签_Origin(Pro):寒假都结束了,这个图还是不会画?【数据绘图】...

寒假前给大家分享了一个图&#xff0c;大家要的教程来了。【数据绘图】好图分享&#xff1a;寒假&#xff1f;不存在的&#xff01;​mp.weixin.qq.com绘图思路&#xff1a;左侧起止时间&#xff1a;散点图&#xff0c;交换XY坐标轴&#xff1b;中间的连线为Drop Lines&#xf…

可以激发设计灵感的音乐_建立灵感库以激发您的创造力

可以激发设计灵感的音乐I often find a lot of inspiration from work I see while scrolling social media. Saving art or images that inspire you allows you to build a library of resources to draw from whenever you’re working on a project.在滚动社交媒体时&#…

若川知乎问答:做前端感觉很吃力怎么办?

前些日&#xff0c;我发了一篇推文《做前端感到越来越吃力了&#xff01;怎么办&#xff1f;》&#xff0c;虽然是推广&#xff0c;但阅读量却很高&#xff0c;推广标题我们大概率不能改&#xff0c;感觉骗了大家&#xff0c;掉粉挺多人。写稿的人可能就是看到了知乎这个问答。…

d3 制作条形图_停止制作常见的坏条形图的5个简单技巧

d3 制作条形图Bar charts were probably the first type of chart you were ever introduced to in first grade. Their simplicity makes them a standard in visualizing data, but it is its accessibility that leads visualizers to often be careless with bar charts.乙…

SVN之使用原则

以下是我起草的部门SVN规范里原则的一部分。文件提交时要求必须提交注释&#xff0c;注明相关修改信息&#xff0c;例如bug号、任务描述等。具体内容可采用约定或者设置的形式。你所提交的改变将体现给其他开发者&#xff0c;要明白提交的后果&#xff0c;提交之前要慎重。代码…

图解 React-router 源码

大家好&#xff0c;我是若川。欢迎加我微信 ruochuan12今天分享一篇react-router源码文章&#xff0c;深入理解路由的本质。微信预计阅读只需8分钟。点击下方卡片关注我&#xff0c;或者查看源码系列文章。阅读源码小 tips&#xff1a;从整体到细节&#xff0c;刚开始不要太拘泥…

android 辅助功能_辅助功能简介

android 辅助功能Accessibility may be more than a moral imperative to ensure products are inclusive of more people who already experience barriers in daily life — it has a very practical outcome, benefiting everyone including the person with the disability…

推荐几个前端大佬,真的厉害!

新的一年&#xff0c;推荐几个还在坚持输出的高质量前端公众号&#xff0c;你想要的&#xff1a;React/Vue/Node/工程化/面试经验等&#xff0c; 这里都有。不多说&#xff0c;直接看介绍。???? 程序员成长指北考拉&#xff0c;一个有趣且乐于分享的妹子&#xff0c;专注 N…

RawCode-本身就是实验性的8位类型

What if a type is created solely from the bit-representation of characters?如果仅根据字符的位表示形式创建类型怎么办&#xff1f; This question was the basis of creating this experimental type. The type no longer uses familiar characters. ‘A’ looks like …

2d访问冲突_Light | 基于环形分隔微镜阵列的高速随机访问轴向聚焦系统

撰稿 | OSANJU 刘 扬01导读近日&#xff0c;来自美国加州大学伯克利分校的Rikky Muller教授团队&#xff0c;在国际顶尖学术期刊《Light: Science & Applications》发表了题为“A micromirror array with annular partitioning for high-speed random-access axial focus…

编译出现ARM与THUMB冲突

问题&#xff1a; fatal error LNK1112: module machine type THUMB conflicts with target machine type ARM 解决方法&#xff1a; 在project-setting-linker-command line下&#xff0c;添加/machine:THUMB&#xff0c;如下&#xff1a; 转载于:https://www.cnblogs.com/xfd…

阿里腾讯面试梳理个人成长经历分享

大家好&#xff0c;我是若川。欢迎加我微信 ruochuan12&#xff0c;长期交流学习。今天分享一篇江西师范大学大四同学学习一年前端入职腾讯的经历&#xff0c;关注很久的读者朋友应该知道我也是毕业于江西不那么知名的高校。微信预计阅读只需18分钟。点击下方卡片关注我&#x…

unity 局部照亮_通过著名的艺术家照亮“光与空间运动”

unity 局部照亮Ever since minimalism momentously gained popularity in the 1960’s, the “Light and Space” movement has naturally acquired prominence for its stunning juxtaposition in geometric abstraction, luminescence, and space. Artwork from this distinc…

如何抓住重点,系统高效地学习数据结构与算法?

你是否曾跟我一样&#xff0c;因为看不懂数据结构和算法&#xff0c;而一度怀疑是自己太笨&#xff1f;实际上&#xff0c;很多人在第一次接触这门课时&#xff0c;都会有这种感觉&#xff0c;觉得数据结构和算法很抽象&#xff0c;晦涩难懂&#xff0c;宛如天书。正是这个原因…

Google Map浏览下载器

很久没有更新博客了&#xff0c;最近为了玩Google Map&#xff0c;专门写了个小工具。用以在浏览Google地图时&#xff0c;将关心区域的图片保存到本地。软件主界面如下图&#xff1a; 主界面提取子库主要功能有&#xff1a; 1、可以浏览Google网站的三种图&#xff1a;交通、地…

Node.js 开发者 2020 年度报告

大家好&#xff0c;我是若川。欢迎加我微信 ruochuan12&#xff0c;长期交流学习。今天分享一篇Node.js报告&#xff0c;记得当时我还参与填写这个调查问卷了&#xff0c;Node.js的重要性不言而喻。微信预计阅读只需7分钟。点击下方卡片关注我&#xff0c;或者查看源码系列文章…

视觉设计_视觉设计:

视觉设计What does the customer first see in your application? Yes, its your application design. So it is very important to pay attention to how the design is made. There’s so many factors to include, like how usually people meaning a symbol, how their pr…

开源分布式中间件 DBLE 快速入门指南

2019独角兽企业重金招聘Python工程师标准>>> 环境准备 DBLE项目资料 DBLE官方网站&#xff1a;https://opensource.actionsky.com 可以详细了解DBLE的背景和应用场景&#xff0c;本文不涉及到的细节都可在官方文档获得更细节都信息&#xff1b;对于刚了解到同学&…