логотип PurpleSchool
логотип PurpleSchool

Создание и использование компонентов с помощью Vue js и C

Автор

Олег Марков

Введение

Когда речь заходит о создании современных web-приложений, всё чаще разработчики стремятся объединять удобный и мощный frontend с максимальной производительностью backend или нативных частей. Vue.js – это современный JavaScript-фреймворк, который делает разработку пользовательских интерфейсов быстрой и приятной. Однако бывает, что одних лишь возможностей JS не хватает: нужно подключить вычисления на нативном уровне — например, если задача требует высокой производительности, математики или взаимодействия с оборудованием.

В таких случаях часто прибегают к языку C, который невероятно быстр и популярен для разработки низкоуровневых библиотек. Интеграция Vue.js и C позволяет выстроить архитектуру приложения, в которой интерфейс написан современно и удобно, а критически важные вычисления или работа с устройствами реализованы на C.

В этой статье вы узнаете:

  • как создавать компоненты во Vue.js,
  • как вызывать нативный код на C из web-приложения,
  • каким образом связывать Vue-компоненты с backend, который использует C,
  • практические примеры такой интеграции.

Основы компонентов во Vue.js

Что такое компонент во Vue.js

В Vue.js компонент — это переиспользуемый блок интерфейса, обладающий своей логикой, стилями и отображением. Каждый компонент можно представить как мини-приложение внутри большого приложения.

Пример простого компонента

Давайте посмотрим, как выглядит простой Vue-компонент:

// MyButton.vue
<template>
  <button @click="increment">
    Количество: {{ count }}
  </button>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count += 1 // Увеличиваем счётчик при каждом клике
    }
  }
}
</script>

<style>
button {
  padding: 10px;
  color: white;
  background: #42b983;
}
</style>

Здесь вы видите: компонент включает шаблон (HTML), логику (data и methods на JS) и стили для кнопки.

Как создавать и регистрировать компонент

Существует два основных вида компонентов:

1. Локальные компоненты
Определяются и используются только внутри одного компонента.

import MyButton from './MyButton.vue' // Импортируем компонент

export default {
  components: {
    MyButton // Регистрируем локально
  }
}

2. Глобальные компоненты
Регистрируются в корне приложения и доступны в любом месте.

import Vue from 'vue'
import MyButton from './MyButton.vue'

Vue.component('MyButton', MyButton) // Регистрируем глобально

Свойства (props) и события (emits)

  • Props позволяют передавать данные в компонент сверху вниз.
  • Emits или события — для передачи сигналов от компонента наверх.

Пример передачи props и генерации событий

// ParentComponent.vue
<MyButton :label="'Нажми меня!'" @clicked="handleClick" />

// MyButton.vue
<template>
  <button @click="handleClick">{{ label }}</button>
</template>
<script>
export default {
  props: {
    label: String // Получаем данные в компонент
  },
  methods: {
    handleClick() {
      this.$emit('clicked') // Отправляем событие наверх
    }
  }
}
</script>

В этом примере родитель передаёт текст кнопки дочернему компоненту и подписывается на событие clicked.

Вызов C-кода из web-приложения

Сама браузерная среда не поддерживает прямой вызов кода на C, но существует несколько способов интеграции:

  • Через WebAssembly (Wasm)
  • Через backend API (например, REST или gRPC)
  • Через Desktop WebView—технологии (например, Electron с Node.js native модулями)

Давайте остановимся на самых популярных подходах.

Интеграция C с помощью WebAssembly (Wasm)

WebAssembly — это технология, которая позволяет запускать код на языках вроде C в браузере на высокой скорости. Вы компилируете свой C-код в специальный двоичный формат (wasm), который можно импортировать в JS-приложение и вызывать как обычные функции.

Пример создания и вызова C-функции внутри Vue через WebAssembly

  1. Компиляция C-кода в wasm

Вам понадобится компилятор Emscripten. Вот пример простейшей C-функции:

