Composables для Vue
Импорт из os-detect/vue. Требуется Vue 3+.
import { useOS, useIsWindows11, useFormFactor, useRuntime, usePrimaryInput } from 'os-detect/vue'Текущая ОС
useOS()
Readonly<Ref<OS>>
Возвращает readonly ref с текущей строкой ОС, вычисляется один раз через readonly(ref(getOS())).
<script setup lang="ts">
import { useOS } from 'os-detect/vue'
const os = useOS() // Readonly<Ref<OS>>
</script>
<template>
<p>Running on {{ os }}</p>
</template>Определение Windows 11
useIsWindows11()
Readonly<Ref<boolean | null>>
Запускает асинхронную проверку detectIsWindows11() внутри onMounted и обновляет ref, когда она завершится; значение начинается с null, пока проверка не завершится.
<script setup lang="ts">
import { useOS, useIsWindows11 } from 'os-detect/vue'
const os = useOS() // Readonly<Ref<OS>>
const isWin11 = useIsWindows11() // Readonly<Ref<boolean | null>>
</script>
<template>
<p v-if="isWin11 === null">Определяем версию Windows…</p>
<p v-else-if="isWin11">Windows 11</p>
<p v-else-if="os === 'windows'">Windows 10 или старше</p>
<p v-else>OS: {{ os }}</p>
</template>Форм-фактор
useFormFactor()
Readonly<Ref<FormFactor>>
Возвращает readonly ref с текущим форм-фактором, вычисляется один раз через readonly(ref(getFormFactor())).
<script setup lang="ts">
import { useFormFactor } from 'os-detect/vue'
const formFactor = useFormFactor() // Readonly<Ref<FormFactor>>
</script>
<template>
<p>Форм-фактор: {{ formFactor }}</p>
</template>Рантайм-окружение
useRuntime()
Readonly<Ref<Runtime>>
Возвращает readonly ref с текущим рантайм-окружением, вычисляется один раз через readonly(ref(getRuntime())). Та же синхронная, кэшируемая форма, что и у useOS().
<script setup lang="ts">
import { useRuntime } from 'os-detect/vue'
const runtime = useRuntime() // Readonly<Ref<Runtime>>
</script>
<template>
<p>Выполняется в: {{ runtime }}</p>
</template>Основной способ ввода
usePrimaryInput()
Readonly<Ref<PrimaryInput>>
Начинается со значения 'unknown', разрешается внутри onMounted, а затем обновляется сам. В отличие от useOS()/useFormFactor()/useRuntime(), этот composable по-настоящему реактивен: он слушает события изменения matchMedia('(pointer: …)') и обновляет ref вживую, если у гибридного устройства прямо во время сессии подключили или отключили клавиатуру/мышь. Слушатели устанавливаются в onMounted и снимаются в onUnmounted.
<script setup lang="ts">
import { usePrimaryInput } from 'os-detect/vue'
const input = usePrimaryInput() // Readonly<Ref<'mouse' | 'touch' | 'unknown'>>
</script>
<template>
<p v-if="input === 'touch'">Показываем более крупные зоны нажатия</p>
</template>SSR (Nuxt)
useOS() вызывает getOS() нетерпеливо внутри ref(getOS()), прямо в теле composable — это выполняется во время setup(), который при SSR (Nuxt) реально выполняется и на сервере тоже, а не только на клиенте. Это значит, что useOS() несёт тот же риск несовпадения при гидратации, что и прямой вызов getOS(): если ОС сервера отличается от клиентской, значение, зашитое в серверный HTML, не совпадёт с тем, что клиент вычислит заново при гидратации. useFormFactor() и useRuntime() следуют тому же паттерну и несут тот же риск — оба разрешают своё значение нетерпеливо, во время setup(), а не внутри onMounted.
У useIsWindows11() этой проблемы нет — она осознанно начинается со значения null и разрешается только внутри onMounted, который никогда не выполняется при SSR. usePrimaryInput() безопасна по той же причине: она начинается со значения 'unknown' и впервые вызывает getPrimaryInput() только внутри onMounted.
Если контент, зависящий от ОС, должен точно совпадать на клиенте, примените тот же паттерн ref + onMounted вручную вместо useOS():
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { getOS } from 'os-detect'
import type { OS } from 'os-detect'
const os = ref<OS | null>(null)
onMounted(() => {
os.value = getOS()
})
</script>
<template>
<p v-if="os">OS: {{ os }}</p>
</template>