【发布时间】: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