// math.c
int add(int a, int b) {
  return a + b;
}

Компилируем:

emcc math.c -o math.wasm -s WASM=1 -s EXPORTED_FUNCTIONS='["_add"]' -s EXPORTED_RUNTIME_METHODS='["cwrap", "ccall"]'
  1. Импорт в Vue-проект

Подключение и вызов из компонента:

// Внутри компонента Vue
mounted() {
  // Загружаем wasm-модуль, передаём путь к файлу
  fetch('math.wasm')
    .then(response => response.arrayBuffer())
    .then(bytes => WebAssembly.instantiate(bytes, {}))
    .then(results => {
      // Получаем значение из экспортированной функции add
      const add = results.instance.exports.add
      const sum = add(3, 5) // sum = 8
      console.log('3 + 5 = ', sum)
    })
}

Большинство современных инструментов frontend (например, Vite, Webpack) позволяют удобно работать с wasm-модулями, поэтому интеграция становится довольно простой.

Пример обертки через Emscripten

Вам может потребоваться использовать дополнительные методы для работы со строками, массивами и т.д. Вот более сложный пример:

import Module from './math.js' // JS-обертка, сгенерированная Emscripten

mounted() {
  Module().then(module => {
    // cwrap позволяет создать JS-функцию-обертку для C-функции
    const add = module.cwrap('add', 'number', ['number','number'])
    const result = add(10, 12)
    console.log('10 + 12 =', result)
  })
}

Комментарии к коду:

  • cwrap создает JS-обертку для C-функции, возвращает число, принимает два числа.
  • result будет равен 22, как вы ожидали.

Вызов C-кода через backend API

Один из самых надёжных способов — вынести логику на C в backend-сервер, который общается с Vue по сети (REST API или WebSocket).

Пример: сервер на C, отвечающий по HTTP

  1. Напишем REST API на языке C. Популярен фреймворк Civetweb или libmicrohttpd. Пример на псевдокоде:
// Пример: обработчик HTTP-запроса, возвращает сумму двух чисел
int sum_handler(struct mg_connection *conn, void *cbdata) {
  // ...парсим параметры a и b из запроса
  int a = ...; int b = ...;
  int result = add(a, b);
  // Отправляем ответ клиенту
  mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n%d", result);
  return 200;
}
  1. Во Vue-компоненте делаем запрос:
methods: {
  async calculateSum(a, b) {
    // Отправляем GET-запрос на бекенд C
    const response = await fetch(`/api/add?a=${a}&b=${b}`)
    const result = await response.text()
    this.sumResult = Number(result)
  }
}
  1. Использование:
<button @click="calculateSum(8, 9)">
  Получить сумму с бэкенда
</button>
<div>
  Результат: {{ sumResult }}
</div>

Теперь frontend и C-бэкенд работают вместе: Vue-компонент отправляет параметры, сервер на C возвращает вычисленный результат.

Коммуникация Desktop приложения с C

Если вы разрабатываете desktop c помощью Vue (например, с помощью Electron или Tauri), тогда вы можете вызвать нативный модуль на C из основной программы.

Пример интеграции Vue + Electron + C (native addon)

  1. Node.js позволяет создавать расширения на C/C++ через N-API или node-gyp.

  2. Создайте C++ биндинг как addon, затем вызывайте его из Electron backend, а уже затем связывайте с Vue.

// addon.cc для Node.js
#include <napi.h>
Napi::Number Add(const Napi::CallbackInfo& info) {
  int arg0 = info[0].As<Napi::Number>().Int32Value();
  int arg1 = info[1].As<Napi::Number>().Int32Value();
  int result = arg0 + arg1;
  return Napi::Number::New(info.Env(), result);
}

Napi::Object Init(Napi::Env env, Napi::Object exports) {
  exports.Set("add", Napi::Function::New(env, Add));
  return exports;
}
NODE_API_MODULE(addon, Init)
  1. После сборки addon подключаете его в основной процесс Electron.
