具体问题如上图,求大牛点拨。谢谢。
PHPz2017-04-11 10:31:59
题目似乎有些问题,{{m.className}},{{user.avatar}}一个前面有m,一个没有,不知道是什么意思,就当做没有处理啦。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p id="template-dom" class="{{className}}">
<p class="user-profile">
<p class="user-avatar">
<img src="{{user.avatar}}">
</p>
{{user.name}}
</p>
</p>
<script>
var render = (function() {
var reg = /{{([^}]*)}}/g
/**
* 根据prop获取model的某个field
* @param model
* @param prop
* @returns {*}
*/
function getField(model, prop) {
let keys = prop.split('.')
for (let key of keys) {
if (model[key] == null) {
return
} else {
model = model[key]
}
}
return model
}
function traverse(el,model){
// 文本节点,替换文本内容
if(el.nodeType == 3 ){
el.textContent = el.textContent.replace(reg,function(word,prop){
return getField(model,prop)
})
}
else {
//非文本节点替换属性内容
var attributes = Array.prototype.slice.call(el.attributes)
for (let attr of attributes) {
let value = attr.value
value = value.replace(reg,function(word,prop){
return getField(model,prop)
})
attr.value = value
}
}
/**
* 递归替换子节点
* @type {Array.<T>}
*/
let childNodes = Array.prototype.slice.call(el.childNodes)
for(let child of childNodes){
traverse(child,model)
}
}
function render(el,model){
traverse(el,model)
}
return render;
})()
</script>
<script>
var m = {
className: 'user',
user:{
name: 'wscn',
avatar:'https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png'
}
}
render(document.getElementById('template-dom'),m)
</script>
</body>
</html>
巴扎黑2017-04-11 10:31:59
new Function(arg1, arg2, ..., argN, function_body)
可能不对,大神轻喷。
自己写了个demo, 不知道对不,这里
但我感觉绕来绕去没什么意思,面试题至于这么整吗?
高洛峰2017-04-11 10:31:59
function render(dom, m) {
var re = /\{\{(.*)\}\}/g;
var outerHTML = dom.outerHTML;
var mapper = outerHTML
.match(re)
.map(v => v.replace(/(\{\{|\}\})/g, '') )
.map(v => {
var x;
try {
x = eval(v);
} catch(e) {
x = '';
}
return x;
});
return outerHTML.replace(re, function() { return mapper.shift(); })
}
对不起,我还是用了 eval
。
原本以为可以用 (new Function('return ' + v))()
之类的替代 eval
的,但实验结果是不可以。
另外,没看懂什么叫不允许替换原始 dom ,所以直接输出字符串了。
最后说一下自己的看法,这类题目平时玩玩还好,真要做面试题?
恶心死人了,活该招不到人。
PHP中文网2017-04-11 10:31:59
试着做了一下,很菜....
function render(e,f){
e.className = f.className;
var imgObj = e.getElementsByTagName('img')[0];
imgObj.src = f.user.avatar;
var obj = e.childNodes;
for (var i = 0; i < obj.length; i++) {
if(obj[i].className == 'user-profile'){
obj = obj[i];
}
};
var o1 = obj.lastChild;
var o2 = document.createElement('p');
o2.textContent = f.user.name;
console.log(obj.lastChild);
obj.replaceChild(o2,o1);
}
高洛峰2017-04-11 10:31:59
也来玩一下,同样的感觉没必要加m.
,都已经把m
对象传入了函数中了。
var render = function (dom, obj) {
var pattern = /\{\{([^(\})]*)\}\}/g,
html = dom.outerHTML,
reps = html.match(pattern)
.map(val => val.replace(/[\{\{\}\}]/g, ""))
.map( (val) => {
var keys = val.split("."),
res = obj;
for (var i of keys) {
res = res[i];
}
return res;
});
dom.outerHTML = html.replace(pattern, () => reps.shift());
};
另外,问下这是哪家公司?
巴扎黑2017-04-11 10:31:59
var render = (function(){
function getValue(keyString, o){
var keys = keyString.split(".");
return keys.reduce(function(prev, curr){
return prev[curr];
}, o);
}
var reg = /\{\{([^\}]*)\}\}/g;
return function(elem, o){
var html = elem.outerHTML;
elem.outerHTML = html.replace(reg, function(match, g){
return getValue(g.trim(), o);
});
}
})();
阿神2017-04-11 10:31:59
不能用eval那就当然是用new Function啦。
不过还是第一个答案那样,用对象键名来取值最好
JSBin实例
var m = {
className: 'user',
user:{
name: 'wscn',
avatar:'https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png'
}
}
var render = function (dom, model) {
var reg = /{{([^{}]*)}}/g
var attrs = Array.prototype.slice.call(dom.attributes)
for (let attr of attrs) {
attr.value = attr.value.replace(reg, function (src, val) {
return new Function('return ' + val)()
})
}
var childs = Array.prototype.slice.call(dom.childNodes)
for (let child of childs) {
if (child.nodeType === 1) {
render(child, model)
} else if (child.nodeType === 3) {
child.nodeValue = child.nodeValue.replace(reg, function (src, val) {
return new Function('return ' + val)()
})
}
}
}
render(document.getElementById('template-dom'), m)