>我们每天使用大量工具。不同的图书馆和框架是我们日常工作的一部分。我们之所以使用它们,是因为我们不想为每个项目重新发明轮子,即使我们不了解引擎盖下的情况。在本文中,我们将揭示最受欢迎的图书馆中发生的一些神奇过程。我们还将查看是否可以复制他们的行为。
>钥匙要点
- > jQuery(例如jQuery)简化dom操纵(例如,从字符串创建元素),正确处理复杂的情况(如嵌套元素)(如嵌套元素)。
ember.js使用计算属性增强JavaScript对象,允许属性像函数一样行为,在依赖性更改时自动更新。 React的JSX语法允许将HTML嵌入JavaScript中,然后由React的JSX Transformer处理以创建动态UI组件。 - >本文展示了用于依赖注入和计算属性的自定义解决方案,展示了开发人员如何在其项目中实施相似的功能。
了解流行的JavaScript框架的基本力学可以使开发人员能够编写更有效和可维护的代码。- 随着单页应用程序的兴起,我们正在使用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树。最后,通过使用一段时间循环,我们将越来越深,直到达到想要的标签为止。'], col: [2, '这是一个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>', '</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>/<<span >\s*\w.*?></span>/g</span>.exec(str); <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span >/>/g</span>, '');</span>
使用该方法,我们将有机会使用所需的依赖项调用该功能。同时,我们没有更改应用程序的工作流程。喷油器仍然是独立的,并且不具有与逻辑相关的功能。>
当然,将显示器的功能传递到Resolve方法无济于事。<span>var stringToDom = function(str) { </span> <span>var wrapMap = { </span> <span>option: [1, '<select 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>/\s*\w.*?></span>/g</span>.exec(str); <span>if(match != null) { </span> <span>var tag = match[0].replace(<span>/</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>
我们的示例在行动中:采用ember的计算属性
Ember是当今最受欢迎的框架之一。它具有许多有用的功能。有一个特别有趣的 - 计算属性。总而言之,计算的属性是充当属性的函数。让我们看看一个简单的示例从灰烬的文档中获取:>有一个具有名称和姓氏属性的类。计算的属性fullname返回包含人的全名的串联字符串。奇怪的是,我们使用.property方法来针对应用于fullname的函数的部分。我个人在其他任何地方都没有看到。而且,快速查看框架的代码揭示了魔术:
<span>var wrapMap = { </span> <span>option: [1, '<select 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>', '</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的计算属性。
> 现在> <span>var match = <span>/<<span >\s*\w.*?></span>/g</span>.exec(str); <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span >/>/g</span>, '');</span>
结果,名称属性不再包含函数,而是计算出等于true and func属性的对象填充了旧功能。真正的魔术发生在计算助手的实现中。它通过对象的所有属性并使用对象。DefineProperty我们已经计算出属性:>
<span>var stringToDom = function(str) { </span> <span>var wrapMap = { </span> <span>option: [1, '<select 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>/\s*\w.*?></span>/g</span>.exec(str); <span>if(match != null) { </span> <span>var tag = match[0].replace(<span>/</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>', '</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>
>我们正在获取', '
'], _default: [1, '', ' ', ''] }; wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; var element = document.createElement('div'); var match = /\s*\w.*?>/g.exec(str); if(match != null) { var tag = match[0].replace(/, '').replace(/>/g, ''); var map = wrapMap[tag] || wrapMap._default, element; str = map[1] + str + map[2]; element.innerHTML = str; // Descend through wrappers to the right content var j = map[0]+1; while(j--) { element = element.lastChild; } } else { // if only text is passed element.innerHTML = str; element = element.lastChild; } return element; }>而不是创建复杂的解析器,几乎发明了我们可能使用纯JavaScript的新语言。我们要做的唯一一件事是使用新函数语法。
><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 text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
控制台中的输出表明我们在正确的轨道上:
> <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>
>实现这一结果非常容易。我们可能会编写一个循环,该循环涉及代码数组的所有元素,并检查项目是否是字符串或对象。但是,这再次涵盖了其中一部分。如果我们有以下模板:<span>var wrapMap = { </span> <span>option: [1, '<select 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>
>我们不能仅仅使表达式加入,并期望列出颜色。因此,而不是将字符串附加到字符串中,而是将它们收集在数组中。这是Parse函数的更新版本:>
<span>var match = <span>/<<span >\s*\w.*?></span>/g</span>.exec(str); <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span >/>/g</span>, '');</span>
>填充代码阵列后,我们开始构建函数的主体。模板的每一行都将存储在阵列r中。如果该行是字符串,我们通过逃脱引号并删除新行和选项卡来清理一点。它通过推送方法添加到数组中。如果我们有代码段,则我们检查它是否不是有效的JavaScript操作员。如果是,那么我们不是将其添加到数组中,而只是将其删除为新行。末端输出的控制台。<span>var stringToDom = function(str) { </span> <span>var wrapMap = { </span> <span>option: [1, '<select 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>/\s*\w.*?></span>/g</span>.exec(str); <span>if(match != null) { </span> <span>var tag = match[0].replace(<span>/</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>
剩下的最后一件事是我们虚拟创建的函数的实际运行:> >
这是一个codepen,演示了最终结果:<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>
参见codepen上的krasimir tsonev(@krasimir)的笔
摘要大型框架和图书馆后面的
是明智的开发人员。他们发现并使用了棘手的解决方案,这些解决方案并非微不足道,甚至是神奇的。在本文中,我们揭示了一些魔术。在JavaScript世界中,我们能够从最好的代码中学习并使用其代码。本文中的代码可从github
下载经常询问有关JavaScript
魔法的问题(常见问题解答)> JavaScript中的魔术方法是什么?它们如何工作?它们不是直接调用的,而是在执行某些动作时被调用。例如,ToString()方法是一种魔术方法,当需要将对象表示为文本值时,它会自动调用。另一个示例是valueof()方法,当对象被表示为原始值时,该方法称为。
>如何在JavaScript中使用魔术方法?例如,您可以在对象中定义toString()方法,以自定义对象将如何表示为字符串。这是一个简单的示例:
让Person = {
lastname:“ doe”, tostring:function() “ this.lastName;
}
};
console.log(person.toString()); //“ John Doe”
> JavaScript中魔术功能的意义是什么?它们可以使您的代码更加直观,更易于理解,并提供一种封装和保护您数据的方法。
>
您可以在JavaScript中提供一些魔术功能的示例?以下是JavaScript中魔术函数的一些示例:1。 ToString():此方法返回代表对象的字符串。
> 1。 valueof():此方法返回对象的原始值。
1。 HasownProperty():此方法返回一个布尔值,指示对象是否具有指定的属性。
> >> >是否有任何限制或缺点,用于在Javascript中使用魔法方法?魔术方法可能非常有用,它们也有一些局限性。首先,它们可以使您的代码更加复杂和更难进行调试,尤其是如果您不熟悉它们的工作方式。如果不正确使用,它们也可以导致出乎意料的行为。
与其他一些编程语言不同,JavaScript没有正式的概念“魔法方法”。但是,它的确具有类似行为的某些方法,例如tostring()和valueof()。这些方法会在某些情况下自动调用,就像其他语言中的魔术方法一样。>
>如何在JavaScript中了解有关魔法方法的更多信息?您可以从官方的JavaScript文档以及在线教程和课程开始。您还可以在自己的项目中练习使用它们来获得动手体验。
>是否有任何工具或库可以帮助使用JavaScript中的魔法方法?可以在JavaScript中使用魔法方法的工具。例如,Lodash是一个流行的JavaScript实用程序库,它为使用数组,对象和其他类型的数据提供了有用的方法。
以上是揭示JavaScript的魔力的详细内容。更多信息请关注PHP中文网其他相关文章!

Python和JavaScript的主要区别在于类型系统和应用场景。1.Python使用动态类型,适合科学计算和数据分析。2.JavaScript采用弱类型,广泛用于前端和全栈开发。两者在异步编程和性能优化上各有优势,选择时应根据项目需求决定。

选择Python还是JavaScript取决于项目类型:1)数据科学和自动化任务选择Python;2)前端和全栈开发选择JavaScript。Python因其在数据处理和自动化方面的强大库而备受青睐,而JavaScript则因其在网页交互和全栈开发中的优势而不可或缺。

Python和JavaScript各有优势,选择取决于项目需求和个人偏好。1.Python易学,语法简洁,适用于数据科学和后端开发,但执行速度较慢。2.JavaScript在前端开发中无处不在,异步编程能力强,Node.js使其适用于全栈开发,但语法可能复杂且易出错。

javascriptisnotbuiltoncorc; saninterpretedlanguagethatrunsonenginesoftenwritteninc.1)javascriptwasdesignedAsalightweight,解释edganguageforwebbrowsers.2)Enginesevolvedfromsimpleterterterpretpreterterterpretertestojitcompilerers,典型地提示。

JavaScript可用于前端和后端开发。前端通过DOM操作增强用户体验,后端通过Node.js处理服务器任务。1.前端示例:改变网页文本内容。2.后端示例:创建Node.js服务器。

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。

JavaScript框架的强大之处在于简化开发、提升用户体验和应用性能。选择框架时应考虑:1.项目规模和复杂度,2.团队经验,3.生态系统和社区支持。

引言我知道你可能会觉得奇怪,JavaScript、C 和浏览器之间到底有什么关系?它们之间看似毫无关联,但实际上,它们在现代网络开发中扮演着非常重要的角色。今天我们就来深入探讨一下这三者之间的紧密联系。通过这篇文章,你将了解到JavaScript如何在浏览器中运行,C 在浏览器引擎中的作用,以及它们如何共同推动网页的渲染和交互。JavaScript与浏览器的关系我们都知道,JavaScript是前端开发的核心语言,它直接在浏览器中运行,让网页变得生动有趣。你是否曾经想过,为什么JavaScr


热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

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

热门文章

热工具

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

记事本++7.3.1
好用且免费的代码编辑器

WebStorm Mac版
好用的JavaScript开发工具

SublimeText3汉化版
中文版,非常好用

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。