Location>code7788 >text

React's useId, and now Vue 3.5 finally has it too!

Popularity:813 ℃/2024-09-24 09:03:33

preamble

React added in a very early version of theuseIdwhich is used to generate unique IDs. in Vue 3.5, there is finally also the long-awaiteduseId. This article is here to take you through the process of figuring outuseIdWhat are the application scenarios and how does he implement them.

Follow the public number: [Front-end Ouyang], give yourself a chance to advance vue

Role of useId

His role is also to generate a unique ID for each call to theuseIdThe generated IDs are all different.

The usage is also very simple, the code is as follows:

<script setup lang="ts">
import { useId } from 'vue'

const id0 = useId();
(id0); // v-0

const id1 = useId();
(id1); // v-1

const id2 = useId();
(id2); // v-2
</script>

See here some of you will have problems, your above examples are all inside the same component to call theuseId. So if I call each of the components inside a differentuseId, are the IDs generated for these components still unique?

For example, in the following example, the parent component code is as follows:

<template>
  <div>
    <UseIdChild1 />
    <UseIdChild2 />
  </div>
</template>

subassemblyUseIdChild1The code is as follows:

<script setup lang="ts">
import { useId } from "vue";

const id0 = useId();
const id1 = useId();

(id0);
(id1);
</script>

subassemblyUseIdChild2The code is as follows:

<script setup lang="ts">
import { useId } from "vue";

const id0 = useId();
const id1 = useId();

(id0);
(id1);
</script>

From the code above you can see that the code inside the two subcomponents is actually the same, so guess the subcomponentUseIdChild1Printed inid0id1and subassembliesUseIdChild2Printed inid0id1Isn't it the same?

The answer is:unlike

UseIdChild1Printed inid0The value of thev-0id1The value of thev-1

UseIdChild2Printed inid0The value of thev-2id1The value of thev-3

With these two examples above, I think you should guess thatuseIdfunction generates unique IDs with the following pattern: "Stringv-on top of thatautocomplete”。

where the prefixvThis can be done byPerform customization.

There are times when we want to render a list of data, and we need a unique id for each item in the list.useIdGo ahead and generate unique ids for each item.

This is the simplest usage scenario, next let's look at in server-side rendering (SSR)useIdof use scenarios.

Using useId in server-side rendering (SSR)

First we need to figure out what are the pain points when rendering server-side?

Let's look at an example of server-side rendering with the following code:

<template>
  <div>
    <label :htmlFor="id">Do you like Vue3.5?</label>
    <input type="checkbox" name="vue3.5" : />
  </div>
</template>

<script setup lang="ts">
const id = ();
</script>

The above code doesn't have any problem if it's running on client-side rendering, but it will have a warning if it's rendering on server-side. As shown below:
warn

The warning above means that the value of the id generated when server-side is0.4050816845323888The value of the id is generated on the client side, but the value of the id is not. However, the value of the id generated on the client side is0.4746900241123273, the id values generated these two times are different, that's why the warning appears.

Some of you may be wondering why after generating an id once on the server side, you go and generate it again on the client side.

To answer the above question, let's first understand the server-side rendering (SSR) process:

  • The first thing that will happen is that an interface request will be initiated on the server side (environment) to get the data needed for page rendering from the backend.

  • According to get the data to generate the HTML string of the page, at this time will be generated once in the server-side id, this step is called thedehydrate(Dehydration)

  • Sends the HTML string generated on the server side to the client (browser).

  • The browser gets the HTML string generated by the server and renders it directly to the page as the first screen content. But at this time click and other events have not been bound to the DOM, so the client needs to be rendered again. It will generate the id again on the client side, this step is calledhydrate(water injection).

Since we are using the()De-generated ids, executed on the server and client side each time()The generated id values are of course different, hence the warning above.

I've got a solution!useIdAfter that, resolving the above warning is as simple as putting the()adapt (a story to another medium)useId()That's all it takes. The code is as follows:

<template>
  <div>
    <label :htmlFor="id">Do you like Vue3.5?</label>
    <input type="checkbox" name="vue3.5" : />
  </div>
