به طور معمول، توسعه دهندگان زمانی که نیاز به انجام کاری با DOM دارند از jQuery استفاده می کنند. با این حال، تقریباً هر گونه دستکاری DOM را می توان روی آن انجام داد جاوا اسکریپت خالصبا استفاده از DOM API آن.

بیایید این API را با جزئیات بیشتری بررسی کنیم:

در پایان، کتابخانه DOM ساده خود را می نویسید که می تواند در هر پروژه ای استفاده شود.

پرس و جوهای DOM

پرس و جوهای DOM با استفاده از متد .querySelector () ساخته می شوند که یک انتخابگر CSS دلخواه را به عنوان آرگومان می گیرد.

Const myElement = document.querySelector ("#foo > div.bar")

اولین عنصر منطبق را برمی گرداند. می توانید برعکس این کار را انجام دهید - بررسی کنید که آیا یک عنصر با انتخابگر مطابقت دارد یا خیر:

MyElement.matches("div.bar") === درست است

اگر می‌خواهید تمام عناصری که با یک انتخابگر مطابقت دارند را بدست آورید، از ساختار زیر استفاده کنید:

Const myElements = document.querySelectorAll(.bar")

اگر می‌دانید به کدام عنصر والد مراجعه کنید، می‌توانید به‌جای جستجوی کل کد، به سادگی در میان فرزندان آن جستجو کنید:

Const myChildElemet = myElement.querySelector("ورودی") // به جای: // document.querySelector("#foo > ورودی div.bar")

این سوال پیش می‌آید: پس چرا از روش‌های کمتر راحت‌تر مانند.getElementsByTagName() استفاده می‌کنیم؟ یک مشکل کوچک وجود دارد - نتیجه ()output.querySelector به روز نمی شود و وقتی اضافه می کنیم عنصر جدید(نگاه کنید به)، تغییر نخواهد کرد.

const element1 = document.querySelectorAll("div") const element2 = document.getElementsByTagName("div") const newElement = document.createElement("div") document.body.appendChild(newElement) element1.length === element2.length // نادرست

همچنین querySelectorAll() همه چیز را در یک لیست جمع آوری می کند که باعث می شود کارایی زیادی نداشته باشد.

چگونه با لیست ها کار کنیم؟

علاوه بر این، .querySelectorAll() دو ویژگی کوچک دارد. شما نمی توانید فقط متدها را روی نتایج فراخوانی کنید و انتظار داشته باشید که برای هر یک از آنها اعمال شود (همانطور که ممکن است با jQuery عادت داشته باشید). در هر صورت، باید روی تمام عناصر موجود در حلقه تکرار کنید. دوم، شیء برگشتی فهرستی از عناصر است، نه یک آرایه. بنابراین، روش های آرایه کار نمی کنند. البته، متدهایی برای لیست ها وجود دارد، چیزی مانند () .forEach، اما، افسوس، آنها برای همه موارد مناسب نیستند. بنابراین بهتر است لیست را به یک آرایه تبدیل کنید:

// استفاده از Array.from() Array.from(myElements).forEach(doSomethingWithEachElement) // یا نمونه اولیه آرایه (قبل از ES6) Array.prototype.forEach.call(myElements, doSomethingWithEachElement) // Easier.forE. (myElements، doSomethingWithEachElement)

هر عنصر دارای ویژگی هایی است که به یک "خانواده" اشاره دارد.

MyElement.children myElement.firstElementChild myElement.lastElementChild myElement.previousElementSibling myElement.nextElementSibling

از آنجایی که رابط Element از رابط Node به ارث رسیده است، ویژگی های زیر نیز وجود دارد:

MyElement.childNodes myElement.firstChild myElement.lastChild myElement.previousSibling myElement.nextSibling myElement.parentNode myElement.parentElement

ویژگی های اول به عنصر اشاره دارد، در حالی که دومی (به استثنای .parentElement) می تواند فهرستی از عناصر از هر نوع باشد. بر این اساس، می توانید نوع عنصر را بررسی کنید:

MyElement.firstChild.nodeType === 3 // این عنصر یک گره متن خواهد بود

اضافه کردن کلاس ها و ویژگی ها

اضافه کردن یک کلاس جدید بسیار آسان است:

myElement.classList.add("foo") myElement.classList.remove("bar") myElement.classList.toggle("baz")

افزودن یک ویژگی به یک عنصر دقیقاً مانند افزودن یک ویژگی به هر شی است:

// مقدار مشخصه را دریافت کنید const value = myElement.value // ویژگی را به عنوان ویژگی عنصر myElement.value = "(!LANG:foo) تنظیم کنید" // Для установки нескольких свойств используйте.Object.assign() Object.assign(myElement, { value: "foo", id: "bar" }) // Удаление атрибута myElement.value = null !}

می توانید از متدهای .getAttibute، .setAttribute() و .removeAttribute() استفاده کنید. آن‌ها فوراً ویژگی‌های HTML عنصر را تغییر می‌دهند (برخلاف ویژگی‌های DOM)، که باعث ایجاد ترسیم مجدد مرورگر می‌شود (شما می‌توانید هر گونه تغییری را با بررسی عنصر با استفاده از ابزارهای توسعه‌دهنده در مرورگر مشاهده کنید). چنین ترسیم مجدد نه تنها به منابع بیشتری نسبت به تنظیم ویژگی های DOM نیاز دارد، بلکه می تواند منجر به خطاهای غیرمنتظره شود.

آنها معمولاً روی عناصری استفاده می‌شوند که دارای ویژگی‌های DOM متناظر نیستند، مانند colspan. یا اگر استفاده از آنها واقعاً ضروری است، به عنوان مثال برای ویژگی های HTML هنگام ارث بردن (نگاه کنید به).

اضافه کردن سبک های CSS

آنها مانند سایر ویژگی ها اضافه می شوند:

MyElement.style.marginLeft = "2em"

مقداری خواص خاصرا می توان با استفاده از .style تنظیم کرد، اما اگر می خواهید مقادیر را پس از انجام محاسبات دریافت کنید، بهتر است از window.getComputedStyle() استفاده کنید. این متد عنصر را می گیرد و یک CSSStyleDeclaration حاوی استایل های خود عنصر و والد آن را برمی گرداند:

Window.getComputedStyle(myElement).getPropertyValue("margin-left")

تغییر DOM

می توانید عناصر را جابجا کنید:

// افزودن عنصر1 به عنوان آخرین فرزند عنصر2 element1.appendChild(element2) // درج عنصر2 به عنوان فرزند عنصر1 قبل از element3 element1.insertBefore(element2, element3)

اگر نمی‌خواهید جابه‌جا شوید، اما نیاز به چسباندن یک کپی دارید، از:

// ایجاد یک کلون const myElementClone = myElement.cloneNode() myParentElement.appendChild(myElementClone)

متد ()cloneNode یک مقدار بولی را به عنوان آرگومان می گیرد و اگر درست باشد، آن را نیز کلون می کند و عناصر کودک.

البته، شما می توانید عناصر جدید ایجاد کنید:

const myNewElement = document.createElement("div") const myNewTextNode = document.createTextNode("متن")

و سپس آنها را مطابق شکل بالا وارد کنید. شما نمی توانید یک عنصر را مستقیماً حذف کنید، اما می توانید آن را از طریق عنصر والد انجام دهید:

MyParentElement.removeChild(myElement)

همچنین می توانید به صورت غیر مستقیم مراجعه کنید:

MyElement.parentNode.removeChild(myElement)

روش های روی عناصر

هر عنصر دارای ویژگی هایی مانند .innerHTML و .textContent است، آنها حاوی کد HTML و بر این اساس، خود متن هستند. مثال زیر محتوای یک عنصر را تغییر می دهد:

// HTML myElement.innerHTML = ` را تغییر دهید

محتوای جدید

بوق بوپ بیپ بوپ

` // این محتوا را حذف می کند myElement.innerHTML = null // افزودن به HTML myElement.innerHTML += ` ادامه خواندن...

در واقع، تغییر HTML ایده بدی است، زیرا تمام تغییراتی که قبلا ایجاد شده بود را از دست می دهد و همچنین کنترل کننده های رویداد را بیش از حد بارگذاری می کند. بهتر است از این روش فقط با حذف کامل تمام HTML و جایگزینی آن با یک کپی از سرور استفاده کنید. مثل این:

const link = document.createElement("a") const text = document.createTextNode("ادامه به خواندن...") const hr = document.createElement("hr") link.href = "foo.html" link.appendChild( متن) myElement.appendChild(پیوند) myElement.appendChild(hr)

با این حال، این منجر به دو بار ترسیم مجدد مرورگر می شود، در حالی که .innerHTML فقط به یک مورد منجر می شود. اگر ابتدا همه چیز را به DocumentFragment اضافه کنید و سپس قطعه مورد نیاز خود را اضافه کنید، می توانید این کار را حل کنید:

Const fragment = document.createDocumentFragment() fragment.appendChild(text) fragment.appendChild(hr) myElement.appendChild(fragment)

گردانندگان رویداد

یکی از ساده ترین کنترل کننده ها:

MyElement.onclick = تابع onclick (رویداد) (console.log(event.type + "Got Fired"))

اما به عنوان یک قاعده کلی، باید از آن اجتناب کرد. در اینجا، onclick. یک ویژگی عنصر است، و در تئوری می‌توانید آن را تغییر دهید، اما نمی‌توانید با استفاده از تابع دیگری که به تابع قدیمی اشاره می‌کند، کنترل‌کننده‌های دیگری را اضافه کنید.

برای اضافه کردن کنترلرها بهتر است از .addEventListener() استفاده کنید. به سه آرگومان نیاز دارد: نوع رویداد، تابعی که هر بار که اجرا می‌شود فراخوانی می‌شود، و یک شیء پیکربندی (بعداً به آن خواهیم پرداخت).

MyElement.addEventListener("کلیک"، تابع (رویداد) (console.log(event.type + "کار انداخته شد") )) myElement.addEventListener("کلیک"، تابع (رویداد) (consol.log(event.type + " دوباره اخراج شدم")))

ویژگی event.target به عنصری اشاره دارد که رویداد به آن متصل شده است.

و بنابراین شما می توانید به تمام ویژگی ها دسترسی داشته باشید:

// ویژگی `forms` آرایه ای است که حاوی پیوندهایی به تمام فرم ها است const myForm = document.forms const myInputElements = myForm.querySelectorAll("input") Array.from(myInputElements).forEach(el => (el.addEventListener(" تغییر "، تابع (رویداد) (consol.log(event.target.value) )) ))

جلوگیری از اقدامات پیش فرض

برای این کار از متد .preventDefault() استفاده می شود که اقدامات استاندارد را مسدود می کند. به عنوان مثال، اگر مجوز سمت مشتری موفقیت آمیز نباشد، ارسال فرم را مسدود می کند:

MyForm.addEventListener("submit"، تابع (رویداد) (const name = this.querySelector("#name") if (name.value === "(!LANG:Donald Duck") { alert("You gotta be kidding!") event.preventDefault() } }) !}

