Skip to content

Commit 99a9572

Browse files
committed
fixes
1 parent 97f10e6 commit 99a9572

1 file changed

Lines changed: 286 additions & 0 deletions

File tree

  • 2-ui/5-loading/01-onload-ondomcontentloaded
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
# Page: DOMContentLoaded, load, beforeunload, unload
2+
3+
دورة حياة صفحه HTML لها ثلاثة احداث مهمة :
4+
5+
- `DOMContentLoaded` -- يتم تحميل المتصفح بالكامل HTML, ويتم انشاء ال DOM, لكن الموارد الخارجية مثل `<img>` وملفات التصميم ربما لم يتم تحميلها.
6+
- `load` -- لا يتم تحمل HTML فقط , لكن ايضأ جميع الموارد الخارجية: الصور, ملفات التصميم الخ.
7+
- `beforeunload/unload` -- المستخدم يغادر الصفحه.
8+
9+
قد يكون كل حدث مفيد:
10+
11+
- `DOMContentLoaded` حدث -- DOM جاهز, بحيث يمكن للمعالج البحث عن عقد DOM , تهيئة الواجهة.
12+
- `load` الحدث -- يتم تحميل المواد الخارجية , لذلك يتم تطبيق الأنماط, وأحجام الصور معروفة الخ.
13+
- `beforeunload` الحدث -- عند مغادرة المستخدم: يمكننا التحقق مما إذا كان المستخدم حفظ التغييرات ونطلب منهم ما إذا كانوا يريدون حقا أن يغادر.
14+
- `unload` -- المستخدم غادر تقريبا, ولكن لا يزال بإمكاننا بدء بعض العمليات، مثل إرسال الإحصائيات.
15+
16+
دعونا نستكشف تفاصيل هذه الأحداث.
17+
18+
## DOMContentLoaded
19+
20+
`DOMContentLoaded` الحدث يحدث علي `document` الكائن.
21+
22+
يجب ان نستخدم `addEventListener` لإمساك الحدث:
23+
24+
```js
25+
document.addEventListener("DOMContentLoaded", ready);
26+
// not "document.onDOMContentLoaded = ..."
27+
```
28+
29+
على سبيل المثال:
30+
31+
```html run height=200 refresh
32+
<script>
33+
function ready() {
34+
alert('DOM is ready');
35+
36+
// image is not yet loaded (unless was cached), so the size is 0x0
37+
alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`);
38+
}
39+
40+
*!*
41+
document.addEventListener("DOMContentLoaded", ready);
42+
*/!*
43+
</script>
44+
45+
<img id="img" src="https://en.js.cx/clipart/train.gif?speed=1&cache=0">
46+
```
47+
48+
علي سبيل المثال `DOMContentLoaded` يتم تشغيل المعالج عند تحميل المستند، حتى يتمكن من رؤية كافة العناصر, متضمنا `<img>` ادناه.
49+
50+
ولكن لا ينتظر حتى يتم تحميل الصورة. لذالك `alert` يظهر حجم الصفر.
51+
52+
للوهلة الأولى, `DOMContentLoaded` الحدث بسيط جدا. DOM جاهز -- ها هو الحدث. هناك القليل من الخصائص المميزة بالرغم من ذلك.
53+
54+
### DOMContentLoaded and scripts
55+
56+
عندما يعالج المتصفح مستند HTML ويأتي عبر علامة `<script>`, يحتاج الي التنفيذ قبل متابعة بناء DOM.هذا إجراء احترازي ، حيث قد ترغب البرامج النصية في تعديل DOM
57+
, وحتي حدث `document.write` بداخلة, لذالك `DOMContentLoaded` يجب أن تنتظر.
58+
59+
لذلك DOMContentLoaded بالتأكيد يحدث بعد هذه البرامج النصية:
60+
61+
```html run
62+
<script>
63+
document.addEventListener("DOMContentLoaded", () => {
64+
alert("DOM ready!");
65+
});
66+
</script>
67+
68+
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.3.0/lodash.js"></script>
69+
70+
<script>
71+
alert("Library loaded, inline script executed");
72+
</script>
73+
```
74+
75+
ف المثال أعلاه, نشاهد أولاً "مكتبة محملة...", ثم "DOM ready!" (يتم تنفيذ جميع البرامج النصية).
76+
77+
```warn header="البرامج النصية التي لا تحظر DOMContentLoaded"
78+
هناك نوعان من الاستثناءات من هذه القاعدة:
79+
1. البرامج النصية ذات السمة `غير متزامن`, التي سنغطيها [بعد فترة وجيزة](info:script-async-defer), لا تحجب `DOMContentLoaded`.
80+
2. البرامج النصية التي يتم إنشاؤها ديناميكيًا باستخدام `document.createElement('script')` ثم إضافته إلى صفحة الويب أيضًا لا تحظر هذا الحدث.
81+
```
82+
83+
### DOMContentLoaded and styles
84+
85+
لا تؤثر أوراق الأنماط الخارجية على DOM, لذلك `DOMContentLoaded` لا تنتظرهم.
86+
87+
لكن هناك مأزق. إذا كان لدينا برنامج نصي بعد النمط، فيجب أن ينتظر ذلك البرنامج النصي حتى يتم تحميل ورقة الأنماط:
88+
89+
```html run
90+
<link type="text/css" rel="stylesheet" href="style.css">
91+
<script>
92+
// the script doesn't not execute until the stylesheet is loaded
93+
alert(getComputedStyle(document.body).marginTop);
94+
</script>
95+
```
96+
97+
السبب في ذلك هو أن البرنامج النصي قد ترغب في الحصول على إحداثيات وخصائص أخرى نمط تعتمد على العناصر، كما هو الحال في المثال أعلاه.وبطبيعة الحال، فإنه يجب أن تنتظر أنماط لتحميل.
98+
99+
نظرا لأن `DOMContentLoaded` ينتظر البرامج النصية ، فإنه ينتظر الآن الأنماط التي تسبقها أيضًا.
100+
101+
### Built-in browser autofill
102+
103+
Firefox, Chrome , Opera تم تشغيل نماذج الملء التلقائي `DOMContentLoaded`.
104+
105+
على سبيل المثال ، إذا كانت الصفحة تحتوي على نموذج به معلومات تسجيل دخول وكلمة مرور ، وتذكر المتصفح القيم ، فقد يحاول ملئها تلقائيًا في `DOMContentLoaded` (إذا وافق عليه المستخدم).
106+
107+
لذلك إذا تم تأجيل `DOMContentLoaded` بواسطة نصوص برمجية طويلة التحميل ، فإن الملء التلقائي ينتظر أيضًا. ربما رأيت ذلك في بعض المواقع (إذا كنت تستخدم الملء التلقائي للمتصفح) - لا يتم ملء حقول تسجيل الدخول / كلمة المرور تلقائيًا على الفور ، ولكن هناك تأخير حتى يتم تحميل الصفحة بالكامل. هذا هو التأخير الفعلي حتى حدث `DOMContentLoaded` .
108+
109+
110+
## window.onload [#window-onload]
111+
112+
يتم تشغيل حدث `load` في كائن `window` عند تحميل الصفحة بأكملها بما في ذلك الأنماط والصور والموارد الأخرى. هذا الحدث متاح عبر خاصية `onload` .
113+
114+
يوضح المثال أدناه أحجام الصور بشكل صحيح ، لأن `window.onload` ينتظر جميع الصور
115+
116+
```html run height=200 refresh
117+
<script>
118+
window.onload = function() { // same as window.addEventListener('load', (event) => {
119+
alert('Page loaded');
120+
121+
// image is loaded at this time
122+
alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`);
123+
};
124+
</script>
125+
126+
<img id="img" src="https://en.js.cx/clipart/train.gif?speed=1&cache=0">
127+
```
128+
129+
## window.onunload
130+
131+
عندما يغادر زائر الصفحة ، يتم تشغيل حدث `unload` في النافذة `window`يمكننا أن نفعل شيئًا هناك لا يتضمن تأخيرًا ، مثل إغلاق النوافذ المنبثقة ذات الصلة.
132+
133+
الاستثناء الملحوظ هو إرسال التحليلات.
134+
135+
لنفترض أننا نجمع بيانات حول كيفية استخدام الصفحة: نقرات الماوس ، والتمرير ، ومناطق الصفحة المعروضة ، وما إلى ذلك.
136+
137+
بطبيعه الحال, حدث `unload` هو عندما يتركنا المستخدم ، ونرغب في حفظ البيانات على خادمنا.
138+
139+
توجد طريقة خاصة `navigator.sendBeacon(url, data)` لهذه الاحتياجات, موضوفة ف المواصفات <https://w3c.github.io/beacon/>.
140+
141+
يرسل البيانات في الخلفية. لا يتأخر الانتقال إلى صفحة أخرى: يغادر المتصفح الصفحة ، لكنه لا يزال ينفذ `sendBeacon`.
142+
143+
إليك كيفية استخدامه:
144+
```js
145+
let analyticsData = { /* object with gathered data */ };
146+
147+
window.addEventListener("unload", function() {
148+
navigator.sendBeacon("/analytics", JSON.stringify(analyticsData));
149+
};
150+
```
151+
152+
- يتم إرسال الطلب كـ POST.
153+
- لا يمكننا إرسال سلسلة فحسب ، بل يمكننا أيضًا إرسال النماذج والتنسيقات الأخرى ، كما هو موضح في الفصل <info: fetch> ، ولكنه عادةً ما يكون كائنًا مشروطًا.
154+
- البيانات محدودة بـ 64 كيلو بايت.
155+
156+
عند الانتهاء من طلب `sendBeacon` , من المحتمل أن يكون المتصفح قد غادر المستند بالفعل ، لذلك لا توجد طريقة للحصول على استجابة الخادم (والتي تكون عادةً فارغة للتحليلات).
157+
158+
هناك ايضا علامة `keepalive` لتنفيذ طلبات "after-page-left" في طريقة [fetch](info:fetch) لطلبات الشبكة العامة. يمكنك الحصول عل المزيد من المعلومات في الفصل <info:fetch-api>.
159+
160+
161+
إذا أردنا إلغاء الانتقال إلى صفحة أخرى ، فلا يمكننا القيام بذلك هنا. لكن يمكننا استخدام حدث آخر --
162+
`onbeforeunload`.
163+
164+
## window.onbeforeunload [#window.onbeforeunload]
165+
166+
إذا بدأ الزائر التنقل بعيدًا عن الصفحة أو حاول إغلاق النافذة ، يطلب معالج `beforeunload` تأكيدًا إضافيًا.
167+
168+
إذا ألغينا الحدث ، فقد يسأل المتصفح الزائر عما إذا كان متأكدًا.
169+
170+
يمكنك تجربتها عن طريق تشغيل هذا الرمز ثم إعادة تحميل الصفحة:
171+
172+
```js run
173+
window.onbeforeunload = function() {
174+
return false;
175+
};
176+
```
177+
178+
لأسباب تاريخية ، يتم أيضًا اعتبار إرجاع سلسلة غير فارغة بمثابة إلغاء للحدث. منذ بعض الوقت ، اعتادت المتصفحات على إظهار الرسالة كرسالة ، ولكن كما تقول [المواصفات الحديثة](https://html.spec.whatwg.org/#unloading-documents) ، لا ينبغي لها ذلك.
179+
180+
هذا مثال:
181+
182+
```js run
183+
window.onbeforeunload = function() {
184+
return "There are unsaved changes. Leave now?";
185+
};
186+
```
187+
188+
تم تغيير السلوك لأن بعض مشرفي المواقع أساءوا استخدام معالج الحدث هذا من خلال عرض رسائل مضللة ومزعجة. لذلك قد لا تزال المتصفحات القديمة تعرضها كرسالة في الوقت الحالي ، ولكن بصرف النظر عن ذلك - لا توجد طريقة لتخصيص الرسالة المعروضة للمستخدم.
189+
190+
## readyState
191+
192+
ماذا يحدث إذا قمنا بتعيين معالج `DOMContentLoaded` بعد تحميل المستند؟
193+
194+
بطبيعة الحال ، لا يعمل أبدا.
195+
196+
هناك حالات لا نكون فيها متأكدين مما إذا كان المستند جاهزًا أم لا. نود أن يتم تنفيذ وظيفتنا عند تحميل DOM ، سواء الآن أو لاحقًا.
197+
198+
تخبرنا خاصية `document.readyState` عن حالة التحميل الحالية.
199+
200+
هناك 3 قيم محتملة:
201+
202+
- `"loading"` -- يتم تحميل المستند.
203+
- `"interactive"` -- تمت قراءة المستند بالكامل.
204+
- `"complete"` -- تمت قراءة المستند بالكامل وتحميل جميع الموارد (مثل الصور) أيضًا.
205+
206+
لذلك يمكننا التحقق من `document.readyState` وإعداد معالج أو تنفيذ الكود فورًا إذا كان جاهزًا.
207+
208+
مثل هذا:
209+
210+
```js
211+
function work() { /*...*/ }
212+
213+
if (document.readyState == 'loading') {
214+
// loading yet, wait for the event
215+
document.addEventListener('DOMContentLoaded', work);
216+
} else {
217+
// DOM is ready!
218+
work();
219+
}
220+
```
221+
222+
هناك أيضًا حدث `readystatechange` الذي يتم تشغيله عندما تتغير الحالة ، لذلك يمكننا طباعة كل هذه الحالات على النحو التالي:
223+
224+
```js run
225+
// current state
226+
console.log(document.readyState);
227+
228+
// print state changes
229+
document.addEventListener('readystatechange', () => console.log(document.readyState));
230+
```
231+
232+
يعد الحدث `readystatechange` آلية بديلة لتتبع حالة تحميل المستند ، وقد ظهر منذ فترة طويلة. في الوقت الحاضر ، نادرًا ما يتم استخدامه.
233+
234+
دعونا نرى تدفق الأحداث بالكامل للتأكد من اكتمالها.
235+
236+
إليك مستند يحتوي على `<iframe>`, `<img>` والمعالجات التي تسجل الأحداث:
237+
238+
```html
239+
<script>
240+
log('initial readyState:' + document.readyState);
241+
242+
document.addEventListener('readystatechange', () => log('readyState:' + document.readyState));
243+
document.addEventListener('DOMContentLoaded', () => log('DOMContentLoaded'));
244+
245+
window.onload = () => log('window onload');
246+
</script>
247+
248+
<iframe src="iframe.html" onload="log('iframe onload')"></iframe>
249+
250+
<img src="http://en.js.cx/clipart/train.gif" id="img">
251+
<script>
252+
img.onload = () => log('img onload');
253+
</script>
254+
```
255+
256+
المثال العملي هو [in the sandbox](sandbox:readystate).
257+
258+
الإخراج النموذجي:
259+
1. [1] initial readyState:loading
260+
2. [2] readyState:interactive
261+
3. [2] DOMContentLoaded
262+
4. [3] iframe onload
263+
5. [4] img onload
264+
6. [4] readyState:complete
265+
7. [4] window onload
266+
267+
تشير الأرقام الموجودة بين قوسين معقوفين إلى الوقت التقريبي لحدوث ذلك. تحدث الأحداث التي تحمل نفس الرقم تقريبًا في نفس الوقت (+ - بضع مللي ثانية).
268+
269+
- `document.readyState` تصبح `interactive` قبل `DOMContentLoaded`. هذان الشيئان يعنيان نفس الشيء في الواقع.
270+
- `document.readyState` تصبح `complete` عندما تكون جميع الموارد (`iframe` and `img`) aيتم تحميلها. هنا يمكننا أن نرى أنه يحدث في نفس الوقت تقريبًا مثل `img.onload` (`img` هو المورد الأخير) و `window.onload`. التحويل الي `complete` الحالة تعني نفس `window.onload`. الفرق هو `window.onload` يعمل دائمًا بعد كل معالجات `load` الاخري.
271+
272+
273+
## الملخص
274+
275+
أحداث تحميل الصفحة:
276+
277+
- `DOMContentLoaded` يتم تشغيل الحدث `document` عندما يكون DOM جاهزا. يمكننا تطبيق JavaScript على العناصر في هذه المرحلة.
278+
- - نص برمجي مثل `<script>...</script>` او `<script src="..."></script>` حظر DOMContentLoaded ، ينتظر المستعرض تنفيذها.
279+
- قد يستمر تحميل الصور والموارد الأخرى.
280+
- يتم تحميل حدث `load` في `window` عند تحميل الصفحة وجميع الموارد. نادرًا ما نستخدمه ، لأنه لا داعي للانتظار لفترة طويلة.
281+
- يتم تشغيل الحدث `beforeunload` في `window` عندما يريد المستخدم مغادرة الصفحة. إذا ألغينا الحدث ، يسأل المتصفح عما إذا كان المستخدم يريد حقًا المغادرة (على سبيل المثال ، لدينا تغييرات غير محفوظة).
282+
- يتم تشغيل الحدث `unload` في `window` عندما يغادر المستخدم أخيرًا ، في المعالج يمكننا فقط القيام بأشياء بسيطة لا تنطوي على تأخير أو سؤال المستخدم. بسبب هذا القيد ، نادرًا ما يتم استخدامه. يمكننا إرسال طلب شبكة باستخدام `navigator.sendBeacon`.
283+
- `document.readyState` هي الحالة الحالية للمستند ، يمكن تتبع التغييرات في حدث `readystatechange` :
284+
- `loading` -- يتم تحميل المستند.
285+
- `interactive` -- يتم تحليل المستند ، ويحدث في نفس الوقت تقريبًا مثل `DOMContentLoaded`, ولكن قبله.
286+
- `complete` -- يتم تحميل المستند والموارد ، يحدث في نفس الوقت تقريبًا مثل `window.onload`, ولكن قبل ذلك.

0 commit comments

Comments
 (0)