var RecursiveComponent = {
name: 'recursive-component',
props: ['i'],
setup() {
const open = ref(false)
return { open }
},
template: `
<div>
<recursive-component v-if="open" :i="i ? i+1 : 1"></recursive-component>
<button @click="open=!open">toggle {{i}}</button>
</div>
`
}
Vue.createApp({
components: { RecursiveComponent },
setup() {
return {
message: 'Привет Vue!'
}
}
}).mount('#app');
<div id="app">
{{ message }}
<recursive-component></recursive-component>
</div>
$emit
и @on
, вниз props
.<b class="aaakjhij" data="hk">jjj!!!!</b>
должно быть уже в шаблоне. Если надо по условию - то использовать v-if или v-for если несколько.<script>
export default {
data() {
return {
data: 'hk',
text: 'jjj!!!!',
show: false
}
},
methods: {
_jjj(){
this.show = true
this.data = 'hk';
this.text = 'jjj!!!!';
},
_kkk(){
this.data = 'ooooooooooo';
this.text = 'ha-ha-haaaa!!!'
}
}
}
</script>
<template>
<div>
<b v-if="show" :data="data">{{text}}</b>
</div>
<button @click="_jjj">11</button>
<button @click="_kkk">12</button>
</template>
import { Ref, computed, ref, watch, onMounted, onUnmounted } from 'vue';
function isHTMLElement(arg: unknown): arg is HTMLElement {
return !!arg && arg instanceof HTMLElement;
}
function useCSSVariable(
variable: string,
el: HTMLElement | Ref<HTMLElement> = document.documentElement
) {
if (!variable.startsWith('--')) variable = `--${variable}`;
if (!isHTMLElement(el)) watch(el, value => (el = value), { immediate: true });
const prev = ref();
let timeoutId: number;
const interval = () => {
const current = isHTMLElement(el)
? getComputedStyle(el).getPropertyValue(variable)
: null;
if (current !== prev.value) prev.value = current;
timeoutId = window.setTimeout(interval, 100);
};
onMounted(() => {
interval();
});
onUnmounted(() => {
clearTimeout(timeoutId);
});
return computed<string>({
set(value) {
let current: null | string = null;
if (isHTMLElement(el)) {
el.style.setProperty(variable, value);
current = el.style.getPropertyValue(variable);
}
if (prev.value !== current) prev.value = current;
},
get() {
return prev.value;
}
});
}
this.$set \ Vue.set
при добавлении нового ключа.const templates = reactive(keyBy(templatesArr, 'id'))
for (let templateId in templates) {
const devices = devicesArr.filter(device => device.templateId === templateId)
Vue.set(templates[templateId], 'devices', devices);
Vue.set(templates[templateId], 'settings', {});
}
// либо просто так:
const templates = keyBy(templatesArr, 'id');
for (let templateId in templates) {
const devices = devicesArr.filter(device => device.templateId === templateId)
Object.assign(templates[templateId], { devices }, {settings: {}})
}
reactive(templates);
reactive
, вместо него был Vue.observable
. Но может добавили, хз, лень смотреть.:) <template>
<input class="hover--red"/>
</template>
<style>
.hover--red:hover {
color: #f00
}
</style>
<script setup>
// ...
const hoverColor = '#f00'
</script>
<template>
<input :style="{'--hover-color': hoverColor}"/>
</template>
<style>
input:hover {
color: var(--hover-color)
}
</style>
v-bind
в <style>
:<script setup>
// ...
const hoverColor = '#f00'
</script>
<template>
<input />
</template>
<style>
input:hover {
color: v-bind(hoverColor)
}
</style>
If you prefer a plain HTML setup without any build steps, you can use this JSFiddle as your starting point.
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
}
}
</script>
<div id="app">{{ message }}</div>
<script type="module">
import { createApp } from 'vue'
createApp({
data() {
return {
message: 'Hello Vue!'
}
}
}).mount('#app')
</script>
<SomeComponent :someProp=""val"/>
<some-component :some-prop=""val"></some-component>
Почему? Птому что 1 - html регистронезависимый и SomeComponent
читается как somecomponent
, а vue такого не знает, 2 - список тэгов которые могут самозакрываться ограничен. function popupLibraryOpen() {
isLibraryOpen.value = true
}
<MyButton @click="popupLibraryOpen">Библиотека игр</MyButton>
<MyButton @click="isLibraryOpen = true">Библиотека игр</MyButton>
<div>
<p>1111</p>
<v-cost />
</div>
<div>
<p>22222</p>
<v-cost />
</div>
<div v-for="{ title } in arr" :key="title">
<p>{{title}}</p>
<div class="cost">
<div class="cost__title">test:</div>
<div class="cost__number">3 400 </div>
</div>
</div>
render
функции, но там уже никаких шаблонов - чистый код. Тема "продвинутая", и в твоём случае явно не нужная, так разбирайся сам если хочешь.:) if (el === event.target || el.contains(event.target)) {
-> if (el !== event.target && !el.contains(event.target)) {
-> if (!el.contains(event.target)) {
// contains работает на самого себя, дополнительно проверять не надо
@click
.value
, иначе у тебя директива поломается при его реактивном изменении(обычно конечно не меняют, но зачем закладывать бомбу?). useApiFetch
, очень многое в vue 3 можно сломать неудачной деструктуризацией. Но допустим сам хук нормальный.isPending
- это ref
, а значит он и должен быть прокси, чтоб собственно работала энтая самая реактивность. Чтоб отобразить в консоли чистый объект - есть хэлпер toRaw
(только после этого он уже не будет динамическим).isPending.value
- то в консоль, очевидно, попадает значение на момент вызова console.log
. Магическим образом прямо в консоли оно уже не изменится.isPending
- можешь сделать так:watch(isPending, (value) => console.log('watch isPending', value), { immediate: true });
{
beforeCreate() {
this._oldTitle = document.title;
},
unmounted() {
if (this.PAGE_TITLE)
document.title = this._oldTitle;
},
watch: {
PAGE_TITLE: {
handler(val, oldVal) {
if (val)
document.title = val;
else
document.title = this._oldTitle;
},
immediate: true
},
}
}
this.PAGE_TITLE
. const PAGE_TITLE = ref('<title>'); // computed(() => ...)
// ...
return {
PAGE_TITLE,
// ...
}
+ expose({ PAGE_TITLE })
foo?.bar
) или nullish coalescing (foo ?? bar
), а версия браузера у вас там старая и не поддерживает такой фичи.Chrome <= 70
(а не last 1
, что там скорее всего по умолчанию), чтоб при билде он эти фичи заменил на старые альтернативы.