<!--https://stackoverflow.com/questions/63652288/does-vue-3-teleport-only-works-to-port-outside-vue-->
<template>
<Teleport :to="to" v-if="isMounted"><slot></slot></Teleport>
</template>
<script>
export default {
name: "MountedTeleport",
props: ['to'],
data() {
return {isMounted: false}
},
mounted() {
this.isMounted = true;
}
}
</script>
<!-- https://codepen.io/sandrarodgers/pen/porZbxW -->
<template>
<div id="app">
<div>Height: {{ height }}</div>
<div>Width: {{ width }}</div>
</div>
</template>
<script>
export default {
data() {
return {
debouncedHeight: 0,
debouncedWidth: 0,
heightTimeout: null,
widthTimeout: null
};
},
computed: {
height: {
get() {
return this.debouncedHeight;
},
set(val) {
if (this.timeout) clearTimeout(this.timeout);
this.heightTimeout = setTimeout(() => {
this.debouncedHeight = val;
}, 5000);
}
},
width: {
get() {
return this.debouncedWidth;
},
set(val) {
if (this.timeout) clearTimeout(this.timeout);
this.widthTimeout = setTimeout(() => {
this.debouncedWidth = val;
}, 5000);
}
},
},
methods: {
resizeHandler(e) {
this.height = window.innerHeight;
this.width = window.innerWidth;
},
},
mounted() {
this.height = window.innerHeight;
this.width = window.innerWidth;
},
created() {
window.addEventListener("resize", this.resizeHandler);
},
destroyed() {
window.removeEventListener("resize", this.resizeHandler);
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
font-size: 1.5rem;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
data() {
return {
// https://medium.com/@trukrs/type-safe-javascript-with-jsdoc-7a2a63209b76
// https://devhints.io/jsdoc
// better suggestion ... eg: this.overlay?. + tab
/**
* @type {boolean}
*/
delaySet: false, // je nastaveny delay?
/**
* @type {?number}
*/
timeout: null, // timeout delay
/**
* @type {number}
*/
ttlIn: 400, // delka prodlevy najeti
/**
* @type {number}
*/
ttlOut: 300, // delka prodlevy pri odjeti
/**
* @type {HTMLElement}
*/
overlay: null, // HTML prvek zacileneho overlaySelector-u
/**
* @type {Array}
*/
listChildren: [] // LI-cka pod zacilenym UL-kem
}
},
<!-- 1) From Child to Parent via scoped slot and dynamic ref-->
<!-- App.vue-->
<template>
<div id="app">
<HelloWorld v-slot="{ setRef }">
<input type="text" :ref="(el) => setRef(el)" />
</HelloWorld>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue';
export default {
name: 'App',
components: {
HelloWorld,
},
};
</script>
<!-- Hello world -->
<template>
<slot v-bind="{ setRef }"></slot>
<button @click="setFocus">SET</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
ref: ''
}
},
methods: {
setFocus()
{
this.ref.focus()
},
setRef(el) {
this.ref = el
console.log(el)
}
}
}
</script>
<template>
<ClickWait color="red" @click="doFoo">Darn Button</ClickWait>
<AnotherClickWait style="background-color:#c0c0c0" @click="doFoo">One More Darn Button</AnotherClickWait>
</template>
import ClickWait from '@/components/ClickWait.vue';
import AnotherClickWait from '@/components/AnotherClickWait.vue';
export default {
name: "App",
components: {
ClickWait, AnotherClickWait
},
methods:{
doFoo(done) {
setTimeout(() => {
console.log('im done with whatever biz logic');
done();
},3000);
}
}
};
// https://www.raymondcamden.com/2021/05/08/updating-and-supporting-url-parameters-with-vuejs
// hard coded for simplicity...
const ITEMS = [
{ name: "Ray", type: "person" },
{ name: "Lindy", type: "person" },
{ name: "Jacob", type: "person" },
{ name: "Lynn", type: "person" },
{ name: "Noah", type: "person" },
{ name: "Jane", type: "person" },
{ name: "Maisie", type: "person" },
{ name: "Carol", type: "person" },
{ name: "Ashton", type: "person" },
{ name: "Weston", type: "person" },
{ name: "Sammy", type: "cat" },
{ name: "Aleese", type: "cat" },
{ name: "Luna", type: "cat" },
{ name: "Pig", type: "cat" },
{ name: "Cayenne", type: "dog" }
]
const app = new Vue({
el:'#app',
data: {
allItems: ITEMS,
filter:'',
typeFilter:[]
},
created() {
let qp = new URLSearchParams(window.location.search);
let f = qp.get('filter');
if(f) this.filter = qp.get('filter');
let tf = qp.get('typeFilter');
if(tf) this.typeFilter = tf.split(',');
},
computed: {
items() {
this.updateURL();
return this.allItems.filter(a => {
if(this.filter !== '' && a.name.toLowerCase().indexOf(this.filter.toLowerCase()) === -1) return false;
if(this.typeFilter.length && !this.typeFilter.includes(a.type)) return false;
return true;
});
}
},
methods:{
updateURL() {
let qp = new URLSearchParams();
if(this.filter !== '') qp.set('filter', this.filter);
if(this.typeFilter.length) qp.set('typeFilter', this.typeFilter);
history.replaceState(null, null, "?"+qp.toString());
}
}
});
<!--
https://chafikgharbi.com/vuejs-nexttick/
https://codepen.io/chafikgharbi/pen/WNGarPG
-->
<template>
<div id="app">
<div ref="box" class="box">
<div v-for="(message, key) in messages" :key="key">{{message.body}}</div>
...
</div>
<button v-on:click="addMessage">Add message</button>
</div>
</template>
<style>
.box {
height: 100px;
width: 300px;
overflow: scroll;
border: 1px solid #000
}
</style>
<script>
export default {
name: "App",
data: () => {
return {
messages: [
{ body: "Message 1" },
{ body: "Message 2" },
{ body: "Message 3" },
{ body: "Message 4" },
{ body: "Message 5" }
]
};
},
methods: {
async addMessage() {
// Add message
this.messages.push({ body: `Message ${this.messages.length+1}`})
// Scroll bottom
this.$refs.box.scrollTop = this.$refs.box.scrollHeight
},
async addMessage() {
// Add message
this.messages.push({ body: `Message ${this.messages.length+1}`})
// Wait for DOM to update
await this.$nextTick()
// Scroll bottom
this.$refs.box.scrollTop = this.$refs.box.scrollHeight
},
async addMessage() {
// Add message
this.messages.push({ body: `Message ${this.messages.length+1}`})
// Wait for DOM to updaten then scroll down
this.$nextTick(() => {
this.$refs.box.scrollTop = this.$refs.box.scrollHeight
})
}
}
};
</script>
import { ref, readonly } from 'vue';
const sharedVar = ref(false);
const toggleOutside = () => {
sharedVar.value = !sharedVar.value;
};
export const useTestState = () => {
const toggleInside = () => {
sharedVar.value = !sharedVar.value;
};
return {
sharedVar: readonly(sharedVar),
toggleOutside,
toggleInside,
};
};