تطوير الواجهة الأمامية للبوابات على برمجيات مفتوحة المصدر: تبادل الخبرات

في الجزء الأول من المقالة حول كيفية إنشاء حلول البوابة لأكبر أرباب العمل في روسيا ، تم وصف العمارة من قبل الواجهة الخلفية. في هذه المقالة سنمر إلى الواجهة.



كما ذكرنا سابقًا في الجزء الأول ، كان هدفنا الرئيسي هو تطوير منصة يمكن تحجيمها وصيانتها بسهولة. غالبًا ما تتم

إعادة استخدام

الواجهة في Vue.js ، وبما أن البوابة بأكملها مقسمة إلى مداخل ، فإن كل منها عبارة عن مثيل Vue منفصل مع جانبه الخاص (Vuex) ، والمسار (Vue Router) والمكونات. يتم نقل كل مثيل إلى مستودعه الخاص.

نظرًا لأن المدخل موجود في المستودع الخاص به ، فإن السؤال الذي يطرح نفسه هو كيفية عدم كتابة الكثير من نفس النوع من التعليمات البرمجية لمداخل مختلفة. لحل هذه المشكلة ، ننقل كل ما يمكن إعادة استخدامه إلى مستودع منفصل ، يتم توصيله بعد ذلك عبر .gitmodules. في الوقت الحالي هناك نوعان من هذه الوحدات الفرعية.

يقوم المرء بتخزين الوظائف المشتركة: وهي المكونات والخدمات والثوابت المشتركة وما إلى ذلك لدينا هذه الوحدة تسمى Vue-common.

تحتوي الوحدة الفرعية الثانية على إعدادات التجميع ، وهي تخزن التكوينات لحزمة الويب ، بالإضافة إلى اللوادر والمساعدين اللازمين أثناء التجميع. تسمى هذه الوحدة Vue-bundler.

لتسهيل العمل مع واجهة برمجة التطبيقات ، تم أيضًا تقسيم طرق REST إلى عامة ومحلية. في Vue-common ، تم تقديم طرق للحصول على قائمة بمستخدمي البوابة الإلكترونية وطرق الإدارة والوصول إلى نظام ملفات المدخل وغيرها. تم نقل جميع نقاط نهاية واجهة برمجة التطبيقات إلى خدمات منفصلة تم تسجيلها عند نقطة الدخول ومتصلة بمثيل Vue. ثم يمكن استخدامها في أي مكان في التطبيق.

يتم تسجيل كل خدمة فردية داخل المكون الإضافي. يحتوي Vue على وظيفة استخدام مضمنة لتوصيل المكونات الإضافية. اقرأ المزيد عن الإضافات هنا .

تم تهيئة المكون الإضافي نفسه على النحو التالي:

class Api {
    constructor () {
        //  http ,   
        this.instance = instance

        //     
       //     this,      http 
        Object.keys(commonServices).forEach(name => commonServices[name](this))
        
        //     
	requireService.keys().forEach(filename => requireService(filename).default(this))
    }

    install () {
	Vue.prototype.$api= this
    }
}

export default new Api()

بالإضافة إلى التهيئة:

  1. يتم إنشاء مثيل عميل http. الذي يحدد القاعدة الأساسية للواجهة الخلفية والرؤوس

    const instance = axios.create({
    	baseURL: '/example/api',
    	responseType: 'json',
    	headers: {
    		'Content-Type': 'application/json',
    		'Cache-Control': 'no-cache',
    		'Pragma': 'no-cache',
    	}
    })
                    backend   ,   axios.

  2. يتم إنشاء الخدمات التي تخزن الطلبات نفسها

    // api -   http 
    export default api => {
    	api.exampleService= {
    		exampleGetRequest(params) {
    			return api.instance.request({
    				method: 'get',
    				url: `example/get`,
    				params
    			})
    		},
    		examplePostRequest(data) {
    			return api.instance.request({
    				method: 'post',
    				url: `example/post`,
    				data
    			})
    		},
    	}
    }
    

    بشكل عام ، يكفي إنشاء مثل هذه الخدمة فقط ، وهي مسجلة بالفعل لكل مدخل في فئة Api
  3. يتم تسجيل الخدمات العامة والمحلية

         const requireService = require.context('./service', false, /.service.js$/)
    

