Open fanmingfei opened 4 years ago
虽然功能不是很完善,但是实现了基本的需求
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 = {}) { let str = el.innerHTML;
update();
function update() {
el.innerHTML = str.replace(/\{([^}]+)\}/g, function () {
return obj[arguments[1]]
})
}
let temp = {
get(target, key) {
if (typeof target[key] === 'object') return new Proxy(obj, temp)
return Reflect.get(target, key);
},
set(target, key, value) {
update();
return Reflect.set(target, key, value);
}
}
return new Proxy(obj, temp);
}
const obj = {
name: 'LiLei',
language: 'JavaScript',
}
function bindHTMLContentWithObject(el,obj){
var object = {}
let reg = /\{\s*([^}]+\S)\s*\}/g
let content = el.innerHTML
for(let key in obj){
Object.defineProperty(object,key,{
set(val){
el.innerHTML += val
}
})
object[key] = obj[key]
}
while (reg.test(content)) {
content = content.replace(reg, (one, two) => {
return obj[two]})
}
el.innerHTML = content
}
bindHTMLContentWithObject(document.getElementById("content"),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>
function bindHTMLContentWithObject(el, obj) {
var obj1 = JSON.parse(JSON.stringify(obj));
var html = el.innerHTML;
el.innerHTML = html.replace(/{(.*?)}/g,function(a,b){
Object.defineProperty(obj,b,{
get(){
return obj1[b]
},
set(val){
obj1[b] = val;
el.innerHTML = html.replace(/{(.*?)}/g,function(a,b){
return obj1[b]
});
}
})
return obj1[b];
});
return obj;
}
const obj = {
name: 'LiLei',
language: 'JavaScript'
}
const newObj = bindHTMLContentWithObject(document.querySelector('#content'), obj)
// content 内容 My name is LiLin, I love JavaScript.
newObj.name = 'HanMeimei' // #content 内容为 My name is HanMeimei, I love JavaScript.
newObj.language = 'Java' // #content 内容为 My name is HanMeimei, I love Java.