ExtJS 7 و Spring Boot 2. كيفية إنشاء SPA يتفاعل مع API الخاص بك والإضافات ReactJS الخارجية؟

خفضت الإصدارات الحديثة من Ext JS ، وخاصة مجموعة الأدوات الحديثة ، الحد الأدنى لدخول الإطار (أمثلة من Sink Kitchen) ، وسهّلت إنشاء الواجهة المطلوبة (مرحبًا Sencha Architect) وحققت الحد الأدنى من حجم تطبيقات الويب (Sencha Cmd).

ربما ، يجب تخفيف هبر بمثال على تنفيذ "مركز ظرفي" ، حيث يمكنك في الوقت الفعلي مشاهدة الكاميرات والأحداث منها (جميع البيانات مزيفة).



لنبدأ. دعنا ننشئ مشروع Spring Boot مع وحدتي تحكم من شأنها أن توفر قائمة من الكاميرات والأحداث الحالية ، وكذلك القدرة على الاشتراك في أحداث جديدة (عبر WebSocket).


بعد ذلك ، أضف النماذج الضرورية والمستودعات وطرق العرض والتبعيات الخارجية:



بمزيد من التفاصيل ، عرض الخريطة يتفاعل مع مكون React في الخريطة.
Ext.define('Cameras.view.override.Map', { override: 'Cameras.view.Map', config: { cameras: {}, react: null }, initialize: function() { let that = this; let e = React.createElement; this.setReact(ReactDOM.render(e(createReactClass({ getInitialState: function() { return { items: [], center: [55.751574, 37.573856]}; }, render: function() { let placemarks = []; for(let i=0; i < this.state.items.length; i++) { let location = this.state.items[i].get("location"); placemarks.push(e(window.ReactYandexMaps.Placemark, { geometry: [location.latitude, location.longitude], options: { preset: 'islands#blueCircleDotIconWithCaption', iconCaptionMaxWidth: '50' } })); } let map = e(window.ReactYandexMaps.Map, { state: { center: this.state.center, zoom: 10 }, width: '100%', height: '100%' }, placemarks); return e(window.ReactYandexMaps.YMaps, null, map); } })), this.mapContainer.dom)); }, getElementConfig: function() { return { reference: 'element', className: 'x-container', children: [{ reference: 'bodyElement', style: 'width: 100%; height: 100%', className: 'x-inner', children: [{ style: 'width: 100%; height: 100%', reference: 'mapContainer', className: Ext.baseCSSPrefix + 'map-container' }] }] }; }, addCamera: function(cameraModel) { if(!this.containsCamera(cameraModel)) { this.getCameras()[cameraModel.get("id")] = cameraModel; this.getReact().setState({ items: Object.values(this.getCameras()) }); this.fitCamera(cameraModel); } }, removeCamera: function(cameraModel) { if(this.containsCamera(cameraModel)) { delete this.getCameras()[cameraModel.get("id")]; this.getReact().setState({ items: Object.values(this.getCameras()) }); } }, fitCamera: function(cameraModel) { if(this.containsCamera(cameraModel)) { let location = this.getCameras()[cameraModel.get("id")].get("location"); this.getReact().setState({ center: [location.latitude, location.longitude] }); } }, privates: { containsCamera: function(cameraModel) { cameraId = "" + cameraModel.get("id"); return Object.keys(this.getCameras()).includes(cameraId); } } }); 


نوافق أيضًا على أن الأحداث ستأتي من مكون CamerasGrid ، كما هو هذا المكون هو المسؤول عن إضافة / إزالة الكاميرات من البطاقة.

وحدة تحكم مكون CamerasGrid التي تضيف إنشاء الحدث إلى المكون
 Ext.define('Cameras.view.CamerasGridViewController', { extend: 'Ext.app.ViewController', alias: 'controller.camerasgrid', init: function() { let socket = new WebSocket("ws://localhost:8080/events/sub"); socket.onopen = function(e) { console.log('onopen'); }; socket.onmessage = this.onMessage.bind(this); }, onMessage: function(event) { let data = Ext.decode(event.data); let gridData = this.getView().getStore().getData(); for(let i=0; i < gridData.length; i++) { let checked = gridData.getAt(i).get("checked"); if(checked !== undefined && checked) { if(gridData.getAt(i).get("id") == data.camera.id) { this.fireViewEvent("cameraRecognition", data); } } } } }); 


والنتيجة هي واجهة مسلية إلى حد ما. ألاحظ أنه مع التصميم المناسب لهيكل التطبيق (حتى لو كان ذلك صغيرًا) ، فإن وقت إنشاء واحد صغير جدًا ، وقد يصل إلى بضع ساعات.



رمز عينة متاح على github.com .

Source: https://habr.com/ru/post/ar479676/


All Articles