preamble
To access the DOM and subcomponents in vue3 you can use a ref for template references, but there are some confusing things about this ref. For example, is the defined ref variable a responsive data or a DOM element? Also the value of the ref attribute in the template is clearly a string, such asref="inputEl"
Why does it have the same name as in the script?inputEl
What about variables tied to one piece? That's why Vue 3.5 introduced auseTemplateRef
function that solves these problems perfectly.
Follow the public number: [Front-end Ouyang], give yourself a chance to advance vue
Problems with ref template references
Let's take a look at one.react
The example of using ref to access a DOM element in the code is as follows:
const inputEl = useRef<HTMLInputElement>(null);
<input type="text" ref={inputEl} />
utilizationuseRef
function defines a function namedinputEl
variable, then set the value of the ref attribute of the input element to the value of theinputEl
variable, so that it is possible to pass theinputEl
The variable accesses the input field.
inputEl
Because it's a.current
attribute of the object, since theinputEl
variable is assigned to the ref attribute, so his.current
attribute is updated to the value of the input DOM element, which is very programmatically intuitive.
Let's go over it again.vue3
in it would be very unprogramming intuitive by comparison.
I wonder how many students like Ouyang, the first contact with vue3 is always in the template likereact
Same as binding a ref variable to the ref attribute instead of the name of the ref variable. For example, code like the following:
<input type="text" :ref="inputEl" />
const inputEl = ref<HTMLInputElement>();
What's even worse is that writing it this way doesn't report errors !!!!When we use theinputEl
variable to access the input box will always get theundefined
。
After much troubleshooting it turns out that the ref property receives not a ref variable, but the name of the ref variable. The correct code would look like this:
<input type="text" ref="inputEl" />
const inputEl = ref<HTMLInputElement>();
There is also the fact that if we draw the logic related to the ref template references into hooks, then we have to define the ref variable corresponding to the ref attribute in the vue component as well.
The hooks code is as follows:
export default function useRef() {
const inputEl = ref<HTMLInputElement>();
function setInputValue() {
if () {
= "Hello, world!";
}
}
return {
inputEl,
setInputValue,
};
}
In the hooks, it defines a file namedinputRef
variables, and in thesetInputValue
function will be passed theinputRef
variable operates on the input field.
The vue component code is as follows:
<template>
<input type="text" ref="inputEl" />
<button @click="setInputValue">do sth (for sb)inputassign a value to something</button>
</template>
<script setup lang="ts">
import useInput from "./useInput";
const { setInputValue, inputEl } = useInput();
</script>
While we won't be using theinputEl
variable, but it still needs to be imported from the hooksuseInput
Variables. Doesn't everyone think this is strange? Importing a variable and not explicitly using that variable.
If you don't go ahead and import from hooks here, theinputEl
variable, then theinputEl
You can't bind an input box to a variable.
useTemplateRef function
To solve the problem of ref template references described above, in Vue 3.5 a newuseTemplateRef
function.
useTemplateRef
The usage of the function is simple: it takes only one argumentkey
, is a string. The return value is a ref variable.
where the value of the parameter key string should be equal to the value of the ref attribute in the template.
The return value is a ref variable whose value points to the DOM element or subcomponent referenced by the template.
Let's look at an example where the previous demo is changed touseTemplateRef
The code after the function is as follows:
<template>
<input type="text" ref="inputRef" />
<button @click="setInputValue">do sth (for sb)inputassign a value to something</button>
</template>
<script setup lang="ts">
import { useTemplateRef } from "vue";
const inputEl = useTemplateRef<HTMLInputElement>("inputRef");
function setInputValue() {
if () {
= "Hello, world!";
}
}
</script>
The value of the ref attribute in the template is a string"inputRef"
。
Use in scriptsuseTemplateRef
function, the first parameter passed in is also the string"inputRef"
。useTemplateRef
The return value of the function is the ref variable pointing to the input field.
due toinputEl
is a ref variable, so to access the DOM element input in the click event you need to use the。
Here we are stuffing the input box with the string "Hello, world!", so we use the = "Hello, world!"
UseduseTemplateRef
function is much more programmatically intuitive than it was before. the value of the ref attribute in template is a string"inputRef"
UseuseTemplateRef
function also passes in the string"inputRef"
You'll be able to get the corresponding template reference.
Use of useTemplateRef in hooks
Going back to the hooks example we talked about earlier, using theuseTemplateRef
The post-hooks code is as follows:
export default function useInput(key) {
const inputEl = useTemplateRef<HTMLInputElement>(key);
function setInputValue() {
if () {
= "Hello, world!";
}
}
return {
setInputValue,
};
}
Now we don't need to export variables in the hooksinputEl
is used, because this variable is only needed inside hooks.
The vue component code is as follows:
<template>
<input type="text" ref="inputRef" />
<button @click="setInputValue">do sth (for sb)inputassign a value to something</button>
</template>
<script setup lang="ts">
import useInput from "./useInput";
const { setInputValue } = useInput("inputRef");
</script>
Since we don't need to use theinputEl
variable, so there's no need to start with theuseInput
variable introduced ininputEl
up. And before not using theuseTemplateRef
program we would have to introduce theinputEl
Variables up.
Dynamically switching ref-bound variables
There are times when we need to dynamically switch the variables referenced by the ref template according to different scenarios, in which case the value of the ref attribute in the template is dynamic, rather than a written string. In this scenariouseTemplateRef
It is also supported with the following code:
<template>
<input type="text" :ref="refKey" />
<button @click="switchRef">switch modes or data streamsrefBound variables</button>
<button @click="setInputValue">do sth (for sb)inputassign a value to something</button>
</template>
<script setup lang="ts">
import { useTemplateRef, ref } from "vue";
const refKey = ref("inputEl1");
const inputEl1 = useTemplateRef<HTMLInputElement>("inputEl1");
const inputEl2 = useTemplateRef<HTMLInputElement>("inputEl2");
function switchRef() {
= === "inputEl1" ? "inputEl2" : "inputEl1";
}
function setInputValue() {
const curEl = === "inputEl1" ? inputEl1 : inputEl2;
if () {
= "Hello, world!";
}
}
</script>
In this scenario the ref binding in the template is a variable.refKey
The program can be accessed by clicking on theSwitching ref-bound variables
The buttons can be toggledrefKey
value of the input box. Correspondingly, the variables bound to the input input box are removed from theinputEl1
The variable is switched toinputEl2
Variables.
useTemplateRef
How was it achieved?
Let's see.useTemplateRef
The source code is actually quite simple, and the simplified code is as follows:
function useTemplateRef(key) {
const i = getCurrentInstance();
const r = shallowRef(null);
if (i) {
const refs = === EMPTY_OBJ ? ( = {}) : ;
(refs, key, {
enumerable: true,
get: () => ,
set: (val) => ( = val),
});
}
return r;
}
first usinggetCurrentInstance
method gets the current vue instance object and assigns it to the variablei
。
then callshallowRef
function generates a shallow ref object with an initial value of null. the ref object is theuseTemplateRef
The ref object returned by the function.
The next step is to determine the current vue instance and if it exists, read the instance'srefs
property object, if the instance object does not have arefs
property, then initialize an empty object to the vue instance object'srefs
Properties.
vue instance object above thisrefs
If you've used vue2, you should be familiar with the attribute object, which holds all the DOM elements and component instances that have the ref attribute registered.
vue3, although unlike vue2, does not incorporate therefs
attribute object is open to the developer, but his internals still use the vue instance'srefs
attribute object to store instances of elements and components registered with the ref attribute in the template.
Here themethodology
refs
Attribute objects are intercepted, and the intercepted field is the variablekey
value, and thiskey
value is the value bound in the template using theref attribute.
Taking our demo above as an example, the code in the template is as follows:
<input type="text" ref="inputRef" />
Here, the ref attribute is used to add the ref attribute to the vue instance'srefs
property object with an input input box registered on top of it.value is pointing to the input field of the DOM element.
Then in the script it is used like thisuseTemplateRef
The:
const inputEl = useTemplateRef<HTMLInputElement>("inputRef")
call (programming)useTemplateRef
function is passed in as a string"inputRef"
inuseTemplateRef
Functions internally use themethodology
refs
Attribute objects are intercepted, and the intercepted fields are variableskey
value, which is the value of the call touseTemplateRef
The string passed in by the function"inputRef"
。
When initialized, vue handles the input input box above theref="inputRef"
It would then execute code like the one below:
refs[ref] = value
at this timevalue
is the value that points to the input field of the DOM element.ref
is the value of the string"inputRef"
。
Then this line of code is assigning the DOM element input input box to therefs
object above theinputRef
Attributes on.
Since there is a great deal of interest here in therefs
object above theinputRef
attribute for write operations, so it will go to theuseTemplateRef
in a functiondefined
set
Intercept. The code is as follows:
const r = shallowRef(null);
(refs, key, {
enumerable: true,
get: () => ,
set: (val) => ( = val),
});
existset
The intercept assigns the DOM element input to the ref variable.r
And thisr
just likeuseTemplateRef
The ref variable returned by the function.
The same is true when the objectrefs
targetinputRef
attribute for read operations will also go here in theget
In the intercept, returnuseTemplateRef
The ref variable defined in the functionr
The value of the
summarize
New in Vue 3.5, theuseTemplateRef
function solves several problems in the ref attribute:
-
It is not programming intuitive that the value of the ref attribute in template is the value of the corresponding ref variable in scriptvariable name。
-
It is not possible to visualize whether a ref variable is responsive data or a DOM element in script without using ts?
-
After pumping the logic related to defining and accessing DOM elements into hooks, the variables that hold the DOM elements must also be imported from the hooks in the component, even though they will not be used in the vue component.
Then we talked aboutuseTemplateRef
function implementation. In theuseTemplateRef
function will define a ref object in theuseTemplateRef
The last thing the function does is return the ref object.
follow withFor vue instances above the
refs
property object for get and set interception.
Initialization, which handles the ref attribute in the template, will have an effect on the vue instance above therefs
attribute object for write operations.
It will then be intercepted by set, where it will set theuseTemplateRef
The value of the ref object defined in the function is assigned to the bound DOM element or component instance.
(indicates contrast)useTemplateRef
function is to return this ref object, so we can pass theuseTemplateRef
The return value of the function gets the DOM element or component instance bound to the ref attribute in the template.
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.