في المكونات ، يتم استخدامها ببساطة شديدة. على سبيل المثال:

export default {
	methods: {
		someMethod() {
    			this.$api.exampleService.exampleGetRequest()
}
}
}

إذا كنت بحاجة إلى تقديم طلبات خارج التطبيق ، فيمكنك القيام بذلك:

//    (@ -     )
import api from ‘@/api’

//        
api.exampleService.exampleGetRequest()

القياس

كما هو مذكور أعلاه ، يتم تجميع حزمة منفصلة لكل بوابة ، ولكل حزمة نقاط دخول خاصة بها. يتم تسجيل المكونات والأصول في كل منها ، ويتم تكوين التفويض للتطوير المحلي ، ويتم توصيل المكونات الإضافية.

يتم تسجيل المكونات عالميًا لكل تطبيق ، محليًا وعامًا.

يبدو تسجيل المكون كما يلي:

import _ from “lodash”

const requireComponent = require.context('@/components', true, /^[^_].+\.vue$/i)

requireComponent.keys().forEach(filename => {
    const componentConfig = requireComponent(filename)

    // Get PascalCase name of component
    const componentName = _.upperFirst(
        _.camelCase(/\/\w+\.vue/.exec(filename)[0].replace(/^\.\//, '').replace(/\.\w+$/, ''))
    )

    Vue.component(componentName, componentConfig.default || componentConfig)
})

في بعض الأحيان يصبح من الضروري للبوابة التي نقوم بتطويرها لإضافة وظائف فريدة ، ولهذا عليك كتابة مكونات فريدة لها ، أو ببساطة تنفيذ مكون بطريقة مختلفة. يكفي إنشاء مكون في مجلد منفصل ، على سبيل المثال / Component-portal / * portal name * / *. Vue ، وتسجيله في نقطة الإدخال المطلوبة ، وإضافة add.context ليس لمجلد واحد ، ولكن لعدة مجلدات.

const contexts = [
    require.context('@/components', true, /^[^_].+\.vue$/i),
   require.context('@/components-portal/example', true, /^[^_].+\.vue$/i)
]

contexts.forEach(requireComponent => {
    requireComponent.keys().forEach(filename => {
        const componentConfig = requireComponent(filename)

        // Get PascalCase name of component
        const componentName = _.upperFirst(
            _.camelCase(/\/\w+\.vue/.exec(filename)[0].replace(/^\.\//, '').replace(/\.\w+$/, ''))
        )

        Vue.component(componentName, componentConfig.default || componentConfig)
    })
})

إذا قمت بتعيين نفس الاسم للمكون لبوابة معينة كما هو الحال في المكتبة العامة للمكونات ، فسيتم إعادة كتابته ببساطة كخاصية للكائن وسيتم استخدامه كعنصر لهذا المدخل.

كما يتم تسجيل الأصول مثل رموز svg عالميًا. نستخدم svg-sprite-loader لإنشاء نقش متحرك من أيقونات svg ثم نستخدمها عبر <use: xlink: href = "# * icon name *" />

يتم تسجيلها على هذا النحو:

const requireAll = (r) => r.keys().forEach(r)

const requireContext = require.context('@/assets/icons/', true, /\.svg$/)

requireAll(requireContext)

من أجل قياس الوظائف ليس فقط ، ولكن أيضًا لأنماط المكونات ، قمنا بتنفيذ آلية لتغيير الأنماط لمدخل معين. تحدد مكونات الملف الواحد الأنماط في علامة <style> ويتم استخدامها افتراضيًا. لتطبيق الأنماط لبوابة معينة ، تحتاج إلى تسجيلها في علامة أخرى

All Articles