[{"data":1,"prerenderedAt":1755},["ShallowReactive",2],{"article-\u002Farticles\u002F688772cfc00f22daabc287ea":3},{"id":4,"title":5,"articleId":6,"body":7,"cover":1739,"coverThumb":1740,"created":1741,"date":1742,"description":1743,"extension":1744,"meta":1745,"navigation":85,"path":1746,"seo":1747,"stem":1748,"tags":1749,"updated":1753,"__hash__":1754},"articles\u002Farticles\u002F688772cfc00f22daabc287ea.md","معالجة الأخطاء (Error handling) في Nuxt","688772cfc00f22daabc287ea",{"type":8,"value":9,"toc":1733},"minimark",[10,14,17,20,23,31,34,37,40,290,293,296,561,567,570,577,617,624,828,841,847,853,856,862,872,875,1601,1607,1610,1613,1616,1619,1622,1628,1634,1637,1642,1645,1648,1653,1656,1659,1662,1667,1670,1675,1678,1681,1684,1689,1692,1695,1700,1703,1706,1709,1714,1717,1720,1723,1726,1729],[11,12,13],"p",{},"الحمد لله الذي علَّم بالقلم، علَّم الإنسان ما لم يعلم، والصلاة والسلام على خير معلِّم الناس الخير سيدنا محمد - صلَّى الله عليه وسلم … أما بعد ،،",[11,15,16],{},"في كل مشروع ويب نطوره، هناك لحظة لا مفر منها: عند حدوث خطأ ما.",[11,18,19],{},"قد يكون الخطأ ناتجًا عن مشكلة في الاتصال بالخادم، أو عن صفحة غير موجودة، أو حتى بسبب إدخال غير صحيح من المستخدم.",[11,21,22],{},"في هذا المقال، نستعرض كيف يوفّر Nuxt أدوات مرنة للتعامل مع الأخطاء بسلاسة، ونوضح كيف يمكنك أن تحوّل لحظات الفشل إلى فرص لبناء تجربة أكثر نضجًا وموثوقية.",[24,25,27],"h2",{"id":26},"معالجة-الأخطاء-مركزيا",[28,29,30],"strong",{},"معالجة الأخطاء مركزيا",[11,32,33],{},"بدلًا من التعامل مع كل خطأ يظهر في التطبيق بشكل منفصل، يمكنك إعداد طريقة واحدة تتولى متابعة جميع الطلبات التي يجريها التطبيق لجلب البيانات، وتراقب ما إذا حدث فيها خطأ.",[11,35,36],{},"هذه الطريقة تشبه الحارس الذي يقف على الباب ويتأكد أن كل شيء يسير بشكل سليم، وإذا وقع خطأ، يتصرف تلقائيًا: يُظهر رسالة مناسبة للمستخدم، أو يُعيد المحاولة، أو يُخبرك كمطور بوجود مشكلة.",[11,38,39],{},"هذا الأسلوب يجعل التطبيق أكثر تنظيمًا وراحة، ويقلّل من التكرار والأخطاء في الصفحات المختلفة.",[41,42,47],"pre",{"className":43,"code":44,"language":45,"meta":46,"style":46},"language-typescript shiki shiki-themes github-dark","\u002F\u002F plugins\u002Fapi.ts\nimport { showError } from '#app'  \n\nexport default defineNuxtPlugin(nuxtApp => {  \n  const config = useRuntimeConfig()  \n  \n  const api = $fetch.create({  \n    baseURL: config.public.BASE_URL,  \n    async onResponseError({ response }) {  \n      if (response?._data?.error) {  \n        await nuxtApp.runWithContext(() => {  \n          showError({ statusCode: response?._data.statusCode })  \n        })  \n      }  \n    },  \n  })  \n  \n  return {  \n    provide: {  \n      api,  \n    },  \n  }  \n})\n","typescript","",[48,49,50,59,80,87,113,132,137,156,168,186,195,215,224,230,236,242,248,253,261,267,273,278,284],"code",{"__ignoreMap":46},[51,52,55],"span",{"class":53,"line":54},"line",1,[51,56,58],{"class":57},"sAwPA","\u002F\u002F plugins\u002Fapi.ts\n",[51,60,62,66,70,73,77],{"class":53,"line":61},2,[51,63,65],{"class":64},"snl16","import",[51,67,69],{"class":68},"s95oV"," { showError } ",[51,71,72],{"class":64},"from",[51,74,76],{"class":75},"sU2Wk"," '#app'",[51,78,79],{"class":68},"  \n",[51,81,83],{"class":53,"line":82},3,[51,84,86],{"emptyLinePlaceholder":85},true,"\n",[51,88,90,93,96,100,103,107,110],{"class":53,"line":89},4,[51,91,92],{"class":64},"export",[51,94,95],{"class":64}," default",[51,97,99],{"class":98},"svObZ"," defineNuxtPlugin",[51,101,102],{"class":68},"(",[51,104,106],{"class":105},"s9osk","nuxtApp",[51,108,109],{"class":64}," =>",[51,111,112],{"class":68}," {  \n",[51,114,116,119,123,126,129],{"class":53,"line":115},5,[51,117,118],{"class":64},"  const",[51,120,122],{"class":121},"sDLfK"," config",[51,124,125],{"class":64}," =",[51,127,128],{"class":98}," useRuntimeConfig",[51,130,131],{"class":68},"()  \n",[51,133,135],{"class":53,"line":134},6,[51,136,79],{"class":68},[51,138,140,142,145,147,150,153],{"class":53,"line":139},7,[51,141,118],{"class":64},[51,143,144],{"class":121}," api",[51,146,125],{"class":64},[51,148,149],{"class":68}," $fetch.",[51,151,152],{"class":98},"create",[51,154,155],{"class":68},"({  \n",[51,157,159,162,165],{"class":53,"line":158},8,[51,160,161],{"class":68},"    baseURL: config.public.",[51,163,164],{"class":121},"BASE_URL",[51,166,167],{"class":68},",  \n",[51,169,171,174,177,180,183],{"class":53,"line":170},9,[51,172,173],{"class":64},"    async",[51,175,176],{"class":98}," onResponseError",[51,178,179],{"class":68},"({ ",[51,181,182],{"class":105},"response",[51,184,185],{"class":68}," }) {  \n",[51,187,189,192],{"class":53,"line":188},10,[51,190,191],{"class":64},"      if",[51,193,194],{"class":68}," (response?._data?.error) {  \n",[51,196,198,201,204,207,210,213],{"class":53,"line":197},11,[51,199,200],{"class":64},"        await",[51,202,203],{"class":68}," nuxtApp.",[51,205,206],{"class":98},"runWithContext",[51,208,209],{"class":68},"(() ",[51,211,212],{"class":64},"=>",[51,214,112],{"class":68},[51,216,218,221],{"class":53,"line":217},12,[51,219,220],{"class":98},"          showError",[51,222,223],{"class":68},"({ statusCode: response?._data.statusCode })  \n",[51,225,227],{"class":53,"line":226},13,[51,228,229],{"class":68},"        })  \n",[51,231,233],{"class":53,"line":232},14,[51,234,235],{"class":68},"      }  \n",[51,237,239],{"class":53,"line":238},15,[51,240,241],{"class":68},"    },  \n",[51,243,245],{"class":53,"line":244},16,[51,246,247],{"class":68},"  })  \n",[51,249,251],{"class":53,"line":250},17,[51,252,79],{"class":68},[51,254,256,259],{"class":53,"line":255},18,[51,257,258],{"class":64},"  return",[51,260,112],{"class":68},[51,262,264],{"class":53,"line":263},19,[51,265,266],{"class":68},"    provide: {  \n",[51,268,270],{"class":53,"line":269},20,[51,271,272],{"class":68},"      api,  \n",[51,274,276],{"class":53,"line":275},21,[51,277,241],{"class":68},[51,279,281],{"class":53,"line":280},22,[51,282,283],{"class":68},"  }  \n",[51,285,287],{"class":53,"line":286},23,[51,288,289],{"class":68},"})\n",[11,291,292],{},"الكود السابق يُستخدم لتجهيز طريقة واحدة داخل التطبيق تقوم بإرسال الطلبات إلى موقع خارجي لجلب البيانات، وفي حال حدث خطأ أثناء ذلك، مثل أن يكون هناك خلل في الرد أو البيانات غير متوفرة، يعرض التطبيق تلقائيًا صفحة خطأ مناسبة بدلًا من أن يتوقف فجأة.",[11,294,295],{},"هذا الترتيب يُسهل عليك التعامل مع الأخطاء في مكان واحد دون الحاجة لتكرار نفس الخطوات في كل صفحة من صفحات الموقع.",[41,297,299],{"className":43,"code":298,"language":45,"meta":46,"style":46},"\u002F\u002F composables\u002FuseAPI.ts\nimport type { NitroFetchRequest } from 'nitropack'  \n  \nexport function useAPI\u003CT = unknown>(  \n  request: NitroFetchRequest | Ref\u003CNitroFetchRequest> | (() => NitroFetchRequest),  \n  opts: Parameters\u003Ctypeof useFetch\u003CT>>[1] = {},  \n) {  \n  const nuxtApp = useNuxtApp()  \n  const serverFetch = useRequestFetch()  \n  const clientFetch = nuxtApp.$api as typeof $fetch  \n  \n  const $f = import.meta.server ? (serverFetch as typeof $fetch) : clientFetch  \n  \n  return useFetch\u003CT>(request, {  \n    ...opts,  \n    $fetch: $f,  \n  })  \n}\n",[48,300,301,306,323,327,351,389,424,429,443,457,478,482,521,525,539,547,552,556],{"__ignoreMap":46},[51,302,303],{"class":53,"line":54},[51,304,305],{"class":57},"\u002F\u002F composables\u002FuseAPI.ts\n",[51,307,308,310,313,316,318,321],{"class":53,"line":61},[51,309,65],{"class":64},[51,311,312],{"class":64}," type",[51,314,315],{"class":68}," { NitroFetchRequest } ",[51,317,72],{"class":64},[51,319,320],{"class":75}," 'nitropack'",[51,322,79],{"class":68},[51,324,325],{"class":53,"line":82},[51,326,79],{"class":68},[51,328,329,331,334,337,340,343,345,348],{"class":53,"line":89},[51,330,92],{"class":64},[51,332,333],{"class":64}," function",[51,335,336],{"class":98}," useAPI",[51,338,339],{"class":68},"\u003C",[51,341,342],{"class":98},"T",[51,344,125],{"class":64},[51,346,347],{"class":121}," unknown",[51,349,350],{"class":68},">(  \n",[51,352,353,356,359,362,365,368,370,373,376,379,382,384,386],{"class":53,"line":115},[51,354,355],{"class":105},"  request",[51,357,358],{"class":64},":",[51,360,361],{"class":98}," NitroFetchRequest",[51,363,364],{"class":64}," |",[51,366,367],{"class":98}," Ref",[51,369,339],{"class":68},[51,371,372],{"class":98},"NitroFetchRequest",[51,374,375],{"class":68},"> ",[51,377,378],{"class":64},"|",[51,380,381],{"class":68}," (() ",[51,383,212],{"class":64},[51,385,361],{"class":98},[51,387,388],{"class":68},"),  \n",[51,390,391,394,396,399,401,404,407,409,412,415,418,421],{"class":53,"line":134},[51,392,393],{"class":105},"  opts",[51,395,358],{"class":64},[51,397,398],{"class":98}," Parameters",[51,400,339],{"class":68},[51,402,403],{"class":64},"typeof",[51,405,406],{"class":68}," useFetch\u003C",[51,408,342],{"class":98},[51,410,411],{"class":68},">>[",[51,413,414],{"class":121},"1",[51,416,417],{"class":68},"] ",[51,419,420],{"class":64},"=",[51,422,423],{"class":68}," {},  \n",[51,425,426],{"class":53,"line":139},[51,427,428],{"class":68},") {  \n",[51,430,431,433,436,438,441],{"class":53,"line":158},[51,432,118],{"class":64},[51,434,435],{"class":121}," nuxtApp",[51,437,125],{"class":64},[51,439,440],{"class":98}," useNuxtApp",[51,442,131],{"class":68},[51,444,445,447,450,452,455],{"class":53,"line":170},[51,446,118],{"class":64},[51,448,449],{"class":121}," serverFetch",[51,451,125],{"class":64},[51,453,454],{"class":98}," useRequestFetch",[51,456,131],{"class":68},[51,458,459,461,464,466,469,472,475],{"class":53,"line":188},[51,460,118],{"class":64},[51,462,463],{"class":121}," clientFetch",[51,465,125],{"class":64},[51,467,468],{"class":68}," nuxtApp.$api ",[51,470,471],{"class":64},"as",[51,473,474],{"class":64}," typeof",[51,476,477],{"class":68}," $fetch  \n",[51,479,480],{"class":53,"line":197},[51,481,79],{"class":68},[51,483,484,486,489,491,494,497,500,503,506,509,511,513,516,518],{"class":53,"line":217},[51,485,118],{"class":64},[51,487,488],{"class":121}," $f",[51,490,125],{"class":64},[51,492,493],{"class":64}," import",[51,495,496],{"class":68},".",[51,498,499],{"class":121},"meta",[51,501,502],{"class":68},".server ",[51,504,505],{"class":64},"?",[51,507,508],{"class":68}," (serverFetch ",[51,510,471],{"class":64},[51,512,474],{"class":64},[51,514,515],{"class":68}," $fetch) ",[51,517,358],{"class":64},[51,519,520],{"class":68}," clientFetch  \n",[51,522,523],{"class":53,"line":226},[51,524,79],{"class":68},[51,526,527,529,532,534,536],{"class":53,"line":232},[51,528,258],{"class":64},[51,530,531],{"class":98}," useFetch",[51,533,339],{"class":68},[51,535,342],{"class":98},[51,537,538],{"class":68},">(request, {  \n",[51,540,541,544],{"class":53,"line":238},[51,542,543],{"class":64},"    ...",[51,545,546],{"class":68},"opts,  \n",[51,548,549],{"class":53,"line":244},[51,550,551],{"class":68},"    $fetch: $f,  \n",[51,553,554],{"class":53,"line":250},[51,555,247],{"class":68},[51,557,558],{"class":53,"line":255},[51,559,560],{"class":68},"}\n",[11,562,563,564,496],{},"الكود السابق يهدف لإنشاء طريقة موحّدة وآمنة لجلب البيانات داخل تطبيق Nuxt، بحيث يتم تحديد العنوان الرئيسي للواجهة البرمجية من إعدادات التطبيق، ثم إعداد نسخة مخصصة من أداة الجلب ",[48,565,566],{},"$fetch",[11,568,569],{},"هذه النسخة تتميز بقدرتها على رصد الأخطاء تلقائيًا، والتصرف عند حدوثها من خلال عرض صفحة خطأ مناسبة للمستخدم دون التأثير على بقية تجربة التصفح.",[11,571,572,573,576],{},"في نهاية الكود، يتم توفير هذه الأداة تحت اسم ",[48,574,575],{},"api"," داخل التطبيق، مما يتيح استخدامها بسهولة في أي مكان دون الحاجة لتكرار الإعدادات أو كتابة معالجة الأخطاء من جديد، وهو ما يجعل الكود أنظف وأكثر تنظيمًا، كما يلي:",[41,578,580],{"className":43,"code":579,"language":45,"meta":46,"style":46},"const { data, status } = await useAPI(`\u002Fapi\u002Fadmin\u002Fusers`)\n",[48,581,582],{"__ignoreMap":46},[51,583,584,587,590,593,596,599,602,604,607,609,611,614],{"class":53,"line":54},[51,585,586],{"class":64},"const",[51,588,589],{"class":68}," { ",[51,591,592],{"class":121},"data",[51,594,595],{"class":68},", ",[51,597,598],{"class":121},"status",[51,600,601],{"class":68}," } ",[51,603,420],{"class":64},[51,605,606],{"class":64}," await",[51,608,336],{"class":98},[51,610,102],{"class":68},[51,612,613],{"class":75},"`\u002Fapi\u002Fadmin\u002Fusers`",[51,615,616],{"class":68},")\n",[11,618,619,620,623],{},"أو يمكنك استخدام ",[48,621,622],{},"api$"," مباشرة كما يلي:",[41,625,627],{"className":43,"code":626,"language":45,"meta":46,"style":46},"const isLoadingSend = ref(false)  \nconst sendMessage = async () => {  \n  const { $api } = useNuxtApp()  \n  \n  const body = {  \n    message: message.value,  \n  }  \n  isLoadingSend.value = true  \n  try {  \n    await $api('\u002Fapi\u002Fcontacts', {  \n      method: 'POST',  \n      body,  \n    })  \n    await router.push('\u002F')  \n    show(`تم ارسل الرسالة بنجاح`, 'success')  \n  } finally {  \n    isLoadingSend.value = false  \n  }  \n}\n",[48,628,629,649,668,685,689,700,705,709,721,728,744,754,759,764,781,798,808,820,824],{"__ignoreMap":46},[51,630,631,633,636,638,641,643,646],{"class":53,"line":54},[51,632,586],{"class":64},[51,634,635],{"class":121}," isLoadingSend",[51,637,125],{"class":64},[51,639,640],{"class":98}," ref",[51,642,102],{"class":68},[51,644,645],{"class":121},"false",[51,647,648],{"class":68},")  \n",[51,650,651,653,656,658,661,664,666],{"class":53,"line":61},[51,652,586],{"class":64},[51,654,655],{"class":98}," sendMessage",[51,657,125],{"class":64},[51,659,660],{"class":64}," async",[51,662,663],{"class":68}," () ",[51,665,212],{"class":64},[51,667,112],{"class":68},[51,669,670,672,674,677,679,681,683],{"class":53,"line":82},[51,671,118],{"class":64},[51,673,589],{"class":68},[51,675,676],{"class":121},"$api",[51,678,601],{"class":68},[51,680,420],{"class":64},[51,682,440],{"class":98},[51,684,131],{"class":68},[51,686,687],{"class":53,"line":89},[51,688,79],{"class":68},[51,690,691,693,696,698],{"class":53,"line":115},[51,692,118],{"class":64},[51,694,695],{"class":121}," body",[51,697,125],{"class":64},[51,699,112],{"class":68},[51,701,702],{"class":53,"line":134},[51,703,704],{"class":68},"    message: message.value,  \n",[51,706,707],{"class":53,"line":139},[51,708,283],{"class":68},[51,710,711,714,716,719],{"class":53,"line":158},[51,712,713],{"class":68},"  isLoadingSend.value ",[51,715,420],{"class":64},[51,717,718],{"class":121}," true",[51,720,79],{"class":68},[51,722,723,726],{"class":53,"line":170},[51,724,725],{"class":64},"  try",[51,727,112],{"class":68},[51,729,730,733,736,738,741],{"class":53,"line":188},[51,731,732],{"class":64},"    await",[51,734,735],{"class":98}," $api",[51,737,102],{"class":68},[51,739,740],{"class":75},"'\u002Fapi\u002Fcontacts'",[51,742,743],{"class":68},", {  \n",[51,745,746,749,752],{"class":53,"line":197},[51,747,748],{"class":68},"      method: ",[51,750,751],{"class":75},"'POST'",[51,753,167],{"class":68},[51,755,756],{"class":53,"line":217},[51,757,758],{"class":68},"      body,  \n",[51,760,761],{"class":53,"line":226},[51,762,763],{"class":68},"    })  \n",[51,765,766,768,771,774,776,779],{"class":53,"line":232},[51,767,732],{"class":64},[51,769,770],{"class":68}," router.",[51,772,773],{"class":98},"push",[51,775,102],{"class":68},[51,777,778],{"class":75},"'\u002F'",[51,780,648],{"class":68},[51,782,783,786,788,791,793,796],{"class":53,"line":238},[51,784,785],{"class":98},"    show",[51,787,102],{"class":68},[51,789,790],{"class":75},"`تم ارسل الرسالة بنجاح`",[51,792,595],{"class":68},[51,794,795],{"class":75},"'success'",[51,797,648],{"class":68},[51,799,800,803,806],{"class":53,"line":244},[51,801,802],{"class":68},"  } ",[51,804,805],{"class":64},"finally",[51,807,112],{"class":68},[51,809,810,813,815,818],{"class":53,"line":250},[51,811,812],{"class":68},"    isLoadingSend.value ",[51,814,420],{"class":64},[51,816,817],{"class":121}," false",[51,819,79],{"class":68},[51,821,822],{"class":53,"line":255},[51,823,283],{"class":68},[51,825,826],{"class":53,"line":263},[51,827,560],{"class":68},[11,829,830,831],{},"للمزيد حول هذا الجزء، يمكنك الرجوع للتوثيق الرسمي ",[832,833,840],"a",{"href":834,"rel":835,"target":839},"https:\u002F\u002Fnuxt.com\u002Fdocs\u002F4.x\u002Fguide\u002Frecipes\u002Fcustom-usefetch",[836,837,838],"nofollow","noopener","noreferrer","_blank","بالضغط هنا",[24,842,844],{"id":843},"صفحة-خطأ-مخصصة",[28,845,846],{},"صفحة خطأ مخصصة",[11,848,849,850,496],{},"في تطبيقات Nuxt، قد تظهر أخطاء غير متوقعة أثناء الاستخدام، وهنا تبرز أهمية وجود صفحة مخصصة لعرض الخطأ تُعرف باسم ",[48,851,852],{},"error.vue",[11,854,855],{},"هذه الصفحة تتيح لك استبدال صفحة الخطأ الافتراضية بتصميم مناسب يعرض رسالة واضحة للمستخدم، مثل رقم الخطأ أو رابط للعودة إلى الصفحة الرئيسية، مما يحافظ على تجربة استخدام محترفة حتى في حالات الفشل.",[11,857,858,859,496],{},"رغم أنها تُسمى \"صفحة خطأ\"، إلا أنها ليست جزءًا من الصفحات العادية، ويجب وضعها خارج مجلد ",[48,860,861],{},"pages",[11,863,864,865,868,869,871],{},"عند حدوث خطأ، يتم تمرير كائن ",[48,866,867],{},"error"," يحتوي على معلومات مهمة مثل رقم الحالة والرسالة، ويمكنك أيضًا تمرير معلومات إضافية ضمن خاصية ",[48,870,592],{},"، لتتمكن من عرض ما يناسب المستخدم والتصرف بمرونة حسب نوع الخطأ.",[11,873,874],{},"فيما يلي مثال علي الكود الكامل لهذه الصفحة كالتالي:",[41,876,880],{"className":877,"code":878,"language":879,"meta":46,"style":46},"language-html shiki shiki-themes github-dark","\u002F\u002F error.vue\n\u003Ctemplate>  \n  \u003Cdiv style=\"min-height: 100vh\">  \n    \u003Cv-row class=\"pt-8 px-4\">  \n      \u003Cv-col cols=\"12\" md=\"6\" class=\"mx-auto\">  \n        \u003Cv-card class=\"mt-4 mt-md-10\" flat>  \n          \u003Cv-card-text>  \n            \u003Cdiv class=\"my-4\">  \n              \u003Cv-row>  \n                \u003Cv-col cols=\"12\" class=\"text-center\">  \n                  \u003Ch4 class=\"text-h4 bold\">خطأ {{ error.statusCode }}\u003C\u002Fh4>  \n  \n                  \u003Cp class=\"mt-4 text-body-1\">  \n                    \u003Cspan> {{ message }}\u003C\u002Fspan>  \n                  \u003C\u002Fp>  \n                \u003C\u002Fv-col>  \n              \u003C\u002Fv-row>  \n            \u003C\u002Fdiv>  \n          \u003C\u002Fv-card-text>  \n        \u003C\u002Fv-card>  \n  \n        \u003Cv-row class=\"mt-4\">  \n          \u003Cv-col cols=\"12\" class=\"d-flex justify-center\">  \n            \u003Cv-btn variant=\"plain\" class=\"\" @click=\"redirectToHome\"> الذهاب للصفحة الرئيسية\u003C\u002Fv-btn>  \n          \u003C\u002Fv-col>  \n        \u003C\u002Fv-row>  \n      \u003C\u002Fv-col>  \n    \u003C\u002Fv-row>  \n  \u003C\u002Fdiv>  \n\u003C\u002Ftemplate>  \n  \n\u003Cscript setup lang=\"ts\">  \nimport { type NuxtError, reloadNuxtApp } from '#app'  \n  \nconst { error } = defineProps\u003C{  \n  error: NuxtError  \n}>()  \n  \nconst errorMessages: Record\u003Cnumber, string> = {  \n  400: 'الطلب غير صالح',  \n  401: 'يجب تسجيل الدخول للوصول إلى هذه الصفحة',  \n  403: 'ليس لديك صلاحية للوصول إلى هذه الصفحة',  \n  404: 'الصفحة غير موجودة',  \n  500: 'حدث خطأ في الخادم، يرجى المحاولة لاحقًا',  \n  502: 'الخادم لا يستجيب حاليًا',  \n  503: 'الخدمة غير متوفرة مؤقتًا',  \n}  \n  \nconst message = errorMessages[error.statusCode] || 'حدث خطأ غير متوقع، يرجى المحاولة لاحقًا'  \n  \nconst redirectToHome = async () => {  \n  await useRouter().push('\u002F')  \n  reloadNuxtApp()  \n}  \n\u003C\u002Fscript>\n","html",[48,881,882,887,898,916,934,967,987,997,1013,1022,1044,1066,1070,1085,1099,1108,1117,1126,1135,1144,1153,1157,1172,1193,1231,1240,1249,1259,1269,1279,1289,1294,1315,1334,1339,1358,1371,1377,1382,1411,1425,1438,1451,1464,1477,1490,1503,1509,1514,1535,1540,1558,1578,1586,1591],{"__ignoreMap":46},[51,883,884],{"class":53,"line":54},[51,885,886],{"class":68},"\u002F\u002F error.vue\n",[51,888,889,891,895],{"class":53,"line":61},[51,890,339],{"class":68},[51,892,894],{"class":893},"s4JwU","template",[51,896,897],{"class":68},">  \n",[51,899,900,903,906,909,911,914],{"class":53,"line":82},[51,901,902],{"class":68},"  \u003C",[51,904,905],{"class":893},"div",[51,907,908],{"class":98}," style",[51,910,420],{"class":68},[51,912,913],{"class":75},"\"min-height: 100vh\"",[51,915,897],{"class":68},[51,917,918,921,924,927,929,932],{"class":53,"line":89},[51,919,920],{"class":68},"    \u003C",[51,922,923],{"class":893},"v-row",[51,925,926],{"class":98}," class",[51,928,420],{"class":68},[51,930,931],{"class":75},"\"pt-8 px-4\"",[51,933,897],{"class":68},[51,935,936,939,942,945,947,950,953,955,958,960,962,965],{"class":53,"line":115},[51,937,938],{"class":68},"      \u003C",[51,940,941],{"class":893},"v-col",[51,943,944],{"class":98}," cols",[51,946,420],{"class":68},[51,948,949],{"class":75},"\"12\"",[51,951,952],{"class":98}," md",[51,954,420],{"class":68},[51,956,957],{"class":75},"\"6\"",[51,959,926],{"class":98},[51,961,420],{"class":68},[51,963,964],{"class":75},"\"mx-auto\"",[51,966,897],{"class":68},[51,968,969,972,975,977,979,982,985],{"class":53,"line":134},[51,970,971],{"class":68},"        \u003C",[51,973,974],{"class":893},"v-card",[51,976,926],{"class":98},[51,978,420],{"class":68},[51,980,981],{"class":75},"\"mt-4 mt-md-10\"",[51,983,984],{"class":98}," flat",[51,986,897],{"class":68},[51,988,989,992,995],{"class":53,"line":139},[51,990,991],{"class":68},"          \u003C",[51,993,994],{"class":893},"v-card-text",[51,996,897],{"class":68},[51,998,999,1002,1004,1006,1008,1011],{"class":53,"line":158},[51,1000,1001],{"class":68},"            \u003C",[51,1003,905],{"class":893},[51,1005,926],{"class":98},[51,1007,420],{"class":68},[51,1009,1010],{"class":75},"\"my-4\"",[51,1012,897],{"class":68},[51,1014,1015,1018,1020],{"class":53,"line":170},[51,1016,1017],{"class":68},"              \u003C",[51,1019,923],{"class":893},[51,1021,897],{"class":68},[51,1023,1024,1027,1029,1031,1033,1035,1037,1039,1042],{"class":53,"line":188},[51,1025,1026],{"class":68},"                \u003C",[51,1028,941],{"class":893},[51,1030,944],{"class":98},[51,1032,420],{"class":68},[51,1034,949],{"class":75},[51,1036,926],{"class":98},[51,1038,420],{"class":68},[51,1040,1041],{"class":75},"\"text-center\"",[51,1043,897],{"class":68},[51,1045,1046,1049,1052,1054,1056,1059,1062,1064],{"class":53,"line":197},[51,1047,1048],{"class":68},"                  \u003C",[51,1050,1051],{"class":893},"h4",[51,1053,926],{"class":98},[51,1055,420],{"class":68},[51,1057,1058],{"class":75},"\"text-h4 bold\"",[51,1060,1061],{"class":68},">خطأ {{ error.statusCode }}\u003C\u002F",[51,1063,1051],{"class":893},[51,1065,897],{"class":68},[51,1067,1068],{"class":53,"line":217},[51,1069,79],{"class":68},[51,1071,1072,1074,1076,1078,1080,1083],{"class":53,"line":226},[51,1073,1048],{"class":68},[51,1075,11],{"class":893},[51,1077,926],{"class":98},[51,1079,420],{"class":68},[51,1081,1082],{"class":75},"\"mt-4 text-body-1\"",[51,1084,897],{"class":68},[51,1086,1087,1090,1092,1095,1097],{"class":53,"line":232},[51,1088,1089],{"class":68},"                    \u003C",[51,1091,51],{"class":893},[51,1093,1094],{"class":68},"> {{ message }}\u003C\u002F",[51,1096,51],{"class":893},[51,1098,897],{"class":68},[51,1100,1101,1104,1106],{"class":53,"line":238},[51,1102,1103],{"class":68},"                  \u003C\u002F",[51,1105,11],{"class":893},[51,1107,897],{"class":68},[51,1109,1110,1113,1115],{"class":53,"line":244},[51,1111,1112],{"class":68},"                \u003C\u002F",[51,1114,941],{"class":893},[51,1116,897],{"class":68},[51,1118,1119,1122,1124],{"class":53,"line":250},[51,1120,1121],{"class":68},"              \u003C\u002F",[51,1123,923],{"class":893},[51,1125,897],{"class":68},[51,1127,1128,1131,1133],{"class":53,"line":255},[51,1129,1130],{"class":68},"            \u003C\u002F",[51,1132,905],{"class":893},[51,1134,897],{"class":68},[51,1136,1137,1140,1142],{"class":53,"line":263},[51,1138,1139],{"class":68},"          \u003C\u002F",[51,1141,994],{"class":893},[51,1143,897],{"class":68},[51,1145,1146,1149,1151],{"class":53,"line":269},[51,1147,1148],{"class":68},"        \u003C\u002F",[51,1150,974],{"class":893},[51,1152,897],{"class":68},[51,1154,1155],{"class":53,"line":275},[51,1156,79],{"class":68},[51,1158,1159,1161,1163,1165,1167,1170],{"class":53,"line":280},[51,1160,971],{"class":68},[51,1162,923],{"class":893},[51,1164,926],{"class":98},[51,1166,420],{"class":68},[51,1168,1169],{"class":75},"\"mt-4\"",[51,1171,897],{"class":68},[51,1173,1174,1176,1178,1180,1182,1184,1186,1188,1191],{"class":53,"line":286},[51,1175,991],{"class":68},[51,1177,941],{"class":893},[51,1179,944],{"class":98},[51,1181,420],{"class":68},[51,1183,949],{"class":75},[51,1185,926],{"class":98},[51,1187,420],{"class":68},[51,1189,1190],{"class":75},"\"d-flex justify-center\"",[51,1192,897],{"class":68},[51,1194,1196,1198,1201,1204,1206,1209,1211,1213,1216,1219,1221,1224,1227,1229],{"class":53,"line":1195},24,[51,1197,1001],{"class":68},[51,1199,1200],{"class":893},"v-btn",[51,1202,1203],{"class":98}," variant",[51,1205,420],{"class":68},[51,1207,1208],{"class":75},"\"plain\"",[51,1210,926],{"class":98},[51,1212,420],{"class":68},[51,1214,1215],{"class":75},"\"\"",[51,1217,1218],{"class":98}," @click",[51,1220,420],{"class":68},[51,1222,1223],{"class":75},"\"redirectToHome\"",[51,1225,1226],{"class":68},"> الذهاب للصفحة الرئيسية\u003C\u002F",[51,1228,1200],{"class":893},[51,1230,897],{"class":68},[51,1232,1234,1236,1238],{"class":53,"line":1233},25,[51,1235,1139],{"class":68},[51,1237,941],{"class":893},[51,1239,897],{"class":68},[51,1241,1243,1245,1247],{"class":53,"line":1242},26,[51,1244,1148],{"class":68},[51,1246,923],{"class":893},[51,1248,897],{"class":68},[51,1250,1252,1255,1257],{"class":53,"line":1251},27,[51,1253,1254],{"class":68},"      \u003C\u002F",[51,1256,941],{"class":893},[51,1258,897],{"class":68},[51,1260,1262,1265,1267],{"class":53,"line":1261},28,[51,1263,1264],{"class":68},"    \u003C\u002F",[51,1266,923],{"class":893},[51,1268,897],{"class":68},[51,1270,1272,1275,1277],{"class":53,"line":1271},29,[51,1273,1274],{"class":68},"  \u003C\u002F",[51,1276,905],{"class":893},[51,1278,897],{"class":68},[51,1280,1282,1285,1287],{"class":53,"line":1281},30,[51,1283,1284],{"class":68},"\u003C\u002F",[51,1286,894],{"class":893},[51,1288,897],{"class":68},[51,1290,1292],{"class":53,"line":1291},31,[51,1293,79],{"class":68},[51,1295,1297,1299,1302,1305,1308,1310,1313],{"class":53,"line":1296},32,[51,1298,339],{"class":68},[51,1300,1301],{"class":893},"script",[51,1303,1304],{"class":98}," setup",[51,1306,1307],{"class":98}," lang",[51,1309,420],{"class":68},[51,1311,1312],{"class":75},"\"ts\"",[51,1314,897],{"class":68},[51,1316,1318,1320,1322,1325,1328,1330,1332],{"class":53,"line":1317},33,[51,1319,65],{"class":64},[51,1321,589],{"class":68},[51,1323,1324],{"class":64},"type",[51,1326,1327],{"class":68}," NuxtError, reloadNuxtApp } ",[51,1329,72],{"class":64},[51,1331,76],{"class":75},[51,1333,79],{"class":68},[51,1335,1337],{"class":53,"line":1336},34,[51,1338,79],{"class":68},[51,1340,1342,1344,1346,1348,1350,1352,1355],{"class":53,"line":1341},35,[51,1343,586],{"class":64},[51,1345,589],{"class":68},[51,1347,867],{"class":121},[51,1349,601],{"class":68},[51,1351,420],{"class":64},[51,1353,1354],{"class":98}," defineProps",[51,1356,1357],{"class":68},"\u003C{  \n",[51,1359,1361,1364,1366,1369],{"class":53,"line":1360},36,[51,1362,1363],{"class":105},"  error",[51,1365,358],{"class":64},[51,1367,1368],{"class":98}," NuxtError",[51,1370,79],{"class":68},[51,1372,1374],{"class":53,"line":1373},37,[51,1375,1376],{"class":68},"}>()  \n",[51,1378,1380],{"class":53,"line":1379},38,[51,1381,79],{"class":68},[51,1383,1385,1387,1390,1392,1395,1397,1400,1402,1405,1407,1409],{"class":53,"line":1384},39,[51,1386,586],{"class":64},[51,1388,1389],{"class":121}," errorMessages",[51,1391,358],{"class":64},[51,1393,1394],{"class":98}," Record",[51,1396,339],{"class":68},[51,1398,1399],{"class":121},"number",[51,1401,595],{"class":68},[51,1403,1404],{"class":121},"string",[51,1406,375],{"class":68},[51,1408,420],{"class":64},[51,1410,112],{"class":68},[51,1412,1414,1417,1420,1423],{"class":53,"line":1413},40,[51,1415,1416],{"class":121},"  400",[51,1418,1419],{"class":68},": ",[51,1421,1422],{"class":75},"'الطلب غير صالح'",[51,1424,167],{"class":68},[51,1426,1428,1431,1433,1436],{"class":53,"line":1427},41,[51,1429,1430],{"class":121},"  401",[51,1432,1419],{"class":68},[51,1434,1435],{"class":75},"'يجب تسجيل الدخول للوصول إلى هذه الصفحة'",[51,1437,167],{"class":68},[51,1439,1441,1444,1446,1449],{"class":53,"line":1440},42,[51,1442,1443],{"class":121},"  403",[51,1445,1419],{"class":68},[51,1447,1448],{"class":75},"'ليس لديك صلاحية للوصول إلى هذه الصفحة'",[51,1450,167],{"class":68},[51,1452,1454,1457,1459,1462],{"class":53,"line":1453},43,[51,1455,1456],{"class":121},"  404",[51,1458,1419],{"class":68},[51,1460,1461],{"class":75},"'الصفحة غير موجودة'",[51,1463,167],{"class":68},[51,1465,1467,1470,1472,1475],{"class":53,"line":1466},44,[51,1468,1469],{"class":121},"  500",[51,1471,1419],{"class":68},[51,1473,1474],{"class":75},"'حدث خطأ في الخادم، يرجى المحاولة لاحقًا'",[51,1476,167],{"class":68},[51,1478,1480,1483,1485,1488],{"class":53,"line":1479},45,[51,1481,1482],{"class":121},"  502",[51,1484,1419],{"class":68},[51,1486,1487],{"class":75},"'الخادم لا يستجيب حاليًا'",[51,1489,167],{"class":68},[51,1491,1493,1496,1498,1501],{"class":53,"line":1492},46,[51,1494,1495],{"class":121},"  503",[51,1497,1419],{"class":68},[51,1499,1500],{"class":75},"'الخدمة غير متوفرة مؤقتًا'",[51,1502,167],{"class":68},[51,1504,1506],{"class":53,"line":1505},47,[51,1507,1508],{"class":68},"}  \n",[51,1510,1512],{"class":53,"line":1511},48,[51,1513,79],{"class":68},[51,1515,1517,1519,1522,1524,1527,1530,1533],{"class":53,"line":1516},49,[51,1518,586],{"class":64},[51,1520,1521],{"class":121}," message",[51,1523,125],{"class":64},[51,1525,1526],{"class":68}," errorMessages[error.statusCode] ",[51,1528,1529],{"class":64},"||",[51,1531,1532],{"class":75}," 'حدث خطأ غير متوقع، يرجى المحاولة لاحقًا'",[51,1534,79],{"class":68},[51,1536,1538],{"class":53,"line":1537},50,[51,1539,79],{"class":68},[51,1541,1543,1545,1548,1550,1552,1554,1556],{"class":53,"line":1542},51,[51,1544,586],{"class":64},[51,1546,1547],{"class":98}," redirectToHome",[51,1549,125],{"class":64},[51,1551,660],{"class":64},[51,1553,663],{"class":68},[51,1555,212],{"class":64},[51,1557,112],{"class":68},[51,1559,1561,1564,1567,1570,1572,1574,1576],{"class":53,"line":1560},52,[51,1562,1563],{"class":64},"  await",[51,1565,1566],{"class":98}," useRouter",[51,1568,1569],{"class":68},"().",[51,1571,773],{"class":98},[51,1573,102],{"class":68},[51,1575,778],{"class":75},[51,1577,648],{"class":68},[51,1579,1581,1584],{"class":53,"line":1580},53,[51,1582,1583],{"class":98},"  reloadNuxtApp",[51,1585,131],{"class":68},[51,1587,1589],{"class":53,"line":1588},54,[51,1590,1508],{"class":68},[51,1592,1594,1596,1598],{"class":53,"line":1593},55,[51,1595,1284],{"class":68},[51,1597,1301],{"class":893},[51,1599,1600],{"class":68},">\n",[11,1602,1603,1604,1606],{},"الكود السابق يمثل تصميمًا مخصصًا لصفحة الخطأ ",[48,1605,852],{}," في تطبيق Nuxt مع استخدام Vuetify لتنسيق الواجهة.",[11,1608,1609],{},"عند حدوث خطأ في التطبيق (مثل صفحة غير موجودة أو خطأ في الخادم)، يتم عرض هذه الصفحة للمستخدم بدلاً من الصفحة الافتراضية.",[11,1611,1612],{},"في الجزء العلوي من الصفحة، يتم عرض رقم الخطأ (مثل 404 أو 500) بشكل واضح، وأسفله رسالة مناسبة حسب نوع الخطأ.",[11,1614,1615],{},"تم إعداد مجموعة من الرسائل المخصصة وفقًا لأكثر رموز الأخطاء شيوعًا، مثل \"الصفحة غير موجودة\" أو \"الخدمة غير متوفرة\"، ويتم اختيار الرسالة المناسبة تلقائيًا بناءً على رمز الخطأ.",[11,1617,1618],{},"أسفل الرسالة، يوجد زر يتيح للمستخدم العودة إلى الصفحة الرئيسية، وعند الضغط عليه، يتم نقله إلى الصفحة الرئيسية ويتم تحديث التطبيق (reload) لضمان استعادة الحالة الطبيعية.",[11,1620,1621],{},"الهدف من هذا الكود هو تحسين تجربة المستخدم عند حدوث مشكلة، من خلال عرض رسالة مفهومة وتصميم متناسق مع شكل التطبيق، بدلًا من صفحة خطأ تقليدية أو مفاجئة.",[11,1623,830,1624],{},[832,1625,840],{"href":1626,"rel":1627,"target":839},"https:\u002F\u002Fnuxt.com\u002Fdocs\u002F4.x\u002Fguide\u002Fdirectory-structure\u002Fapp\u002Ferror",[836,837,838],[24,1629,1631],{"id":1630},"نصائح-إضافية",[28,1632,1633],{},"نصائح إضافية",[11,1635,1636],{},"فيما يلي مجموعة من النصائح المتقدمة التي تُمكنك من التعامل مع الأخطاء بأسلوب احترافي، مع تقديم تجربة استخدام أكثر استقرارًا وموثوقية.",[11,1638,1639],{},[28,1640,1641],{},"1- لا تُظهر التفاصيل التقنية للمستخدم",[11,1643,1644],{},"المستخدم لا يهتم برسائل الخطأ المعقدة، بل قد تسبب له القلق أو التشتت.",[11,1646,1647],{},"لذلك، من الأفضل إخفاء التفاصيل البرمجية والرسائل التي تتضمن مسارات الملفات أو أخطاء الخادم، وعرض رسالة مفهومة ومختصرة بدلاً منها، فهذا يرفع مستوى الثقة بالتطبيق ويمنح تجربة استخدام أكثر راحة.",[11,1649,1650],{},[28,1651,1652],{},"2- اجعل الرسالة بسيطة ومفهومة",[11,1654,1655],{},"عند حدوث خطأ، لا تترك المستخدم في حيرة.",[11,1657,1658],{},"قدّم رسالة توضح ما حدث بشكل بسيط، مثل: \"حدث خلل مؤقت، يرجى المحاولة لاحقًا.\"",[11,1660,1661],{},"أما التفاصيل الدقيقة، فاحتفظ بها في سجلات المطورين أو أدوات التتبع، لضمان حل المشكلة دون إزعاج المستخدم.",[11,1663,1664],{},[28,1665,1666],{},"3- سجّل الأخطاء بذكاء",[11,1668,1669],{},"لا تكتف بإخفاء الخطأ، بل احرص على تسجيله لتتمكن من تتبعه لاحقًا، هذا الأمر يساعدك على تحسين التطبيق باستمرار وتفادي تكرار المشاكل.",[11,1671,1672],{},[28,1673,1674],{},"4- فكر في واجهة بديلة عند الخطأ",[11,1676,1677],{},"في بعض الحالات، من الأفضل إظهار \"واجهة بديلة\" (Fallback UI) بدلاً من تعطيل الصفحة بالكامل.",[11,1679,1680],{},"مثلًا، إذا تعذّر تحميل المحتوى من الخادم، يمكنك عرض رسالة توضح أن الاتصال فُقد، مع زر لإعادة المحاولة.",[11,1682,1683],{},"هذا يمنح المستخدم شعورًا بالتحكم ويُبقيه داخل التجربة.",[11,1685,1686],{},[28,1687,1688],{},"5- استخدم try\u002Fcatch",[11,1690,1691],{},"عند التعامل مع خدمات خارجية أو عمليات غير مضمونة (مثل استدعاء API أو قراءة بيانات ديناميكية)، استخدم try\u002Fcatch لضبط الأخطاء ومنع توقف التطبيق بشكل مفاجئ.",[11,1693,1694],{},"هذا يتيح لك عرض رسائل مناسبة، وتحسين استقرار التطبيق خاصة في البيئات الحقيقية.",[11,1696,1697],{},[28,1698,1699],{},"6- اختبر سيناريوهات الخطأ قبل الإطلاق",[11,1701,1702],{},"لا تنتظر أن يكتشف المستخدمون الأخطاء أولًا.",[11,1704,1705],{},"جرّب بنفسك ماذا سيحدث عند فقد الاتصال، أو إدخال بيانات غير صحيحة، أو الوصول إلى صفحة غير موجودة.",[11,1707,1708],{},"هذه الاختبارات تساعدك على تحسين الردود وتقديم تجربة أكثر احترافية حتى في ظروف الفشل.",[24,1710,1712],{"id":1711},"خاتمة",[28,1713,1711],{},[11,1715,1716],{},"إن التعامل مع الأخطاء ليس مجرد كود إضافي، بل هو استثمار مباشر في راحة المستخدم وثقة الفريق بالتطبيق.",[11,1718,1719],{},"باستخدام إمكانيات Nuxt المتقدمة، يمكنك تصميم تجربة متماسكة حتى في أسوأ الظروف.",[11,1721,1722],{},"وتذكر دائمًا أن التطبيق الجيد لا يعني خلوه من الأخطاء، بل حسن تعامله معها.",[11,1724,1725],{},"فاستثمر وقتك في بناء تجربة متوازنة بين الأداء والوضوح.",[11,1727,1728],{},"وفقنى الله وإياك إلى ما يحبه ويرضاه ،،",[1730,1731,1732],"style",{},"html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s4JwU, html code.shiki .s4JwU{--shiki-default:#85E89D}",{"title":46,"searchDepth":61,"depth":82,"links":1734},[1735,1736,1737,1738],{"id":26,"depth":61,"text":30},{"id":843,"depth":61,"text":846},{"id":1630,"depth":61,"text":1633},{"id":1711,"depth":61,"text":1711},"\u002Fimages\u002F68877398c00f22daabc287f8.webp","\u002Fimages\u002F68877398c00f22daabc287f8_thumb.webp","2025-07-28T12:53:35.598Z","2025-07-28T13:00:26.799Z","دليل عملي مبسط لطرق معالجة الأخطاء في تطبيقات Nuxt، يساعدك على تحسين استقرار التطبيق وتقديم تجربة أكثر احترافية وراحة للمستخدم.","md",{},"\u002Farticles\u002F688772cfc00f22daabc287ea",{"title":5,"description":1743},"articles\u002F688772cfc00f22daabc287ea",[1750],{"id":1751,"label":1752},"65ae26381d50740dab36fdb7","اطار Nuxt","2025-07-28T13:01:19.346Z","nygfPYv7FCrSgIaCo69PJac6vCtPu22i9XH4Xx6GscA",1788209571918]