Я инженер-программист, использующий и Vue.js, и React. Такие технологии, как Vue Composition API и React Hooks, действительно спасли мне жизнь.

С другой стороны, из-за очень сложных задач обработки данных в приложении, которое я поддерживаю, я написал множество классов обслуживания, чтобы помочь мне выполнить эти задачи. Но мне показалось неудобным то, что мне нужно вручную управлять инициализацией этих классов и их зависимостей.

Я использовал серверные фреймворки, такие как Nest и Spring, и такие технологии, как внедрение зависимостей, хорошо решили эту проблему. Итак, я подумал, есть ли способ объединить этот шаблон проектирования с Vue.js и React.

Фреймворк Весселиз - результат моей практики. Это легкий контейнер IoC, вдохновленный Nest, который может легко интегрироваться с приложениями Vue.js и React. Если вам интересно, вы можете обратиться к этому полному руководству пользователя.

Ниже приведены основные концепции 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

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 и способы их использования.