目录
钥匙要点
>这是一个典型的AngularJS控制器。它执行HTTP请求,从JSON文件中获取数据,然后将其传递给当前范围。我们没有执行todoctrl函数 - 我们没有机会通过任何参数。框架确实如此。那么,这些$范围和$ http变量来自哪里?这是一个超级酷的功能,非常类似于黑魔法。让我们看看它是如何完成的。
>有一个具有名称和姓氏属性的类。计算的属性fullname返回包含人的全名的串联字符串。奇怪的是,我们使用.property方法来针对应用于fullname的函数的部分。我个人在其他任何地方都没有看到。而且,快速查看框架的代码揭示了魔术:
疯狂的反应模板
首页 web前端 js教程 揭示JavaScript的魔力

揭示JavaScript的魔力

Feb 21, 2025 am 09:38 AM

揭示JavaScript的魔力

>我们每天使用大量工具。不同的图书馆和框架是我们日常工作的一部分。我们之所以使用它们,是因为我们不想为每个项目重新发明轮子,即使我们不了解引擎盖下的情况。在本文中,我们将揭示最受欢迎的图书馆中发生的一些神奇过程。我们还将查看是否可以复制他们的行为。

>

钥匙要点

  • > jQuery(例如jQuery)简化dom操纵(例如,从字符串创建元素),正确处理复杂的情况(如嵌套元素)(如嵌套元素)。 ember.js使用计算属性增强JavaScript对象,允许属性像函数一样行为,在依赖性更改时自动更新。 React的JSX语法允许将HTML嵌入JavaScript中,然后由React的JSX Transformer处理以创建动态UI组件。
  • >本文展示了用于依赖注入和计算属性的自定义解决方案,展示了开发人员如何在其项目中实施相似的功能。
  • 了解流行的JavaScript框架的基本力学可以使开发人员能够编写更有效和可维护的代码。
  • >从字符串创建DOM元素
  • 随着单页应用程序的兴起,我们正在使用JavaScript做很多事情。应用程序逻辑的很大一部分已移至浏览器。在页面上生成或替换元素是一项常见的任务。与下面显示的相似的代码已经变得非常普遍。
  • 结果是在文档正文中添加了一个新的
    元素。这个简单的操作仅使用一行jQuery完成。没有jQuery,代码有些复杂,但没有太多:
  • >
  • 我们定义了创建临时
    元素的自己的实用程序方法字符串。我们更改了其InnerHTML属性,最后我们简单地退回了第一个孩子,实际上我们需要的是我们所需要的。它以同样的方式工作。但是,我们将通过以下代码观察不同的结果:

    >

    在页面上,在页面上没有差异。但是,如果我们使用Chrome的开发人员工具检查生成的标记,我们将获得一个有趣的结果:>

    <span>var text = $('<div>Simple text</div>');
    </span>
    <span>$('body').append(text);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制

    >看起来我们的字符串todom函数仅创建了一个文本节点,而不是实际的

    标签。但与此同时,jQuery以某种方式设法这样做。问题在于,包含HTML元素的字符串通过浏览器中的解析器运行。解析器忽略了未放置在正确上下文中的标签,而我们只会得到一个文本节点。没有表格的表行对于浏览器无效。

    > jQuery通过创建正确的上下文并仅提取所需部分来成功解决问题。如果我们挖掘了库的代码,我们将看到这样的地图:>

    <span>var text = $('<div>Simple text</div>');
    </span>
    <span>$('body').append(text);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    需要特殊处理的每个元素都分配了一个阵列。这个想法是构造正确的DOM元素,并依赖嵌套的级别来获取我们需要的东西。例如,对于 元素,我们需要用 child创建一个表。因此,我们有两个层次的嵌套。

    有一个地图,我们必须找出最终想要的标签。以下代码从 简单的文本

    提取TR

    <span>var stringToDom = function(str) {
    </span>  <span>var temp = document.createElement('div');
    </span>
      temp<span>.innerHTML = str;
    </span>  <span>return temp.childNodes[0];
    </span><span>}
    </span><span>var text = stringToDom('<div>Simple text</div>');
    </span>
    <span>document.querySelector('body').appendChild(text);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    其余的正在找到正确的上下文并返回DOM元素。这是函数stringTodom的最终变体:

    <span>var tableRow = $('<tr><td>Simple text</td></tr>');
    </span><span>$('body').append(tableRow);
    </span>
    <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
    </span><span>document.querySelector('body').appendChild(tableRow);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    请注意,我们正在检查字符串中是否有标签 - 匹配!= null。如果不是,我们只是返回文本节点。仍然有一个临时
    的用法,但是这次我们传递了正确的标签,因此浏览器可以创建有效的DOM树。最后,通过使用一段时间循环,我们将越来越深,直到达到想要的标签为止。

    这是一个codepen,显示了我们的实现:

    参见codepen上的krasimir tsonev(@krasimir)的笔xlcgn。

    让我们继续探索奇妙的AngularJS依赖注入。

    揭示agnularjs依赖注射

    当我们开始使用AngularJs时,它的双向数据绑定给人留下深刻的印象。我们注意到的第二件事是它的神奇依赖注入。这是一个简单的示例:

    >这是一个典型的AngularJS控制器。它执行HTTP请求,从JSON文件中获取数据,然后将其传递给当前范围。我们没有执行todoctrl函数 - 我们没有机会通过任何参数。框架确实如此。那么,这些$范围和$ http变量来自哪里?这是一个超级酷的功能,非常类似于黑魔法。让我们看看它是如何完成的。

    >我们有一个JavaScript函数,可以在系统中显示用户。相同的功能需要访问DOM元素才能放置生成的HTML和AJAX包装器以获取数据。为了简化示例,我们将模拟数据和HTTP请求。

    <span>var text = $('<div>Simple text</div>');
    </span>
    <span>$('body').append(text);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制

    我们将使用

    标签作为内容持有人。 AjaxWrapper是模拟请求的对象,DatamOckup是包含我们用户的数组。这是我们将使用的功能:
    <span>var stringToDom = function(str) {
    </span>  <span>var temp = document.createElement('div');
    </span>
      temp<span>.innerHTML = str;
    </span>  <span>return temp.childNodes[0];
    </span><span>}
    </span><span>var text = stringToDom('<div>Simple text</div>');
    </span>
    <span>document.querySelector('body').appendChild(text);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制

    当然,如果我们运行显示器(正文,AjaxWrapper),我们将在页面上看到三个名称,以及在我们的控制台中请求的 /api /用户。我们可以说我们的方法具有两个依赖性 - 身体和AjaxWrapper。因此,现在的想法是使该函数在不传递参数的情况下工作,即,我们必须通过调用DisplayUser()来获得相同的结果。如果到目前为止,我们使用代码执行此操作,则结果将是:

    >
    <span>var tableRow = $('<tr><td>Simple text</td></tr>');
    </span><span>$('body').append(tableRow);
    </span>
    <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
    </span><span>document.querySelector('body').appendChild(tableRow);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制

    >正常,因为未定义Ajax参数。

    >提供依赖性注入机制的大多数框架具有一个模块,通常命名为

    >喷油器。要使用依赖关系,我们需要在此处注册。后来,在某个时候,我们的资源由同一模块提供给应用程序的逻辑。>

    让我们创建我们的喷油器:

    <span>var wrapMap = {
    </span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
    </span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
    </span>  <span>area: [1, '<map>', '</map>'],
    </span>  <span>param: [1, '<object>', '</object>'],
    </span>  <span>thead: [1, '<table>', '</table>'],
    </span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
    </span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
    </span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
    </span>  <span>_default: [1, '<div>', '</div>']
    </span><span>};
    </span>wrapMap<span>.optgroup = wrapMap.option;
    </span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
    </span>wrapMap<span>.th = wrapMap.td;</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    我们只需要两种方法。第一个,注册,接受我们的资源(依赖项)并在内部存储它们。第二个接受我们注入的目标 - 具有依赖性和需要接收参数的功能。这里的关键时刻是喷油器不应调用我们的功能。那是我们的工作,我们应该能够控制这一点。我们可以在解决方法中做的是返回包装目标并调用目标的封闭。例如:

    <span>var match = <span>/&lt;<span>\s*\w.*?&gt;</span>/g</span>.exec(str);
    </span><span>var tag = match[0].replace(<span>/&lt;/g</span>, '').replace(<span>/&gt;/g</span>, '');</span>
    登录后复制
    登录后复制
    使用该方法,我们将有机会使用所需的依赖项调用该功能。同时,我们没有更改应用程序的工作流程。喷油器仍然是独立的,并且不具有与逻辑相关的功能。

    >

    当然,将显示器的功能传递到Resolve方法无济于事。

    >我们仍然遇到相同的错误。下一步是找出传递的目标需求。它的依赖性是什么?这是我们可以从Angularjs中采用的棘手部分。我再次对框架的代码进行了一些挖掘,并找到了以下内容:
    <span>var stringToDom = function(str) {
    </span>  <span>var wrapMap = {
    </span>    <span>option: [1, '<select multiple="multiple">', '</select>'],
    </span>    <span>legend: [1, '<fieldset>', '</fieldset>'],
    </span>    <span>area: [1, '<map>', '</map>'],
    </span>    <span>param: [1, '<object>', '</object>'],
    </span>    <span>thead: [1, '<table>', '</table>'],
    </span>    <span>tr: [2, '<table><tbody>', '</tbody></table>'],
    </span>    <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
    </span>    <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
    </span>    <span>_default: [1, '<div>', '</div>']
    </span>  <span>};
    </span>  wrapMap<span>.optgroup = wrapMap.option;
    </span>  wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
    </span>  wrapMap<span>.th = wrapMap.td;
    </span>  <span>var element = document.createElement('div');
    </span>  <span>var match = <span>/<<span>\s*\w.*?></span>/g</span>.exec(str);
    </span>
      <span>if(match != null) {
    </span>    <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span>/>/g</span>, '');
    </span>    <span>var map = wrapMap[tag] || wrapMap._default, element;
    </span>    str <span>= map[1] + str + map[2];
    </span>    element<span>.innerHTML = str;
    </span>    <span>// Descend through wrappers to the right content
    </span>    <span>var j = map[0]+1;
    </span>    <span>while(j--) {
    </span>      element <span>= element.lastChild;
    </span>    <span>}
    </span>  <span>} else {
    </span>    <span>// if only text is passed
    </span>    element<span>.innerHTML = str;
    </span>    element <span>= element.lastChild;
    </span>  <span>}
    </span>  <span>return element;
    </span><span>}</span>
    登录后复制
    登录后复制
    >

    >我们故意跳过了一些零件,因为它们更像是实施细节。这是对我们来说很有趣的代码。注释函数类似于我们的解决方法。它将传递的目标函数转换为字符串,删除注释(如果有),然后提取参数。让我们使用它并查看结果:
    <span>function <span>TodoCtrl</span>($scope<span>, $http</span>) {
    </span>  $http<span>.get('users/users.json').success(function(data) {
    </span>    $scope<span>.users = data;
    </span>  <span>});
    </span><span>}</span>
    登录后复制
    登录后复制

    这是控制台中的输出:>
    <span>var dataMockup = ['John', 'Steve', 'David'];
    </span><span>var body = document.querySelector('body');
    </span><span>var ajaxWrapper = {
    </span>  <span>get: function(path<span>, cb</span>) {
    </span>    <span>console.log(path + ' requested');
    </span>    <span>cb(dataMockup);
    </span>  <span>}
    </span><span>}</span>
    登录后复制
    登录后复制

    如果我们获得了argdecl数组的第二个元素,我们将找到所需依赖项的名称。这正是我们需要的,因为拥有名称我们将能够从喷油器的存储中传递资源。这是有效的版本并成功涵盖了我们的目标:

    <span>var text = $('<div>Simple text</div>');
    </span>
    <span>$('body').append(text);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制

    请注意,我们正在使用.split(/,?/g)将字符串Domel,Ajax转换为数组。之后,我们正在检查依赖项是否已注册,如果是,则将其传递给目标函数。喷油器外部的代码看起来像:

    <span>var stringToDom = function(str) {
    </span>  <span>var temp = document.createElement('div');
    </span>
      temp<span>.innerHTML = str;
    </span>  <span>return temp.childNodes[0];
    </span><span>}
    </span><span>var text = stringToDom('<div>Simple text</div>');
    </span>
    <span>document.querySelector('body').appendChild(text);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制

    这种实现的好处是,我们可以在许多功能中注入DOM元素和Ajax包装器。我们甚至可以这样分发应用程序的配置。无需将对象从类传递到类。这只是寄存器和解决方法。

    > 当然,我们的喷油器并不完美。仍然有一些改进的空间,例如支持范围定义。目前,目标功能通过新创建的范围调用,但通常我们将要通过自己的范围。我们应该支持还发送自定义参数以及依赖关系。

    > 如果我们想在缩小后保持代码工作,则喷油器会变得更加复杂。众所周知,缩影替换了函数,变量甚至方法的参数的名称。而且,由于我们的逻辑依赖于这些名称,因此我们需要考虑解决方法。一种可能的解决方案再次来自AngularJS:

    >

    而不是仅显示显示器的显示器,我们正在传递实际依赖的名称。
    <span>var tableRow = $('<tr><td>Simple text</td></tr>');
    </span><span>$('body').append(tableRow);
    </span>
    <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
    </span><span>document.querySelector('body').appendChild(tableRow);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    我们的示例在行动中:

    参见codepen上的krasimir tsonev(@krasimir)的笔bxdar。

    采用ember的计算属性

    Ember是当今最受欢迎的框架之一。它具有许多有用的功能。有一个特别有趣的 - 计算属性。总而言之,计算的属性是充当属性的函数。让我们看看一个简单的示例从灰烬的文档中获取:

    >有一个具有名称和姓氏属性的类。计算的属性fullname返回包含人的全名的串联字符串。奇怪的是,我们使用.property方法来针对应用于fullname的函数的部分。我个人在其他任何地方都没有看到。而且,快速查看框架的代码揭示了魔术:

    库通过添加新属性来调整全局函数对象的原型。这是在类的定义期间运行一些逻辑的好方法。
    <span>var wrapMap = {
    </span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
    </span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
    </span>  <span>area: [1, '<map>', '</map>'],
    </span>  <span>param: [1, '<object>', '</object>'],
    </span>  <span>thead: [1, '<table>', '</table>'],
    </span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
    </span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
    </span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
    </span>  <span>_default: [1, '<div>', '</div>']
    </span><span>};
    </span>wrapMap<span>.optgroup = wrapMap.option;
    </span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
    </span>wrapMap<span>.th = wrapMap.td;</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    >

    ember使用getters和setter与对象的数据一起操作。这简化了计算属性的实现,因为我们之前还有一层可以达到实际变量。但是,如果我们能够使用普通的JavaScript对象使用计算的属性,将会更有趣。例如:

    <span>var text = $('<div>Simple text</div>');
    </span>
    <span>$('body').append(text);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制

    >名称用作常规属性,但实际上是一个获取或设置firstName和lastname的函数。

    >有一个JavaScript的建筑功能,可以帮助我们实现这个想法。看看以下片段:

    <span>var stringToDom = function(str) {
    </span>  <span>var temp = document.createElement('div');
    </span>
      temp<span>.innerHTML = str;
    </span>  <span>return temp.childNodes[0];
    </span><span>}
    </span><span>var text = stringToDom('<div>Simple text</div>');
    </span>
    <span>document.querySelector('body').appendChild(text);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制

    object.defineproperty方法可以接受范围,属性的名称,getter和setter。我们要做的就是写这两种方法的主体。就是这样。我们将能够运行上面的代码,我们将获得预期的结果:

    >
    <span>var tableRow = $('<tr><td>Simple text</td></tr>');
    </span><span>$('body').append(tableRow);
    </span>
    <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
    </span><span>document.querySelector('body').appendChild(tableRow);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制

    object.defineproperty正是我们所需要的,但是我们不想迫使开发人员每次编写它。我们可能需要提供多填充,运行其他逻辑或类似的东西。在理想情况下,我们希望提供与Ember类似的界面。只有一个函数是类定义的一部分。在本节中,我们将编写一个称为Computize的实用程序函数,该函数将处理我们的对象,并以某种方式将名称函数转换为具有相同名称的属性。

    >
    <span>var wrapMap = {
    </span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
    </span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
    </span>  <span>area: [1, '<map>', '</map>'],
    </span>  <span>param: [1, '<object>', '</object>'],
    </span>  <span>thead: [1, '<table>', '</table>'],
    </span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
    </span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
    </span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
    </span>  <span>_default: [1, '<div>', '</div>']
    </span><span>};
    </span>wrapMap<span>.optgroup = wrapMap.option;
    </span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
    </span>wrapMap<span>.th = wrapMap.td;</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制

    >我们想将名称方法用作设置器,同时与Getter一起使用。这类似于Ember的计算属性。

    > 现在

    >一旦添加上述行,我们将能够将.compented()添加到每个函数定义的末尾:>
    <span>var match = <span>/&lt;<span>\s*\w.*?&gt;</span>/g</span>.exec(str);
    </span><span>var tag = match[0].replace(<span>/&lt;/g</span>, '').replace(<span>/&gt;/g</span>, '');</span>
    登录后复制
    登录后复制
    结果,名称属性不再包含函数,而是计算出等于true and func属性的对象填充了旧功能。真正的魔术发生在计算助手的实现中。它通过对象的所有属性并使用对象。DefineProperty我们已经计算出属性:

    >

    <span>var stringToDom = function(str) {
    </span>  <span>var wrapMap = {
    </span>    <span>option: [1, '<select multiple="multiple">', '</select>'],
    </span>    <span>legend: [1, '<fieldset>', '</fieldset>'],
    </span>    <span>area: [1, '<map>', '</map>'],
    </span>    <span>param: [1, '<object>', '</object>'],
    </span>    <span>thead: [1, '<table>', '</table>'],
    </span>    <span>tr: [2, '<table><tbody>', '</tbody></table>'],
    </span>    <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
    </span>    <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
    </span>    <span>_default: [1, '<div>', '</div>']
    </span>  <span>};
    </span>  wrapMap<span>.optgroup = wrapMap.option;
    </span>  wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
    </span>  wrapMap<span>.th = wrapMap.td;
    </span>  <span>var element = document.createElement('div');
    </span>  <span>var match = <span>/<<span>\s*\w.*?></span>/g</span>.exec(str);
    </span>
      <span>if(match != null) {
    </span>    <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span>/>/g</span>, '');
    </span>    <span>var map = wrapMap[tag] || wrapMap._default, element;
    </span>    str <span>= map[1] + str + map[2];
    </span>    element<span>.innerHTML = str;
    </span>    <span>// Descend through wrappers to the right content
    </span>    <span>var j = map[0]+1;
    </span>    <span>while(j--) {
    </span>      element <span>= element.lastChild;
    </span>    <span>}
    </span>  <span>} else {
    </span>    <span>// if only text is passed
    </span>    element<span>.innerHTML = str;
    </span>    element <span>= element.lastChild;
    </span>  <span>}
    </span>  <span>return element;
    </span><span>}</span>
    登录后复制
    登录后复制
    请注意,我们正在删除原始属性名称。在某些浏览器对象中。defineProperty仅在尚未定义的属性上起作用。

    >

    这是使用.competed()函数的用户对象的最终版本。
    <span>function <span>TodoCtrl</span>($scope<span>, $http</span>) {
    </span>  $http<span>.get('users/users.json').success(function(data) {
    </span>    $scope<span>.users = data;
    </span>  <span>});
    </span><span>}</span>
    登录后复制
    登录后复制
    >

    >返回全名的函数用于更改名称和姓氏。这就是检查通过的参数并处理第一个的想法。如果存在,我们将其拆分并将值应用于正常属性。

    >

    我们已经提到了所需的用法,但让我们再看一次:>
    <span>var dataMockup = ['John', 'Steve', 'David'];
    </span><span>var body = document.querySelector('body');
    </span><span>var ajaxWrapper = {
    </span>  <span>get: function(path<span>, cb</span>) {
    </span>    <span>console.log(path + ' requested');
    </span>    <span>cb(dataMockup);
    </span>  <span>}
    </span><span>}</span>
    登录后复制
    登录后复制

    以下codepen在实践中显示了我们的工作:

    参见codepen上的krasimir tsonev(@krasimir)的笔Ahpqo。

    疯狂的反应模板

    >您可能已经听说过Facebook的框架反应。它围绕着一切都是组成部分的想法。有趣的是组件的定义。让我们来看看以下示例:

    <span>var text = $('<div>Simple text</div>');
    </span>
    <span>$('body').append(text);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制

    >我们开始考虑的第一件事是这是JavaScript,但这是无效的。有一个渲染功能,它可能会丢失错误。但是,诀窍是将此代码放在带有自定义类型属性的<script>标签中。浏览器没有处理它,这意味着我们免受错误的安全。 React有自己的解析器,将我们写的代码转换为有效的JavaScript。 Facebook的开发人员称为XML Like Language <ancland> jsx<em>。他们的JSX变压器为390K,包含大约12000行代码。因此,这有点复杂。在本节中,我们将创建一些简单的方法,但仍然非常强大。以React风格解析HTML模板的JavaScript类。> </script>

    > Facebook采取的方法是将JavaScript代码与HTML标记混合。因此,可以说,我们有以下模板:

    >

    <span>var stringToDom = function(str) {
    </span>  <span>var temp = document.createElement('div');
    </span>
      temp<span>.innerHTML = str;
    </span>  <span>return temp.childNodes[0];
    </span><span>}
    </span><span>var text = stringToDom('<div>Simple text</div>');
    </span>
    <span>document.querySelector('body').appendChild(text);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    和使用它的组件:

    >

    <span>var tableRow = $('<tr><td>Simple text</td></tr>');
    </span><span>$('body').append(tableRow);
    </span>
    <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
    </span><span>document.querySelector('body').appendChild(tableRow);</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    的想法是,我们指出了模板的ID并定义了应应用的数据。我们实施的最后一部分是将两个要素合并的实际引擎。让我们称其为引擎,然后以这样的方式启动:

    <span>var wrapMap = {
    </span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
    </span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
    </span>  <span>area: [1, '<map>', '</map>'],
    </span>  <span>param: [1, '<object>', '</object>'],
    </span>  <span>thead: [1, '<table>', '</table>'],
    </span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
    </span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
    </span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
    </span>  <span>_default: [1, '<div>', '</div>']
    </span><span>};
    </span>wrapMap<span>.optgroup = wrapMap.option;
    </span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
    </span>wrapMap<span>.th = wrapMap.td;</span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    >我们正在获取

