<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ibrahim Zbib</title>
    <description>The latest articles on DEV Community by Ibrahim Zbib (@ibrahim_zbib_9806de6128af).</description>
    <link>https://dev.to/ibrahim_zbib_9806de6128af</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3636359%2F50c4ba6d-2745-499c-8572-19d9237b5db1.png</url>
      <title>DEV Community: Ibrahim Zbib</title>
      <link>https://dev.to/ibrahim_zbib_9806de6128af</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ibrahim_zbib_9806de6128af"/>
    <language>en</language>
    <item>
      <title>Latest Updates in Vue</title>
      <dc:creator>Ibrahim Zbib</dc:creator>
      <pubDate>Sat, 29 Nov 2025 18:19:20 +0000</pubDate>
      <link>https://dev.to/ibrahim_zbib_9806de6128af/latest-updates-in-vue-3p38</link>
      <guid>https://dev.to/ibrahim_zbib_9806de6128af/latest-updates-in-vue-3p38</guid>
      <description>&lt;p&gt;The objective of this page is to provide a quick and easy reference to some of the feature update from Vue 3.3 to Vue 3.5, onwards in order to modernize, optimize and clean ones codebase with new features and updates to legacy features.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 Legacy Macros

&lt;ul&gt;
&lt;li&gt;1.1 defineProps()&lt;/li&gt;
&lt;li&gt;1.2 withDefaults()&lt;/li&gt;
&lt;li&gt;1.3 defineEmits()&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;2 Legacy Features

&lt;ul&gt;
&lt;li&gt;2.1 Computed()&lt;/li&gt;
&lt;li&gt;2.2 Watch()&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;3 New Macros

&lt;ul&gt;
&lt;li&gt;3.1 defineModel()&lt;/li&gt;
&lt;li&gt;3.2 defineSlots()&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;4 New Features

&lt;ul&gt;
&lt;li&gt;4.1 useTemplateRefs()&lt;/li&gt;
&lt;li&gt;4.2 useId()&lt;/li&gt;
&lt;li&gt;4.3 onWatcherCleanup()&lt;/li&gt;
&lt;li&gt;4.4 data-allow-mismatch&lt;/li&gt;
&lt;li&gt;4.5 Shortened v-bind&lt;/li&gt;
&lt;li&gt;4.6 Generic Component&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;5 Lazy Hydration Strategies
&lt;/li&gt;

&lt;li&gt;6 Typescript Composition Api
&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Legacy Macros
&lt;/h2&gt;

&lt;h3&gt;
  
  
  defineProps()
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Reactive Destructured Props
&lt;/h4&gt;

&lt;p&gt;Props can now be destructured and assigned default values the way objects do from a &lt;strong&gt;defineProps&lt;/strong&gt; call&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const {
  foo = 'hello', // optional
  bar // required - see defined type and no default value assigned
} = defineProps&amp;lt;{ foo?: string, bar: string }&amp;gt;()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to retain the reactivity of destructured props values, is important to wrap them in getters outside the template&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;watch(foo /* ... */) // ❌ -&amp;gt; throws error in complie-time, 'foo' by it's self isn't a reactive value
watch(() =&amp;gt; foo /* ... */) // ✅ -&amp;gt; wrap 'foo' in getter, in order to make it reactive (behaves like [ref_variable].value)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Typescript
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Type Handling with Props
&lt;/h5&gt;

&lt;p&gt;Typescript now handles validation type-checking in compile-time&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Props { msg?: string labels?: string[] };
const { msg = 'hello', labels = ['one', 'two'] } = defineProps&amp;lt;Props&amp;gt;()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  See More
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vuejs.org/guide/components/props#reactive-props-destructure" rel="noopener noreferrer"&gt;https://vuejs.org/guide/components/props#reactive-props-destructure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://vuejs.org/guide/typescript/composition-api#typing-component-props" rel="noopener noreferrer"&gt;https://vuejs.org/guide/typescript/composition-api#typing-component-props&lt;/a&gt; &lt;strong&gt;[TS]&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;See different patterns of defining props via&lt;/li&gt;
&lt;li&gt;Type-based props declarations (checks and validates compile time)&lt;/li&gt;
&lt;li&gt;Run-time props declaration&lt;/li&gt;
&lt;li&gt;Combining Type-based and Run-time Validation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  withDefaults() [Only supported on Typescript]
&lt;/h3&gt;

