-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
2020-03-10 HTML与对象数据进行单向绑定 #5
Comments
虽然功能不是很完善,但是实现了基本的需求 function bindHTMLContentWithObject(el, obj) {
let content = el.innerHTML;
const content_backup = content;
const newObj = {};
const reg = /\{\s*([\w]*?)\s*\}/m;
while (reg.test(content)) {
content = content.replace(reg, ($1, $2) => {
let val = newObj[$2] = obj[$2];
Object.defineProperty(newObj, $2, {
enumerable: true,
configurable: true,
get() {
return val;
},
set(newVal) {
if (newVal === val) return;
val = newVal;
compile(el, newObj, content_backup);
}
})
return obj[$2];
})
}
el.innerHTML = content;
return newObj;
}
function compile(el, obj, content) {
const reg = /\{\s*([\w]*?)\s*\}/m;
while (reg.test(content)) {
content = content.replace(reg, ($1, $2) => {
return obj[$2];
});
}
el.innerHTML = content;
} |
function bindHTMLContentWithObject(el, obj = {}) {
} |
|
<!-- html部分 -->
<div id="content">
My name is {a.b.name}, I love {language}.
</div>
<button id='btn'>change</button> // js部分
function bindHTMLContentWithObject(el, obj) {
const text = el.innerText
replace(obj)
function replace(obj) {
const newText = text.replace(/{[\d,\w,_,.]+}/g, vari => {
const keys = vari.trim().slice(1, -1).split('.')
let val = obj[keys.shift()] || ''
while (keys.length) {
val = val[keys.shift()] || ''
}
return val
})
el.innerText= newText
}
// 使用Object.defineProperty
function watchByDp(obj) {
const backup = JSON.parse(JSON.stringify(obj))
Object.keys(obj).forEach(key => {
if (Object.prototype.toString.call(obj[key]) === '[object Object]') {
watchByDp(obj[key])
}
Object.defineProperty(obj, key, {
get(){
return backup[key]
},
set(val){
backup[key] = val
replace(backup)
}
})
})
return obj
}
// return watchByDp(obj)
// 使用Proxy
function watchByProxy(obj, oldObj){
let newObj = {}
Object.keys(obj).forEach(key => {
if (Object.prototype.toString.call(obj[key]) === '[object Object]') {
obj[key] = watchByProxy(obj[key], oldObj)
}
})
return new Proxy(obj, {
set(obj, key, val) {
obj[key] = val
replace(oldObj)
}
})
}
return watchByProxy(obj, obj)
}
const obj = {
a:{b:{name: 'LiLei'}},
language: 'JavaScript'
}
const newObj = bindHTMLContentWithObject(document.querySelector('#content'), obj)
document.querySelector('#btn').addEventListener('click', e => {
newObj.a.b.name = '222'
newObj.language = 'dwdwew'
}) |
<!DOCTYPE html>
<html>
<body>
<div id="content">
My name is {name}, I love {language}.
</div>
<script>
const bindHTMLContentWithObject = (() => {
const registers = [];
function update() {
requestIdleCallback(update);
for (const [el, obj, tokens, contents] of registers) {
let newContent = "";
let needUpdate = false;
for (let i = 0; i < tokens.length; i++) {
const [key, oldValue] = tokens[i];
const newValue = obj[key];
if (newValue !== oldValue) {
needUpdate = true;
tokens[i][1] = newValue;
}
newContent += `${contents[i]}${newValue}`;
}
newContent += content[tokens.length] || "";
if (needUpdate) {
el.innerHTML = newContent;
}
}
}
requestIdleCallback(update);
return (el, obj) => {
const reg = /\{[^{}]+?\}/g;
const tokens = el.innerHTML
.match(reg)
.map(token => [token.substr(1, token.length - 2), undefined]);
const contents = el.innerHTML.split(reg);
registers.push([el, obj, tokens, contents]);
};
})();
const obj = {
name: "LiLei",
language: "JavaScript"
};
const newObj = bindHTMLContentWithObject(
document.querySelector("#content"),
obj
);
</script>
</body>
</html> |
继续另一波骚操作 <!DOCTYPE html>
<html>
<body>
<div id="content">
My name is {name}, I love {language}.
</div>
<script>
const bindHTMLContentWithObject = (() => {
const registers = [];
function update() {
requestIdleCallback(update);
for (const [el, obj] of registers) {
for (let i = 0; i < el.childNodes.length; i += 1) {
const node = el.childNodes[i];
if (node.nodeType === 8) {
const key = node.textContent;
i += 1;
const tokenNode = el.childNodes[i];
if (tokenNode.textContent !== obj[key]) {
tokenNode.textContent = obj[key];
}
}
}
}
}
requestIdleCallback(update);
return (el, obj) => {
const reg = /\{[^{}]+?\}/g;
const contents = el.textContent.split(reg);
const fragment = document.createDocumentFragment();
el.textContent.match(reg).forEach((token, i) => {
const key = token.substr(1, token.length - 2);
const content = contents.shift();
const contentNode = document.createTextNode(content);
const commondNode = document.createComment(key);
const tokenNode = document.createTextNode(obj[key]);
fragment.appendChild(contentNode);
fragment.appendChild(commondNode);
fragment.appendChild(tokenNode);
});
if (contents.length) {
fragment.appendChild(document.createTextNode(contents.shift()));
}
el.textContent = "";
el.appendChild(fragment);
registers.push([el, obj]);
};
})();
const obj = {
name: "LiLei",
language: "JavaScript"
};
const newObj = bindHTMLContentWithObject(
document.querySelector("#content"),
obj
);
</script>
</body>
</html> |
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The text was updated successfully, but these errors were encountered: