如何为HTMLELement创建代理

时间:2019-05-06 15:39:59

标签: javascript dom proxy

如何为浏览器本机dom对象创建代理?

我想拦截元素样式的设置。因此,我为dom对象创建了一个代理。但是,当我使用诸如getComputedStyle之类的函数时,它将导致错误。

from selenium.common.exceptions import StaleElementReferenceException
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


base_url = "https://startup-days-2019.events.startupinvest.ch"
driver = webdriver.Firefox()
wait = WebDriverWait(driver, 10)

driver.get(base_url + "/participants")
size = int(wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".opportunities-count-number"))).text)

participants = []
while len(participants) < size:
    participant_cards = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".participants-main-container a")))
    for card in participant_cards:
        try:
            href = card.get_attribute("href")
            if href not in participants:
                participants.append(href)
        except StaleElementReferenceException:
            pass

    driver.execute_script("arguments[0].scrollIntoView();", participant_cards[len(participant_cards)-1])

for participant in participants:
    driver.get(participants)

el是本机浏览器dom对象。在我的代码中,有许多方法的参数为el,这些方法可能会修改el。我想防止其中的某些方法修改el,因此我尝试代理el对象。但是在代理之后,dom对象的某些方法不能在代理对象上使用,例如getComputedStyler。

我在下面创建一个演示。

  const setHandler = (target: any, prop: PropertyKey, value: any, _receiver?: any) => {
    if (/*some condition*/) {
      target[prop] = value
    }
    return true
  }

  const getHandler = (target: any, prop: PropertyKey, _receiver?: any) => {
    return target[prop]
  }

  const style = new Proxy(el.style, {
    get: getHandler,
    set: setHandler
  })
  const classList = new Proxy(el.classList,{
    get: getHandler,
    set: setHandler
  })

  const proxy = new Proxy(el/*HTMLElement*/, {
    get: (target, prop, _receiver) => {
      if (prop === 'target') {
        return target
      }
      if (prop === 'style') {
        return style
      }
      if (prop === 'classList') {
        return classList
      }
      return getHandler(target, prop, target)
    },
    set: setHandler
  })

  const style = getComputedStyle(el)

(function() {
  const node = document.querySelector('#demo')
  const proxy = new Proxy(node, {
    getPrototypeOf(target){
      return Object.getPrototypeOf(target)
    },
    get(target, prop, receiver){
      let value = target[prop]
      if (typeof value === 'function') {
        value = Function.prototype.bind.call(value, target)
      }
      return value
    },
    set(target, prop,value, receiver){
      target[prop] = value
    },
    apply(target, args, newTarget) {
      return Object.apply(target,args)
    },
  })
  console.log(proxy)
  console.log(Object.getPrototypeOf(proxy))         
 
  console.log(proxy.style)

  // error: Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.
  const style = getComputedStyle(proxy)
  console.log(style)
})()

0 个答案:

没有答案