Аз съм софтуерен инженер, който използва както Vue.js, така и React. Технологии като Vue Composition API и React Hooks наистина ми спасиха живота.

От друга страна, поради много сложните задачи за обработка на данни в приложението, което поддържам, написах много сервизни класове, които да ми помогнат да изпълня тези задачи. Но открих, че нещо неудобно е, че трябва ръчно да управлявам инициализирането на тези класове и техните зависимости.

Използвал съм сървърни рамки като Nest и Spring и технологии като инжектиране на зависимости решиха този проблем добре. Така че си помислих, има ли начин да комбинирам този дизайн модел с Vue.js и React.

Рамката Vesselize е резултат от моята практика. Това е лек IoC контейнер, вдъхновен от Nest, който може безпроблемно да се интегрира с Vue.js и React приложения. Ако се интересувате, можете да се обърнете към това пълно ръководство за потребителя.

По-долу са основните концепции на Vesselize и как да го използвате.

Основни концепции на Vesselize

Доставчици

Във Vesselize доставчиците обикновено са конструктори, които могат да бъдат инстанцирани. Може да бъде и всеки фабричен метод и декларирани стойности. Всички те ще бъдат регистрирани в контейнера за търсене и инжектиране на зависимости.

Контейнер

Отговорността на контейнера е да инициализира екземплярите и да разреши техните зависимости.

Контекст

По подразбиране екземплярите са единични. Като посочим контекстен обект, можем също да създадем екземпляр, обвързан с този контекст.

Първи стъпки с Vesselize и Vue.js

По-долу използваме код, за да демонстрираме как да използваме Vesselize в приложение Vue.js.

Инсталация

yarn add @vesselize/vue
# OR
npm i @vesselize/vue

Създаване на доставчици

Имаме следните три класа услуги:

  • UserAPI се използва за получаване на данни от сървъра.
  • UserService извиква UserAPI, за да получи данни и да ги обработи.
  • AuthService се използва за определяне на ролята на потребителя, като например дали е администратор.
// file: api/UserAPI.js
class UserAPI {
  async fetchUser(id) {
    return fetch(`/path/to/user/${id}`).then(res => res.json());
  }
}
​
// file: services/UserService.js
class UserService {
  userAPI = null;
​
  async getUser(id) {
    const user = await this.userAPI.fetchUser(id);
    
    // data processing stuff...
    
    return user;
  }
  
  // Inject userAPI instance through vesselize
  setVesselize(vesselize) {
    this.userAPI = vesselize.get('UserAPI');
  }
}
​
// file: services/AuthService.js
class AuthService {
  constructor(maxAdminUserId) {
    this.maxAdminUserId = maxAdminUserId;
  }
​
  isAdmin(user) {
    return user.id <= this.maxAdminUserId;
  }
}

Създайте плъгин Vesselize

Следният код използва createVesselize за създаване на плъгин Vue.js, който също е контейнер.

import { createVesselize } from '@vesselize/vue';
import UserAPI from './api/UserAPI';
import UserService from './services/UserService';
import RoleAuthService from './services/RoleAuthService';
​
const vesselize = createVesselize({
  providers: [
    {
      token: 'UserAPI',
      useClass: UserAPI
    },
    {
      token: 'UserService',
      useClass: UserService
    },
    {
      token: 'AuthService',
      useFactory() {
        const maxAdminUserId = 1;
​
        return new AuthService(maxAdminUserId);
      }
    }
  ]
});

Използвайте Vesselize Plugin

import { createApp } from 'vue';
import router from './router';
import store from './store';
import vesselize from './vesselize';
import App from './App.vue';
​
const app = createApp(App)
  .use(store)
  .use(router)
  .use(vesselize);
​
app.mount('#app');

Придобиване на екземпляр в компонент

Чрез useInstance Composition API екземплярите на услугата могат да бъдат получени в компоненти.

<template>
  <div>Profile</div>
  <p>{{ JSON.stringify(user) }}</p>
  <p>Role: {{ isAdmin ? 'Administrator' : 'User' }}</p>
</template>
​
<style scoped></style>
​
<script>
import { computed, ref, watchEffect } from 'vue';
import { useRoute } from 'vue-router';
import { useInstance } from '@vesselize/vue';
​
export default {
  setup() {
    const route = useRoute();
    const userId = computed(() => route.params.id);
    const user = ref({});
    const isAdmin = ref(false);
    // Inject instances through Vue Composition API
    const userService = useInstance('UserService');
    const authService = useInstance('AuthService');
​
    watchEffect(() => {
      if (userId.value) {
        userService.getUser(userId.value).then((data) => {
          user.value = data;
          isAdmin.value = authService.isAdmin(data);
        });
      }
    });
​
    return {
      user,
      isAdmin,
    };
  },
};
</script>

И накрая, ако искате да опитате директно vesselize с Vue.js, ето пълен примерен проект: vesselize-vue-starter.

Първи стъпки с Vesselize и React

Нека да разгледаме как същият пример може да бъде имплементиран в React.

Инсталация

yarn add @vesselize/react
# OR
npm i @vesselize/react

Създаване на доставчици

Същите UserAPI, UserService, AuthService класове на обслужване като по-горе.

Комбинирайте доставчици

Комбинирайте всички доставчици в масив.

import UserAPI from './api/UserAPI';
import UserService from './services/UserService';
import RoleAuthService from './services/RoleAuthService';
​
const providers = [
  {
    token: 'UserAPI',
    useClass: UserAPI
  },
  {
    token: 'UserService',
    useClass: UserService
  },
  {
    token: 'AuthService',
    useFactory() {
      const maxAdminUserId = 1;
​
      return new AuthService(maxAdminUserId);
    }
  }
];
​
export default providers;

Добавете VesselizeProvider

Използвайте VesselizeProvider, за да обвиете вашия App компонент.

import { VesselizeProvider } from '@vesselize/react';
import providers from './providers';
import UserProfile from './components/UserProfile';
​
function App() {
  return (
    <VesselizeProvider providers={providers}>
      <UserProfile />
    </VesselizeProvider>
  );
}
​
export default App;

Придобиване на екземпляр в компонент

Чрез куката useInstance екземплярите на услугата могат да бъдат получени в компоненти.

import { useParams }  from 'react-router-dom'
import { useState, useEffect } from 'react';
import { useInstance } from '@vesselize/react';
​
function UserProfile() {
  const { id } = useParams();
  const [user, setUser] = useState({});
  const [isAdmin, setIsAdmin] = useState(false);
  // Inject instances through hook
  const userService = useInstance('UserService');
  const authService = useInstance('AuthService');
​
  useEffect(() => {
    userService.getUser(id).then((data) => {
      setUser(data);
      setIsAdmin(authService.isAdmin(data));
    });
  }, [id, userService, authService]);
​
  return (
    <div>
      <span>{JSON.stringify(user)}</span>
      <p>Role: {isAdmin ? 'Administrator' : 'User'}</p>
    </div>
  );
}
​
export default UserProfile;

И накрая, това е кодовото хранилище за примерния проект, създаден от create-react-app: vesselize-react-starter.

Последни мисли

Научих много, като създадох Vesselize и се надявам, че може да ви бъде полезно.

Благодаря за четенето, приятен ден!

Хранилище на Github: https://github.com/vesselize

Документация: https://vesselize.js.org

По-долу са основните концепции на Vesselize и как да го използвате.