结构化和绑定(ajax响应)

Structuring and Binding (ajax response)

本文关键字:响应 ajax 绑定 结构化      更新时间:2024-05-14

在我多年的编码工作中遇到的一个常见模式是对来自服务器响应(XMLHttpRequest)的数据进行结构化/绑定。创建元素并按特定顺序附加它们以及绑定(属性、事件、内容)的问题正是我在这里试图实现的。


为了示例和简单起见,我试图创建一个tr-td嵌套结构,并绑定var instructs对象的属性(表行、表数据)。

JSON响应(伪数据)

var response =[{"employeeNumber":"1002","lastName":"Murphy","firstName":"Diane","extension":"x5800","email":"dmurphy@classicmodelcars.com","officeCode":"1","reportsTo":null,"jobTitle":"President"},{"employeeNumber":"1056","lastName":"Patterson","firstName":"Mary","extension":"x4611","email":"mpatterso@classicmodelcars.com","officeCode":"1","reportsTo":"1002","jobTitle":"VP Sales"},{"employeeNumber":"1076","lastName":"Firrelli","firstName":"Jeff","extension":"x9273","email":"jfirrelli@classicmodelcars.com","officeCode":"1","reportsTo":"1002","jobTitle":"VP Marketing"},{"employeeNumber":"1088","lastName":"Patterson","firstName":"William","extension":"x4871","email":"wpatterson@classicmodelcars.com","officeCode":"6","reportsTo":"1056","jobTitle":"Sales Manager (APAC)"},{"employeeNumber":"1102","lastName":"Bondur","firstName":"Gerard","extension":"x5408","email":"gbondur@classicmodelcars.com","officeCode":"4","reportsTo":"1056","jobTitle":"Sale Manager (EMEA)"},{"employeeNumber":"1143","lastName":"Bow","firstName":"Anthony","extension":"x5428","email":"abow@classicmodelcars.com","officeCode":"1","reportsTo":"1056","jobTitle":"Sales Manager (NA)"},{"employeeNumber":"1165","lastName":"Jennings","firstName":"Leslie","extension":"x3291","email":"ljennings@classicmodelcars.com","officeCode":"1","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1166","lastName":"Thompson","firstName":"Leslie","extension":"x4065","email":"lthompson@classicmodelcars.com","officeCode":"1","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1188","lastName":"Firrelli","firstName":"Julie","extension":"x2173","email":"jfirrelli@classicmodelcars.com","officeCode":"2","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1216","lastName":"Patterson","firstName":"Steve","extension":"x4334","email":"spatterson@classicmodelcars.com","officeCode":"2","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1286","lastName":"Tseng","firstName":"Foon Yue","extension":"x2248","email":"ftseng@classicmodelcars.com","officeCode":"3","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1323","lastName":"Vanauf","firstName":"George","extension":"x4102","email":"gvanauf@classicmodelcars.com","officeCode":"3","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1337","lastName":"Bondur","firstName":"Loui","extension":"x6493","email":"lbondur@classicmodelcars.com","officeCode":"4","reportsTo":"1102","jobTitle":"Sales Rep"},{"employeeNumber":"1370","lastName":"Hernandez","firstName":"Gerard","extension":"x2028","email":"ghernande@classicmodelcars.com","officeCode":"4","reportsTo":"1102","jobTitle":"Sales Rep"},{"employeeNumber":"1401","lastName":"Castillo","firstName":"Pamela","extension":"x2759","email":"pcastillo@classicmodelcars.com","officeCode":"4","reportsTo":"1102","jobTitle":"Sales Rep"},{"employeeNumber":"1501","lastName":"Bott","firstName":"Larry","extension":"x2311","email":"lbott@classicmodelcars.com","officeCode":"7","reportsTo":"1102","jobTitle":"Sales Rep"},{"employeeNumber":"1504","lastName":"Jones","firstName":"Barry","extension":"x102","email":"bjones@classicmodelcars.com","officeCode":"7","reportsTo":"1102","jobTitle":"Sales Rep"},{"employeeNumber":"1611","lastName":"Fixter","firstName":"Andy","extension":"x101","email":"afixter@classicmodelcars.com","officeCode":"6","reportsTo":"1088","jobTitle":"Sales Rep"},{"employeeNumber":"1612","lastName":"Marsh","firstName":"Peter","extension":"x102","email":"pmarsh@classicmodelcars.com","officeCode":"6","reportsTo":"1088","jobTitle":"Sales Rep"},{"employeeNumber":"1619","lastName":"King","firstName":"Tom","extension":"x103","email":"tking@classicmodelcars.com","officeCode":"6","reportsTo":"1088","jobTitle":"Sales Rep"},{"employeeNumber":"1621","lastName":"Nishi","firstName":"Mami","extension":"x101","email":"mnishi@classicmodelcars.com","officeCode":"5","reportsTo":"1056","jobTitle":"Sales Rep"},{"employeeNumber":"1625","lastName":"Kato","firstName":"Yoshimi","extension":"x102","email":"ykato@classicmodelcars.com","officeCode":"5","reportsTo":"1621","jobTitle":"Sales Rep"},{"employeeNumber":"1702","lastName":"Gerard","firstName":"Martin","extension":"x2312","email":"mgerard@classicmodelcars.com","officeCode":"4","reportsTo":"1102","jobTitle":"Sales Rep"}];

装订(说明)