&lt;p&gt;Alternative to destructuring props like an object, one can keep props wrapped in props object and assign defaults with the &lt;strong&gt;withDefaults&lt;/strong&gt; vue-typescript macro&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;⚠️ Make sure to wrap default values of props that are &lt;strong&gt;objects or  arrays&lt;/strong&gt; in &lt;strong&gt;withDefaults&lt;/strong&gt; with &lt;strong&gt;getter function&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Typescript
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Props {
 msg?: string
labels?: string[]
};

const props = withDefaults(
 defineProps&amp;lt;Props&amp;gt;(),
 {
   msg: 'hello',
   labels: () =&amp;gt; ['one', 'two'] // array and object defaults must be wrapped in getter func
 }
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  See More
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vuejs.org/guide/typescript/composition-api#props-default-values" rel="noopener noreferrer"&gt;https://vuejs.org/guide/typescript/composition-api#props-default-values&lt;/a&gt; &lt;strong&gt;[TS]&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vuejs.org/api/sfc-script-setup#default-props-values-when-using-type-declaration" rel="noopener noreferrer"&gt;https://vuejs.org/api/sfc-script-setup#default-props-values-when-using-type-declaration&lt;/a&gt; &lt;strong&gt;[TS]&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  defineEmits()
&lt;/h3&gt;

&lt;p&gt;Some compatibility enhancements made with Typescript&lt;/p&gt;

&lt;h4&gt;
  
  
  Typescript
&lt;/h4&gt;

&lt;p&gt;The emit function can also be typed using either &lt;em&gt;&lt;strong&gt;runtime declaration OR type declaration&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Runtime Declaration
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup lang="ts"&amp;gt;
//runtime
const emit = defineEmits(['change', 'update', 'submit']);
emit('change', 'hello'); // ✅
emit('update', 'world'); // ✅
emit('submit', '!'); // ✅ -&amp;gt; ⚠️ although payload passed in will be ignored by callback func
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Type Declaration
&lt;/h5&gt;

&lt;h6&gt;
  
  
  Older Syntax
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup lang="ts"&amp;gt;
// type-based
const emit = defineEmits&amp;lt;{ (e: 'change', id: number): void (e: 'update', value: string): void (e: 'submit'): void }&amp;gt;();
emit('change', 'hello'); // ✅
emit('update', 'world'); // ✅
emit('submit', '!'); // ❌ -&amp;gt; throws error in complie-time, no payload expected
emit('submit'); // ✅ -&amp;gt; no payload passed in, as expected
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  Newer Syntax
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup lang="ts"&amp;gt;
// type-based
// 3.3+: alternative, more succinct syntax
const emit = defineEmits&amp;lt;{
change: [id: number]
update: [value: string]
submit: []; // Event with no payload
}&amp;gt;();
emit('change', 'hello'); // ✅
emit('update', 'world'); // ✅
emit('submit', '!'); // ❌ -&amp;gt; throws error in complie-time, no payload expected
emit('submit'); // ✅ -&amp;gt; no payload passed in, as expected
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  See More
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vuejs.org/api/sfc-script-setup#defineprops-defineemits" rel="noopener noreferrer"&gt;https://vuejs.org/api/sfc-script-setup#defineprops-defineemits&lt;/a&gt; &lt;strong&gt;[TS]&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vuejs.org/guide/typescript/composition-api.html#typing-component-emits" rel="noopener noreferrer"&gt;https://vuejs.org/guide/typescript/composition-api.html#typing-component-emits&lt;/a&gt; &lt;strong&gt;[TS]&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vuejs.org/guide/components/events" rel="noopener noreferrer"&gt;https://vuejs.org/guide/components/events&lt;/a&gt; &lt;strong&gt;[TS]&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Legacy Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Computed()
&lt;/h3&gt;

&lt;p&gt;The computed wrapper getter function now accepts the previous value as a param to the getter function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const somethingComputed = computed( (previousValue) =&amp;gt; somethingRef.value || previousValue );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// previousValue can only be accessed in getter function

const somethingComputed = computed({
  get: (previousValue) =&amp;gt; somethingRef.value || previousValue,
  set: (newValue) =&amp;gt; {
      somethingRef.value = newValue;
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Typescript
&lt;/h4&gt;

&lt;p&gt;Example below demonstrates how computed can be type defined in Typescript&lt;/p&gt;

&lt;p&gt;Below the computed getter will throw an error if it returns anything other then type ‘number’&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const double = computed&amp;lt;number&amp;gt;(() =&amp;gt; count.value * 2);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Watch()
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Once
&lt;/h4&gt;

&lt;p&gt;The watch now accepts a new new optional parameter called &lt;strong&gt;once&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Implied by the name:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If once is true → watch callback function only executes once&lt;/li&gt;
&lt;li&gt;If once is false → keeps usual behavior and watch callback function is called on eacvh reactive update&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By default the value is false for this optional parameter&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;watch(() =&amp;gt; something.value, () =&amp;gt; {}, { once: false }); // 'once' false by default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;watch(() =&amp;gt; something.value, () =&amp;gt; {}, { once: true }); // executes only once
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Flush
&lt;/h4&gt;

&lt;p&gt;The watch now accepts a new new optional parameter called &lt;strong&gt;flush&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This option controls the timing of the callback function's execution relative to when the component is rendered.&lt;/p&gt;

&lt;h5&gt;
  
  
  Pre (default)
&lt;/h5&gt;

&lt;p&gt;The callback runs before the component's render function is executed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// runs callback before DOM is mounted or updated
watch(() =&amp;gt; something.value, () =&amp;gt; {}, { flush: 'pre' }); // default value for 'flush'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Post
&lt;/h5&gt;

&lt;p&gt;The callback runs after the component's render function has executed and the DOM has been updated&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// runs callback after DOM is mounted or updated
watch(() =&amp;gt; something.value, () =&amp;gt; {}, { flush: 'post' });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  New Macros
&lt;/h2&gt;

&lt;h3&gt;
  
  
  defineModel()
&lt;/h3&gt;

&lt;p&gt;Simplifies the experience of 2-way binding in Vue with v-model&lt;/p&gt;

&lt;h4&gt;
  
  
  Type
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function defineModel&amp;lt;T = any&amp;gt;(
  options?: object // see 'optional params' below
): Ref&amp;lt;T&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  v-model - Before vs Now
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt; we would&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; have to declare modelValue in props&lt;/li&gt;
&lt;li&gt; also updates it’s value via emit event
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- ChildComponent.vue --&amp;gt;
&amp;lt;!-- BEFORE --&amp;gt;
&amp;lt;script setup&amp;gt;
const props = defineProps(['modelValue']);
const emit = defineEmits(['update:modelValue']);
console.log(props.modelValue);
function onInput(e) {
  emit('update:modelValue', e.target.value);
} &amp;lt;/script&amp;gt;
&amp;lt;template&amp;gt;
&amp;lt;input :value="modelValue" @input="onInput" /&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now&lt;/strong&gt; prop registration and modelValue update event are handled by &lt;strong&gt;defineModel&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;defineModel&lt;/strong&gt; returns a ref value which can be directly accessed and updated&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- ChildComponent.vue --&amp;gt;
&amp;lt;!-- NOW --&amp;gt;
&amp;lt;script setup&amp;gt;
const modelValue = defineModel();
// optional params defineModel({});

function onInput(e) {
  modelValue.value = e.target.value;
}
&amp;lt;/script&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;input v-model="modelValue" /&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Optional Params
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Option Name&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Example Usage&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;type&lt;/td&gt;
&lt;td&gt;Specifies the expected JavaScript type(s) for the prop (e.g., &lt;code&gt;number&lt;/code&gt;, &lt;code&gt;boolean&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;).&lt;/td&gt;
&lt;td&gt;&lt;code&gt;defineModel({ type: number })&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;required&lt;/td&gt;
&lt;td&gt;A boolean indicating if the parent component &lt;em&gt;must&lt;/em&gt; provide a value via &lt;code&gt;v-model&lt;/code&gt;.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;defineModel({ required: true })&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;default&lt;/td&gt;
&lt;td&gt;Sets a default value for the prop if the parent does not provide one.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;defineModel({ default: 'Hello' })&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;validator&lt;/td&gt;
&lt;td&gt;A function for custom prop validation.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;defineModel({ validator: (value) =&amp;gt; value &amp;gt; 0 })&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;local&lt;/td&gt;
&lt;td&gt;When &lt;code&gt;true&lt;/code&gt;, allows the ref to be mutated locally even if the parent didn't pass a corresponding &lt;code&gt;v-model&lt;/code&gt;, essentially making the two-way binding optional.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;defineModel({ local: true, default: 'hi' })&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Typescript
&lt;/h4&gt;

&lt;p&gt;Type based declarations are supported by defineModel in typescript&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup lang="ts"&amp;gt;
const modelValue = defineModel&amp;lt;string&amp;gt;() // ^? Ref&amp;lt;string | undefined&amp;gt;
// default model with options, required removes possible undefined values
const modelValue = defineModel&amp;lt;string&amp;gt;({ required: true });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  See more
&lt;/h4&gt;

&lt;p&gt;There’s a lot more to unpack with this feature which are very well explained in the documents provided below&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://blog.vuejs.org/posts/vue-3-3#definemodel" rel="noopener noreferrer"&gt;https://blog.vuejs.org/posts/vue-3-3#definemodel&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;note, this feature is &lt;strong&gt;no longer experimental - it’s stable as of Vue 3.5&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href="https://escuelavue.es/en/devtips/vue-3-modelvalue-definemodel-macro" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://escuelavue.es/en/devtips/vue-3-modelvalue-definemodel-macro" rel="noopener noreferrer"&gt;https://escuelavue.es/en/devtips/vue-3-modelvalue-definemodel-macro&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href="https://vuejs.org/guide/components/v-model" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://vuejs.org/guide/components/v-model" rel="noopener noreferrer"&gt;https://vuejs.org/guide/components/v-model&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  defineSlots() [Only supported on Typescript]
&lt;/h3&gt;

&lt;p&gt;is used to define expected slots and their props expected slot props type&lt;/p&gt;

&lt;h4&gt;
  
  
  Type
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function defineSlots&amp;lt;T = (Record&amp;lt;string, (props: any) =&amp;gt; any&amp;gt;)&amp;gt;(): T;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Typescript
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup lang="ts"&amp;gt;
defineSlots&amp;lt;{
  default?: (props: { msg: string }) =&amp;gt; any;
  item?: (props: { id: number }) =&amp;gt; any ;
 }&amp;gt;();
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also returns the slots object, which is equivalent to the slots object exposed on the setup context or returned by &lt;a href="https://vuejs.org/api/sfc-script-setup#useslots-useattrs" rel="noopener noreferrer"&gt;useSlots()&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  See More
&lt;/h4&gt;

&lt;p&gt;checkout more about limitations and details on this typescript based feature&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://blog.vuejs.org/posts/vue-3-3#typed-slots-with-defineslots" rel="noopener noreferrer"&gt;https://blog.vuejs.org/posts/vue-3-3#typed-slots-with-defineslots&lt;/a&gt; &lt;strong&gt;[TS]&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vuejs.org/api/sfc-script-setup#defineslots" rel="noopener noreferrer"&gt;https://vuejs.org/api/sfc-script-setup#defineslots&lt;/a&gt; &lt;strong&gt;[TS]&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  New Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  useTemplateRefs()
&lt;/h3&gt;

&lt;p&gt;returns reactive value of template Element referenced with the &lt;em&gt;&lt;strong&gt;ref&lt;/strong&gt;&lt;/em&gt; attribute&lt;/p&gt;

&lt;h4&gt;
  
  
  Type
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function useTemplateRefs&amp;lt;T = HTMLElement&amp;gt;(key: string):Readonly&amp;lt;ShallowRef&amp;lt;T | null&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Template Refs - Before vs Now
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt; we would assign the ref template attribute the same name as the ref variable assigned to ref(null) in the setup context&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
 &amp;lt;div ref="myDiv"&amp;gt;This is my element.&amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script setup&amp;gt;
import { ref } from 'vue';
const myDiv = ref(null);
console.log(myDiv.value);
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now&lt;/strong&gt; we use the same string assigned to the template ref attribute and pass it to the useTemplateRefs() api&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div ref="myDiv"&amp;gt;This is my element.&amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script setup&amp;gt;
import { useTemplateRef } from 'vue';
const myElementRef = useTemplateRef('myDiv'); // either null or html Element
console.log(myElementRef.value);
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Typescript
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div ref="myDiv"&amp;gt;This is my element.&amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script setup lang="ts"&amp;gt;
import { useTemplateRef } from 'vue';
const myElementRef = useTemplateRef&amp;lt;HTMLDivElement&amp;gt;('myDiv'); // or if the type can be inferred by @vue/language-tools, then type casting isn't necessary
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  See More
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vuejs.org/api/composition-api-helpers.html#usetemplateref" rel="noopener noreferrer"&gt;https://vuejs.org/api/composition-api-helpers.html#usetemplateref&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.vuejs.org/posts/vue-3-5#usetemplateref" rel="noopener noreferrer"&gt;https://blog.vuejs.org/posts/vue-3-5#usetemplateref&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vuejs.org/guide/typescript/composition-api#typing-template-refs" rel="noopener noreferrer"&gt;https://vuejs.org/guide/typescript/composition-api#typing-template-refs&lt;/a&gt; &lt;strong&gt;[TS]&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vuejs.org/guide/typescript/composition-api#typing-component-template-refs" rel="noopener noreferrer"&gt;https://vuejs.org/guide/typescript/composition-api#typing-component-template-refs&lt;/a&gt; &lt;strong&gt;[TS]&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  useId()
&lt;/h3&gt;

&lt;p&gt;Generates a unique ids that are stable across (don’t change) SSR and CSR (&lt;em&gt;&lt;strong&gt;no risk of hydration mismatch&lt;/strong&gt;&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;These ids are crucial for correctly associating labels with form elements and other accessibility attributes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;⚠️ useId should never be called inside a computed wrapper&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Type
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function useId: string
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
 &amp;lt;form&amp;gt;
   &amp;lt;label :for="myId"&amp;gt;Name:&amp;lt;/label&amp;gt;
   &amp;lt;input :id="myId" type="text" /&amp;gt;
 &amp;lt;/form&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script setup&amp;gt;
import { useId } from 'vue';
const myId = useId(); // or if the type can be inferred by @vue/language-tools, then type casting isn't necessary
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  See More
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vuejs.org/api/composition-api-helpers.html#useid" rel="noopener noreferrer"&gt;https://vuejs.org/api/composition-api-helpers.html#useid&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;onWatcherCleanup()&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Register a cleanup function to be executed when the current watcher (i.e. watch or watchEffect) is about to re-run (triggers).&lt;/p&gt;

&lt;h4&gt;
  
  
  Data Flow
&lt;/h4&gt;

&lt;p&gt;Open image-20251106-163414.png&lt;/p&gt;

&lt;h4&gt;
  
  
  When to Use it
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Cancel API requests&lt;/li&gt;
&lt;li&gt;Clear timers&lt;/li&gt;
&lt;li&gt;Remove event listeners&lt;/li&gt;
&lt;li&gt;Free resources&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import { onWatcherCleanup, watch, ref } from 'vue';

const controller = new FetchController()
const id = ref('');
const data = ref(null);

watch(() =&amp;gt; id.value, (newId) =&amp;gt; {
// note - this isn't best pratice, we shouldn't be awaiting async operations in watcher
// the purpose of this example is to show how onWatcherCleanup works             try {
 const response = await controller.fetch(newId);
 if (!response.ok) {
   throw new Error('data not found');
 }
 data.value = await response.json();
} catch {
 data.value = null
}
/*
- watcher cleanup registered - hoisted to the top of watcher callback and executes first before the try / catch blocks execute
*/

onWatcherCleanup(() =&amp;gt; {
// terminates ongoing fetch calls, when the id updates (watcher is triggered)
  if(controller.isFetching) {
    controller.abort();
  }
 });
});
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  See More
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.vuejs.org/posts/vue-3-5#onwatchercleanup" rel="noopener noreferrer"&gt;https://blog.vuejs.org/posts/vue-3-5#onwatchercleanup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/alexanderop/vue-35s-onwatchercleanup-mastering-side-effect-management-in-vue-applications-9pn"&gt;https://dev.to/alexanderop/vue-35s-onwatchercleanup-mastering-side-effect-management-in-vue-applications-9pn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vuejs.org/api/reactivity-core.html#onwatchercleanup" rel="noopener noreferrer"&gt;https://vuejs.org/api/reactivity-core.html#onwatchercleanup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  data-allow-mismatch
&lt;/h3&gt;

&lt;p&gt;This attribute allows developers to ignore hydration mismatch console warnings.&lt;/p&gt;

&lt;h4&gt;
  
  
  When to Use it
&lt;/h4&gt;

&lt;p&gt;Whenever template difference between server-side template and client-side template (after hydration) is expected (i.e. template that’s time sensitive)&lt;/p&gt;

&lt;h4&gt;
  
  
  Optional Params
&lt;/h4&gt;

&lt;p&gt;The value can limit the allowed mismatch to a specific type. Allowed values are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Option Name&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Example Usage&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;Ignores mismatch warnings of HTML text&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;div data-allow-mismatch="text"&amp;gt;Test&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;children&lt;/td&gt;
&lt;td&gt;Ignores mismatch warnings of direct, nested children elements&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;div data-allow-mismatch="children"&amp;gt;Test&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;class&lt;/td&gt;
&lt;td&gt;Ignores mismatch warnings of Element class attribute&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;div data-allow-mismatch="class"&amp;gt;Test&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;style&lt;/td&gt;
&lt;td&gt;Ignores mismatch warnings of Element style attribute&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;div data-allow-mismatch="style"&amp;gt;Test&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;attribute&lt;/td&gt;
&lt;td&gt;Ignores mismatch warnings of general Element attribute mismatches&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;div data-allow-mismatch="attribute"&amp;gt;Test&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;⚠️ If no value is provided, all types of mismatches will be allowed.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template
 &amp;lt;div data-allow-mismatch&amp;gt;{{ time }}&amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script setup&amp;gt;
const time = new Date().getTime(); // value changes between ssr and csr
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  See More
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.vuejs.org/posts/vue-3-5#data-allow-mismatch" rel="noopener noreferrer"&gt;https://blog.vuejs.org/posts/vue-3-5#data-allow-mismatch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vuejs.org/api/ssr.html#data-allow-mismatch" rel="noopener noreferrer"&gt;https://vuejs.org/api/ssr.html#data-allow-mismatch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Shortened v-bind
&lt;/h3&gt;

&lt;p&gt;Binding reactive values to a components (via &lt;code&gt;v-bind&lt;/code&gt;) now works the same way as property assignment for Javascript Objects.&lt;/p&gt;

&lt;h4&gt;
  
  
  Shortened v-bind - Before vs Now
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt; we would need to write out component v-bind assignments, even for values that share the same name in the setup context&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
 &amp;lt;TestComponent :test="test" /&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script setup&amp;gt;
import { ref } from 'vue';
const test = ref(null);
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now&lt;/strong&gt; v-bind attributes can be shortened to this when the they share the same name in the script context&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
 &amp;lt;TestComponent :test /&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script setup&amp;gt;
import { ref } from 'vue';
const test = ref(null);
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  See More
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.vuejs.org/posts/vue-3-4#v-bind-same-name-shorthand" rel="noopener noreferrer"&gt;https://blog.vuejs.org/posts/vue-3-4#v-bind-same-name-shorthand&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Generic Component [Only supported on Typescript]
&lt;/h3&gt;

&lt;p&gt;Vue components now support generic types on Typescript based Vue components. Generic types makes Vue components more flexible in terms of type requirements and reusable, allowing the component to work with props of different data types.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;⚠️ The data type observed for a particular generic must be consistent when passing in prop values, unless generics specified types are extended (ex. &lt;code&gt;generic="T extends string | number"&lt;/code&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;See Generic in ChildComponent.vue&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- ChildComponent.vue --&amp;gt;
&amp;lt;template&amp;gt;
 &amp;lt;p&amp;gt;{{ list.length }}&amp;lt;/p&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script setup lang="ts" generic="T, U"&amp;gt;
defineProps&amp;lt;{
 list: T[], // ✅
 list2: U[], // ✅
 list3: U[], // ❌ -&amp;gt; throws error in complie-time, expects type 'U' is of type 'string'
}&amp;gt;();
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- ParentComponent.vue --&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;ChildComponent
    :list="[1,2,3]"
    :list2="['one', 'two', 'three']"
    :list3="[true, false]"
  &amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script setup lang="ts"&amp;gt;
import ChildComponent from './ChildComponent.vue'
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  See More
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vuejs.org/api/sfc-script-setup.html#generics" rel="noopener noreferrer"&gt;https://vuejs.org/api/sfc-script-setup.html#generics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.vuejs.org/posts/vue-3-3#generic-components" rel="noopener noreferrer"&gt;https://blog.vuejs.org/posts/vue-3-3#generic-components&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lazy Hydration Strategies
&lt;/h2&gt;

&lt;p&gt;the Vue native api, &lt;strong&gt;defineAsyncComponent()&lt;/strong&gt;, now includes an option to defer hydration (JS is executed on the the browser making the server-side template interactable).&lt;/p&gt;

&lt;p&gt;Vue uses a number of hydration strategies, which allows developers to flexibly defer when parts of the server-side template becomes hydrated (JS execution of sever-side template is deferred), &lt;strong&gt;thus improving core web vital metrics, mainly INP (by deferring JS execution on the Main Thread during page load)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;See the documentation &lt;a href="https://vuejs.org/guide/components/async.html#lazy-hydration" rel="noopener noreferrer"&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt; to explore the different hydration strategies developers can use to defer hydration in the code base&lt;/p&gt;

&lt;h4&gt;
  
  
  See More
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://vueschool.io/articles/vuejs-tutorials/lazy-hydration-and-server-components-in-nuxt-vue-js-3-performance/" rel="noopener noreferrer"&gt;https://vueschool.io/articles/vuejs-tutorials/lazy-hydration-and-server-components-in-nuxt-vue-js-3-performance/&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explains how lazy hydration via using the NUXT library&lt;/li&gt;
&lt;li&gt;As an abstract it explains, very well, how hydration works&lt;/li&gt;
&lt;li&gt;explains the benefits of using of lazy-hydration&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Typescript Composition Api
&lt;/h2&gt;

&lt;p&gt;Follow the documentation to see how Composition Api is integrated with Typescript &lt;a href="https://vuejs.org/guide/typescript/composition-api" rel="noopener noreferrer"&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>news</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
