Javascript is required
Weekly Vue News Logo Weekly Vue News
a { color: #42B883; text-decoration: none; } a:hover { color: #33a06f } .overflow-auto { overflow: auto } p {margin: 5px 0px} .ct-36e85c{color:#6A9955} .ct-8f9f80{color:#C8C8C8} .ct-ae5419{color:#808080} .ct-78eef5{color:#9CDCFE} .ct-0d8ec4{color:#B5CEA8} .ct-c2bbeb{color:#CE9178} .ct-c746e8{color:#DCDCAA} .ct-b1c360{color:#4FC1FF} .ct-220622{color:#569CD6} .ct-e8c10a{color:#C586C0} .ct-f3f815{color:#D4D4D4} FOLLOW_UP_PLACEHOLDER

#title Weekly Vue News #91 - Declare and Mutate v-model Props as Normal Variable Using defineModel #preview Ready for your weekly Vue & Nuxt dose?

View and discuss online, Weekly Vue News #91

Declare and Mutate v-model Props as Normal Variable Using defineModel

Hi πŸ‘‹

Last week I focused on enhancing the code coverage of E2E tests for,, and

In this week's issue, I provide a valuable tip for improving your development workflow. We'll explore how to declare and mutate v-model props as normal variables using defineModel.

But that's not all! I've curated a collection of exceptional content related to Vue.js, Nuxt.js and web development in general.

So, get ready to level up your Vue.js and Nuxt.js skills and stay at the forefront of web development. Let's embark on this exciting journey together!

Have a lovely week β˜€οΈ

To support me:

Vue Tip: Declare and Mutate v-model Props as Normal Variable Using defineModel

This experimental feature will be available in Vue 3.3. If you want to try it out now in Vue 2 or Vue 3, you can use it with the Vue Macros library.

defineModel is a compiler macro that allows you to declare and mutate v-model props as the same as a normal variable.

Example without defineModel

Let's take a look at a simple example that uses v-model. We have a Parent.vue component that passes a counter ref to a Child.vue component:

1<script setup lang="ts">
2import { ref } from 'vue'
3import Child from './components/Child.vue'
5const state = ref({ count: 0 })
9 <div>
10 <span>Parent state: {{ state }}</span>
11 <Child v-model="state.count" />
12 </div>

Let's take a look at the implementation of the child component:

1<script setup lang="ts">
2import { ref } from 'vue'
4const props = defineProps<{ modelValue: number }>()
6const emit = defineEmits<{
7 (e: 'update:modelValue', value: number): void
10const onClick = () => {
11 props.modelValue += 1
12 emit('update:modelValue', props.modelValue)
17 <div>
18 <span>Child state: {{ modelValue }}</span>
19 <button @click="onClick">Increment child state</button>
20 </div>

As Child.vue receives the v-model you need to declare a prop called modelValue which receives the v-model value. Additionally, you need to declare an emit called update:modelValue that is used to update the parent that the modelValue has been updated.

As props are readonly and you should not mutate them, you cannot update modelValue and will receive the following warning:

Set operation on key "modelValue" failed: target is readonly.

I wrote a tip about this topic and how you can solve this warning. defineModel provides a nice solution to this problem, so let's take a look at it.

Example with defineModel

In the following example, I'm using Vue Macros's defineModels which behaves identically to defineModel available since Vue 3.3.0-alpha.9

We can simplify our child component by using defineModels:

1<script setup lang="ts">
2const { modelValue, count } = defineModels<{
3 modelValue: number
6const onClick = () => {
7 modelValue.value += 1
12 <div class="container">
13 <span>Child with defineModels state: {{ modelValue }}</span>
14 <button @click="onClick">Increment child state</button>
15 </div>

The defineModels compiler macro will declare a prop with the same name and a corresponding update:propName event when it is compiled.

By updating the modelValue ref, the corresponding update:propName event is automatically emitted.

Try it yourself in the following StackBlitz project:

⚑ Open DemoCurated Vue & Nuxt ContentπŸ“• Vue.js Certification

πŸ‘‰πŸ» The official certification of competence for the Vue.js Framework is now available.
πŸ› οΈ Nuxt SEO Kit
πŸ‘‰πŸ» An amazing All-In-One SEO layer for Nuxt 3 by @harlan_zw
πŸ‘‰πŸ» Supports robots.txt, HTTP header, meta tags, sitemap.xml, and much more
πŸ“• Advanced Data Fetching with Nuxt 3
When refreshing async data, when should you use refresh vs watch source?
πŸ‘‰πŸ» Use refresh() when you know server side data has changed
πŸ‘‰πŸ» Use a watch source when the data loaded is dependent upon client side data
πŸ“• Handling Assets in Nuxt 3
πŸ‘‰πŸ» Nuxt 3 gives us two great options for managing all of our assets in our web app.
πŸ‘‰πŸ» But what’s the difference, and how do you know which to use?
πŸ“• Vite 4.3 is out!

πŸ‘‰πŸ» A minor release of the popular frontend toolchain, but one that focuses on performance.
Quote of the weekCurated Web Development ContentπŸ“• Introducing npm package provenance
πŸ‘‰πŸ» Verifiably link npm packages to their source repository and build instructions.
πŸ‘‰πŸ» Developers building npm projects on GitHub Actions can now publish provenance alongside their packages.
πŸ“• How Passwordless Works
πŸ‘‰πŸ» This post explains how passwordless can be implemented using modern technologies such as WebAuthn
πŸ‘‰πŸ» Passwordless provides a better user experience and security than the traditional password-based approach.
πŸ“• A list of programming playgrounds

πŸ‘‰πŸ» This is a very handy list of places for you to code online without having to install anything on your machine.
πŸ“• What's New in DevTools (Chrome 113)
πŸ‘‰πŸ» Chrome 113 will allow you to override network response headers, including CORS headers.
πŸ‘‰πŸ» It also offers Nuxt, Vite, and Rollup debugging improvements.
Comments? Join the discussion about this issue here.

Until next week,

Michael Hoffmann (Curator) Share via Facebook Twitter LinkedIn Unsubscribe from this newsletter
Holzapfelkreuther Str. 19, 81375 Munich, Germany
Weekly Vue News LogoWeekly newsletter that gives you high-quality tips and curated content about Vue & Nuxt.
I will never share any of your personal data.
Β© 2023 All rights reserved.