const addon = require('./build/Release/addon.node')
console.log(addon.add(2,3)) // 5
  1. Связываем Vue через IPC.
// В Vue запрашиваем данные у main процесса через IPC
this.$electron.ipcRenderer.invoke('add', 4, 5).then(result => {
  this.sum = result // sum = 9
})

Связь компонентов Vue с внешним кодом

В реальных приложениях приходится прописывать интерфейсы, чтобы компоненты могли работать с сервером или wasm через JS. Главное здесь — соблюдать архитектурные принципы: компоненты Vue не должны содержать логики платформозависимого или нативного кода, а лишь оперировать уже подготовленными JS-методами, которые делают всю "грязную работу".

Обработка ошибок и асинхронность

При работе через fetch, WebAssembly и другие асинхронные интерфейсы всегда обрабатывайте ошибки:

try {
  const response = await fetch(url)
  if (!response.ok) throw new Error('Ошибка сервера')
  const data = await response.json()
  // работа с данными
} catch (e) {
  this.error = e.message
}

Архитектура: разделение ответственности

Старайтесь размещать все обращения к нативным методам или серверам в отдельных сервисах или composables, чтобы компонент работал только с результатами.

Пример структуры

src/
  components/
    MyComponent.vue
  services/
    mathApi.js // Всё взаимодействие с C/wasm здесь

В mathApi.js:

export async function add(a, b) {
  const response = await fetch(`/api/add?a=${a}&b=${b}`)
  return Number(await response.text())
}

В компоненте:

import { add } from '../services/mathApi'

methods: {
  async getSum(a, b) {
    this.result = await add(a, b)
  }
}

Такой подход обеспечивает гибкость и удобство поддержки.

Заключение

Комплексное приложение, в котором frontend написан на Vue.js, а сложная логика или критически важные вычисления реализованы на C, даёт большие возможности: комфорт и скорость работы с UI сочетаются с мощью и эффективностью нативного кода. Вы можете создать переиспользуемые компоненты интерфейса и связать их с нативными модулями через WebAssembly, backend API или специальные десктопные связки. Такое разделение сохраняет чистоту архитектуры и облегчает поддержку вашего приложения.

Используйте props для передачи данных между компонентами, события для отправки сигналов наверх, а для интеграции с C выбирайте подходящий способ согласно требованиям задачи и типу приложения (web или desktop). Следуйте принципам разделения ответственности — и ваш проект будет улучшаться и масштабироваться легко.

Частозадаваемые технические вопросы по теме статьи и ответы на них

В: Как передавать сложные данные (структуры, массивы) между C-кодом и Vue.js через WebAssembly?
О: Строки и большие массивы требуют сериализации. Для массивов используйте указатель на буфер в wasm-памяти, а затем через JS-обертки (например, через Emscripten) записывайте/считывайте данные. Для строк — используйте специальные функции Emscripten, такие как allocateUTF8 или Pointer_stringify.

В: Можно ли напрямую вызвать C-библиотеку из браузера, без WebAssembly?
О: Нет, браузер не может напрямую загружать C-библиотеки из соображений безопасности. Используйте WebAssembly или backend-прокси.

В: Как тестировать логику, когда часть функционала на C, а часть на Vue?
О: Логику на C тестируйте изолированно с помощью C-тест-раннеров (например, Unity, CUnit). Для end-to-end тестирования автоматически поднимайте сервер (или Wasm-модуль) и пишите тесты на JS (например, с Cypress или Jest) для взаимодействия с API или wasm-функциями.

В: С какими ограничениями надо считаться при использовании WebAssembly в браузере?
О: Wasm работает в песочнице — нельзя напрямую читать файлы пользователя, обращаться к DOM или манипулировать браузерными API, всё это делается через проксирующие JS-функции.

