Директива v-bind позволяет **динамически привязывать значения к HTML-атрибутам**. Без неё атрибуты всегда статические — значение задаётся прямо в шаблоне и не меняется. С v-bind значение атрибута берётся из переменной компонента и автоматически обновляется при её изменении.
<!-- Статический атрибут — всегда одинаковый -->
<a href="https://example.com">Ссылка</a>
<!-- Динамический атрибут — значение из переменной -->
<a v-bind:href="url">Ссылка</a>Директива v-bind используется настолько часто, что Vue предоставляет сокращение — двоеточие ::
<!-- Полная запись -->
<img v-bind:src="imageUrl" v-bind:alt="imageAlt">
<!-- Сокращённая запись (рекомендуется) -->
<img :src="imageUrl" :alt="imageAlt">
<script setup>
const imageUrl = ref('https://example.com/photo.jpg')
const imageAlt = ref('Фото пользователя')
</script>Если нужно привязать сразу несколько атрибутов, можно передать объект в v-bind без указания конкретного атрибута:
<template>
<input v-bind="inputAttrs">
</template>
<script setup>
const inputAttrs = reactive({
type: 'text',
placeholder: 'Введите текст',
maxlength: 100,
disabled: false,
})
</script>Это эквивалентно записи :type="inputAttrs.type" :placeholder="inputAttrs.placeholder" и т.д.
Привязка :class — одна из самых мощных возможностей v-bind. Можно передавать объект, где ключи — имена классов, а значения — условия их применения:
<template>
<button
:class="{
btn: true,
'btn-primary': isPrimary,
'btn-disabled': isDisabled,
active: isActive
}"
>
Кнопка
</button>
</template>Класс добавляется, только если значение в объекте равно true.
Директива :style принимает объект CSS-свойств. Имена свойств можно писать в camelCase или в кавычках в kebab-case:
<template>
<div :style="{
color: textColor,
fontSize: fontSize + 'px',
'background-color': bgColor,
fontWeight: isBold ? 'bold' : 'normal'
}">
Стилизованный блок
</div>
</template>
<script setup>
const textColor = ref('#333')
const fontSize = ref(16)
const bgColor = ref('#f5f5f5')
const isBold = ref(false)
</script>В редких случаях может понадобиться динамическое имя самого атрибута. Это делается через квадратные скобки:
<!-- attrName может быть 'href', 'src', 'disabled' и т.д. -->
<component :[attrName]="attrValue" /><template>
<a
:href="link.url"
:target="link.external ? '_blank' : '_self'"
:rel="link.external ? 'noopener noreferrer' : null"
>
{{ link.text }}
</a>
</template>
<script setup>
const link = reactive({
url: 'https://vuejs.org',
text: 'Документация Vue',
external: true,
})
</script>Обратите внимание: если атрибут равен null или undefined, Vue полностью убирает его из DOM-элемента.
Эмуляция v-bind: динамическая установка атрибутов DOM-элемента через объект с настройками
// Эмулируем поведение v-bind — динамическое применение атрибутов к элементу.
// В Vue это делается декларативно в шаблоне, здесь показана логика "под капотом".
// Функция применяет объект атрибутов к DOM-элементу (или псевдо-элементу)
function applyBindings(element, bindings) {
for (const [attr, value] of Object.entries(bindings)) {
if (value === null || value === undefined) {
// v-bind удаляет атрибут если значение null/undefined
console.log(` Атрибут "${attr}" удалён (значение null/undefined)`)
delete element[attr]
} else {
element[attr] = value
console.log(` Атрибут "${attr}" = ${JSON.stringify(value)}`)
}
}
}
// Псевдо-DOM-элемент (в браузере это был бы document.createElement)
const pseudoElement = {}
// Начальное состояние — как v-bind на первом рендере
console.log('=== Начальный рендер ===')
applyBindings(pseudoElement, {
href: 'https://vuejs.org',
target: '_blank',
rel: 'noopener noreferrer',
disabled: null, // null — атрибут не добавляется
})
console.log('\nСостояние элемента:', pseudoElement)
// Обновление состояния — как v-bind при изменении реактивных данных
console.log('\n=== После обновления данных ===')
applyBindings(pseudoElement, {
href: 'https://vuejs.org/guide/',
target: '_self',
rel: null, // убираем rel
disabled: true, // теперь кнопка отключена
})
console.log('\nОбновлённое состояние:', pseudoElement)
// Эмуляция :class с объектом
console.log('\n=== Динамические классы (:class) ===')
function resolveClass(classObject) {
return Object.entries(classObject)
.filter(([, active]) => active)
.map(([name]) => name)
.join(' ')
}
const isPrimary = true
const isDisabled = false
const isActive = true
const className = resolveClass({
btn: true,
'btn-primary': isPrimary,
'btn-disabled': isDisabled,
active: isActive,
})
console.log('Итоговый класс:', className)
// btn btn-primary active
// Эмуляция :style с объектом
console.log('\n=== Динамические стили (:style) ===')
function resolveStyle(styleObject) {
return Object.entries(styleObject)
.map(([prop, val]) => `${prop}: ${val}`)
.join('; ')
}
const fontSize = 16
const textColor = '#333'
const isBold = true
const styleAttr = resolveStyle({
'font-size': fontSize + 'px',
color: textColor,
'font-weight': isBold ? 'bold' : 'normal',
})
console.log('Итоговый style:', styleAttr)Директива v-bind позволяет **динамически привязывать значения к HTML-атрибутам**. Без неё атрибуты всегда статические — значение задаётся прямо в шаблоне и не меняется. С v-bind значение атрибута берётся из переменной компонента и автоматически обновляется при её изменении.
<!-- Статический атрибут — всегда одинаковый -->
<a href="https://example.com">Ссылка</a>
<!-- Динамический атрибут — значение из переменной -->
<a v-bind:href="url">Ссылка</a>Директива v-bind используется настолько часто, что Vue предоставляет сокращение — двоеточие ::
<!-- Полная запись -->
<img v-bind:src="imageUrl" v-bind:alt="imageAlt">
<!-- Сокращённая запись (рекомендуется) -->
<img :src="imageUrl" :alt="imageAlt">
<script setup>
const imageUrl = ref('https://example.com/photo.jpg')
const imageAlt = ref('Фото пользователя')
</script>Если нужно привязать сразу несколько атрибутов, можно передать объект в v-bind без указания конкретного атрибута:
<template>
<input v-bind="inputAttrs">
</template>
<script setup>
const inputAttrs = reactive({
type: 'text',
placeholder: 'Введите текст',
maxlength: 100,
disabled: false,
})
</script>Это эквивалентно записи :type="inputAttrs.type" :placeholder="inputAttrs.placeholder" и т.д.
Привязка :class — одна из самых мощных возможностей v-bind. Можно передавать объект, где ключи — имена классов, а значения — условия их применения:
<template>
<button
:class="{
btn: true,
'btn-primary': isPrimary,
'btn-disabled': isDisabled,
active: isActive
}"
>
Кнопка
</button>
</template>Класс добавляется, только если значение в объекте равно true.
Директива :style принимает объект CSS-свойств. Имена свойств можно писать в camelCase или в кавычках в kebab-case:
<template>
<div :style="{
color: textColor,
fontSize: fontSize + 'px',
'background-color': bgColor,
fontWeight: isBold ? 'bold' : 'normal'
}">
Стилизованный блок
</div>
</template>
<script setup>
const textColor = ref('#333')
const fontSize = ref(16)
const bgColor = ref('#f5f5f5')
const isBold = ref(false)
</script>В редких случаях может понадобиться динамическое имя самого атрибута. Это делается через квадратные скобки:
<!-- attrName может быть 'href', 'src', 'disabled' и т.д. -->
<component :[attrName]="attrValue" /><template>
<a
:href="link.url"
:target="link.external ? '_blank' : '_self'"
:rel="link.external ? 'noopener noreferrer' : null"
>
{{ link.text }}
</a>
</template>
<script setup>
const link = reactive({
url: 'https://vuejs.org',
text: 'Документация Vue',
external: true,
})
</script>Обратите внимание: если атрибут равен null или undefined, Vue полностью убирает его из DOM-элемента.
Эмуляция v-bind: динамическая установка атрибутов DOM-элемента через объект с настройками
// Эмулируем поведение v-bind — динамическое применение атрибутов к элементу.
// В Vue это делается декларативно в шаблоне, здесь показана логика "под капотом".
// Функция применяет объект атрибутов к DOM-элементу (или псевдо-элементу)
function applyBindings(element, bindings) {
for (const [attr, value] of Object.entries(bindings)) {
if (value === null || value === undefined) {
// v-bind удаляет атрибут если значение null/undefined
console.log(` Атрибут "${attr}" удалён (значение null/undefined)`)
delete element[attr]
} else {
element[attr] = value
console.log(` Атрибут "${attr}" = ${JSON.stringify(value)}`)
}
}
}
// Псевдо-DOM-элемент (в браузере это был бы document.createElement)
const pseudoElement = {}
// Начальное состояние — как v-bind на первом рендере
console.log('=== Начальный рендер ===')
applyBindings(pseudoElement, {
href: 'https://vuejs.org',
target: '_blank',
rel: 'noopener noreferrer',
disabled: null, // null — атрибут не добавляется
})
console.log('\nСостояние элемента:', pseudoElement)
// Обновление состояния — как v-bind при изменении реактивных данных
console.log('\n=== После обновления данных ===')
applyBindings(pseudoElement, {
href: 'https://vuejs.org/guide/',
target: '_self',
rel: null, // убираем rel
disabled: true, // теперь кнопка отключена
})
console.log('\nОбновлённое состояние:', pseudoElement)
// Эмуляция :class с объектом
console.log('\n=== Динамические классы (:class) ===')
function resolveClass(classObject) {
return Object.entries(classObject)
.filter(([, active]) => active)
.map(([name]) => name)
.join(' ')
}
const isPrimary = true
const isDisabled = false
const isActive = true
const className = resolveClass({
btn: true,
'btn-primary': isPrimary,
'btn-disabled': isDisabled,
active: isActive,
})
console.log('Итоговый класс:', className)
// btn btn-primary active
// Эмуляция :style с объектом
console.log('\n=== Динамические стили (:style) ===')
function resolveStyle(styleObject) {
return Object.entries(styleObject)
.map(([prop, val]) => `${prop}: ${val}`)
.join('; ')
}
const fontSize = 16
const textColor = '#333'
const isBold = true
const styleAttr = resolveStyle({
'font-size': fontSize + 'px',
color: textColor,
'font-weight': isBold ? 'bold' : 'normal',
})
console.log('Итоговый style:', styleAttr)Напиши функцию `resolveBindings(state)`, которая принимает объект состояния и возвращает объект с атрибутами для ссылки. Если `state.external === true`, атрибут `target` должен быть `"_blank"` и должен быть атрибут `rel: "noopener noreferrer"`. Если `state.disabled === true`, добавь `disabled: true`. Если `state.external === false`, атрибуты `target` и `rel` должны быть `null`.
Используй тернарный оператор для условных значений: `target: state.external ? "_blank" : null`. Собери объект с нужными полями и верни его.
Токены для AI-помощника закончились
Купи токены чтобы задавать вопросы AI прямо в уроке