سؤال

لدي وظيفة تأخذ كائنًا كمعلمة ، وتستخدم بنية الكائن لإنشاء عقد DOM متداخلة ، لكنني أتلقى الخطأ التالي:

http://new.app/:75NOT_FOUND_ERR: DOM Exception 8: An attempt was made to reference a Node in a context where it does not exist.

ما أود أن أفعله وظيفتي ، هو ، عندما يتم تزويده بكائن مناسب كمعلمة ، مثال:

var nodes = {
    tweet: {
        children: {
            screen_name: {
                tag: "h2"
            },
            text: {
                tag: "p"
            }
        },
        tag: "article"
    }
};

سيؤدي إلى إنشاء عقد DOM التالية:

<article>
    <h2></h2>
    <p></p>
</article>

ها هي محاولتي حتى الآن:

function create(obj) {
    for(i in obj){  
        var tmp = document.createElement(obj[i].tag);  
        if(obj[i].children) {  
            tmp.appendChild(create(obj[i].children)); /* error */
        }; 
        document.getElementById("tweets").appendChild(tmp);  
    };  
};

أنا بالفعل أعاني!

من الناحية المثالية ، أود في النهاية إضافة المزيد من مفاتيح الطفل إلى كل كائن ، وليس فقط tag, ، لكن أيضا id, innerHTML, class إلخ.

أي HEL سيكون موضع تقدير كبير ، على الرغم من من فضلك: أنا متأكد إطار أو مكتبة يمكن أن أفعل هذا من أجلي في بضعة أسطر من التعليمات البرمجية ، أو شيء مشابه ، ولكن أفضل عدم استخدام واحدة لهذا المشروع بالذات.

إذا تمكنت من شرح إجاباتك بإيجاز أيضًا ، فستساعدني حقًا في تعلم كيفية عمل كل هذا ، وأين أخطأت!

شكرًا لك!

NB: لقد قمت بتغيير الخط في وظيفتي التي تتحدث عنها رسالة الخطأ.

لقد غيرته من:

mp.appendChild(obj[i].children);

ل:

mp.appendChild(create(obj[i].children));

هذا لأنني أريد إنشاء أي مفاتيح متداخلة في كائن الأطفال ، لذلك screen_name لو كان مفتاح الأطفال ، سيتم إنشاءهم أيضًا. آسف, ، أتمنى أنك تستطيع فهم هذا!

أنا أنظر إلى http://jsperf.com/create-sned-domructure بالنسبة لبعض المؤشرات ، قد يساعدك هذا أيضًا!

هل كانت مفيدة؟

المحلول

يجب كتابة وظيفة "إنشاء" الخاص بك بشكل متكرر.

لإنشاء عقدة من بياناتك (بشكل عام) ، تحتاج إلى:

  1. ابحث عن خاصية "العلامة" وإنشاء عنصر جديد
  2. امنح العنصر قيمة "المعرف" للعنصر (مأخوذة من البيانات)
  3. لكل عنصر في "الأطفال" ، اصنع عقدة وإلحاقها

هكذا:

function create(elementDescription) {
  var nodes = [];
  for (var n in elementDescription) {
    if (!elementDescription.hasOwnProperty(n)) continue;
    var elem = elementDescription[n];
    var node = document.createElement(elem.tag);
    node.id = n; // optional step
    var cnodes = create(elem.children);
    for (var c = 0; c < cnodes.length; ++c)
      node.appendChild(cnodes[c]);
    nodes.push(node);
  }
  return nodes;
}

سيؤدي ذلك إلى إرجاع مجموعة من عناصر المستندات التي تم إنشاؤها من كائن "المواصفات" الأصلي. وهكذا من مثالك ، تتصل:

var createdNodes = create(nodes);

و "CreatedNodes" ستكون مجموعة من عنصر واحد ، <article> علامة مع معرف "التغريدات". هذا العنصر سيكون له طفلان ، <h2> علامة مع معرف "screen_name" و <p> علامة مع معرف "النص". (الآن بعد أن فكرت في الأمر ، قد ترغب في تخطي مهمة "المعرف" ما لم يكن وصف العقدة "معرف" صريح ، أو شيء ما.)

وهكذا إذا كان لديك ملف <div> في صفحتك تسمى "Tweets" (لاستخدام مثالك ، على الرغم من أنك إذا كنت ترغب بالتأكيد في قطع جزء إعداد "ID" من وظيفتي) ، فستضيف نتائج مثل هذه:

var createdNodes = create(nodes), tweets = document.getElementById('tweets');

for (var eindex = 0; eindex < createdNodes.length; ++eindex)
  tweets.appendChild(createdNodes[eindex]);

نصائح أخرى

أضفت قائمة ملحق وظيفة تقبل قائمة العناصر ، والحاوية التي يجب إلحاقها. لقد أزلت إلحاق "التغريدات" جزءًا من وظيفة إنشاء لفصل الكود بشكل أكثر فعالية.

function create(obj) {
    var els = [];
    for(i in obj){  
        var tmp = document.createElement(obj[i].tag);  
        var children;
        if(children = obj[i].children) {  
            var childEls = create(children);
            appendList(childEls, tmp);
        }
        els.push(tmp);
    }; 
    return els;
};
function appendList(list, container){
    for(var i = 0, el; el = list[i]; i++){
        container.appendChild(el);
    }
};
// gets an array of root elements populated with children
var els = create(nodes); 
// appends the array to "tweets"
appendList(els, document.getElementById("tweets")); 

البناء على الإجابة السابقة: أعتقد أنك لا تزال بحاجة إلى إنشاء العنصر الذي تحاول إلحاقه:

tmp.appendchild (الأطفال [prop] .tag) ؛

يجب ان يكون

tmp.appendchild (document.createElement (الأطفال [prop] .tag)) ؛

function create(obj) {
    for(i in obj){  
        var tmp = document.createElement(obj[i].tag);  
        var children;
        if(children = obj[i].children) {  
            for(var prop in children)
                tmp.appendChild(document.createElement(children[prop].tag));   
        }
        document.getElementById("tweets").appendChild(tmp);  
    };  
};
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top