当前位置: 首页 > 科技观察

说说前端组件化

时间:2023-03-21 17:29:41 科技观察

在这里,我们来学习一下前端组件化的知识,而组件化是前端架构中最重要的部分。说到前端架构,其实前端架构最热门的话题有两个,一个是组件化,一个是架构模式。组件化的概念从研究如何扩展HTML标签开始,最终扩展出一套前端架构体系。而它最重要的作用就是提高前端代码的复用性。架构模式就是大家非常熟悉的MVC、MVVM等设计模式。这个话题主要关注的是前端和数据逻辑层的交互。因此,在前端架构中,组件化可以说是重中之重。在实际工程中,组件化往往比架构模式更重要。因为组件化直接决定了一个前端团队代码的复用率,而一个好的组件化系统可以帮助前端团队提高代码复用率,从而提高团队的整体效率。因为复用率提高了,大家重复写的代码量就会减少,效率也会提高,这样团队成员的心理和精神负担就会少很多。!!所以学习组件化可以说是非常重要的。这里我们先从了解什么是组件化,以及一个组件的基本组件开始。组件的基本概念组件分为模块和对象。组件与UI有很强的相关性,所以某种意义上我们可以把组件看作是特殊的模块或者特殊的对象。!!组件化既是对象又是模块。组件化的特点是可以使用树状结构进行组合,具有一定的模板配置能力。这是我们组件的一个基本概念。对象和组件的区别先来看对象,它有三大要素:属性——属性方法——方法继承关系——Inherit一个普通的对象在JavaScript中可以通过它的属性、方法、继承关系来描述.而这里的继承,在JavaScript中,使用的是原型继承。这里所说的“普通对象”不包括复杂的函数对象或者其他特殊的对象,但是在JavaScript中,属性和方法是一个。与组件相比,组件包含更多的语义元素。组件中的元素包括:Properties——Propertiesmethod——Methodsinheritance——Inheritcharacteristics——Attribute配置和状态——Config&Stateevents——EventlifeCycle-Lifecyclesubcomponents-ChildrenProperties和Attribute在英文中的含义非常不同,但它们通常被翻译成“属性”。如果两个词都出现,Attribute将被翻译为“feature”,Properties将被翻译为“attribute”。如何区分这两个元素?这里我会在后面的文章中和大家一起详细了解。接下来是组件的Config,是组件的一个配置。我们经常在构造函数创建对象时使用Config,我们传入这个构造函数的参数称为“Config”(配置)。同时,组件也会有一个状态。当用户操作或调用某些方法时,状态会发生变化。这是组件的状态,它会随着一些行为而改变。状态和属性、属性和配置可能都是熟悉的或相同的。Event是对“事件”的感知,一个事件由组件传递出去。我们的组件主要是用来描述UI之类的东西,基本上它都会有这种事件来实现某种类型的交互。每个组件都会有一个lifecycle生命周期,本文后面会详细研究。组件的children是很重要的一个部分,children也是组件中的必要条件,因为没有children组件是不可能形成树状结构的,所以对界面的描述能力会差很多。之前有一些流行的拖拽系统,我们可以将一些写好的UI组件拖到页面上来构建我们的系统界面。但是后来发现除了可以在某些区域进行拖拽之外,还需要一些组件嵌套组件的自动排序和功能需求。这时候如果组件之间没有树状结构就不好用了。最后,组件在对象的基础上增加了很多语义相关的概念,这使得组件成为一个非常适合描述UI的概念。Component组件我们用一张图来更深入地理解组件。组件更改最直接的来源是用户输入和操作。例如,当用户在我们的选择框组件中选择一个选项时,我们的state状态甚至我们的子组件children都会在这个时候发生变化。图中右侧的情况是组件的开发者与组件的关系。其中之一是开发人员使用组件的标记代码来影响组件。其实就是开发者通过组件的Attribute改变了组件的一些特性或特性。!!属性是一种声明性语言,也是标记代码。而MarkupCode也不一定像我们的HTML一样是类XML的语言。在标记语言这个大生态中,其实有很多语言可以用来描述一个界面的结构。但是最主流的是基于XML的系统。我们Web领域最常见的就是XML。JSX也可以理解为嵌入在编程语言中的XML结构。除了使用Attribute之外,开发者还可以使用Property来影响组件。这个组件本身有Property(属性),当开发者修改一个组件的属性时,这个组件就会改变。而这个和对象中的属性Property是同一个概念。!!Attribute和Property是一样的吗?有时是,有时不是,这完全取决于组件系统的设计者。组件的实现者或设计者可以统一属性和特性。我们甚至可以将state、config、attribute、property这四个统一起来。然后是method方法,用来描述一个复杂的过程,但是JavaScript中的property是允许get、set等方法的,所以说到底,method和property的作用是差不多的。所以这里我们可以确定一个概念,就是使用组件的开发者会使用方法和属性,这些组件的元素。但是如果开发一个组件的开发人员需要向使用该组件的程序员传递消息,这时候就需要一个event事件。当一个组件由于某种行为或事件触发了变化时,该组件将向用户发送一个事件消息。所以这里事件的方向是反的,从组件到外部。通过这张图,我们可以清楚的知道组件各个元素的作用以及它们的信息流向。特性Attribute在所有组件的元素中,最复杂的无非是Attribute和Property。从英文单词Attribute的理解上,我们更强调描述性。比如我们形容一个头发很多,长相帅气,皮肤白皙的人。这些都是Attributes,也可以说是对某个事物的特性、特点的描述。财产更像是一种从属关系。比如我们在开发中经常会发现一个对象,它有一个Property是另一个对象,那么它们之间很有可能存在从属关系,子对象从属于父对象。但这里也有一个特例。如果我们有一个弱引用,一个对象引用另一个对象,这是一个完全不同的概念。以上就是这两个词在英文中的区别,但是在实际的应用场景中也是不一样的。因为Property是一种从属关系,所以在我们面向对象中经常会用到。而Attribute最初是在我们的XML中使用的。有时它们相同,有时它们不同。Attributevs.Property这里我们使用一些例子来了解Attribute和Property之间的区别。我们可以看看它们在HTML中不等价的场景。Attribute:HTML中的属性可以同时通过HTML属性设置也可以通过JavaScript设置属性:myComponent.a='value';这里是定义一个元素的a='value'。这不是属性,而是属性!!很多同学认为这只是两种不同的写法,其实他们的行为是不同的。Class属性

