dom 相关问题

通过文档对象模型,将此标记用于有关其他语言与XML / HTML交互的问题。不要将其用作HTML,JavaScript或SAX的简写 - 使用其他标记来表示语言和标记。

JavaScript 以编程方式监听输入值变化

我正在尝试找出通过 JavaScript 更改输入值的位置 我的输入看起来像: 我正在尝试找出通过 JavaScript 更改输入值的位置 我的输入如下: <input type="text" size="1" name="MyDatePicker" role="combobox" autocomplete="off" > 我在浏览器的控制台中输入了以下内容: function handleChange(event) {debugger;} document.getElementsByName('MyDatePicker')[0].addEventListener('change', handleChange) document.getElementsByName('MyDatePicker')[0].addEventListener('input', handleChange) 但我没有使用 handleChange 功能。 有没有办法在以编程方式而不是通过 UI 更改输入值时触发事件? 您可以添加全局输入处理程序并过滤输入名称。 // Add a global listener document.addEventListener('input', function(event) { // Filter on the name if (event.target.name === 'MyDatePicker') { handleChange(event); // Forward the event } }); // Handle as if we attached this to input[name="MyDatePicker"] function handleChange(event) { console.log('Current value:', event.target.value); } <input type="text" name="MyDatePicker" role="combobox" size="1" autocomplete="off">

回答 1 投票 0

将 JavaScript 中的 CSS 自定义属性/变量设置为 String 类型

