【问题标题】:Access objects by a combination of an object and two paths通过对象和两条路径的组合访问对象
【发布时间】:2021-02-19 23:55:21
【问题描述】:

我想组合一个对象、一个变量中的路径和一个路径,类似于https://stackoverflow.com/a/43849204/14480225 中解释的内容,但带有 3 个“部分”。

这是最小的可重现示例: 我希望 combine() 函数根据 bar 值打印 selector[0].children[foo].textContentselector[0].children[foo].children[0].textContent

const selector = document.getElementsByClassName('main')
const foo = 0
let bar = ''

const toggle = () => {
  if (bar === '') bar = '.children[0]'
  else bar = ''
}

const test = () => {
  console.log(combine('selector[0].children[foo]', bar, '.textContent'))
  //I want a function like combine() that will print 'selector[0].children[foo].textContent' or 'selector[0].children[foo].children[0].textContent' depending on bar value.
}
<div class='main'>
  <h1>Hello<span>world</span></h1>
  <button onclick='toggle()'>toggle</button>
  <button onclick='test()'>test</button>
</div>

我有一个返回多个相似属性的类 (10)。我的构造函数输入了一个值,该值可用于确定最小示例中的 bar 之类的内容。通过在最小示例中更改 bar 之类的内容,每个属性都可以获得预期的输出。 我希望这样的东西能够在不同的案例之间切换,而不必为每个 bar 案例编写大量的开关,因此需要大量的代码重复。

【问题讨论】:

  • @ikiK - 这就是 OP 希望你为他们写的 ;-); OP 让我们阅读一本 12 页的小说(另一个问题),所以它们可以简明扼要,我猜想省略细节。例如,在代码中,Op 通过 selector[0].children 同时声明“在我自己的代码中”selector.children - 所以,OP 是否在“我的代码中”使用不同的选择器 - 我们不知道。
  • 这听起来像 XY Problem 。没有描述要解决的问题,除了可以执行我想要的代码。 OP 应该定义问题,而不是规定如何编写解决方案。
  • 好吧,我试过了,我问了最终结果,所以我除了得到 if x then ? if y then ? 。应该清楚之后判断HTML。但我没听懂……@RandyCasburn
  • 我明白了,感谢您的尝试。但是问题不在于生成可以用作从元​​素获取文本的方式的字符串,比如说。看起来问题陈述可能是这样的:给定选择器和选择器的哪个子项以及要检索的属性名称,生成一个接受这些参数并返回属性值的函数。是这样的吧?
  • @RandyCasburn 是的,明白了

标签: javascript string typescript object


【解决方案1】:

这样的?但请在使用之前阅读这里的eval()call javascript object method with a variable

const selector = document.getElementsByClassName('main')
const foo = 0
let bar = ''

const toggle = () => {
  if (bar === '') bar = '.children[0]'
  else bar = ''
}

function combine(){
let result = "selector[0].children[foo]"+bar+".textContent"
return result
}

const test = () => {
  console.log(eval(combine()))
  //I want a function like combine() that will print 'selector[0].children[foo].textContent' or 'selector[0].children[foo].children[0].textContent' depending on bar value.
}
<div class='main'>
  <h1>Hello<span>world</span></h1>
  <button onclick='toggle()'>toggle</button>
  <button onclick='test()'>test</button>
</div>

这是一种安全的使用方式:

const selector = document.getElementsByClassName('main')
const foo = 0
let bar = ''

const toggle = () => {
  if (bar === '') bar = '.children[0]'
  else bar = ''
}

function combine(){
return Function('"use strict";return (selector[0].children[foo]'+bar+'.textContent)')()
}

const test = () => {
  console.log(combine())

}
<div class='main'>
  <h1>Hello<span>world</span></h1>
  <button onclick='toggle()'>toggle</button>
  <button onclick='test()'>test</button>
</div>

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#never_use_eval

【讨论】:

  • 工作,谢谢!但是我担心安全性, eval 有多危险, eval 在我的上下文中是否危险?我正在编写一个获取开放网站的 Deno 模块。而且你的两个链接是相同的。
  • @Weebonn 是的,我不知道,有一些关于它的讨论,是的,我想知道如何做到这一点,并记得我在某处看到它,你应该更多地研究它。跨度>
  • 在 MDN 文档中看到 eval 可以用其他东西代替,但我无法让它工作。见developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…!
  • @Weebonn 感谢您的链接!修复它,检查新的 sn-p
  • 更新:不是 deno-dom 问题,也不是 deno 问题,这在 Deno 中有效:(new Function("selector", "foo", '"use strict";return (selector[0].children[foo]' + bar + '.textContent)'))(selector, foo),请参阅 this 了解原因。
【解决方案2】:

您需要使用querySelector 来查找您要查找的元素。

阅读querySelectorquerySelectorAll,以便您更好地理解。

不推荐使用eval,有风险。

看看你是否喜欢下面我的想法。

const selector = document.getElementsByClassName('main')
const path = ":nth-child(1)"

function getText(s, p) {
  if (s.length) // Is array
     return Array.from(s).map(x=> x.querySelector(p)?.textContent ?? "").join(" ");
  return  s.querySelector(p)?.textContent;
}

console.log(getText(selector, path))
<div class='main'>
  <h1>Hello<span>world</span></h1>
  <button onclick='toggle()'>toggle</button>
  <button onclick='test()'>test</button>
</div>

【讨论】:

    【解决方案3】:

    正如我们在 cmets 中所讨论的,这是一个采用树参数并从您选择的元素中动态检索属性的解决方案。或者,如果您将深度包含为子项的数量,则将从该子项检索道具。

    演示

    给定:

    需要传递一个 CSS 选择器 子元素的编号或空字符串 所需值的属性名称

    时间:

    将这三个给定参数传递给函数

    然后:

    如果提供了使用选择器选择的元素,则该函数应返回从由数字标识的子元素标识的属性的值。

    点击测试运行

    // NOTE: No error checking - this is only a demonstration
    
    function getValueFromDOM(selector, child, prop) {
      if (!child) {
        return document.querySelector(`${selector}`)[prop];
      } 
      return document.querySelector(`${selector}`).querySelector(`:nth-child(${child})`)[prop];
    }
    
    var children = [1, 2, 3, 4];
    var output = document.getElementById('output');
    
    function test() {
      children.forEach(child => {
        const value = getValueFromDOM('.main', child, 'textContent');
        output.innerHTML += `<p>${value}</p>`;
      });
      // With empty second argument - will print 'main'
      output.innerHTML += getValueFromDOM('.main', '', 'className')
    
    }
    
    document.querySelector('button:last-of-type').addEventListener('click', test);
    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
    </head>
    
    <body>
    
      <div class='main'>
        <h4>Hello<span>world</span></h4>
        <button>toggle</button>
        <button>test</button>
        <div>Four</div>
        <div>Five</div>
        <div>Six</div>
      </div>
      <h3>Output:</h3>
      <div id="output"></div>
    </body>
    
    </html>

    【讨论】:

      猜你喜欢
      • 2011-09-23
      • 2017-08-17
      • 1970-01-01
      相关资源
      最近更新 更多