متد .stopPropagation() به شما کمک می کند اگر یک کنترل کننده رویداد خاص به فرزند و یک کنترل کننده دوم برای همان رویداد متصل به والد داشته باشید.

همانطور که قبلا ذکر شد، متد ()addEventListener آرگومان سوم اختیاری را به عنوان یک شی پیکربندی می گیرد. این شی باید دارای یکی از ویژگی های بولی زیر باشد (همه به طور پیش فرض روی false تنظیم شده اند):

  • ضبط: رویداد قبل از هر عنصر دیگری در DOM به این عنصر متصل می شود.
  • Once: یک رویداد را فقط یک بار می توان پین کرد.
  • passive: event.preventDefault() نادیده گرفته می شود (استثنا در هنگام خطا).

متداول ترین ویژگی .capture است و آنقدر رایج است که یک مختصر برای آن وجود دارد: به جای ارسال آن در یک شیء پیکربندی، فقط مقدار آن را در اینجا مشخص کنید:

MyElement.addEventListener (نوع، شنونده، درست)

هندلرها با استفاده از متد .removeEventListener حذف می شوند، که دو آرگومان دارد: نوع رویداد و ارجاع به کنترل کننده برای حذف. به عنوان مثال، ویژگی Once را می توان به صورت زیر پیاده سازی کرد:

MyElement.addEventListener("تغییر"، تابع شنونده (رویداد) (consol.log(event.type + "روی " + این فعال شد) this.removeEventListener("تغییر"، شنونده)))

وراثت

فرض کنید یک عنصر دارید و می‌خواهید یک کنترل کننده رویداد برای همه عناصر فرزند آن اضافه کنید. سپس باید آنها را با استفاده از روش myForm.querySelectorAll("input") همانطور که در بالا نشان داده شده است حلقه بزنید. با این حال، می‌توانید به سادگی عناصری را به فرم اضافه کنید و محتوای آنها را با event.target بررسی کنید.

MyForm.addEventListener("تغییر"، تابع (رویداد) (const target = event.target if (target.matches("input")) (consol.log(target.value) ))

و یک مزیت دیگر این روش این است که کنترل کننده به طور خودکار به عناصر فرزند جدید متصل می شود.

انیمیشن

ساده ترین راه برای افزودن انیمیشن استفاده از CSS با ویژگی انتقال است. اما برای انعطاف بیشتر (به عنوان مثال، برای یک بازی)، جاوا اسکریپت مناسب تر است.

فراخوانی متد window.setTimeout() تا زمانی که انیمیشن به پایان برسد ایده خوبی نیست، زیرا ممکن است برنامه شما به خصوص در دستگاه های تلفن همراه مسدود شود. بهتر است از window.requestAnimationFrame() برای ذخیره تمام تغییرات تا ترسیم مجدد بعدی استفاده کنید. تابعی را به عنوان آرگومان می گیرد که به نوبه خود یک مهر زمانی دریافت می کند:

const start = window.performance.now() const duration = 2000 window.requestAnimationFrame(function fadeIn (اکنون)) ( const progress = now - start myElement.style.opacity = پیشرفت / مدت اگر (پیشرفت< duration) { window.requestAnimationFrame(fadeIn) } }

به این ترتیب انیمیشن بسیار روان به دست می آید. مارک براون در مقاله خود به این موضوع پرداخته است.

نوشتن کتابخانه خودمان

این واقعیت که در DOM باید همیشه روی عناصر تکرار کنید تا کاری با آنها انجام دهید، در مقایسه با نحو jQuery $(.foo").css((color: "red")) بسیار خسته کننده به نظر می رسد. اما چرا برخی از روش های خود را برای آسان تر کردن این کار نمی نویسید؟

Const $ = تابع $(انتخاب کننده، متن = سند) ( عناصر const = Array.from(context.querySelectorAll(انتخاب کننده)) برمی گرداند ( عناصر، html (newHtml) ( this.elements.forEach(element => ( element.innerHTML = newHtml )) این را برگرداند ), css (newCss) ( this.elements.forEach(element => ( Object.assign(element.style, newCss) )) این را برگرداند, در (رویداد، کنترل کننده، گزینه ها) ( this.elements .forEach(element => ( element.addEventListener(رویداد، کنترل‌کننده، گزینه‌ها))) این را برگردانید)))

شبه کد

$(".rightArrow").click(function() (rightArrowParents = this.dom(); //.dom(); تابع شبه است ... باید کل هشدار را نشان دهد(rightArrowParents); ));

پیام هشدار این خواهد بود:

بدن div.lol a.rightArrow

چگونه می توانم این را با javascript/jquery دریافت کنم؟

استفاده از jQuery مانند این (به دنبال راه حلی که از jQuery به جز رویداد استفاده نمی کند، اگر مهم باشد تابع بسیار کمتری فراخوانی می کند):

مثال زمان واقعی:

$(".rightArrow").click(function() ( var rightArrowParents = ; $(this).parents().addBack().not("html").each(function() ( var entry = this.tagName .toLowerCase(); if (this.className) ( ورودی += "." + this.className.replace(/ /g, "."); ) rightArrowParents.push(entry); )); هشدار(rightArrowParents.join (""))؛ بازگشت نادرست؛ ))؛

اینجا کلیک کنید

(در مثال‌های زنده، من ویژگی کلاس را در div به lol multi به‌روزرسانی کرده‌ام تا مدیریت چندین کلاس را نشان دهم.)

در اینجا یک راه حل برای تطبیق دقیق عناصر وجود دارد.

درک این نکته مهم است که انتخاب کننده (واقعی نیست) که ابزارهای کروم نشان می‌دهند یک عنصر را به‌طور منحصربه‌فرد در DOM شناسایی نمی‌کنند. ( برای مثال، بین لیستی از عناصر span متوالی تمایز قائل نمی شود. هیچ اطلاعات موقعیت یابی / نمایه سازی وجود ندارد)

$.fn.fullSelector = تابع () ( var path = this.parents().addBack(); var quickCss = path.get().map(function (مورد) ( var self = $(item), id = item .id ? "#" + item.id: ""، clss = item.classList.length ? item.classList.toString().split(" ").map(function (c) ( return "." + c; )).join(""): ""، name = item.nodeName.toLowerCase()، index = self.siblings(name).length ? ":nth-child(" + (self.index() + 1) + ")" : ""؛ if (name === "html" || name === "body") (نام بازگشتی؛ ) بازگشت نام + فهرست + id + clss; )).join(" > ") بازگشت QuickCss؛ )؛

و شما می توانید از آن به صورت زیر استفاده کنید:

Console.log($("some-selector").fullSelector());

من قطعه را از T.J. به یک پلاگین کوچک jQuery بروید. من از نسخه jQuery استفاده کرده‌ام، حتی اگر او درست می‌گوید، سربار کاملاً غیرضروری است، اما من فقط از آن برای اهداف اشکال‌زدایی استفاده می‌کنم، بنابراین اهمیتی نمی‌دهم.

استفاده:

دهانه تو در تو
دهانه ساده
قبل

// نتیجه (آرایه): ["body"، "div.sampleClass"] $("span").getDomPath(false) // نتیجه (رشته): body > div.sampleClass $("span").getDomPath( ) // نتیجه (آرایه): ["body", "div#test"] $("pre").getDomPath(false) // نتیجه (رشته): body > div#test $("pre").getDomPath ()

var obj = $("#show-editor-button")، مسیر = ""; while (نوع obj.prop("tagName") != "تعریف نشده")( if (obj.attr("کلاس"))( مسیر = "."+obj.attr("کلاس").replace(/\s /g , ".") + path; ) if (obj.attr("id"))( path = "#"+obj.attr("id") + مسیر؛ ) path = " " +obj.prop( "tagName").toLowerCase() + path; obj = obj.parent(); ) console.log(path);

سلام این تابع خطای مربوط به ظاهر نشدن عنصر فعلی در مسیر را برطرف می کند

هماکنون بررسی اش کن

$j(".wrapper").click(function(event) ( selectedElement=$j(event.target); var rightArrowParents = ; $j(event.target).parents().not("html,body") .each(function() (var entry = this.tagName.toLowerCase(); if (this.className) ( ورودی += "." + this.className.replace(/ /g، "."); )دیگر اگر (this.id)( entry += "#" + this.id; ) entry=replaceAll(entry,"..","."); rightArrowParents.push(entry); )); rightArrowParents.reverse(); //if(event.target.nodeName.toLowerCase()=="a" || event.target.nodeName.toLowerCase()=="h1")( var entry = event.target.nodeName.toLowerCase()؛ اگر (event.target.className) ( ورودی += "." + event.target.className.replace(/ /g، ".")؛ )دیگر if(event.target.id)( ورودی += "#" + event.target.id; ) rightArrowParents.push(entry); //)

جایی که $j = متغیر jQuery

همچنین مشکل را با .. در نام کلاس حل کنید

در اینجا تابع جایگزین است:

تابع escapeRegExp(str) ( return str.replace(/([.*+?^=!:$()()|\[\]\/\\])/g، "\\$1"); ) تابع replaceAll(str, find, replace) ( return str.replace (new RegExp(escapeRegExp(find), "g"), جایگزین)؛ )

در اینجا یک نسخه JS بومی است که مسیر jQuery را برمی گرداند. من همچنین شناسه برای عناصر، در صورت وجود، اضافه می کنم. این به شما این امکان را می دهد که در صورت مشاهده id در آرایه، کوتاه ترین مسیر را طی کنید.

varpath = getDomPath(element); console.log(path.join(" > "));

Body > section:eq(0) > div:eq(3) > section#content > section#firehose > div#firehoselist > article#firehose-46813651 > header > h2 > span#title-46813651

در اینجا تابع است.

تابع getDomPath(el) ( var stack = ; while (el.parentNode != null) (consol.log(el.nodeName)؛ var sibCount = 0؛ var sibIndex = 0؛ برای (var i = 0؛ i< el.parentNode.childNodes.length; i++) { var sib = el.parentNode.childNodes[i]; if (sib.nodeName == el.nodeName) { if (sib === el) { sibIndex = sibCount; } sibCount++; } } if (el.hasAttribute("id") && el.id != "") { stack.unshift(el.nodeName.toLowerCase() + "#" + el.id); } else if (sibCount >1) ( stack.unshift(el.nodeName.toLowerCase() + ":eq(" + sibIndex + ")")؛ ) else (stack.unshift(el.nodeName.toLowerCase()); ) el = el.parentNode ; ) return stack.slice(1); // عنصر html را حذف می کند)

این روزها اپلیکیشن های پیچیده و سنگین تحت وب رایج شده اند. کتابخانه های متقابل مرورگر و آسان برای استفاده مانند jQuery با عملکرد گسترده خود می توانند کمک زیادی به دستکاری DOM در پرواز کنند. بنابراین، تعجب آور نیست که بسیاری از توسعه دهندگان از چنین کتابخانه هایی بیشتر از کار با DOM API بومی استفاده می کنند، که مشکلات زیادی داشت. و در حالی که تفاوت های مرورگر هنوز یک مشکل است، DOM اکنون در وضعیت بهتری نسبت به 5-6 سال پیش که jQuery محبوبیت پیدا می کرد، است.

در این مقاله، من توانایی DOM را برای دستکاری HTML با تمرکز بر روابط والدین، فرزند و همسایگان نشان خواهم داد. من با یک تقسیم بندی پشتیبانی مرورگر از این ویژگی ها به پایان می رسم، اما به خاطر داشته باشید که کتابخانه نوع jQuery به دلیل اشکالات و ناهماهنگی در اجرای عملکرد بومی همچنان گزینه خوبی است.

شمارش گره های کودک

من از نشانه گذاری HTML زیر برای نمایش استفاده خواهم کرد و آن را چندین بار در طول مقاله تغییر خواهیم داد:

  • مثال یک
  • مثال دو
  • مثال سه
  • مثال چهار
  • مثال پنج
  • مثال ششم

Var myList = document.getElementById("myList"); console.log(myList.children.length); // 6 console.log(myList.childElementCount); // 6

همانطور که می بینید، نتایج یکسان است، اگرچه تکنیک های استفاده شده متفاوت است. در حالت اول از اموال فرزندان استفاده می کنم. این یک ویژگی فقط خواندنی است و مجموعه ای را برمی گرداند عناصر HTML، در داخل عنصر درخواستی قرار دارد. برای شمارش تعداد آنها از ویژگی length این مجموعه استفاده می کنم.

در مثال دوم، من از متد childElementCount استفاده می‌کنم، که به نظرم روشی منظم‌تر و بالقوه قابل نگهداری‌تر است (در این مورد بعداً، فکر نمی‌کنم در درک این که چه کار می‌کند مشکلی نداشته باشید).

می توانم سعی کنم از childNodes.length (به جای Children.length) استفاده کنم، اما به نتیجه نگاه کنید:

Var myList = document.getElementById("myList"); console.log(myList.childNodes.length); // 13

13 را برمی گرداند زیرا childNodes مجموعه ای از تمام گره ها از جمله فضاها است - اگر به تفاوت بین گره های فرزند و گره های عنصر فرزند اهمیت می دهید این را در نظر داشته باشید.

بررسی وجود گره های کودک

برای بررسی اینکه آیا یک عنصر دارای گره های فرزند است، می توانم از متد hasChildNodes() استفاده کنم. روش برمی گردد بولیحضور یا عدم حضور آنها را نشان می دهد:

Var myList = document.getElementById("myList"); console.log(myList.hasChildNodes()); // درست است، واقعی

من می دانم که لیست من دارای گره های فرزند است، اما می توانم HTML را طوری تغییر دهم که هیچ کدام وجود نداشته باشد. اکنون نشانه گذاری به این صورت است:

و در اینجا نتیجه اجرای مجدد hasChildNodes() است:

Console.log(myList.hasChildNodes()); // درست است، واقعی

روش همچنان true را برمی گرداند. اگرچه لیست حاوی هیچ عنصری نیست، اما حاوی یک فاصله است که یک نوع گره معتبر است. این روشهمه گره ها را در نظر می گیرد، نه فقط گره های عنصر را. برای اینکه hasChildNodes() false را برگرداند، باید علامت گذاری را دوباره تغییر دهیم:

و اکنون نتیجه مورد انتظار در کنسول نمایش داده می شود:

Console.log(myList.hasChildNodes()); // نادرست

البته، اگر بدانم ممکن است با یک فاصله مواجه شوم، ابتدا وجود گره های فرزند را بررسی می کنم، سپس از ویژگی nodeType برای تعیین وجود گره های عنصر در بین آنها استفاده می کنم.

افزودن و حذف عناصر کودک

تکنیک هایی وجود دارد که می توان برای افزودن و حذف عناصر از DOM استفاده کرد. معروف ترین آنها بر اساس ترکیبی از متدهای createElement() و appendChild() است.

VarmyEl = document.createElement("div"); document.body.appendChild(myEl);

در این صورت من در حال ایجاد هستم

با استفاده از متد createElement() و سپس اضافه کردن آن به بدنه. بسیار ساده و احتمالا قبلا از این تکنیک استفاده کرده اید.

اما به جای درج یک عنصر خاص، می توانم از appendChild() نیز استفاده کنم و به سادگی عنصر موجود را جابجا کنم. فرض کنید نشانه گذاری زیر را داریم:

  • مثال یک
  • مثال دو
  • مثال سه
  • مثال چهار
  • مثال پنج
  • مثال ششم

متن نمونه

با کد زیر می توانم مکان لیست را تغییر دهم:

Var myList = document.getElementById("myList")، container = document.getElementById("c"); container.appendChild(myList);

DOM نهایی به شکل زیر خواهد بود:

متن نمونه

  • مثال یک
  • مثال دو
  • مثال سه
  • مثال چهار
  • مثال پنج
  • مثال ششم

توجه داشته باشید که کل لیست از جای خود (بالای پاراگراف) حذف شده و بعد از آن، قبل از بدنه پایانی درج شده است. در حالی که متد appendChild() معمولا برای اضافه کردن عناصر ایجاد شده با createElement() استفاده می شود، می توان از آن برای جابجایی عناصر موجود نیز استفاده کرد.

همچنین می توانم با removeChild() یک عنصر فرزند را به طور کامل از DOM حذف کنم. در اینجا نحوه حذف لیست ما از مثال قبلی آمده است:

Var myList = document.getElementById("myList")، container = document.getElementById("c"); container.removeChild(myList);

اکنون عنصر حذف شده است. متد removeChild() عنصر حذف شده را برمی گرداند و در صورتی که بعداً به آن نیاز داشته باشم می توانم آن را ذخیره کنم.

Var myOldChild = document.body.removeChild(myList); document.body.appendChild(myOldChild);

روش ChildNode.remove() نیز وجود دارد که به تازگی به مشخصات اضافه شده است:

Var myList = document.getElementById("myList"); myList.remove();

این روش یک شی از راه دور را بر نمی گرداند و در IE (فقط Edge) کار نمی کند. و هر دو روش گره های متنی را همانند گره های عنصر حذف می کنند.

جایگزینی عناصر کودک

من می‌توانم یک عنصر فرزند موجود را با یک عنصر جدید جایگزین کنم، چه آن عنصر جدید وجود داشته باشد یا آن را از ابتدا ایجاد کرده باشم. در اینجا نشانه گذاری است:

متن نمونه

Var myPar = document.getElementById("par")، myDiv = document.createElement("div"); myDiv.className = "مثال"; myDiv.appendChild(document.createTextNode("متن عنصر جدید")); document.body.replaceChild(myDiv، myPar);

متن عنصر جدید

همانطور که می بینید، متد ()placeChild دو آرگومان می گیرد: عنصر جدید و عنصر قدیمی که جایگزین می شود.

من همچنین می توانم از این روش برای جابجایی یک عنصر موجود استفاده کنم. نگاهی به HTML زیر بیندازید:

متن نمونه 1

متن نمونه 2

متن مثال 3

می توانم پاراگراف سوم را با پاراگراف اول با کد زیر جایگزین کنم:

Var myPar1 = document.getElementById("par1")، myPar3 = document.getElementById("par3"); document.body.replaceChild(myPar1, myPar3);

اکنون DOM تولید شده به شکل زیر است:

متن نمونه 2

متن نمونه 1

انتخاب عناصر خاص کودک

چند وجود دارد روش های مختلفانتخاب یک عنصر خاص همانطور که قبلا نشان داده شد، می توانم با استفاده از مجموعه فرزندان یا ویژگی childNodes شروع کنم. اما بیایید گزینه های دیگر را بررسی کنیم:

ویژگی های firstElementChild و lastElementChild دقیقاً همان کاری را انجام می دهند که از نام آنها انتظار دارید: اولین و آخرین عنصر فرزند را انتخاب کنید. بیایید به نشانه گذاری خود برگردیم:

  • مثال یک
  • مثال دو
  • مثال سه
  • مثال چهار
  • مثال پنج
  • مثال ششم

من می توانم اولین و آخرین عناصر را با این ویژگی ها انتخاب کنم:

Var myList = document.getElementById("myList"); console.log(myList.firstElementChild.innerHTML); // "نمونه یک" console.log(myList.lastElementChild.innerHTML); // "مثال شش"

همچنین می‌توانم از ویژگی‌های previousElementSibling و nextElementSibling استفاده کنم اگر بخواهم عناصر فرزند را غیر از اولین یا آخرین انتخاب کنم. این کار با ترکیب ویژگی های firstElementChild و lastElementChild انجام می شود:

Var myList = document.getElementById("myList"); console.log(myList.firstElementChild.nextElementSibling.innerHTML); // "مثال دو" console.log(myList.lastElementChild.previousElementSibling.innerHTML); // "مثال پنج"

همچنین ویژگی های مشابه firstChild، lastChild، previousSibling، و nextSibling وجود دارد، اما آنها همه انواع گره ها را در نظر می گیرند، نه فقط عناصر را. به طور کلی، ویژگی هایی که فقط گره های عنصر را در نظر می گیرند، مفیدتر از ویژگی هایی هستند که همه گره ها را انتخاب می کنند.

درج محتوا در DOM

من قبلاً به روش هایی برای درج عناصر در DOM نگاه کرده ام. بیایید به موضوع مشابهی برویم و نگاهی به ویژگی های جدید برای درج محتوا بیاندازیم.

اول، یک متد insertBefore() ساده وجود دارد که بسیار شبیه به ()placeChild است، دو آرگومان می گیرد و روی عناصر جدید و همچنین عناصر موجود کار می کند. در اینجا نشانه گذاری است:

  • مثال یک
  • مثال دو
  • مثال سه
  • مثال چهار
  • مثال پنج
  • مثال ششم

پاراگراف مثال

به پاراگراف توجه کنید، من ابتدا آن را حذف می کنم و سپس آن را قبل از لیست درج می کنم، همه اینها در یک لحظه:

Var myList = document.getElementById("myList")، container = document.getElementBy("c")، myPar = document.getElementById("par"); container.insertBefore(myPar, myList);

در HTML به دست آمده، پاراگراف قبل از لیست قرار می گیرد، و این روش دیگری برای بسته بندی عنصر است.

پاراگراف مثال

  • مثال یک
  • مثال دو
  • مثال سه
  • مثال چهار
  • مثال پنج
  • مثال ششم

مانند ()placeChild، insertBefore() دو آرگومان می گیرد: عنصری که باید اضافه کنیم و عنصری که می خواهیم آن را قبل از آن درج کنیم.

این روش ساده است. بیایید یک روش قدرتمندتر برای درج اکنون امتحان کنیم: متد insertAdjacentHTML().