المراقب هو كائن يراقب حالة عنصر معين ويسجل التغييرات فيه. العنصر الذي تتم مراقبته (كدت أكتب "الذي من أجله يتم تنظيم المراقبة") يسمى الهدف. يمكن للمراقب مراقبة حالة عنصر أو أكثر ، وفي بعض الحالات أيضًا أحفاد العنصر المستهدف.
هناك ثلاثة أنواع رئيسية من المراقبين في JavaScript:
- ResizeObserver
- تقاطع
- الطفرة
في هذه المقالة ، أقترح التركيز على التطبيق العملي لكل مراقب.
مراقب تغيير الحجم
موعد
مشاهدة تغيير حجم العنصر الهدف.
نظرية
MDN
مقالي عن حبري
الدعم
مثال
في المثال التالي ، نلاحظ عرض الحاوية مع المعرف "box". عندما يكون عرض الحاوية أقل من 768 بكسل ، نقوم بتغيير لون خلفية الحاوية ولون النص (إلى العكس باستخدام "filter: invert (100٪)") ، وتقليل حجم خط العنوان والنص الأساسي ، وإخفاء المعلومات الإضافية.
تبدو الترميز كما يلي:
<div id="box" class="box">
<h1 id="title" class="title">Some Awesome Title</h1>
<p id="text" class="text">Some Main Text</p>
<span id="info" class="info">Some Secondary Info</span>
</div>
الأنماط:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.box,
.title,
.text,
.info {
transition: 0.3s;
}
.box {
background: #ddd;
color: #222;
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.title,
.info {
margin: 1rem;
}
.title {
font-size: 2rem;
}
.text {
font-size: 1.25rem;
}
النصي:
//
const changeStyles = (elements, properties, values) =>
elements.forEach((element, index) => {
element.style[properties[index]] = values[index];
});
// ResizeObserver
const observer = new ResizeObserver((entries) => {
// ( )
for (const entry of entries) {
//
const width = entry.contentRect.width;
//
// 768px
//
if (width < 768) {
changeStyles(
[box, title, text, info],
["filter", "fontSize", "fontSize", "opacity"],
["invert(100%)", "1.5rem", "1rem", "0"]
);
} else {
// 768px
//
changeStyles(
[box, title, text, info],
["filter", "fontSize", "fontSize", "opacity"],
["invert(0%)", "2rem", "1.25rem", "1"]
);
}
}
});
// "box"
observer.observe(box);
Sandbox:
تقاطع
موعد
مشاهدة تقاطع العنصر الهدف مع العنصر الأصل أو إطار عرض الصفحة (منفذ العرض).
نظرية
MDN
مقالي عن حبري
الدعم
مثال
في المثال التالي ، نشاهد جميع الأقسام على الصفحة ونكتب رقم القسم الحالي (معرفه) إلى التخزين المحلي. يتم ذلك بحيث عندما يعود المستخدم إلى الصفحة ، قم بتمرير منفذ العرض إلى القسم الذي توقف عنده. يرجى ملاحظة أن المثال يطبق التمرير السلس: في الصفحات التي تحتوي على الكثير من المعلومات ، من الأفضل التمرير على الفور.
وضع علامة على:
<main id="main">
<section id="1" class="section">
<h3 class="title">First Section Title</h3>
<p class="text">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ipsam nostrum ex delectus distinctio reprehenderit facere vitae beatae ab dolores, aliquam maiores officia mollitia unde et! Quaerat odit in minus dolor corrupti nemo nam beatae. Ex consequatur rem laborum necessitatibus omnis, soluta fuga maiores repellendus eveniet? Blanditiis quae officiis maiores vitae nobis in voluptate, dicta voluptas rerum. Et laudantium consequuntur vitae tenetur doloremque accusantium tempora quos magni repudiandae voluptatem perferendis velit reprehenderit laborum libero soluta quis id, quidem assumenda nihil obcaecati expedita, aliquam suscipit nesciunt facere. Voluptate rem perferendis ab iste? Maxime, earum quos! Modi, aut quis nihil quidem accusamus vero sunt debitis architecto soluta repellendus fugit suscipit aspernatur labore a est sit dolores in necessitatibus ea tenetur corporis. Exercitationem mollitia impedit qui nemo voluptate numquam perspiciatis repellendus repellat a odio fugit dolor ducimus labore ex veritatis pariatur aliquam enim distinctio libero doloremque saepe quaerat consectetur, ut sapiente. Laboriosam dignissimos iure praesentium modi ab perferendis at molestias maiores suscipit, expedita aut aperiam nam voluptates similique optio minus quam! Voluptas ullam sunt, a officiis accusamus adipisci sed saepe voluptatem minima maxime est assumenda cum quibusdam voluptates provident in quasi vitae. Corrupti voluptatibus laborum ipsum quia, cupiditate adipisci assumenda dolores sunt distinctio, recusandae nesciunt aliquid, explicabo ullam eligendi perspiciatis rerum architecto? Cumque numquam blanditiis, magnam delectus velit laudantium aliquid quibusdam excepturi vero nihil necessitatibus, sed officiis, molestias hic autem modi consequuntur iusto sapiente dolore. Voluptates tenetur provident eius distinctio iure rerum minima eum eaque. Ea autem, deleniti atque magnam eius modi dicta assumenda tempore ducimus molestias. Aperiam enim tenetur, hic blanditiis velit quod odio deserunt sequi quisquam dignissimos animi amet magnam excepturi dicta quidem error quis officia natus. Temporibus nobis dolores veritatis eius illo quas perspiciatis reiciendis dolorum optio, commodi, animi quos at! Amet praesentium totam ab error esse optio quo, quis iusto!
</p>
</section>
<section id="2" class="section">
<h3 class="title">Second Section Title</h3>
<p class="text">
...
</p>
</section>
<section id="3" class="section">
<h3 class="title">Third Section Title</h3>
<p class="text">
...
</p>
</section>
</main>
الأنماط:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #eee;
color: #222;
text-align: center;
}
main {
max-width: 768px;
margin: auto;
}
.section {
padding: 1rem;
}
.title {
font-size: 1.5rem;
margin: 1rem;
}
.text {
font-size: 1.25rem;
}
النصي:
// ,
const findLastSection = () => {
//
// -
const number = localStorage.getItem("numberOfSection") || 1;
//
const section = document.getElementById(number);
// ( )
const position = Math.round(section.offsetTop);
//
scrollTo({
top: position,
//
behavior: "smooth",
});
};
findLastSection();
//
const createObserver = () => {
// IntersectionObserver
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
//
if (entry.isIntersecting) {
//
localStorage.setItem("numberOfSection", entry.target.id);
}
});
},
{
//
// 10%
threshold: 0.1,
}
);
//
const sections = main.querySelectorAll("section");
//
sections.forEach((section) => observer.observe(section));
};
createObserver();
Sandbox:
الطفرة
موعد
راقب التغييرات في السمات والمحتوى النصي للعنصر الهدف وأحفاده. ربما ، من حيث الوظيفة ، هذا هو أكثر المراقبين إثارة للاهتمام الذين ندرسهم.
نظرية
MDN
برنامج تعليمي حديث لـ JavaScript
الدعم
مثال
في المثال التالي ، سنقوم بتنفيذ خدعة بسيطة ، حيث يتتبع المراقب عدد المهام في القائمة. من حيث الوظائف ، سيكون مراقبنا مشابهًا لـ "useEffect" في React.js أو "watch" في Vue.js.
وضع علامة على:
<div id="box" class="box"></div>
الأنماط:
@import url("https://fonts.googleapis.com/css2?family=Stylish&display=swap");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: stylish;
font-size: 1rem;
color: #222;
}
.box {
max-width: 512px;
margin: auto;
text-align: center;
}
.counter {
font-size: 2.25rem;
margin: 0.75rem;
}
.form {
display: flex;
margin-bottom: 0.25rem;
}
.input {
flex-grow: 1;
border: none;
border-radius: 4px;
box-shadow: 0 0 1px inset #222;
text-align: center;
font-size: 1.15rem;
margin: 0.5rem 0.25rem;
}
.input:focus {
outline-color: #5bc0de;
}
.btn {
border: none;
outline: none;
background: #337ab7;
padding: 0.5rem 1rem;
border-radius: 4px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5);
color: #eee;
margin: 0.5rem 0.25rem;
cursor: pointer;
user-select: none;
width: 92px;
text-shadow: 0 0 1px rgba(0, 0, 0, 0.5);
}
.btn:active {
box-shadow: 0 0 1px rgba(0, 0, 0, 0.5) inset;
}
.btn.danger {
background: #d9534f;
}
.list {
list-style: none;
}
.item {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}
.item + .item {
border-top: 1px dashed rgba(0, 0, 0, 0.5);
}
.text {
flex: 1;
font-size: 1.15rem;
margin: 0.5rem;
padding: 0.5rem;
background: #eee;
border-radius: 4px;
}
النصي:
//
const todos = [
{
id: "1",
text: "Learn HTML",
},
{
id: "2",
text: "Learn CSS",
},
{
id: "3",
text: "Learn JavaScript",
},
{
id: "4",
text: "Stay alive",
},
];
//
const Item = (todo) => `
<li
class="item"
id="${todo.id}"
>
<span class="text"}">
${todo.text}
</span>
<button
class="btn danger"
data-type="delete"
>
Delete
</button>
</li>
`;
//
const Template = `
<form id="form" class="form">
<input
type="text"
class="input"
id="input"
>
<button
class="btn"
data-type="add"
>
Add
</button>
</form>
<ul id="list" class="list">
${todos.reduce(
(html, todo) =>
(html += `
${Item(todo)}
`),
""
)}
</ul>
`;
// IIFE
(() => {
// "box"
box.innerHTML = `
<h1 id="counter" class="counter">
${todos.length} todo(s) left
</h1>
${Template}
`;
//
input.focus();
// MutationObserver
const observer = new MutationObserver(() => {
//
const count = todos.length;
// , , ,
counter.textContent = `
${count > 0 ? `${count} todo(s) left` : "There are no todos"}
`;
});
//
observer.observe(list, {
childList: true,
});
//
const addTodo = () => {
if (!input.value.trim()) return;
const todo = {
id: Date.now().toString().slice(-4),
text: input.value,
};
list.insertAdjacentHTML("beforeend", Item(todo));
todos.push(todo);
input.value = "";
input.focus();
};
//
const deleteTodo = (item) => {
const index = todos.findIndex((todo) => todo.id === item.id);
item.remove();
todos.splice(index, 1);
};
//
form.onsubmit = (e) => e.preventDefault();
//
box.addEventListener("click", (e) => {
if (e.target.tagName !== "BUTTON") return;
//
const { type } = e.target.dataset;
const item = e.target.parentElement;
//
switch (type) {
case "add":
addTodo();
break;
default:
deleteTodo(item);
break;
}
});
})();
Sandbox:
أتمنى أن تجد شيئًا مثيرًا للاهتمام لنفسك. شكرآ لك على أهتمامك.