</template>

<script setup lang="ts">
const id = useId();
</script>

on account ofuseIdWhen rendered on the server side, it generatesv-0, when rendered on the client side it is stillv-0

Some of you may have questions, but the previous is not about theuseIdEach execution gives the number that follows+1. So after executing it once on the server side, and then going to the client side to execute it again, it's reasonable that it should generate a different ID, right?

useIdThe generated "self-incrementing numeric part" is maintained on top of the vue instanceidsattribute, the server-side rendering will generate a vue instance on the end. But the client-side rendering regenerates a new vue instance in the browser, at which point theidsattribute is also reset, so it's not a bad idea to execute theuseIdThe generated values are the same.

How useId is implemented

Let's see.useIdThe source code for this is very simple! The simplified code is below:

function useId(): string {
  const i = getCurrentInstance()
  if (i) {
    return ( || 'v') + '-' + [0] + [1]++
  }
  return ''
}

this onegetCurrentInstancefunction I think many students are familiar with, his role is to return the current vue instance.

do sth (for sb)useIdMake a breakpoint to look at the current vue instancei, as shown below:
instance

As you can see in the image above the vue instance on theidsproperty is an array whose first item is the empty string, the second item is the number 0, and the third item is also the number 0

Let's get back to it.useIdis how the unique ID is returned, as follows:

return ( || 'v') + '-' + [0] + [1]++

The unique ID generated consists of three parts:

  • The first part is the prefix, fromis taken from the If not configured, then the stringv

  • The second part of the string is written dead-

  • Part III is[0] + [1]++whichids[0] value is the empty string.[1]++Here the value is taken first and then executed++, so the value of the third part is a number0. Re-calluseIdwhen it is executed due to the fact that the last execution of a++up. The numeric value at this point is1and execute it again.++

See here some of you have questions again, here looksidsattribute is present on top of the vue instance. Each vue component has a vue instance, then each component has its own maintainedidsProperties.
So in your previous exampleUseIdChild1subassemblies andUseIdChild2Subcomponents in the respective generatedid0should have the same valuev-0Right, why is onev-0The other one isv-2And?

The answer is really simple, all vue instances above theidsproperties are all in the same array, pointing to the one above the top-level component instance of theidsattribute. The source code for creating a vue instance is shown below:
source

As you can see from the image above when there is no parent component, that is, the topmost instance of the vue component, theidsproperty is set to an array['', 0, 0]

When generating a vue instance of a child component, since the parent component has above it theidsattribute, so just use the one above the parent component. The pointers are all pointing to the topmost vue instance above theidsattribute, which is why it says that all vue component instances above theidsproperties all point to the same array.

That's whyUseIdChild1subassemblies andUseIdChild2Subcomponents in the respective generatedid0The value of av-0The other one isv-2

summarize

Vue 3.5 adds a newuseIdIt is possible to generate unique IDs within a Vue application, and we can use theuseIdGenerate a unique id for each item in the list data.

And in a server-side rendering (SSR) scenario, the server and client execute theuseIdThe same ID is generated. to take advantage of this feature we can use theuseIdResolve some warnings caused by inconsistencies between server-side and client-side generated IDs in SSR applications.

At the end of the day, we talked aboutuseIdThe implementation is also simple, with the generated ID divided into three parts:

  • The first part is the prefix:If it is not configured, then it is the stringv

  • The second part of the string:-

  • The third part of the value is a self-incrementing number that exists on top of the vue instance'sidsattribute on top of all vue instances.idsproperties all point to the same array. This is why it is important to say that theuseIdThis can be done in theVue In-AppGenerate a unique ID instead of theInside a Vue componentGenerate unique IDs.

Follow the public number: [Front-end Ouyang], give yourself a chance to advance vue

Also Ouyang wrote an open source ebookvue3 Compilation Principles Revealed, reading this book can give you a qualitative improvement in your knowledge of vue compilation. This book is accessible to beginner and intermediate front-ends and is completely free, just asking for a STAR.