В: Как быстро отлаживать связку C и Vue в случае ошибок?
О: Для WebAssembly используйте sourcemap, расширение DevTools "WebAssembly" и логи в консоли Emscripten. В случае backend — логируйте запросы, используйте отладчики для C и middleware типа curl или Postman для проверки REST API.

Стрелочка влевоРуководство по nextTick для работы с DOMУправление состоянием и реактивностью через inject и provideСтрелочка вправо

Все гайды по Vue

Руководство по валидации форм во Vue.jsИнтеграция Tiptap для создания редакторов на VueРабота с таблицами во Vue через TanStackИнструкция по установке и компонентам Vue sliderУправление пакетами Vue js с помощью npmУправление пакетами и node modules в Vue проектахКак использовать meta для улучшения SEO на VueПолный гайд по компоненту messages во Vuejs5 правил использования Inertia с Vue и LaravelРабота с модулями и пакетами в VueИнструкция по работе с grid на VueGithub для Vue проектов - подробная инструкция по хранению и совместной работеНастройка ESLint для Vue проектов и поддержка качества кодаОбработка ошибок и отладка в Vue.jsИспользование Vue Devtools для отладки и мониторинга приложенийРабота с конфигурационными файлами и скриптами VueСоздание и настройка проектов Vue с помощью Vue CLI3 способа интеграции Chart.js с Vue для создания графиковРабота с Canvas во VueИнструкция по реализации календаря во VueРабота с Ant Design Vue для создания UI на Vue
Обзор и использование утилит Vue для удобной разработкиРабота с обновлениями компонента и жизненным циклом updateРазрешение конфликтов и ошибок с помощью Vue resolveИспользование query-параметров и их обработка в маршрутах VueЗагрузка и управление состоянием загрузки в VueИспользование библиотек Vue для расширения функционалаРабота с JSON данными в приложениях VueКак работать с экземплярами компонента Instance во VueПолучение данных и API-запросы во Vue.jsЭкспорт и импорт данных и компонентов в VueОбработка событий и их передача между компонентами VuejsГайд по defineEmits на Vue 3Понимание core функционала Vue и его применениеПонимание и применение Composition API в Vue 3Понимание и работа с компилятором VueКогда и как использовать $emit и call во VueВзаимодействие с внешними API через Axios в Vue
Веб приложения на Vue архитектура и лучшие практикиИспользование Vite для быстрого старта и сборки проектов на Vue 3Работа с URL и ссылками в приложениях на VueРабота с пользовательскими интерфейсами и UI библиотеками во VueОрганизация и структура исходных файлов в проектах VueИспользование Quasar Framework для разработки на Vue с готовыми UI-компонентамиОбзор популярных шаблонов и стартовых проектов на VueИнтеграция Vue с PHP для создания динамичных веб-приложенийКак организовать страницы и маршруты в проекте на VueNuxt JS и Vue 3 для SSR приложенийСоздание серверных приложений на Vue с помощью Nuxt jsИспользование Vue Native для разработки мобильных приложенийОрганизация и управление индексной страницей в проектах VueИспользование Docker для контейнеризации приложений на VueИнтеграция Vue.js с Django для создания полноценных веб-приложенийСоздание и работа с дистрибутивом build dist Vue приложенийРабота со стилями и CSS в Vue js для красивых интерфейсовСоздание и структурирование Vue.js приложенияНастройка и сборка проектов Vue с использованием современных инструментовИнтеграция Vue с Bitrix для корпоративных решенийРазработка административных панелей на Vue jsКак исправить ошибку cannot find module vue
5 библиотек для создания tree view во VueИнтеграция Tailwind CSS с Vue для современных интерфейсовИнтеграция Vue с серверной частью и HTTPS настройкамиКак обрабатывать async операции с Promise во VueИнтеграция Node.js и Vue.js для разработки приложенийРуководство по интеграции Vue js в NET проектыПримеры использования JSX во VueГайд по импорту и регистрации компонентов на VueМногоязычные приложения на Vue с i18nИнтеграция FLIR данных с Vue5 примеров использования filter во Vue для упрощения разработки3 примера реализации drag-and-drop во Vue
Управление переменными и реактивными свойствами во VueИспользование v for и slot в VueПрименение v-bind для динамической привязки атрибутов в VueУправление пользователями и их данными в Vue приложенияхСоздание и использование UI Kit для Vue приложенийТипизация и использование TypeScript в VuejsИспользование шаблонов в Vue js для построения интерфейсовИспользование Swiper для создания слайдеров в VueРабота со стилями и стилизацией в VueСтруктура и особенности Single File Components SFC в VueРабота со SCSS в проектах на Vue для стилизацииРабота со скроллингом и прокруткой в Vue приложенияхПрименение script setup синтаксиса в Vue 3 для упрощения компонентовИспользование scoped стилей для изоляции CSS в компонентах Vue3 способа улучшить навигацию Vue с push()Обработка запросов и асинхронных операций в VueПонимание и использование provide inject для передачи данных между компонентамиПередача и использование props в Vue 3 для взаимодействия компонентовПередача данных между компонентами с помощью props в Vue jsУправление property и функциями во Vue.jsРабота со свойствами компонентов VueУправление параметрами и динамическими данными во VueРабота с lifecycle-хуком onMounted во VueОсновы работы с объектами в VueПонимание жизненного цикла компонента Vue js на примере mountedИспользование модальных окон modal в Vue приложенияхИспользование методов в компонентах Vue для обработки логикиИспользование метода map в Vue для обработки массивовИспользование хуков жизненного цикла Vue для управления состоянием компонентаРабота с ключами key в списках и компонентах VueОбработка пользовательского ввода в Vue.jsРабота с изображениями и их оптимизация в VueИспользование хуков жизненного цикла в VueОрганизация сеток и гридов для верстки интерфейсов на VueСоздание и управление формами в VueОрганизация файлов и структура проекта Vue.jsКомпоненты Vue создание передача данных события и emitРабота с динамическими компонентами и данными в Vue3 способа манипулирования DOM на VueРуководство по div во VueИспользование директив в Vue и их расширенные возможностиОсновы и применение директив в VueИспользование директив и их особенности на Vue с помощью defineИспользование компонентов datepicker в Vue для выбора датОрганизация циклов и итераций во VueКак работает компиляция Vue CoreСоздание и использование компонентов в Vue JSОбработка кликов и пользовательских событий в VueИспользование классов в Vue для организации кода и компонентовИспользование директивы checked для управления состоянием чекбоксов в VueГайд на checkbox компонент во VueОтображение данных в виде графиков с помощью Vue ChartСоздание и настройка кнопок в VueСоздание и настройка кнопок в Vue приложенияхРабота с lifecycle-хуками beforeCreate и beforeMount во VueИспользование массивов и методов их обработки в VueИспользование массивов и их обработка в Vue
Использование Vuetify для создания современных интерфейсов на VueИспользование transition во VueТестирование компонентов и приложений на VueРабота с teleport для управления DOM во VueПять шагов по настройке SSR в VuejsИспользование Shadcn UI компонентов с Vue для продвинутых интерфейсовИспользование router-link для навигации в Vue RouterКак использовать require в Vue для динамического импорта модулейРабота с динамическим рендерингом и виртуальным DOM на Vue.jsИспользование ref для управления ссылками и реактивностью в Vue 3Использование Vue Pro и его преимущества для профессиональной разработкиРуководство по nextTick для работы с DOMСоздание и использование компонентов с помощью Vue js и CУправление состоянием и реактивностью через inject и provideДинамическое обновление компонентов и данных на VueГлубокое изучение документации Vue и как эффективно её использоватьИспользование Crystal с Vue для разработкиИспользование вычисляемых свойств для динамического отображения данных на Vue jsОптимизация производительности и предупреждения в Vue
Открыть базу знаний