var instructs={
    tag:"tr",
    attributes:{class:"table-row"},
    props:{
        email:{
            tag:"td",
            content: null,
            attributes:{class:"table-data",id:"table-data-id"}
        },
        employeeNumber:{
            tag:"td",
            attributes:{class:"table-data"},
            content: null,
            props:{
                x:{
                    tag: "input",
                    attributes:{class:"table-input"},
                    content: "test"
                }
            }
        },
        extension:{
            tag:"td",
            content: null,
            attributes:{class:"table-data"}
        },
        firstName:{
            tag:"td",
            content: null,
            attributes:{class:"table-data"}
        },
        jobTitle:{
            tag:"td",
            content: null,
            attributes:{class:"table-data"}
        },
        lastName:{
            tag:"td",
            content: null,
            attributes:{class:"table-data"}
        },
        officeCode:{
            tag:"td",
            content: null,
            attributes:{class:"table-data"}
        },
        reportsTo:{
            tag:"td",
            content: null,
            attributes:{class:"table-data"}
        }
    }
};

我的函数(汇编)

function assemble(r,s,n){
    var n = n || new DocumentFragment();    
    if(typeof r !== 'string'){ //HAS CHILDREN
        r.forEach((o)=>{ 
            for(y in s){
                switch(y){
                    case "tag":
                        var tag = document.createElement(s[y]);
                        n.appendChild(tag);
                        break;
                    case "attributes":
                        for(a in s[y]) tag.setAttribute(a,s[y][a]);
                        break;
                    case "content":
                        if(s.content === null){
                            //append current property value
                        }
                        else{
                            tag.innerHTML = s.content;
                        }
                        break;
                    case "props":
                        for(k in o) assemble(k,s[y][k],tag); //EXECUTE PER CHILDREN
                        break;
                }
            }
        });
    }
    else{
        for(x in s){
            switch(x){
                case "tag":
                    var tag = document.createElement(s[x]);
                    n.appendChild(tag);
                    break;
                case "content":
                    if(s.content === null){
                        //append current property value
                    }
                    else{
                        tag.innerHTML = s.content;
                    }
                    break;
                case "attributes":
                    for(a in s[x]) tag.setAttribute(a,s[x][a]);
                    break;
                case "props":
                    for(c in s[x]) assemble(r,s[x][c],tag);
                    break;
            }
        }   
        return n;
    }
    return n;
}               
document.addEventListener('DOMContentLoaded',()=>{
     var data = assemble(response,instructs);           
     console.log(data);
});

我要寻找的最终结果是嵌套tr>td的数组/片段,它们都具有class属性,并且值附加到innerHTML

<tr class ="table-row">
    <td class="table-data">how do I bind the response values?</td>
    <td class="table-data">how do I bind the response values?</td>
    <td class="table-data">how do I bind the response values?</td>
    <td class="table-data">how do I bind the response values?</td>
    <td class="table-data">how do I bind the response values?</td>
    <td class="table-data">how do I bind the response values?</td>
    <td class="table-data">how do I bind the response values?</td>
</tr>

问题:

如何将响应中的属性值绑定到tdinnerHTML

尝试下面的一个。对不起,我开始重构Yours,最后我重写了它。注意content总是被视为innerHTML,区分文本(append-createTextNode func result)和html(innerHTML prop)也不是一个坏主意。在您的数据中,instructs.props.employeeNumber.props.x.content应该移动到instructs.props.employeeNumber.props.x.attributes.value中,看看input[text]标记是如何工作的。顺便说一句,我看到这里有很多东西可以讨论。希望它能有所帮助!

function assemble (data, instr) {
    var n = document.createDocumentFragment(), i;
    function create(d) {
        var objData = d;
        return (function _(_instr, _key, _n) {
            var innerHTML = !!_key && _key in objData ? objData[_key] : null,
                tag = null, i;
            if ('tag' in _instr) {
                tag = document.createElement(_instr.tag);
                tag.innerHTML = 'content' in _instr && !!_instr.content ? _instr.content : innerHTML;
                if ('attributes' in _instr) {
                    for (i in _instr.attributes) tag.setAttribute(i, _instr.attributes[i]);
                }
                //recur finally
                if ('props' in _instr) {
                    for (i in _instr.props) _(_instr.props[i], i, tag);
                }
                !!_n && _n.appendChild(tag);
            }
            return tag;
        })(instr, null);
    }
    return (function (){
        for (i in data) {
            n.appendChild(create(data[i]));
        }
        return n;
    })();
}

虽然我的回答没有涉及问题的代码上下文,但对于结构化和绑定json响应,我通常使用regex模板。我觉得它的宣言简洁明了。ex,

html:

<table>
  <tbody id="employee">
  </tbody>
</table>

js:

var template = function(tpl, data) {
  return tpl.replace(/'$'{([^'}]+)?'}/g, function($1, $2) {
    return data[$2];
  });
};
var rowTemplate = '<tr class ="table-row">'
                     <td class="table-data">${email}</td>'
                     <td class="table-data"><input type="text" value=' ${employeeNumber}' /></td>'
                     <td class="table-data">${firstName}</td>'
                     <td class="table-data">${lastName}</td>'
                     <td class="table-data">${email}</td>'
                     <td class="table-data">${jobTitle}</td>'
                     <td class="table-data">${extension}</td>'
                   </tr>';
var response = [{"employeeNumber":"1002","lastName":"Murphy","firstName":"Diane","extension":"x5800","email":"dmurphy@classicmodelcars.com","officeCode":"1","reportsTo":null,"jobTitle":"President"}, ....]
var b = document.getElementById('employee');
for (var i = 0; i < response.length; i++) {
  var tr = document.createElement('x');
  b.appendChild(tr);
  tr.outerHTML = template(rowTemplate, response[i]);
}

小提琴

希望这能有所帮助。