考虑以下场景: document.body.style.setProperty("--text", "world") 正文::之前{ --文本:“你好”; 内容:var(--text, "..."); } 正文::之后{ 内容: var(--text, "..."...

回答 3 投票 0

如何将两个数组值和冒号组合成一个段落?

https://github.com/branebilan/BasketLigaDicmo2/blob/main/BasketJS.js 代码行号 85。 我正在自动化当地篮球联赛网站的球队和个人统计数据,并且我正在努力...

回答 1 投票 0

使用 PHP 和简单 HTML DOM 解析 HTML 时遇到问题

我正在尝试使用 simple_html_dom.php 解析 HTML。 我试图解析的 HTML 如下所示。 我可以成功获取每个产品名称:产品 1、产品 2、产品 3 等...

回答 3 投票 0

Javascript:从下往上遍历给定的元素树处理元素

这难倒了我。我有一个 说法,它包含一个元素树、子元素、子元素、子元素等等。我想从下到上处理所有这些元素。那就是 这把我难住了。我有一个 <div> 说法,它包含一个元素树、子元素、子元素、子元素等等。我想从下到上处理所有这些元素。除非它的所有子元素都已被处理,否则永远不会处理给定的元素。 显然,<div>下面有任意数量的叶子,我们需要从每个叶子向上走,但永远不要经过具有未处理的子节点的节点。 我想知道在我付出太多之前这是否是一个解决问题的方法。我的直觉是,在形式上,算法是分成几个部分的: 枚举所有叶子(树中的死端元素) 沿着每个分支走到第一个路口 枚举已处理所有子项的所有结点 沿着树枝走到下一个路口 等等等等 我可以感觉到那里的一种模式,它随时枚举已完全处理的节点(没有未处理的子节点),逐一向上走到下一个节点,然后再次枚举直到到达顶部。建议采用递归方法,直到未处理节点的枚举长度为零。 听起来很可行,但对枚举没有未处理子节点的节点的最有效方法有点困惑。正如我所说,如果问题得到解决并且有一个使用本机 Javascript 的标准解决方案,我会热衷于利用它。 嗯,您可以使用简单的递归方法,仅在将 lambda func 应用于元素 e 的所有子元素之后才应用它。该解决方案清楚地处理其子元素之后的元素。 traverse(document.body, (e) => console.log(e)) function traverse(e, func) { Array.from(e.children).forEach(child => { traverse(child, func) }); func(e) } <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>Example</h1> <button>Some button</button> <pre> <code><span>inner span</span> some code</code> <span>span</span> </pre> <script type="module" src="js/dom-traverse.js"></script> </body> </html>

回答 1 投票 0

如何替换 div 元素内的文本?

我需要动态设置 DIV 元素内的文本。最好的、浏览器安全的方法是什么?我有prototypejs 和scriptaculous 可用。 我需要动态设置 DIV 元素内的文本。最好的、浏览器安全的方法是什么?我有prototypejs和scriptaculous可用。 <div id="panel"> <div id="field_name">TEXT GOES HERE</div> </div> 该函数如下所示: function showPanel(fieldName) { var fieldNameElement = document.getElementById('field_name'); //Make replacement here } 您可以简单地使用: fieldNameElement.innerHTML = "My new text!"; 为 2013 年及以后阅读本文的所有人更新: 这个答案有很多搜索引擎优化,但所有答案都严重过时,并且依赖于库来完成所有当前浏览器开箱即用的事情。 要替换 div 元素内的文本,请使用 .textContent(),所有当前浏览器都提供了标准方法。 fieldNameElement.textContent = "New text"; function showPanel(fieldName) { var fieldNameElement = document.getElementById("field_name"); while(fieldNameElement.childNodes.length >= 1) { fieldNameElement.removeChild(fieldNameElement.firstChild); } fieldNameElement.appendChild(fieldNameElement.ownerDocument.createTextNode(fieldName)); } 这样做的好处: 它只使用DOM,因此该技术可以移植到其他语言,并且不依赖于非标准的innerHTML fieldName 可能包含 HTML,这可能是试图进行 XSS 攻击。 如果我们知道它只是文本,我们应该创建一个文本节点,而不是让浏览器将其解析为 HTML 如果我要使用 javascript 库,我会使用 jQuery,并执行以下操作: $("div#field_name").text(fieldName); 请注意,@AnthonyWJones 的评论是正确的:“field_name”不是一个特别具有描述性的 ID 或变量名称。 我会使用 Prototype 的 update 方法,它支持纯文本、HTML 片段或任何定义 toString 方法的 JavaScript 对象。 $("field_name").update("New text"); Element.更新文档 $('field_name').innerHTML = 'Your text.'; Prototype 的一个漂亮功能是 $('field_name') 与 document.getElementById('field_name') 做同样的事情。用它! :-) John Topley 使用 Prototype 的 update 函数的回答是另一个很好的解决方案。 快速的答案是使用innerHTML(或原型的更新方法,几乎是一样的)。 innerHTML 的问题是您需要转义所分配的内容。 根据您的目标,您需要使用其他代码来完成此操作,或者 在 IE 中:- document.getElementById("field_name").innerText = newText; FF:- document.getElementById("field_name").textContent = newText; (实际上FF的代码中有以下内容) HTMLElement.prototype.__defineGetter__("innerText", function () { return this.textContent; }) HTMLElement.prototype.__defineSetter__("innerText", function (inputText) { this.textContent = inputText; }) 现在,如果您需要尽可能广泛的浏览器支持,那么我可以使用innerText,那么这不是一个完整的解决方案,但在原始中使用innerHTML也不是。 如果您确实希望我们从您上次停下的地方继续,您可以这样做: if (fieldNameElement) fieldNameElement.innerHTML = 'some HTML'; nodeValue 也是您可以使用的标准 DOM 属性: function showPanel(fieldName) { var fieldNameElement = document.getElementById(field_name); if(fieldNameElement.firstChild) fieldNameElement.firstChild.nodeValue = "New Text"; } el.innerHTML=''; el.appendChild(document.createTextNode("yo")); 如果您倾向于在网站上开始使用大量 JavaScript,那么 jQuery 可以让 DOM 的使用变得极其简单。 http://docs.jquery.com/Manipulation 使其变得简单: $("#field-name").text("一些新文本。"); 如果无法假设结构,请使用innerText - 使用 Text#data 更新现有文本 性能测试 function showPanel(fieldName) { var fieldNameElement = document.getElementById(field_name); fieldNameElement.removeChild(fieldNameElement.firstChild); var newText = document.createTextNode("New Text"); fieldNameElement.appendChild(newText); } 这是一个简单的 jQuery 方法: var el = $('#yourid .yourclass'); el.html(el.html().replace(/Old Text/ig, "New Text"));

回答 13 投票 0

如何使用简单的html dom从td读取内容

这是我的代码: 有事 某事2 这是我的代码: <tr> <td class="text"> <div><a href="somethinghref">Something</a></div> </td> <td>Something2</td> <td>Something3</td> </tr> 我想从 td 获取内容并像这样以单行返回 某事 - 某事2 对于 HTML DOM 操作,有一个名为 jQuery 的库,您可以使用它轻松遍历 HTML dome。 贝娄是您问题的解决方案。 <!doctype html> <html> <head> <meta charset="utf-8"> <title>Untitled Document</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> </head> <body> <table id="tblNewAttendees"> <tr> <td class="text"><div><a href="somethinghref">Something</a></div</td> <td>Something2</td> <td>Something3</td> </tr> </table> <div class="table-content"></div> <script> $(document).ready(function(){ var content =''; $('#tblNewAttendees tr').each(function() { $.each(this.cells, function(){ //alert($(this).text()); content+=$(this).text()+" - "; }); }); $(".table-content").html(content); }); </script> </body> </html>

回答 1 投票 0

使用 React.createElement 时对象可能未定义

这是我的球: 从“csstype”导入CSS; const CircleAroundNumber: CSS.Properties = { 边框半径:“50%”, 宽度:“70px”, 高度:“70px”, 填充:&

回答 1 投票 0

file_get_html 错误,不起作用

我正在使用 Simple HTML Dom 尝试抓取 HTML 表格。 我按照他们的说明进行操作,并查看了许多其他代码示例,但 file_get_html 似乎不起作用。 这是我的代码: &l...

回答 3 投票 0

任何人都可以给我一个具体或明确的解释,什么时候在 JavaScript 中使用 QUERY 选择器和 ID 选择器? [已关闭]

我想通过 Id 选择器从 html 部分获取复选框,但没有得到所需的输出。之后我尝试通过 querySelector ,然后得到我想要的输出。所以这就是

回答 1 投票 0

Next Js 生产中出现黑屏块错误

Next JS 这个错误是什么?它只发生在生产中。请帮我 下一个 js 中的错误块图像 我预计页面会正常加载,但是当我更改路线或按 f5 时,我有时会......

回答 1 投票 0

如何正则表达式和替换innerText,然后恢复HTML元素

我想要正则表达式并仅替换html的文本内容(innerText),并最终保留所有HTML元素(或按原样恢复它们)。 正则表达式不能检查 HTML 元素,而只能检查

回答 1 投票 0

如何使用 Web::Scraper 抓取以下内容?

这个问题与How to Parse this HTML with Web::Scraper? 不同但相关。 我必须使用 Web::Scraper 抓取页面,其中 HTML 可能会略有变化。有时可以是 这个问题与 How to Parse this HTML with Web::Scraper?. 不同但相关 我必须使用 Web::Scraper 抓取页面,其中 HTML 可能会略有变化。有时也可以 <div> <p> <strong>TITLE1</strong> <br> DESCRIPTION1 </p> <p> <strong>TITLE2</strong> <br> DESCRIPTION2 </p> <p> <strong>TITLE3</strong> <br> DESCRIPTION3 </p> </div> 我用 Web::Scraper 使用以下代码提取 my $test = scraper { process 'div p', 'test[]' => scraper { process 'p strong', 'name' => 'TEXT'; process '//p/text()', 'desc' => [ 'TEXT', sub { s/^\s+|\s+$//g } ]; }; }; 但有时它包含以下 HTML(请注意,每个标题和描述不再用 <p> 分隔)。 <div> <p> <strong>TITLE1</strong> <br> DESCRIPTION1 <strong>TITLE2</strong> <br> DESCRIPTION2 <strong>TITLE3</strong> <br> DESCRIPTION3 </p> </div> 如何将上面的 HTML 抓取到 test => [ { desc => "DESCRIPTION1 ", name => "TITLE1" }, { desc => "DESCRIPTION2 ", name => "TITLE2" }, { desc => "DESCRIPTION3 ", name => "TITLE3" }, ] 我尝试修改上面的代码,但我无法弄清楚使用什么 HTML 来“拆分”唯一的标题和描述对。 我从未使用过 WebScraper,但它的行为似乎很糟糕或者很奇怪。 以下 XPath 表达式或多或少应该适用于这两种情况(需要进行小的调整): //div//strong/text() //div//br/following-sibling::text() 将它们插入 xmllint (libxml2) 时: tmp >xmllint --html --shell a.html / > cat / ------- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> <html><body> <div> <p> <strong>TITLE1</strong> <br> DESCRIPTION1 </p> <p> <strong>TITLE2</strong> <br> DESCRIPTION2 </p> <p> <strong>TITLE3</strong> <br> DESCRIPTION3 </p> </div> </body></html> / > xpath //div//strong/text() Object is a Node Set : Set contains 3 nodes: 1 TEXT content=TITLE1 2 TEXT content=TITLE2 3 TEXT content=TITLE3 / > xpath //div//br/following-sibling::text() Object is a Node Set : Set contains 3 nodes: 1 TEXT content= DESCRIPTION1 2 TEXT content= DESCRIPTION2 3 TEXT content= DESCRIPTION3 / > load b.html / > cat / ------- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> <html><body><div> <p> <strong>TITLE1</strong> <br> DESCRIPTION1 <strong>TITLE2</strong> <br> DESCRIPTION2 <strong>TITLE3</strong> <br> DESCRIPTION3 </p> </div></body></html> / > xpath //div//strong/text() Object is a Node Set : Set contains 3 nodes: 1 TEXT content=TITLE1 2 TEXT content=TITLE2 3 TEXT content=TITLE3 / > xpath //div//br/following-sibling::text() Object is a Node Set : Set contains 5 nodes: 1 TEXT content= DESCRIPTION1 2 TEXT content= 3 TEXT content= DESCRIPTION2 4 TEXT content= 5 TEXT content= DESCRIPTION3 当您将这些的各种版本插入 WebScraper 时,它们不起作用。 process '//div', 'test[]' => scraper { process '//strong', 'name' => 'TEXT'; process '//br/following-sibling::text()', 'desc' => 'TEXT'; }; 结果: /tmp >for f in a b; do perl bs.pl file:///tmp/$f.html; done { test => [{ desc => " DESCRIPTION1 ", name => "TITLE1" }] } { test => [{ desc => " DESCRIPTION1 ", name => "TITLE1" }] } process '//div', 'test[]' => scraper { process '//div//strong', 'name' => 'TEXT'; process '//div//br/following-sibling::text()', 'desc' => 'TEXT'; }; 结果: /tmp >for f in a b; do perl bs.pl file:///tmp/$f.html; done { test => [{ desc => " DESCRIPTION1 ", name => "TITLE1" }] } { test => [{ desc => " DESCRIPTION1 ", name => "TITLE1" }] } 即使是最基本的情况: process 'div', 'test[]' => scraper { process 'strong', 'name' => 'TEXT'; }; 结果: /tmp >for f in a b; do perl bs.pl file:///tmp/$f.html; done { test => [{ name => "TITLE1" }] } { test => [{ name => "TITLE1" }] } 即使你通过 use Web::Scraper::LibXML 告诉它使用 libxml2 -什么也没有! 为了确保我不会发疯,我尝试使用 Ruby 的 Nokogiri: /tmp >for f in a b; do ruby -rnokogiri -rpp -e'pp Nokogiri::HTML(File.read(ARGV[0])).css("div p strong").map &:text' $f.html; done ["TITLE1", "TITLE2", "TITLE3"] ["TITLE1", "TITLE2", "TITLE3"] 我缺少什么。 我想我已经解决了。我不确定这是否是最好的方法,但它似乎可以处理这两种情况。 my $test = scraper { process '//div', 'test' => scraper { process '//div//strong//text()', 'name[]' => 'TEXT'; process '//p/text()','desc[]' => ['TEXT', sub { s/^\s+|\s+$//g} ]; } }; my $res = $test->scrape(\$html); #get the names and descriptions my @keys = @{$res->{test}->{name}}; my @values = @{$res->{test}->{desc}}; #merge two arrays into hash my %hash; @hash{@keys} = @values;

回答 2 投票 0

如何识别一个元素中有一个封闭的shadow Root?

#shadow-root(关闭) 我如何检测这个笑话类中有一个封闭的影子根。 试过了...

回答 1 投票 0

为什么异步循环 `File.stream().getReader().read()` 可能会阻塞主线程?

const el = document.getElementById('el'); const out = document.getElementById('out'); 埃尔.

回答 1 投票 0

选择 ::before 或 ::after 伪元素中的文本

看这个非常简单的代码 p::之前{ 内容:“之前-”; } 你好 ...

回答 4 投票 0

iMacros 标签查找 TXT 并单击附近的(上一个)链接

下面是Wordpress后端标签管理部分的示例代码。我正在尝试编写一个 iMacros 来查找标签并将其删除。但是,标签文本不会位于任何 HTML 标签的下方。 以下是Wordpress后端标签管理部分的示例代码。我正在尝试编写一个 iMacros 来查找标签并将其删除。但是,标签文本不在任何 HTML 标签下方。 <div class="tagchecklist"> <span> <a id="post_tag-check-num-0" class="ntdelbutton" tabindex="0">X</a> &nbsp;Orange </span> <span> <a id="post_tag-check-num-1" class="ntdelbutton" tabindex="0">X</a> &nbsp;Apple </span> <span> <a id="post_tag-check-num-2" class="ntdelbutton" tabindex="0">X</a> &nbsp;Banana </span> <span> <a id="post_tag-check-num-3" class="ntdelbutton" tabindex="0">X</a> &nbsp;Grape </span> </div> 我尝试过但没有成功,因为 TAG 无法访问 TAG POS=1 TYPE=(Not sure what to put here) ATTR=TXT:Banana TAG POS=R-1 TYPE=A ATTR=TXT:* 我需要脚本来查找包含 Banana 文本的 SPAN,然后单击 SPAN 中的 X 按钮。 感谢您的帮助。 相对定位不能很好地解决这个问题,所以: SET !EXTRACT_TEST_POPUP NO TAG POS=1 TYPE=SPAN ATTR=TXT:*Banana* EXTRACT=HTM SET FP EVAL("parseInt('{{!EXTRACT}}'.match(/check-num-(\\d)/)[1]) + 1;") TAG POS={{FP}} TYPE=A ATTR=TXT:* 有趣的“老”问题,啊啊……! => 7 年后,有了“新”解决方案... “Double相对定位”(*)的典型用途,“香蕉”元素作为Anchor,就像提问者正在尝试的那样......: TAG POS=1 TYPE=SPAN ATTR=TXT:Banana TAG POS=R1 TYPE=* ATTR=* TAG POS=R-1 TYPE=A ATTR=TXT:* => 第一个 R-POS 与 R1 以获得包含链接的 SPAN 元素的 outside,...第二个 R-POS 与 R-1 使 iMacros 能够“看到”再次在同一个 SPAN 元素里面... (*):有关“双重相对定位”的更多信息,请谷歌搜索这3个术语(带双引号)或搜索iMacros论坛,这个概念是“我的”,我已经解释了几十次(因为2014)在 iMacros 论坛上... (我不敢发布任何(直接)链接,因为带有站点外部资源链接的答案通常最终会被标记和删除......)

回答 2 投票 0

使用 playwright 检查元素类是否包含字符串

我正在尝试获取第18天的元素,并检查它是否在其类上禁用。 我正在尝试获取第 18 天的元素,并检查它的类上是否有 disabled。 <div class="react-datepicker__day react-datepicker__day--tue" aria-label="day-16" role="option">16</div> <div class="react-datepicker__day react-datepicker__day--wed react-datepicker__day--today" aria-label="day-17" role="option">17</div> <div class="react-datepicker__day react-datepicker__day--thu react-datepicker__day--disabled" aria-label="day-18" role="option">18</div> 这是我的代码,假设 this.xpath = 'xpath=.//*[contains(@class, "react-datepicker__day") and not (contains(@class, "outside-month")) and ./text()="18"]' async isDateAvailable () { const dayElt = await this.page.$(this.xpath) console.log(dayElt.classList.contains('disabled'))) \\this should return true 我似乎无法让它发挥作用。错误提示 TypeError: 无法读取未定义的属性“包含”。你能帮我指出我在这里做错了什么吗? 看来你可以写了 expect(page.locator('.selector-name')).toHaveClass(/target-class/) /target-class/ - 需要斜杠,因为它是 RegExp 为了通过一个调用检查几个类,我使用这个助手(这是因为 api 方式对我不起作用https://playwright.dev/docs/test-assertions#locator-assertions-to-have-class) : async function expectHaveClasses(locator: Locator, className: string) { // get current classes of element const attrClass = await locator.getAttribute('class') const elementClasses: string[] = attrClass ? attrClass.split(' ') : [] const targetClasses: string[] = className.split(' ') // Every class should be present in the current class list const isValid = targetClasses.every(classItem => elementClasses.includes(classItem)) expect(isValid).toBeTruthy() } 在className中,你可以编写几个用空格分隔的类: const result = await expectHaveClasses(page.locator('.item'), 'class-a class-b') 您必须在浏览器内对其进行评估。 $ 将返回一个 ElementHandle,它是浏览器 DOM 元素的包装器,因此您必须使用例如evaluate然后就可以了。或者简单地使用 $eval 查找元素,将其传递到在浏览器 JavaScript 引擎内执行的回调中。这意味着类似的事情会起作用: // @ts-check const playwright = require("playwright"); (async () => { const browser = await playwright.chromium.launch(); const context = await browser.newContext(); const page = await context.newPage(); await page.setContent(` <div id="a1" class="foo"></div> `) console.log( await page.$eval("#a1", el => el.classList.contains("foo1")) ) await browser.close(); })(); 对于OP的原始代码,XPath通常不是推荐的在Playwright中选择元素的方法。更喜欢定位器。我可能会按文本和角色进行选择,然后断言类存在。话又说回来,类不是“用户可见”的,因此那里可能还有更好的断言机会。 如果剧作家测试不符合OP的情况,这个答案正确地提供了evaluate,尽管我会用定位器写它:const isDisabled = await page.getByLabel("day-18") .evaluate(el => el.classList.contains("disabled")); 将此线程视为断言元素类的规范,这个答案很好地展示了如何使用正则表达式来匹配单个类,但也提倡在其expectHaveClasses帮助器中使用antipattern:const isValid = targetClasses.every(classItem => elementClasses.includes(classItem)) expect(isValid).toBeTruthy() 问题是失败时的错误消息将不清楚并且可能难以调试。此外,当元素位于 DOM 中时,断言不会等待类更改为正确的类,而是会异步调整其类列表。 类列表通常不会那么长,所以我会分别枚举每个类名: const loc = page.locator("p") await expect(loc).toHaveClass(/\bfoo\b/); await expect(loc).toHaveClass(/\bbar\b/); await expect(loc).toHaveClass(/\bbaz\b/); 这是一个很好的例子,WET 和避免过早抽象可能比 DRY 更好,因为正确干燥代码的门槛相当高。 从技术上讲,前瞻也是可能的: await expect(loc).toHaveClass(/(?=.*\ba\b)(?=.*\bb\b)(?=.*\bc\b)/); 但是这是不可读的,所以如果你要这样做,那么助手可能会有意义: import {expect, test} from "@playwright/test"; // ^1.30.0 test.beforeEach(({page}) => page.setContent('<p class="a b c d"></p>')); const hasWordsRegex = (...a) => new RegExp(a.map(e => `(?=.*\\b${e}\\b)`).join("")); test("has classes 'a', 'b' and 'c'", async ({page}) => { await expect(page.locator("p")).toHaveClass(hasWordsRegex("a", "b", "c")); }); 请注意,这并不严格,因此存在类 d 是可以的。这是常见情况。如果您真的认真对待这个模式,您可以将其放入自定义匹配器中: import {expect, test} from "@playwright/test"; // ^1.30.0 test.beforeEach(({page}) => page.setContent('<p class="a b c d"></p>')); const hasWordsRegex = (...a) => new RegExp(a.map(e => `(?=.*\\b${e}\\b)`).join("")); expect.extend({ async toHaveAllClasses(received, ...classes) { const className = await received.evaluate(el => el.className); if (hasWordsRegex(...classes).test(className)) { return { message: () => "passed", pass: true, }; } return { message: () => `failed: element class '${className}' ` + `did not match expected '${classes.join(" ")}'`, pass: false, }; }, }); test("has classes 'a', 'b' and 'c'", async ({page}) => { await expect(page.locator("p")).toHaveAllClasses("a", "b", "c"); }); test("is missing at least one of 'a', 'b', 'c' or 'x'", async ({page}) => { await expect(page.locator("p")).not.toHaveAllClasses("a", "b", "c", "x"); }); 除了可读性之外,正则表达式的另一个问题是忘记转义正则表达式特殊字符。谨慎使用正则表达式!在上面的示例中,可能不清楚在幕后使用正则表达式,从而导致令人困惑的失败。它可以在没有正则表达式的情况下重写: expect.extend({ async toHaveAllClasses(received, ...classes) { const [classList, className] = await received.evaluate(el => [[...el.classList], el.className]); const missing = classes.filter(e => !classList.includes(e)); if (missing.length) { return { message: () => `failed: element class '${className}' ` + `did not contain '${missing.join(", ")}'`, pass: false, }; } return { message: () => "passed", pass: true, }; }, }); 如果您想在存在额外类时失败,您可以添加相反方向的检查: const extra = classList.filter(e => !classes.includes(e)); if (extra.length) { return { message: () => `failed: element class '${className}' ` + `had extra class '${extra.join(", ")}' ` + `that wasn't part of the expected class '${classes.join(" ")}'`, pass: false, }; } 这可以让您以任意顺序准确检查多个类。 (希望如此)这里的最后一个问题是 evaluate 不会等待类通过测试——它会立即检查一次,然后成功或失败。诸如waitForFunction、轮询或重试之类的东西可以帮助创建等待,但希望这些小烦恼足以激发为什么使用一些toHaveClass调用可能是在撰写本文时最好的解决方案。

回答 3 投票 0

如何使用库存系统在 Vue/JS/HTML 中启用拖放功能?

我想重新创建一个像《我的世界》中的库存系统,因为它有助于理解很多 Web 开发内容,并且总体上成为一名更好的开发人员,我的代码无法正常工作并更新我的

回答 1 投票 0

无法使用 HTML 中的输入元素在 TS 文件中定义变量

我正在尝试从 HTML 文件中的按钮运行 ts/js 文件。 我正在使用 TS 和 Node js。 这是我收到错误的一些代码 document.addEventListener('DOMContentLoaded', () => { 常量

回答 1 投票 0

© www.soinside.com 2019 - 2024. All rights reserved.