Published: July 3, 2026
إذا سبق لك استخدام برنامج تعديل مستندات أو تطبيق جداول بيانات أو أي تطبيق يكون فيه لصق المحتوى من الحافظة تفاعلاً أساسيًا، فأنت تعرف توقعات المستخدمين: يجب أن تبدو عملية اللصق فورية.
في كثير من الحالات، تقرأ تطبيقات الويب بيانات من الحافظة أكثر مما تحتاج إليه، ما قد يجعل عملية لصق المحتوى تبدو أبطأ من المفترض، ويؤدي إلى إهدار دورات وحدة المعالجة المركزية، ويستخدم الذاكرة للبيانات التي لا يحتاج إليها التطبيق مطلقًا.
قراءة التنسيق الانتقائية تعالج مشكلة الأداء هذه من خلال تعديل Async Clipboard API لتلبية توقعات المستخدمين بشكل أفضل وتوفير ما يحتاج إليه المطوّرون، أي قراءة التنسيقات التي يحتاج إليها التطبيق فعليًا فقط.
المشكلة: قراءة جميع تنسيقات البيانات مسبقًا
عندما ينسخ المستخدم بيانات من أي تطبيق، مثل Excel أو "مستندات Google" أو Photoshop، يكتب التطبيق عادةً عدة تمثيلات للبيانات نفسها في حافظة النظام: نص عادي وHTML وصورة وأحيانًا تنسيقات مخصّصة. ونادرًا ما يحتاج تطبيق الويب الذي يقرأ البيانات (عندما يلصق المستخدم بيانات من الحافظة) إلى كل هذه التمثيلات. قد يحتاج برنامج تعديل جداول البيانات إلى HTML. وقد يرغب برنامج تعديل النصوص في عرض أمر "اللصق كنص عادي". وقد يحتاج برنامج تعديل الرموز البرمجية إلى النص فقط ولا شيء آخر.
حتى الآن،
navigator.clipboard.read()
جلبت كل تمثيل متاح للبيانات من حافظة النظام
، ونفّذت عملية الضبط (التي قد تستغرق وقتًا، خاصةً مع حمولات HTML أو
الصور الكبيرة)، واحتفظت بالبايتات في الذاكرة، حتى بالنسبة إلى التنسيقات التي لن يستخدمها التطبيق
مطلقًا. كلما زادت حمولة البيانات غير المستخدَمة، زادت المدة التي كان على المستخدم الانتظار فيها، وزادت الذاكرة التي تستهلكها علامة التبويب، وذلك في الوقت الذي تكون فيه استجابة عملية اللصق مهمة جدًا.
الحلّ: تعداد التنسيقات فقط، ثم قراءتها عند الطلب
اعتبارًا من Chrome وEdge 149، تصف الكائنات
ClipboardItem
التي تعرضها الطريقة navigator.clipboard.read() فقط
محتوى الحافظة، بدلاً من منح إمكانية الوصول إلى البيانات على الفور. لا تتم قراءة البايتات الفعلية لتنسيق معيّن من الحافظة إلا عند استدعاء
ClipboardItem.getType(mimeType).
ولا تتغيّر واجهة برمجة التطبيقات. وسيظل الرمز الذي كتبته أمس يعمل اليوم، ما يمنحك مزايا فورية على مستوى الأداء:
// Enumerate the available MIME types.
// No payload is fetched yet.
const items = await navigator.clipboard.read();
for (const item of items) {
if (item.types.includes('text/html')) {
// Only read the HTML data.
// The data is fetched (and sanitized) here only.
const blob = await item.getType('text/html');
useThePastedHtml(await blob.text());
break;
}
// text/plain, image/png, or any other custom formats
// stored in the clipboard are never read.
}
هناك ميزة أخرى على مستوى الأداء وهي أنّ التخزين المؤقت تلقائي. إنّ استدعاء
getType('text/html') مرّتين على ClipboardItem نفسه يقرأ من حافظة النظام
مرة واحدة فقط ويعرض Blob المخزّنة مؤقتًا في الاستدعاء الثاني.
المزايا
وقت الاستجابة. إنّ العمل الذي كان يجب تنفيذه عند استدعاء navigator.clipboard.read()، مثل نسخ البايتات بين العمليات أو ضبط HTML أو فك ترميز الصور، لا يتم الآن إلا للتنسيقات التي يحتاج إليها تطبيقك فعليًا. تحصل التطبيقات التي تقرأ تنسيقًا واحدًا فقط على معظم التوفير. كلما زادت التنسيقات التي تتخطّاها، زادت المكاسب. يستفيد HTML أكثر من غيره لأنّ عملية ضبط HTML مكلفة.
الذاكرة. في السابق، كان استدعاء navigator.clipboard.read() عندما تحتوي الحافظة على صورة بحجم 50 ميغابايت يعني أنّه يجب استخدام 50 ميغابايت في ذاكرة أداة العرض لصفحة الويب إلى أن يتم إصدار ClipboardItem، حتى إذا كان التطبيق يحتاج فقط إلى تمثيل text/plain للبيانات. الآن، لا تستخدم الذاكرة في عملية العرض إلا التنسيقات التي يقرأها تطبيقك عند استدعاء ClipboardItem.getType(). بالنسبة إلى التطبيقات التي يكون فيها اللصق شائعًا، مثل برامج تعديل المستندات أو أدوات إنشاء الرسائل الإلكترونية أو أدوات التصميم، يؤدي ذلك إلى تقليل استخدام الذاكرة بشكل كبير أثناء عملية اللصق، خاصةً في الجلسات المتعددة علامات التبويب حيث قد تقرأ عدة برامج تعديل الحافظة بالتوازي.
لا حاجة إلى تفعيل الميزة. تحصل جميع المواقع الإلكترونية على الويب على هذه المزايا تلقائيًا. لست بحاجة إلى نقل الرمز أو حظر الرمز خلف منطق رصد الميزات.
تغيير واحد في السلوك يجب الانتباه إليه
تؤدي قراءة البيانات لاحقًا إلى تغيير طفيف في السلوك: لم يعُد كائن ClipboardItem لقطة ثابتة للحافظة في اللحظة التي تم فيها حلّ استدعاء navigator.clipboard.read().
عند استدعاء read() وعرض ClipboardItem، يكون هذا العنصر مجرد مقبض كسول للبيانات في حافظة النظام.
إذا تغيّرت محتويات الحافظة بين استدعاء read() واستدعاء لاحق لـ getType()، سيتم رفض هذا الاستدعاء باستخدام InvalidStateError. وينطبق ذلك حتى على تنسيق سبق لك قراءته بنجاح على ClipboardItem نفسه.
// Read from the clipboard.
const items = await navigator.clipboard.read();
// Get the first ClipboardItem.
const item = items[0];
// Actually fetch the data now, which works fine.
const text = await item.getType('text/plain');
// The user writes something new to the clipboard
// by copying from another app, or your own code writes to
// the clipboard again.
await navigator.clipboard.writeText('something new');
// Fetching the data from the earlier ClipboardItem
// rejects with InvalidStateError, because the contents
// of the clipboard changed.
const html = await item.getType('text/html');
يحدث ذلك لأنّ عرض بيانات لم تعُد تعكس الحافظة سيؤدي إلى حدوث ارتباك ومشاكل يصعب تصحيحها.
من الناحية العملية، يكون التغيير غير مرئي لمعظم الرموز، لأنّ التطبيقات عادةً ما تستدعي read() وgetType() بالتتابع داخل معالج اللصق نفسه. ومع ذلك، قد ترغب في مراقبة الحالات التي يكون لديك فيها رمز يحتفظ بـ ClipboardItem عبر حدود غير متزامنة.
في ما يلي مثال على الحالة التي قد يصبح فيها هذا التغيير مشكلة: تخزين كائنات ClipboardItem مؤقتًا على window أو عرضها في واجهة مستخدم لسجلّ الحافظة أو انتظار تفاعل المستخدم قبل استدعاء getType(). لتجنُّب حدوث مشاكل في سيناريو كهذا:
- يمكنك تضمين استدعاءات
getType()في بلوكاتtry / catch، والتعامل معInvalidStateErrorكإشارة إلى أنّ الحافظة قد تم تعديلها ويجب أن يقرأ الرمز مرة أخرى. - إذا كنت بحاجة إلى الاحتفاظ ببيانات الحافظة، يمكنك نسخ
Blobإلى البنية الخاصة بك بمجرد استدعاءgetType(). لا تتعامل معClipboardItemعلى أنّه مساحة تخزين طويلة الأجل. - استخدِم الحدث
clipboardChangeلإبطال المقابض القديمة بشكل استباقي.
المعايير والمتصفّحات المتوافقة
قراءة التنسيق الانتقائية هي تغيير في مواصفات Clipboard APIs مدفوع من قِبل فريق Web Editing Working Group وفريق منصة Microsoft Edge على الويب.
يتوافق Safari أيضًا مع هذا السلوك، وأشار Firefox إلى موقف إيجابي من المعايير والنية في التوافق معها.
هذا التحسين على مستوى الأداء وقابلية التشغيل التفاعلي في Clipboard API مهم، وإن كان غير ملحوظ، ويتوافق Chromium الآن مع النموذج نفسه.