以上是揭示JavaScript的魔力的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

前端热敏纸小票打印遇到乱码问题怎么办? 前端热敏纸小票打印遇到乱码问题怎么办? Apr 04, 2025 pm 02:42 PM

前端热敏纸小票打印的常见问题与解决方案在前端开发中,小票打印是一个常见的需求。然而,很多开发者在实...

神秘的JavaScript:它的作用以及为什么重要 神秘的JavaScript:它的作用以及为什么重要 Apr 09, 2025 am 12:07 AM

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

谁得到更多的Python或JavaScript? 谁得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript开发者的薪资没有绝对的高低,具体取决于技能和行业需求。1.Python在数据科学和机器学习领域可能薪资更高。2.JavaScript在前端和全栈开发中需求大,薪资也可观。3.影响因素包括经验、地理位置、公司规模和特定技能。

JavaScript难以学习吗? JavaScript难以学习吗? Apr 03, 2025 am 12:20 AM

学习JavaScript不难,但有挑战。1)理解基础概念如变量、数据类型、函数等。2)掌握异步编程,通过事件循环实现。3)使用DOM操作和Promise处理异步请求。4)避免常见错误,使用调试技巧。5)优化性能,遵循最佳实践。

JavaScript的演变:当前的趋势和未来前景 JavaScript的演变:当前的趋势和未来前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? 如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中将具有相同ID的数组元素合并到一个对象中?在处理数据时,我们常常会遇到需要将具有相同ID�...

如何实现视差滚动和元素动画效果,像资生堂官网那样?
或者:
怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? 如何实现视差滚动和元素动画效果,像资生堂官网那样? 或者: 怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? Apr 04, 2025 pm 05:36 PM

实现视差滚动和元素动画效果的探讨本文将探讨如何实现类似资生堂官网(https://www.shiseido.co.jp/sb/wonderland/)中�...

console.log输出结果差异:两次调用为何不同? console.log输出结果差异:两次调用为何不同? Apr 04, 2025 pm 05:12 PM

深入探讨console.log输出差异的根源本文将分析一段代码中console.log函数输出结果的差异,并解释其背后的原因。�...

See all articles