Read this on my blog Hey all! Yesterday I gave my talk on Nuxt server components at Nuxt Nation (which is currently still happening if you want to check it out). Next week I'll be giving a talk on Nuxt layers at VueConf Toronto. Other than that, I hope you're having a great week! Enjoy the tips, new podcast episode, and articles. — Michael 🔥 Smooth dragging (and other mouse movements) If you ever need to implement dragging or to move something along with the mouse, here's how you do it: - Always throttle your mouse events using
requestAnimationFrame . Lodash's throttle method with no wait parameter will do this. If you don't throttle, your event will fire faster than the screen can even refresh, and you'll waste CPU cycles and the smoothness of the movement. - Don't use absolute values of the mouse position. Instead, you should check how far the mouse has moved between frames. This is a more reliable and smoother method. If you use absolute values, the element's top-left corner will jump to where the mouse is when you first start dragging. Not a great UX if you grab the element from the middle.
Here's a basic example of tracking mouse movements using the Composition API. I didn't include throttling in order to keep things clearer: // In your setup() function window.addEventListener("mousemove", (e) => { // Only move the element when we're holding down the mouse if (dragging.value) { // Calculate how far the mouse moved since the last // time we checked const diffX = e.clientX - mouseX.value; const diffY = e.clientY - mouseY.value; // Move the element exactly how far the mouse moved x.value += diffX; y.value += diffY; } // Always keep track of where the mouse is mouseX.value = e.clientX; mouseY.value = e.clientY; });
<template> <div class="drag-container"> <img alt="Vue logo" src="./assets/logo.png" :style="{ left: `${x}px`, top: `${y}px`, cursor: dragging ? 'grabbing' : 'grab', }" draggable="false" @mousedown="dragging = true" /> </div> </template>
<script setup> import { ref } from "vue"; const dragging = ref(false); const mouseX = ref(0); const mouseY = ref(0); const x = ref(100); const y = ref(100); window.addEventListener("mousemove", (e) => { if (dragging.value) { const diffX = e.clientX - mouseX.value; const diffY = e.clientY - mouseY.value; x.value += diffX; y.value += diffY; } mouseX.value = e.clientX; mouseY.value = e.clientY; }); window.addEventListener("mouseup", () => { dragging.value = false; }); </script>
🔥 Nested Ref Properties in Templates One thing that's a little tedious with refs is when you need to access a nested property within the template: <template> <div id="app"> <p v-for="el in arr"></p> </div> </template>
const arr = reactive([]); arr.push(ref({ text: 'hello' })); arr.push(ref({ text: 'world' })); setTimeout(() => (arr[0].value.text = 'nothing'), 1000);
You can't just rely on auto-unwrapping of refs, you have to explicitly access the .value and then grab the nested property from there: ref.value.nestedProperty
In this case, using a reactive value might be preferable — if the syntax is really bothering you. 🔥 Easily Mock API Routes in Nuxt If you've ever written unit tests, you'll have needed to mock out API endpoints that are used in your components or stores. With @nuxt/test-utils this is really simple, because you get the registerEndpoint utility method: import { registerEndpoint } from '@nuxt/test-utils/runtime'; import userTestData from './userTestData.json'; registerEndpoint('/users/', () => userTestData); // ...tests
You can mock any server route (API endpoint), including external endpoints if you need. 🎙️ #033 — Vue or React? (with CJ from Syntax) Alex is accompanied by the wonderful CJ Reynolds in this episode of DejaVue. The Senior Creator at Syntax.fm brings not only Vue experience but also a history of Angular JS and React, as well as various other technologies. The two content creators talk about how CJ became a senior creator at the well-known Syntax.fm podcast and how it is different from streaming on Twitch and his previous content creation processes. Further, CJ gives insights on how the Denver Vue meetup evolved (now the DenverScript meetup) and shares some hopes when it comes to the meetup scene. Alex and CJ then discuss more technical topics - for example why CJ never fully switched over to Vue but still writes it a lot. The discussion eventually goes into comparisons between Vue and React, highlighting what Vue does "better" than React and how the Vue ecosystem shapes the web development work. Watch on YouTube or listen on your favorite podcast platform. Chapters: In case you missed them: 📜 Controlling When Components Are Loaded in Nuxt Nuxt gives us a few different options for controlling when components are loaded. In this article I explore the different options and how to use each. Check it out here: Controlling When Components Are Loaded in Nuxt 📜 Custom Error Pages in Nuxt Custom error pages are a great way to give your users a better experience when something goes wrong. In this article, we'll go over how to create them in Nuxt. Check it out here: Custom Error Pages in Nuxt 📅 Upcoming Events Here are some upcoming events you might be interested in. Let me know if I've missed any! VueConf Toronto 2024 — (November 18, 2024 to November 20, 2024) My favourite Vue conference, in my own backyard! A three-day event with workshops, speakers from around the world, and socializing. I will be speaking on Nuxt Layers! Check it out here Vuejs Amsterdam 2025 — (March 12, 2025 to March 13, 2025) The biggest Vue conference in the world! A two-day event with workshops, speakers from around the world, and socializing. Check it out here 💬 Less Documentation "The best reaction to "this is confusing, where are the docs" is to rewrite the feature to make it less confusing, not write more docs." — Jeff Atwood 🧠 Spaced-repetition: Hybrid API: Composition API + Options API The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨🔬 Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory. You don't have to decide between Options API and Composition API, you can use both: export default { setup() { const darkMode = ref(false); return { darkMode } }, methods: { saveDarkMode() { localStorage.setItem('dark-mode', this.darkMode); }, } };
We can also update values from the Options API: export default { setup() { const darkMode = ref(false); return { darkMode } }, methods: { changeTheme(val) { this.darkMode = val; } } };
Although you can access Composition API from the Options API, it's a one-way street. The Composition API cannot access anything defined through the Options API: export default { setup() { const darkMode = ref(false); // We can't access the method this.changeTheme(true); return { darkMode } }, methods: { changeTheme(val) { this.darkMode = val; } }
This can be useful for incremental adoption of the Composition API, because it lets you use reusable composables in your Options API. But mixing two styles of writing components is likely to cause more headaches than it solves, so please think twice before doing this! 🔗 Want more Vue and Nuxt links? Michael Hoffman curates a fantastic weekly newsletter with the best Vue and Nuxt links. Sign up for it here.
p.s. I also have four products/courses: Clean Components Toolkit, Vue Tips Collection 2, Mastering Nuxt 3, and Reusable Components |
评论
发表评论