【问题标题】:Is there a reason why this Proxy always throws 'set' on proxy: trap returned falsish for property 'main' but still runs perfectly otherwise?这个代理总是在代理上抛出“设置”是否有原因:陷阱为属性“主”返回错误但仍然运行完美?
【发布时间】:2020-03-29 22:05:56
【问题描述】:

我正在使用 javascript 开发一个项目,我正在尝试制作类似于 AngularJS 的东西,但有点不同,只是为了好玩,因为我认为数据绑定是一个非常酷的想法,而且非常正确实施时很有用。我定义了一个 Proxy 对象来检测何时发生更改,以及一些处理 HTML 和数据绑定的函数。它正在工作,并将替换像这样的内容 where (main = 'hello'):

<div>
  %{ main }%
</div>

用这个:

<div class = 'binding-0'>
  hello
</div>

如果 'main' 更改为其他内容,div 元素也将更改其值。 但是,每当我使用我为全局对象定义的 set 方法来处理在 html 中找到的所有变量时,我都会收到此错误:

Uncaught TypeError: 'set' on proxy: trap returned falsish for property 'main'
    at app.js:112

知道为什么吗?它仍然会做它应该做的事情,但总是抛出这个错误。
代码如下:

'use strict'
let global;
global = new Proxy({}, {
  set: function(target, property, value) {
    target[property] = value;
    doEval();
  },
  configurable: true,
  writable: true
});
let set = {};
let elements = [];
const find = document,
  a = (qs) => find.querySelector(qs),
  b = (cn) => find.getElementsByClassName(cn),
  c = (tn) => find.getElementsByTagName(tn);
Element.prototype.evaluate = function() {
  let element = this;
  if (element.children.length < 1) {
    let split = element.innerText.split(/\%{|\}%/gi);
    let bindingNum = element.className.split('binding')[1];
    if (split[1] !== undefined) {
      if (elements[bindingNum]) {
        element.outerHTML = elements.indexOf(bindingNum);
      } else {
        elements.push(element.outerHTML);
        element.className = 'binding-' + elements.indexOf(element.outerHTML);
        elements.pop();
        elements.push(element.outerHTML);
      }
      endEval(element);
    } else {
      if (bindingNum == -0) {
        bindingNum = 0;
      }
      if (elements[bindingNum]) {
        element.outerHTML = elements[bindingNum];
        element = a('.' + element.className);
        endEval(element);
      }
    }
  }
};
Object.defineProperty(Element.prototype, 'actions', {
  set: function(action) {
    let element = this;
    if (action.js) {
      Object.entries(action.js).forEach(function(event) {
        element.addEventListener(event[0], event[1], false);
      });
    }
    if (action.css) {
      Object.entries(action.css).forEach(function(style) {
        element.style[style[0]] = style[1];
      })
    }
  },
  get: function() {
    return {
      css: this.style
    }
  }
});

function doEval() {
  Array.from(c('*')).forEach(function(element) {
    element.evaluate();
  });
}

function endEval(element) {
  let newSplit = element.innerText.split(/\%|\%/gi);
  element.innerText = null;
  newSplit.forEach(function(prop) {
    if (prop.includes('{') && prop.includes('}')) {
      let finalProp = prop.split(/\{|\}/gi)[1].trim();
      if (global[finalProp] !== undefined) {
        element.innerHTML += global[finalProp];
      } else {
        global[finalProp];
        console.warn(finalProp + ' is not defined');
      }
    } else {
      element.innerHTML += prop;
    }
  });
}
window.onload = doEval;
a('.click-me').actions = {
  js: {
    click: function() {
      global.main++;
    }
  },
  css: {
    userSelect: 'none'
  }
}
global.main = 0;
<!doctype html>
<html>

<head></head>

<body>
  <div>
    %{ main }%
  </div>
  <div class='click-me'>
    Click me!
  </div>
  <script src='app.js'></script>
</body>

</html>

我现在不知道如何在不引发错误的情况下使其正常工作。我在不同的地方尝试了try {} catch (TypeError) {},但没有成功。

【问题讨论】:

    标签: javascript html ecmascript-6 data-binding


    【解决方案1】:

    根据MDN Proxy docs

    set 方法应该返回一个布尔值。返回true 表示分配成功。如果 set 方法返回 false,并且赋值发生在严格模式代码中,则会抛出 TypeError

    您的 set 方法不返回布尔值(特别是 true),因此根据这些文档,您应该在严格模式下收到 TypeError。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多