
مكون رد فعل لتحرير أو عرض بيانات JSON/كائن

مهم
تغيير التغييرات:
theme . يجب الآن استيراد المواضيع المدمجة بشكل منفصل وتمريرها ، بدلاً من مجرد تسمية الموضوع كسلسلة. هذا أفضل لتهز الأشجار ، لذلك لن يتم تجميع الموضوعات غير المستخدمة مع بنيتك. انظر الموضوعات والأنماطsetData وعدم استخدام onUpdate لتحديث بياناتك خارجيًا. انظر إدارة الدولة. npm i json-edit-react
أو
yarn add json-edit-react
import { JsonEditor } from 'json-edit-react'
// In your React component:
return
< JsonEditor
data = { jsonData }
setData = { setJsonData } // optional
{ ... otherProps } /> (للمستخدم النهائي)
إنها توضيحية ذاتية إلى حد ما (انقر فوق أيقونة "تحرير" لتحريرها ، إلخ) ، ولكن هناك بعض الطرق غير الواضحة للتفاعل مع المحرر:
Cmd/Ctrl/Shift-Enter لإضافة سطر جديد ( Enter يقدم القيمة)Enter لخط جديد ، و Cmd/Ctrl/Shift-EnterEscape لإلغاء التحريرCmd/Ctrl سيؤدي إلى نسخ المسار إلى العقدة المحددة بدلاً من قيمتهاjsonParse Prop. القيمة المطلوبة الوحيدة هي data (على الرغم من أنك ستحتاج إلى توفير طريقة setData لتحديث بياناتك).
| دعم | يكتب | تقصير | وصف |
|---|---|---|---|
data | object|array | البيانات المراد عرضها / تحريرها | |
setData | object|array => void | طريقة لتحديث كائن data الخاص بك. انظر إدارة الحالة أدناه للحصول على ملاحظات إضافية. | |
rootName | string | "data" | اسم لعرضه في المحرر كجذر لكائن البيانات. |
onUpdate | UpdateFunction | وظيفة لتشغيلها كلما تم تحديث قيمة (تحرير أو حذف أو إضافة) في المحرر. انظر وظائف التحديث. | |
onEdit | UpdateFunction | وظيفة لتشغيل كلما تم تحرير القيمة. | |
onDelete | UpdateFunction | وظيفة لتشغيلها كلما تم حذف القيمة. | |
onAdd | UpdateFunction | وظيفة لتشغيل كلما تمت إضافة خاصية جديدة. | |
onChange | OnChangeFunction | وظيفة لتعديل/تقييد إدخال المستخدم أثناء الكتابة - انظر وظائف OnChange. | |
onError | OnErrorFunction | وظيفة لتشغيلها كلما أبلغ المكون عن خطأ - انظر Onerrorfunction. | |
showErrorMessages | boolean | true | ما إذا كان يجب على المكون عرض رسائل الخطأ الخاصة به أم لا (ربما ترغب فقط في تعطيل ذلك إذا قدمت وظيفة onError الخاصة بك) |
enableClipboard | boolean|CopyFunction | true | سواء أكان لتمكين زر "النسخ إلى الحافظة" في واجهة المستخدم أم لا. إذا تم توفير وظيفة ، يتم افتراض true وسيتم تشغيل هذه الوظيفة كلما تم نسخ عنصر. |
indent | number | 3 | حدد مقدار المسافة البادئة لكل مستوى من مستوى التعشيش في البيانات المعروضة. |
collapse | boolean|number|FilterFunction | false | تحدد العقد التي سيتم عرض العقد في شجرة JSON "مفتوحة" في واجهة المستخدم عند الحمل. إذا كان boolean ، فسيكون إما كل شيء أو لا شيء. يحدد number عمق التعشيش بعد إغلاق العقد. لمزيد من التحكم الدقيق ، يمكن توفير وظيفة - انظر وظائف المرشح. |
collapseAnimationTime | number | 300 | الوقت (بالميلي ثانية) للرسوم المتحركة الانتقالية عند انهيار العقد التجميع. |
restrictEdit | boolean|FilterFunction | false | إذا كان true ، فلا يُسمح بالتحرير. يمكن توفير وظيفة لمزيد من الخصوصية - انظر وظائف المرشح |
restrictDelete | boolean|FilterFunction | false | كما هو الحال مع restrictEdit ولكن للحذف |
restrictAdd | boolean|FilterFunction | false | كما هو الحال مع restrictEdit ولكن لإضافة خصائص جديدة |
restrictTypeSelection | boolean|DataType[]|TypeFilterFunction | true | لتقييد أنواع البيانات التي يمكن للمستخدم تحديدها. يمكن أن تكون قائمة بأنواع البيانات (على سبيل المثال [ 'string', 'number', 'boolean', 'array', 'object', 'null' ] ) أو منطقية. يمكن توفير وظيفة - يجب أن تأخذ نفس المدخلات مثل FilterFunction S ، ولكن يجب أن يكون الإخراج boolean | DataType[] . |
restrictDrag | boolean|FilterFunction | true | ضبط على false لتمكين وظائف السحب والإفلات. انظر Drag-N-Drop |
searchText | string | undefined | سيتم ترشيح رؤية البيانات عن طريق المطابقة مقابل القيمة ، باستخدام الطريقة المحددة أدناه في searchFilter |
searchFilter | "key"|"value"|"all"|SearchFilterFunction | undefined | حدد كيفية مطابقة searchText لتصفية العناصر المرئية. انظر البحث/التصفية |
searchDebounceTime | number | 350 | Debounce الوقت عند تغيير searchText |
keySort | boolean|CompareFunction | false | إذا كان true ، فسيتم طلب مفاتيح الكائن (باستخدام JS .sort() الافتراضي). يمكن أيضًا توفير وظيفة المقارنة لتحديد سلوك الفرز. |
showArrayIndices | boolean | true | سواء كنت لعرض الفهرس (كمفتاح خاصية) لعناصر الصفيف أم لا. |
showStringQuotes | boolean | true | سواء كنت لعرض قيم السلسلة أم لا في "عروض الأسعار". |
showCollectionCount | boolean|"when-closed" | true | سواء كان ذلك لعرض عدد العناصر في كل مجموعة (كائن أو صفيف). |
defaultValue | any|DefaultValueFilterFunction | null | عند إضافة خاصية جديدة ، يتم تهيئة هذه القيمة. يمكن توفير وظيفة مع نفس المدخلات تقريبًا مثل FilterFunction S ، ولكن يجب إخراج قيمة. هذا يسمح باستخدام قيمة افتراضية مختلفة اعتمادًا على حالة البيانات (على سبيل المثال الافتراضي للمستوى العلوي هو كائن ، ولكن سلسلة أخرى.) |
stringTruncate | number | 250 | سيتم عرض قيم السلسلة أطول من هذه الأحرف التي سيتم عرضها للاقتطاف (مع ... ). ستكون السلسلة الكاملة دائمًا مرئية عند التحرير. |
translations | كائن LocalisedStrings | { } | يمكن ترجمة سلاسل واجهة المستخدم (مثل رسائل الخطأ) عن طريق تمرير كائن يحتوي على قيم سلسلة محلية (لا يوجد سوى عدد قليل). انظر التوطين |
theme | ThemeInput | default | إما واحدة من السمات المدمجة (التي تم استيرادها بشكل منفصل) ، أو كائن يحدد بعض خصائص السمة أو جميعها. انظر الموضوعات. |
className | string | اسم فئة CSS لتطبيق على المكون. في معظم الحالات ، سيكون تحديد خصائص theme أكثر وضوحًا. | |
id | string | اسم سمة id HTML على حاوية المكون الرئيسية. | |
icons | {[iconName]: JSX.Element, ... } | { } | استبدل الرموز المدمجة من خلال تحديدها هنا. انظر الموضوعات. |
minWidth | number|string (قيمة CSS) | 250 | الحد الأدنى عرض لحاوية المحرر. |
maxWidth | number|string (قيمة CSS) | 600 | أقصى عرض لحاوية المحرر. |
rootFontSize | number|string (قيمة CSS) | 16px | حجم الخط "الأساسي" الذي يتم استخلاص جميع الأزواج الأخرى (في em S). عن طريق تغيير هذا ، سوف تقوم بتوسيع نطاق المكون بأكمله. حاوية. |
customNodeDefinitions | CustomNodeDefinition[] | يمكنك توفير مكونات مخصصة لتجاوز العقد المحددة في شجرة البيانات ، وفقًا لوظيفة الشرط. انظر انظر العقد المخصصة لمزيد من التفاصيل. (يتم توفير مكون بسيط مخصص لتحويل سلاسل URL إلى روابط نشطة في الحزمة الرئيسية - انظر هنا) | |
customText | CustomTextDefinitions | بالإضافة إلى توضع سلاسل النص المكون ، يمكنك أيضًا تغييره ديناميكيًا ، اعتمادًا على البيانات. انظر نص مخصص لمزيد من التفاصيل. | |
customButtons | CustomButtonDefinition[] | [] | يمكنك إضافة الأزرار الخاصة بك إلى لوحة أزرار التحرير إذا كنت ترغب في إجراء عملية مخصصة على البيانات. انظر الأزرار المخصصة |
jsonParse | (input: string) => JsonData | JSON.parse | عند تحرير كتلة من JSON مباشرة ، قد ترغب في السماح لبعض المدخلات "الخاطئة" - على سبيل المثال "اقتباسات واحدة" ، أو فواصل زائدة ، أو أسماء الحقول غير المخصصة. في هذه الحالة ، يمكنك توفير طريقة تحليل JSON من طرف ثالث. أوصي JSON5 ، وهو ما يستخدم في العرض التوضيحي |
jsonStringify | (data: JsonData) => string | (data) => JSON.stringify(data, null, 2) | وبالمثل ، يمكنك تجاوز العرض الافتراضي لسلسلة JSON عند بدء تحرير JSON. يمكنك توفير معلمات تنسيق مختلفة إلى JSON.stringify() الأصلي ، أو توفير خيار طرف ثالث ، مثل JSON5 المذكورة أعلاه. |
errorMessageTimeout | number | 2500 | الوقت (بالمللي ثانية) لعرض رسالة الخطأ في واجهة المستخدم. |
keyboardControls | KeyboardControls | كما هو موضح أعلاه | تجاوز بعض أو كل عناصر التحكم في لوحة المفاتيح. انظر تخصيص لوحة المفاتيح للحصول على التفاصيل. |
insertAtTop | boolean| "object | "array" | false | إذا كان true ، فإدراج قيمًا جديدة في الأعلى بدلاً من القاع. يمكن تعيين السلوك فقط للمصفوفات أو الكائنات عن طريق الإعداد على "object" أو "array" على التوالي. |
يوصى بإدارة حالة data بنفسك خارج هذا المكون - فقط تمرير في طريقة setData ، والتي تسمى داخليًا لتحديث data . ومع ذلك ، هذا ليس إلزاميًا - إذا لم تقدم طريقة setData ، فسيتم إدارة البيانات داخليًا ، وهذا سيكون جيدًا إذا لم تكن تفعل أي شيء مع البيانات. البديل هو استخدام وظائف التحديث لتحديث data خارجيًا ، ولكن لا ينصح بذلك إلا في الظروف الخاصة حيث يمكنك مواجهة مشكلات في الحفاظ على بياناتك متزامنة مع الحالة الداخلية (وهو ما يتم عرضه) ، بالإضافة إلى إعادة توريد غير ضرورية. يجب استخدام وظائف التحديث بشكل مثالي فقط لتنفيذ الآثار الجانبية ، والتحقق من الأخطاء ، أو تحوير البيانات قبل إعدادها باستخدام setData .
يمكن تنفيذ رد الاتصال عند حدوث تحديث للبيانات (تحرير أو حذف أو إضافة). قد ترغب في استخدام هذا لتحديث بعض الحالة الخارجية ، أو إجراء مكالمة API ، أو تعديل البيانات قبل حفظها ، أو التحقق من صحة بنية البيانات مقابل مخطط JSON. إذا كنت تريد نفس الوظيفة لجميع التحديثات ، فسيكون مجرد دعامة onUpdate كافية. ومع ذلك ، إذا كنت بحاجة إلى شيء مختلف للتحرير والحذف والإضافة ، فيمكنك توفير وظائف تحديث منفصلة عبر الدعائم onEdit و onDelete و onAdd .
ستتلقى الوظيفة الكائن التالي كمعلمة:
{
newData , // data state after update
currentData , // data state before update
newValue , // the new value of the property being updated
currentValue , // the current value of the property being updated
name , // name of the property being updated
path // full path to the property being updated, as an array of property keys
// (e.g. [ "user", "friends", 1, "name" ] ) (equivalent to "user.friends[1].name")
}لا يمكن للوظيفة إرجاع أي شيء (في هذه الحالة يتم تحديث البيانات بشكل طبيعي) ، أو قيمة لتمثيل النجاح/الفشل أو قيمة الخطأ أو البيانات المعدلة. يمكن أن تكون قيمة الإرجاع واحدة مما يلي ، ويتم التعامل معها وفقًا لذلك:
true / void / undefined : تستمر البيانات في التحديث كالمعتادfalse : يعتبر التحديث خطأ ، لذلك لا يتم تحديث البيانات (تعود إلى القيمة السابقة) ، ويتم عرض رسالة خطأ عام في واجهة المستخدمstring : تعتبر أيضًا خطأً ، لذلك لا يوجد تحديث للبيانات ، ولكن رسالة خطأ واجهة المستخدم ستكون السلسلة المقدمة[ "value", <value> ] <value> يمكنك استخدام هذا لتعديل إدخال المستخدم تلقائيًا - على سبيل المثال ، فرز صفيف ، أو إدخال حقل الطابع الزمني في كائن.[ "error", <value> ] : نفس string ، ولكن بتنسيق tuple الأطول. على غرار وظائف التحديث ، يتم تنفيذ وظيفة onChange مع تغير إدخال المستخدم. يمكنك استخدام هذا لتقييد أو تقييد إدخال المستخدم - مثل الحد من الأرقام على القيم الإيجابية ، أو منع فترات انقطاع الخط في السلاسل. يجب أن تقوم الوظيفة بإرجاع قيمة من أجل تحديث حقل إدخال المستخدم ، لذلك إذا لم يتم إجراء أي تغييرات ، فما عليك سوى إرجاعها غير المعدلة.
يشبه كائن الإدخال إدخال وظيفة التحديث ، ولكن مع عدم وجود حقل newData (نظرًا لأن هذه العملية تحدث قبل تحديث البيانات).
// in <JsonEditor /> props
onChange = ( { newValue , name } ) => {
if ( name === "age" && newValue < 0 ) return 0 ;
if ( name === "age" && newValue > 100 ) return 100 ;
return newValue
} onChange = ( { newValue , name } ) => {
if ( name === 'name' && typeof newValue === "string" )
return newValue . replace ( / [^a-zA-Zs]|n|r / gm , '' ) ;
return newValue ;
} عادةً ما يعرض المكون رسائل خطأ بسيطة عندما يتم اكتشاف حالة خطأ (مثل إدخال JSON غير صالح أو مفاتيح مكررة أو أخطاء مخصصة يتم إرجاعها بواسطة وظائف onUpdate )). ومع ذلك ، يمكنك توفير رد اتصال onError الخاص بك من أجل تنفيذ واجهة المستخدم الخاصة بك ، أو تشغيل آثار جانبية إضافية. (في الحالة السابقة ، ربما ترغب في تعطيل showErrorMessages الدش ، أيضًا)
{
currentData , // data state before update
currentValue , // the current value of the property being updated
errorValue , // the erroneous value that failed to update the property
name , // name of the property being updated
path , // full path to the property being updated, as an array of property keys
// (e.g. [ "user", "friends", 1, "name" ] ) (equivalent to "user.friends[1].name"),
error : {
code , // one of 'UPDATE_ERROR' | 'DELETE_ERROR' | 'ADD_ERROR' | 'INVALID_JSON' | 'KEY_EXISTS'
message // the (localised) error message that would be displayed
}
}(يمكن رؤية مثال على خطب خطأ مخصص في العرض التوضيحي مع مجموعة بيانات "العقد المخصصة" - عند إدخال إدخال JSON غير صالح ، يتم عرض إشعار "Toast" بدلاً من رسالة خطأ المكون العادي.)
يتم تنفيذ رد اتصال مماثل كلما تم نسخ عنصر إلى الحافظة (إذا تم تمريرها إلى Propboard enableClipboard ) ، ولكن مع معلمة إدخال مختلفة:
key // name of the property being copied
path // path to the property
value // the value copied to the clipboard
type // Either "path" or "value" depending on whether "Cmd/Ctrl" was pressed
stringValue // A nicely stringified version of `value`
// (i.e. what the clipboard actually receives)نظرًا لوجود القليل جدًا من ملاحظات المستخدم عند النقر فوق "نسخ" ، فإن الفكرة الجيدة هي تقديم نوع من الإخطار في هذا رد الاتصال.
بالإضافة إلى الأزرار "النسخ" و "التحرير" و "الحذف" التي تظهر حسب كل قيمة ، يمكنك إضافة الأزرار الخاصة بك إذا كنت بحاجة إلى السماح ببعض العمليات المخصصة على البيانات. قم بتوفير مجموعة من تعريفات الأزرار في Proptons customButtons ، في بنية التعريف التالية:
{
Element : React . FC ,
onClick : ( nodeData : NodeData , e : React . MouseEvent ) => void
} عندما تكون NodeData هي نفس بنية البيانات التي تتلقاها "وظائف التحديث" السابقة.
يمكنك التحكم في العقد في بنية البيانات التي يمكن تحريرها أو حذفها أو إضافتها إلى نوع البيانات أو تغييرها ، عن طريق تمرير وظائف المرشح. سيتم استدعاء هذه الخاصية في كل خاصية في البيانات وسيتم تنفيذ السمة اعتمادًا على ما إذا كانت الوظيفة تُرجع true أو false ( لا يمكن تحرير الوسائل true ).
تستقبل الوظيفة الكائن التالي:
{
key , // name of the property
path , // path to the property (as an array of property keys)
level , // depth of the property (with 0 being the root)
index , // index of the node within its collection (based on display order)
value , // value of the property
size , // if a collection (object, array), the number of items (null for non-collections)
parentData , // parent object containing the current node
fullData // the full (overall) data object
collapsed // whether or not the current node is in a
// "collapsed" state (only for Collection nodes)
} تتوفر وظيفة المرشح للدعوة collapse أيضًا ، بحيث يمكنك ظهور بياناتك مع فتح مجموعات متداخلة بعمق ، مع انهيار كل شيء آخر ، على سبيل المثال.
لتقييد أنواع البيانات ، تكون وظيفة تصفية (النوع) أكثر تطوراً قليلاً. المدخلات هي نفسها ، ولكن يمكن أن يكون الإخراج إما boolean (والتي من شأنها تقييد الأنواع المتاحة للعقدة المحددة إما إلى كل أو لا شيء ) ، أو مجموعة من أنواع البيانات المراد تقييدها. القيم المتاحة هي:
"string""number""boolean""null""object""array" لا توجد وظيفة قيود محددة لتحرير أسماء مفاتيح الكائن ، ولكن يجب أن تعود true لكل من restrictEdit restrictDelete ( restrictAdd للمجموعات) ، لأن تغيير الاسم الرئيسي يعادل حذف خاصية وإضافة واحدة جديدة.
يمكنك أيضًا تعيين قيمة افتراضية ديناميكية عن طريق تمرير وظيفة مرشح إلى الدعامة defaultValue - الإدخال هو نفسه ما ورد أعلاه ، ولكنه يأخذ أيضًا القيمة key الجديدة مثل المعلمة الثانية ، وبالتالي يمكن أن تعتمد القيمة الجديدة على المفتاح الجديد المضافة.
يمكن أن يتيح لك استخدام كل مرشحات التقييد معًا تطبيق مخطط بيانات متطور بشكل معقول.
// in <JsonEditor /> props
restrictEdit = { ( { level } ) => level === 0 }id يتم تحريره: restrictEdit = { ( { key } ) => key === "id" }
// You'd probably want to include this in `restrictDelete` as well restrictDelete = { ( { size } ) => size !== null } restrictAdd = { ( { key } ) => key !== "address" && key !== "users" }
// "Adding" is irrelevant for non-collection nodesstring إلا إلى سلاسل أو كائنات (من أجل التعشيش)null في أي مكانboolean منطقية restrictTypeSelection = { ( { path , value } ) => {
if ( path . includes ( 'user' ) ) return [ 'string' , 'number' , 'boolean' ]
if ( typeof value === 'boolean' ) return false
if ( typeof value === 'string' ) return [ 'string' , 'object' ]
return [ 'string' , 'number' , 'boolean' , 'array' , 'object' ] // no "null"
} }بالإضافة إلى التحكم ديناميكيًا في الوصول إلى أدوات التحرير المختلفة كما هو موضح أعلاه ، من الممكن القيام بالتحقق من صحة مخطط JSON الكامل من خلال إنشاء وظيفة تحديث تقوم بتمرير البيانات إلى مكتبة التحقق من مخطط الطرف الثالث (مثل AJV). سيؤدي ذلك بعد ذلك إلى رفض أي إدخال غير صالح ، وعرض خطأ في واجهة المستخدم (أو عبر وظيفة onerror مخصصة). يمكنك رؤية مثال على ذلك في العرض التوضيحي مع مجموعة بيانات "التحقق من صحة مخطط JSON" (ومجموعة بيانات "العقد المخصصة").
يمكن أن تكون وظيفة التحقق من صحة onUpdate (باستخدام AJV) شيئًا من هذا القبيل:
import { JsonEditor } from 'json-edit-react'
import Ajv from 'ajv'
import schema from './my-json-schema.json'
const ajv = new Ajv ( )
const validate = ajv . compile ( schema )
/// Etc....
// In the React component:
return
< JsonEditor
data = { jsonData }
onUpdate = { ( { newData } ) => {
const valid = validate ( newData )
if ( ! valid ) {
console . log ( 'Errors' , validate . errors )
const errorMessage = validate . errors
?. map ( ( error ) => ` ${ error . instancePath } ${ error . instancePath ? ': ' : '' } ${ error . message } ` )
. join ( 'n' )
// Send detailed error message to an external UI element, such as a "Toast" notification
displayError ( {
title : 'Not compliant with JSON Schema' ,
description : errorMessage ,
status : 'error' ,
} )
// This string returned to and displayed in json-edit-react UI
return 'JSON Schema error'
}
} }
{ ... otherProps } />ملحوظة
هذه ميزة جديدة ويجب اعتبارها "تجريبية". يرجى تقديم ملاحظات أو اقتراحات للمساعدة في تحسينه.
يتحكم خاصية restrictDrag التي يمكن سحب العناصر (إن وجدت) إلى مواقع جديدة. افتراضيًا ، يتم إيقاف تشغيل هذا ، لذلك يجب تعيين restrictDrag = false لتمكين هذه الوظيفة. مثل قيود التحرير أعلاه ، يمكن أن تأخذ هذه الخاصية أيضًا وظيفة مرشح للتحكم الدقيق في الحبيبات. هناك بعض الاعتبارات الإضافية ، على الرغم من:
jsonb (Binary JSON) ، يكون الترتيب الرئيسي بلا معنى ، لذلك في المرة التالية التي يتم فيها تحميل الكائن ، سيتم سرد المفاتيح أبجديًا.restrictDrag على عنصر المصدر (أي العقدة التي يتم سحبها) ، وليس الوجهة.restrictDelete Prop) ، لأن سحب العقدة إلى وجهة جديدة هو مجرد حذفها وإضافتها إلى مكان آخر. يمكن تصفية البيانات المعروضة بناءً على إدخال البحث من مستخدم. يجب التقاط مدخلات المستخدم بشكل مستقل (لا نقدم واجهة مستخدم هنا) ونقدمها مع دعامة searchText . يتم إزالة هذا المدخلات داخليًا (يمكن تعيين الوقت مع searchDebounceTime Prop) ، لذلك لا حاجة لذلك أيضًا. يتم تحديد القيم التي يتم اختبارها مقابل searchText مع searchFilter Prop. افتراضيًا (لم يتم تعريف searchFilter ) ، سوف يتطابق مع قيم البيانات (مع المطابقة الجزئية غير الحساسة للحالة-أي إدخال "ILB" ، سوف يتطابق مع قيمة "Bilbo").
يمكنك تحديد ما يجب مطابقة عن طريق تعيين searchFilter إلى "key" (أسماء الممتلكات المتطابقة) أو "value" (الافتراضي الموضح أعلاه) أو "all" (تطابق كل من الخصائص والقيم). يجب أن يكون هذا كافيًا لمعظم حالات الاستخدام ، ولكن يمكنك تحديد SearchFilterFunction . وظيفة البحث هي نفس التوقيع مثل FilterFunctions أعلاه ولكنها تأخذ وسيطة إضافية واحدة searchText ، أي
( { key , path , level , value , ... etc } : FilterFunctionInput , searchText : string ) => boolean هناك وظيفتان مساعدتان ( matchNode() و matchNodeKey() ) تم تصديرهما بالحزمة التي قد تجعل إنشاء وظيفة البحث الخاصة بك أسهل (هذه هي الوظائف المستخدمة داخليًا لمطابقة "key" و "value" الموضحة أعلاه). يمكنك أن ترى ماذا يفعلون هنا.
يمكن رؤية مثال على وظيفة البحث المخصص في العرض التوضيحي مع مجموعة بيانات "قائمة العميل" - تتطابق وظيفة البحث بالاسم واسم المستخدم ، وجعل الكائن "العميل" بأكمله مرئيًا عند إحدى هذه المباريات ، بحيث يمكن استخدامها للعثور على شخص معين وتعديل تفاصيله المحددة:
( { path , fullData } , searchText ) => {
// Matches *any* node that shares a path (i.e. a descendent) with a matching name/username
if ( path ?. length >= 2 ) {
const index = path ?. [ 0 ]
return (
matchNode ( { value : fullData [ index ] . name } , searchText ) ||
matchNode ( { value : fullData [ index ] . username } , searchText )
)
} else return false
} هناك مجموعة صغيرة من الموضوعات المدمجة (كما هو موضح في التطبيق التجريبي). من أجل استخدام واحدة من هذه ، ما عليك سوى استيرادها من الحزمة وتمريرها كدعم موضوع:
import { JsonEditor , githubDarkTheme } from 'json-edit-react'
// ...other imports
const MyApp = ( ) => {
const [ data , setData ] = useState ( { one : 1 , two : 2 } )
return < JsonEditor
data = { data }
setData = { setData }
theme = { githubDarkTheme }
// other props...
/>
}تتوفر السمات التالية في الحزمة (على الرغم من أنها واقعيًا ، فهي موجودة أكثر لعرض القدرات-أنا منفتح على موضوعات مدمجة بشكل أفضل ، لذلك لا تتردد في إنشاء مشكلة مع الاقتراحات):
githubDarkThemegithubLightThememonoDarkThememonoLightThemecandyWrapperThemepsychedelicThemeومع ذلك ، يمكنك تمرير كائن السمة الخاص بك ، أو جزء منه. بنية السمة هي كما يلي (هذا هو تعريف السمة "الافتراضي"):
{
displayName : 'Default' ,
fragments : { edit : 'rgb(42, 161, 152)' } ,
styles : {
container : {
backgroundColor : '#f6f6f6' ,
fontFamily : 'monospace' ,
} ,
collection : { } ,
collectionInner : { } ,
collectionElement : { } ,
dropZone : { } ,
property : '#292929' ,
bracket : { color : 'rgb(0, 43, 54)' , fontWeight : 'bold' } ,
itemCount : { color : 'rgba(0, 0, 0, 0.3)' , fontStyle : 'italic' } ,
string : 'rgb(203, 75, 22)' ,
number : 'rgb(38, 139, 210)' ,
boolean : 'green' ,
null : { color : 'rgb(220, 50, 47)' , fontVariant : 'small-caps' , fontWeight : 'bold' } ,
input : [ '#292929' , { fontSize : '90%' } ] ,
inputHighlight : '#b3d8ff' ,
error : { fontSize : '0.8em' , color : 'red' , fontWeight : 'bold' } ,
iconCollection : 'rgb(0, 43, 54)' ,
iconEdit : 'edit' ,
iconDelete : 'rgb(203, 75, 22)' ,
iconAdd : 'edit' ,
iconCopy : 'rgb(38, 139, 210)' ,
iconOk : 'green' ,
iconCancel : 'rgb(203, 75, 22)' ,
} ,
} خاصية styles هي التي تركز عليها. يشير كل مفتاح ( property ، bracket ، itemCount ) إلى جزء من واجهة المستخدم. القيمة لكل مفتاح هي :
string ، وفي هذه الحالة يتم تفسيرها على أنها اللون (أو لون الخلفية في حالة container وضوء inputHighlight )null ). يتيح لك ذلك تغيير تصميم العناصر المختلفة بشكل ديناميكي على أساس المحتوى أو الهيكل.null . (في الصفيف ، يكون للعناصر اللاحقة أسبقية أعلى)للحصول على مثال بسيط ، إذا كنت ترغب في استخدام موضوع "githubdark" ، ولكن فقط قم بتغيير بعض الأشياء الصغيرة ، فستقوم بتحديد شيء مثل هذا:
// in <JsonEditor /> props
theme = { [
githubDarkTheme ,
{
iconEdit : 'grey' ,
boolean : { color : 'red' , fontStyle : 'italic' , fontWeight : 'bold' , fontSize : '80%' } ,
} ,
] } التي من شأنها أن تغير أيقونة "تحرير" والقيم المنطقية من هذا: 
في هذا: 
أو يمكنك إنشاء موضوعك الخاص من نقطة الصفر والكتابة فوق كائن السمة بأكمله.
لذلك ، لتلخيص ، يمكن أن يستغرق الدعامة theme إما :
"candyWrapperTheme"fragments styles أو displayName وما إلى ذلك ، أو فقط جزء styles (على مستوى الجذر)[ "<themeName>, {...overrides } ]يمكنك اللعب مع التحرير المباشر للمواضيع في التطبيق التجريبي من خلال تحديد "تحرير هذا الموضوع!" من محدد "البيانات التجريبية" (على الرغم من أنك لن تتمكن من إنشاء وظائف في JSON).
هناك طريقة أخرى لتنظيم المكون هي استهداف فئات CSS مباشرة. يحتوي كل عنصر في المكون على اسم فريد فريد ، لذلك يجب أن تكون قادرًا على تحديد موقعه في مفتش المستعرض الخاص بك وتجاوزه وفقًا لذلك. تبدأ جميع أسماء الفصول ببادئة jer- ، مثل jer-collection-header-row ، jer-value-string .
خاصية fragments أعلاه هي مجرد راحة للسماح بتحديد "شظايا" النمط المتكرر مرة واحدة وإشارة إلى استخدام الاسم المستعار. على سبيل المثال ، إذا كنت تريد أن تكون كل الرموز زرقاء وأكبر قليلاً وتباعدت ، فقد تحدد جزءًا مثل ذلك:
fragments: { iconAdjust : { color : "blue" , fontSize : "110%" , marginRight : "0.6em" } }ثم في كائن السمة ، فقط استخدم:
{
... ,
iconEdit : "iconAdjust" ,
iconDelete : "iconAdjust" ,
iconAdd : "iconAdjust" ,
iconCopy : "iconAdjust" ,
}ثم ، عندما تريد تعديله لاحقًا ، تحتاج فقط إلى تحديثه في مكان واحد!
يمكن أيضًا خلط الشظايا مع خصائص إضافية ، وحتى شظايا أخرى ، مثل ذلك:
iconEdit: [ "iconAdjust" , "anotherFragment" , { marginLeft : "1em" } ] داخليًا ، تتم جميع التحجيم والتباعد في em S ، لا px أبدًا (بصرف النظر عن حجم rootFontSize ، الذي يحدد حجم "القاعدة"). هذا يجعل التحجيم أسهل كثيرًا - فقط قم بتغيير الدعامة rootFontSize (أو ضبط fontSize على الحاوية الرئيسية من خلال استهداف الفصل ، أو التغيير والتبديل في السمة) ، وشاهد مقياس المكون بالكامل وفقًا لذلك.
يمكن استبدال الرموز الافتراضية ، ولكن تحتاج إلى تزويدها كعناصر React/HTML. فقط حدد أي أو جميعها داخل icons الدعامة ، مفتاح على النحو التالي:
icons = { {
add : < YourIcon />
edit : < YourIcon / >
delete : < YourIcon />
copy : < YourIcon / >
ok : < YourIcon / >
cancel : < YourIcon / >
chevron : < YourIcon / >
} }ستحتاج مكونات الأيقونة إلى تحديد أنماطها الخاصة ، حيث لن تتم إضافة أنماط السمة إلى العناصر المخصصة.
قم بتوطين تطبيقك عن طريق تمرير كائن translations لاستبدال السلاسل الافتراضية. المفاتيح والقيم الافتراضية (الإنجليزية) هي كما يلي:
{
ITEM_SINGLE : '{{count}} item' ,
ITEMS_MULTIPLE : '{{count}} items' ,
KEY_NEW : 'Enter new key' ,
ERROR_KEY_EXISTS : 'Key already exists' ,
ERROR_INVALID_JSON : 'Invalid JSON' ,
ERROR_UPDATE : 'Update unsuccessful' ,
ERROR_DELETE : 'Delete unsuccessful' ,
ERROR_ADD : 'Adding node unsuccessful' ,
DEFAULT_STRING : 'New data!' ,
DEFAULT_NEW_KEY : 'key' ,
} يمكنك استبدال بعض العقد في شجرة البيانات بمكوناتك المخصصة. قد يكون مثال على عرض صورة ، أو محرر مخصص للتاريخ ، أو فقط لإضافة بعض bling المرئي. راجع مجموعة بيانات "العقد المخصصة" في العرض التوضيحي التفاعلي لرؤيتها في العمل. (هناك أيضًا منتقي تاريخ مخصص يظهر عند تحرير سلاسل ISO في مجموعات البيانات الأخرى.)
يتم توفير العقد المخصصة في الدعامة customNodeDefinitions ، كمجموعة من كائنات الهيكل التالي:
{
condition , // a FilterFunction, as above
element , // React Component
customNodeProps , // object (optional)
hideKey , // boolean (optional)
defaultValue , // JSON value for a new instance of your component
showOnEdit // boolean, default false
showOnView // boolean, default true
showEditTools // boolean, default true
name // string (appears in Types selector)
showInTypesSelector , // boolean (optional), default false
// Only affects Collection nodes:
showCollectionWrapper // boolean (optional), default true
wrapperElement // React component (optional) to wrap *outside* the normal collection wrapper
wrapperProps // object (optional) -- props for the above wrapper component
} condition هو مجرد وظيفة مرشح ، مع نفس معلمات الإدخال ( key ، path ، value ، إلخ) ، element هو مكون رد فعل. سيتم تشغيل كل عقدة في بنية البيانات من خلال كل وظيفة شرط ، وسيتم استبدال أي مطابقة بمكونك المخصص. لاحظ أنه إذا كانت العقدة تتطابق مع أكثر من شروط تعريف مخصصة (من مكونات متعددة) ، فسيتم استخدامها الأول ، لذلك ضعها في الصفيف بترتيب الأولوية.
سيتلقى المكون جميع الدعائم نفسها كمكون عقدة قياسي (انظر قاعدة كود) ، ولكن يمكنك تمرير دعائم إضافية إلى المكون الخاص بك إذا لزم الأمر من خلال كائن customNodeProps . يتم استخدام مثال شامل على منتقي التاريخ المخصص في العرض التوضيحي (جنبًا إلى جنب مع زوجين آخران أكثر أساسية) ، والتي يمكنك فحصها لمعرفة كيفية الاستفادة من الدعائم القياسية واثنين من الدعائم المخصصة. عرض رمز المصدر هنا
بشكل افتراضي ، سيتم تقديم المكون الخاص بك على يمين مفتاح الخاصية الذي ينتمي إليه ، مثل أي قيمة أخرى. ومع ذلك ، يمكنك إخفاء المفتاح نفسه عن طريق تعيين hideKey: true ، وسيأخذ المكون المخصص الصف بأكمله. (انظر "المربع" الذي قدمه "مربع" في مجموعة بيانات "العقد المخصصة" للحصول على مثال.)
أيضًا ، بشكل افتراضي ، سيتم التعامل مع المكون الخاص بك كعنصر "عرض" ، أي سيظهر في عارض JSON ، ولكن عند التحرير ، سيعود إلى واجهة التحرير القياسية. ومع ذلك ، يمكن تغيير هذا مع Props showOnEdit و showOnView و showEditTools . على سبيل المثال ، قد تكون هناك حاجة إلى منتقي التاريخ فقط عند التحرير والركض كما هو للعرض. يشير showEditTools Prop إلى أيقونات التحرير (نسخ ، إضافة ، تحرير ، حذف) والتي تظهر على يمين كل قيمة على Hover. إذا اخترت تعطيلها ، لكنك لا تزال ترغب في الحصول على وضع "تحرير" ، فسيتعين عليك توفير آلية واجهة المستخدم الخاصة بك لتبديل التحرير.
يمكنك السماح للمستخدمين بإنشاء مثيلات جديدة من العقد الخاصة بك عن طريق تحديدها كـ "نوع" في محدد الأنواع عند تحرير/إضافة قيم. تعيين showInTypesSelector: true لتمكين هذا. ومع ذلك ، إذا تم تمكين ذلك ، فأنت بحاجة أيضًا إلى توفير name (وهو ما سيراه المستخدم في المحدد) و defaultValue وهو البيانات التي يتم إدخالها عندما يختار المستخدم هذا "النوع". (يجب أن يعود defaultValue true إذا تم تمريره من خلال وظيفة condition حتى يتم عرضها على الفور باستخدام المكون المخصص الخاص بك.)
يتم توفير مكون ومخصص بسيط مخصص لتحويل سلاسل URL إلى روابط قابلة للنقر مع الحزمة الرئيسية لتستخدمها خارج المربع. فقط استيراد واستخدام مثل ذلك:
import { JsonEditor , LinkCustomNodeDefinition } from 'json-edit-react'
// ...Other stuff
return (
< JsonEditor
{ ... otherProps }
customNodeDefinitions = { [ LinkCustomNodeDefinition , ... otherCustomDefinitions ] }
/>
) في معظم الحالات ، سيكون من الأفضل (وأبسط) إنشاء العقد المخصصة لمطابقة العقد القيمة (أي عدم وجود array أو عقد جمع object ) ، وهو ما تظهره جميع الأمثلة التجريبية. ومع ذلك ، إذا كنت ترغب في استهداف عقدة مجموعة كاملة ، فهناك بعض الأشياء الأخرى التي يجب معرفتها:
children ، بل تصبح فقط مسؤولية المكون عن التعامل معها.element العادي ، الذي سيتم عرضه داخل أقواس التجميع (أي يبدو أنه محتويات المجموعة)wrapperElement اختياري ، يتم عرضه خارج المجموعة (يمكن توفير الدعائم كما هو موضح أعلاه مع wrapperProps ). مرة أخرى ، يمكن عرض المحتويات الداخلية (بما في ذلك element المخصص) باستخدام children React. في هذا المثال ، تُظهر الحدود الزرقاء wrapperElement ، ويظهر الحدود الحمراء element الداخلي: 
showCollectionWrapper ( true افتراضي) ، والتي ، عند ضبطها على false ، تخفي عناصر التجميع المحيطة (أي شيفرون إخفاء/عرض الأقواس). في هذه الحالة ، يجب عليك توفير آلية إخفاء/عرض في المكون إذا كنت تريد ذلك. من الممكن تغيير سلاسل النص المختلفة التي يعرضها المكون. يمكنك توطينه ، ولكن يمكنك أيضًا تحديد وظائف لتجاوز النص المعروض بناءً على شروط معينة. على سبيل المثال ، لنفترض أننا نريد أن يقدم نص عدد الممتلكات (على سبيل المثال 6 items افتراضيًا) ملخصًا لنوع معين من العقدة ، والذي يمكن أن يبدو لطيفًا عند الانهيار. على سبيل المثال (مأخوذة من العرض التوضيحي):

تأخذ خاصية customText كائنًا ، مع أي من المفاتيح المحلية كمفاتيح ، مع وظيفة تُرجع سلسلة (أو null ، مما يؤدي إلى تعطلها إلى السلسلة الموضعية أو الافتراضية). المدخلات لهذه الوظائف هي نفسها بالنسبة لوظائف المرشح ، لذلك في هذا المثال ، سيتم تعريفه على النحو التالي:
// The function definition
const itemCountReplacement = ( { key , value , size } ) => {
// This returns "Steve Rogers (Marvel)" for the node summary
if ( value instanceof Object && 'name' in value )
return ` ${ value . name } ( ${ ( value ) ?. publisher ?? '' } )`
// This returns "X names" for the alias lists
if ( key === 'aliases' && Array . isArray ( value ) )
return ` ${ size } ${ size === 1 ? 'name' : 'names' } `
// Everything else as normal
return null
}
// And in component props...
. . . otherProps ,
customText = {
ITEM_SINGLE : itemCountReplacement ,
ITEMS_MULTIPLE : itemCountReplacement ,
} تم توضيح عناصر التحكم في لوحة المفاتيح الافتراضية أعلاه ، ولكن من الممكن تخصيص/تجاوزها. فقط تمرير في لوحة keyboardControls مع الإجراءات التي ترغب في تجاوزها. كائن التكوين الافتراضي هو:
{
confirm : 'Enter' , // default for all Value nodes, and key entry
cancel : 'Escape' ,
objectConfirm : { key : 'Enter' , modifier : [ 'Meta' , 'Shift' , 'Control' ] } ,
objectLineBreak : 'Enter' ,
stringConfirm : 'Enter' ,
stringLineBreak : { key : 'Enter' , modifier : 'Shift' } ,
numberConfirm : 'Enter' ,
numberUp : 'ArrowUp' ,
numberDown : 'ArrowDown' ,
booleanConfirm : 'Enter' ,
clipboardModifier : [ 'Meta' , 'Control' ] ,
collapseModifier : 'Alt' ,
}إذا كنت (على سبيل المثال) ، ترغب فقط في تغيير الإجراء "التأكيد" العام إلى "CMD-Enter" (على MAC) أو "Ctrl-Enter" ، فأنت فقط تمر:
keyboardControls = {
confirm : {
key : "Enter" ,
modifier : [ "Meta" , "Control" ]
}
}اعتبارات :
stringConfirm و numberConfirm و booleanConfirm إذا كان ينبغي أن تختلف عن قيمة confirm الخاصة بك.clipboardModifier الافتراضية). على الرغم من أن وظائف التراجع/إعادة من المحتمل أن تكون مرغوبة في معظم الحالات ، إلا أن هذا ليس مبنيًا على المكون ، لسببين رئيسيين:
يتم تصدير بعض وظائف المساعد والمكونات والأنواع التي قد تكون مفيدة في تطبيقاتك الخاصة (من إنشاء وظائف المرشح أو التحديث ، أو المكونات المخصصة) من الحزمة:
themes : كائن يحتوي على جميع تعريفات السمة المدمجةLinkCustomComponent : المكون المستخدم لتقديم الارتباطات التشعبيةLinkCustomNodeDefinition : تعريف العقدة المخصصة للروابط التشعبيةIconAdd ، IconEdit ، IconDelete ، IconCopy ، IconOk ، IconCancel ، IconChevron : جميع مكونات الأيقونات المدمجةmatchNode ، matchNodeKey : مساعدون لتحديد وظائف البحث المخصصةtruncate : وظيفة لاقتطاع سلسلة إلى طول محدد. انظر هناextract : وظيفة لاستخراج قيمة كائن متداخلة بعمق من مسار السلسلة. انظر هناassign : دالة لتعيين قيمة كائن عميق من مسار السلسلة. انظر هناThemeName : القائمة الحرفية للسلسلة لأسماء الموضوعات المدمجةTheme : كائن موضوع كاملThemeInput : نوع الإدخال لدعوة themeJsonEditorProps : جميع الدعائم الإدخال لمكون محرر JSONJsonData : كائن data الرئيسي - أي بنية JSON صالحةUpdateFunction ، OnChangeFunction ، OnErrorFunction FilterFunction ، CopyFunction ، SearchFilterFunction ، CompareFunction ، TypeFilterFunction ، LocalisedString ، CustomNodeDefinition ، CustomTextDefinitions ، CustomTextFunction ،TranslateFunction : الوظيفة التي تأخذ مفتاح توطين وإرجاع سلسلة مترجمةIconReplacements : نوع الإدخال icons الدعامةCollectionNodeProps : تم تمرير جميع الدعائم داخليًا إلى العقد "جمع" (أي الكائنات/المصفوفات)ValueNodeProps : جميع الدعائم مرت داخليًا إلى العقد "القيمة" (أي ليس الكائنات/المصفوفات)CustomNodeProps : تم تمرير جميع الدعائم داخليًا إلى العقد المخصصة ؛ في الأساس نفس مثل CollectionNodeProps مع حقل customNodeProps إضافي لتمرير الدعائم الفريدة لمكونكDataType : "string" | "number" | "boolean" | "null" | "object" | "array"KeyboardControls : هيكل لدعوة تخصيص لوحة المفاتيح يرجى فتح مشكلة: https://github.com/carlosnz/json-edit-react/issues
الميزات الرئيسية التي أرغب في تقديمها هي:
This component is heavily inspired by react-json-view, a great package that I've used in my own projects. However, it seems to have been abandoned now, and requires a few critical fixes, so I decided to create my own from scratch and extend the functionality while I was at it.
defaultValue function takes the new key as second parameteroverflow: clip setting based on animating statetrue to represent successsetData prop to discourage reliance on internal data state managementuseEffect hooksnull #90onError callback available for custom error handlingrootFontSize prop to set the "base" size for the componentonChange prop to allow validation/restriction of user input as they typedata if user hasn't actually changed a value (prevents Undo from being unnecessarily triggered)wrapperElement propid propindex in Filter (and other) function inputdefaultValue prop