早年JavaScript的Class是a关键字,所以早期的Class作为关键字是不允许作为属性名的。但是现在已经改变了,关键字也可以用作属性名称。为了让这个关键字可以这样使用,在HTML中做了一个折衷的设计。属性在HTML中仍称为类,但DOM对象中的属性变为类名。但是两人还处于一种相互映照的关系中,这种神奇的关系往往会让大家掉进一些坑里。例如,在React中,如果我们写className,它会自动设置Class。Style属性现在在JavaScript语言中,已经没有class和className的不一致了。我们可以像这样使用div.class。但是name类在HTML中仍然不支持,这是一些历史包袱造成的问题。有时Attribute是字符串,但在Property中是字符串语义后的对象。最典型的是Style。
在HTMLStyle中的属性是一个字符串,我们可以使用getAttribute和setAttribute来获取和设置这个属性。但是如果我们使用这个Style属性,我们将得到一个键值结构。HTML中href的属性和属性的含义非常相似。但它的属性是解析后的url。比如我们的href的值为“//m.taobao.com”。这时候之前的http或者https协议是基于当前页面的,所以这里的href需要重新编译,以响应当前页面的协议。做过http转https的同学应该都知道,当我们让我们的网站使用https协议时,我们需要将所有硬编码的http或者httpsurl改成使用//。那么我们href里面写的东西就会出来,那就是attribute。如果解决了,那就是我们的财产了。我们在上面的代码中也可以看到,我们可以同时访问property和attribute。尽管它们的语义非常接近,但它们并不是一回事。但如果我们改变任何一方,它就会改变另一方。这是我们需要注意的。输入和值是最神奇的一对,值也是一个特殊的坑。我们中的许多人认为property和attribute中的值是完全等价的。其实不是,这个属性中输入的值相当于一个值的默认值。无论是用户在input中输入值,还是开发者使用JavaScript给input赋值,input的属性都不会相应改变。输入显示时,属性会先显示,所以属性中的值相当于一个默认值。这是一个非常有名的坑。如果早期同学用的是JQuery,我们会认为里面的prop和attr是一样的。没想到踩到了价值坑。所以后来JQuery库想出了一个方法叫val,这样我们就不用考虑attribute或者property的值,直接使用它提供的val值即可。!!一方面,这是为了增强对HTML特性和属性的认识。另一方面,让我们认识到,即使是最顶尖的计算机专家设计的标签系统中,也有两个相似但不等价的属性。那么如果我们要设计一个标签系统,我们应该让属性和属性等价还是不等价?学习完组件化的全部知识,我们一起来回答这个问题。如何设计组件状态这里我们分析组件设计中property、attribute、state、config的区别。这里Winer先生给我们整理了一张表,分为四种场景:Markupset-使用标签设置JavaScriptSet-使用JavaScript代码设置JavaScriptChange-使用JavaScript代码更改UserInputChange-最终用户的Input更改MarkupsetJavaScriptsetJavaSscriptChangeUserInputChange????property????attribute????state????config所以我们一一说说:Propertycannotbemarkedasstatic可以通过JavaScript设置和更改。在大多数情况下,用户输入不应更改该属性,但在少数情况下,它可能是源由于我们的业务逻辑,可以接受用户输入来更改属性。用户输入不一定会改变它。和Property一样,可以通过markup和JavaScript来设置,也是可以通过JavaScript改变的State。它会在组件内部更改,不会从组件外部更改。如果我们要设计一个组件从外部改变组件的状态,那么我们组件内部的状态就会失控。因为我们不知道什么时候我们组件的状态会在组件外被改变,所以我们的状态的一致性无法得到保证。但是作为组件设计者和实践者,我们必须确保用户输入能够改变我们组件的状态。例如,如果用户单击一个选项卡,则单击的选项卡将被激活。这种交互一般是由状态控制的。ConfigConfig在组件中是一次性有效的东西,只有在我们的组件构建时才会触发。所以它是不可变的。也因为它的不变性,我们通常将配置留给全局。通常每个页面都会有一个config,然后在页面中使用这个。组件生命周期Lifecycle说到生命周期,我们最容易想到的有两种,一种是创建,另一种是销毁。世间万物的生命,必然有生与死,这两个生命周期。那么这两个起点和终点之间的生命周期是怎样的呢?我们需要考虑在组件的构造和销毁之间发生了什么。一个组件很重要的一点就是创建后是否显示。这就涉及到生命周期中的挂载,即组件是否挂载到“屏幕的树”上。我们可以在React和Vue中看到这个生命周期。我们经常会利用这个生命周期在组件挂载后做一些相应的初始化操作。有挂载就一定有卸载,所以组件中的mount和unmount是一组生命周期。并且挂载和卸载的整个生命周期可以重复发生。我们可以mount它,然后remove它,然后再mount它,这样这个生命周期就可以周而复始的重复。所以unmount之后,我们可以回到创建的构建组件本次生命周期的状态。那么组件的状态什么时候会发生变化呢?这里我们有两种情况:程序员使用代码来改变或设置这个组件的状态。用户输入会影响组件的状态。比如我们的用户点击了一个按钮或者Tab,这个时候就会触发这个组件的状态变化。同时也会产生一个组件生命周期,这个生命周期就是Render渲染或者Update更新。所有这些生命周期加起来就是一个组件的完整生命周期。我们看到的所谓willMount和didMount,无非是在这个生命周期中比较细的位置。下面我给大家附上一张完整的生命周期图。Children最后说一下Children(子组件)的概念。Children是构建组件树最重要的组件特性,实际上使用的Children有两种:Content类型的Children——我们有几个Children,但是最后可以显示几个Children。对于这种类型的Children,它的组件树非常简单。Template-typeChildren——此时整个Children充当一个模板。比如我们设计了一个列表,但是最终的结果不一定和我们Children代码中写的一样。因为我们的List肯定是用于多个列表数据的,所以列表的表示数量和我们传入组件的data数据有关。如果我们有100个实际孩子,我们的列表模板将被复制100次。在设计我们的组件树的孩子时,我们必须考虑这两种不同的场景。比如在React中,它没有模板类型的children,但是它的children可以传函数,然后这个function可以返回一个children。这时候,它就充当了一个模板children。所以我们在Vue中做一些没完没了的滚动列表的时候,这对Vue的templatechildren有一定的要求。结束语到这里我们就学习完了整个组件的概念和知识。在下一篇文章中,我们将一起设计搭建一个组件系统,全方位了解其实用知识。我们也会用一些典型的组件和典型的功能,让大家对组件的实现有一定的了解。本文转载自微信公众号“科技银河”,可通过以下二维码关注。转载本文请联系科技银河公众号。