preface

Since the last article “Vue super Fun New Features: The introduction of JS variables in CSS” became popular, many friends have liked and left comments, so I decided to make “Vue Super fun New Features” into a series.

Because most of the Vue 3 articles so far have focused on Composition API and responsive optimizations, while these new features are great, others have been overlooked. Or some articles are simply mentioned, and then write a simple Demo, the explanation is not detailed enough and not in-depth enough.

In addition to the responsive optimization and Composition API, there are some new features that are very useful. So be sure to follow me as I unlock all the fun new features of Vue 3.

lenovo

I’m sure you’ve all heard the word portal at some point. If you haven’t heard of it, at least you’ve seen Doraemon. (The post-00s generation seems to have barely seen it.)

What are some of the most common doraemon props?

  • A time machine
  • Bamboo dragonfly
  • An arbitrary door

The fact that these three items appear so often proves that these three items are more versatile than other items.

The new version of Vue implements one of these three: the Arbitrary gate (portal).

portal

If you only see the word portal, you may not be able to imagine what the function is.

So let’s use any doraemon gate as an example:

What are the characteristics of any doraemon gate?

  • destination
  • Influenced by the destination environment
  • The destination has to be very precise

Let’s explain:

  • Destination: The use of any door is “open the door with the destination in mind, otherwise you will lead to unpredictable areas.”

  • Influenced by your destination environment: If your destination is extremely cold, you will look something like this:

  • The destination has to be very precise: According to incomplete statistics, for every 10 times nobita uses any door, 3 times he opens the door and finds Shizuka in the bath. The reason for this is that:Nobita just wanted to see itWhen Nobita opens the door, he wants to go to “Shizuka’s house”. Shizuka’s house has many rooms, but Nobita doesn’t give any door a clear indication of which room to go to, so he goes directly to shizuka’s room (The shower) :

The portal in Vue

Let’s take a look at these features in Vue’s portal:

  • Destination: The portal is used by giving a CSS selector as the destination.

  • Affected by the destination environment: If the destination writes a CSS property (such as color) that can be inherited, then the DOM that is passed to it will be affected by this style.

  • The destination must be very precise: if you give the destination a selector that matches many elements (e.g., div), it will only send you to the first div that matches (probably not the one you want to go to).

Maybe a lot of people are still a little giddy, but what’s the use of this thing? I wrote components to wrap the DOM together, so why would I want the DOM to go somewhere else?

If you want to introduce a DOM into another DOM element, you should just introduce the component. Isn’t that what componentization is all about?

The meaning of the portal

Consider a case like this:

You may be familiar with the rowhead diagram. Outside the rowhead diagram is a row of buttons that control the location of indicators on the panel inside the rowhead diagram.

Isn’t that simple, you might think? Encapsulates a component that contains this row of buttons, a rotograph, and panel indicators. And then you define a position variable, which button you click on, and that variable changes.

Then the panel indicator points relative to the rotation diagram to carry out absolute positioning, the specific positioning direction depends on this position variable to control.

The problem is that the row of buttons does not have to be in a fixed position. It may be on the left side of the rotation diagram, or on the right. The four buttons might even be in other DOM elements, far from the rotograph.

When you hear it, you think it’s okay, I just split it into two components. Buttons are a separate component, and the playcharts and panel Pointers are another:

As shown in the red box above, these are two different components, and you can place them anywhere or as far away as you like.

When clicking a button, just use: Emit, eventBus, Vuex… Wait for a series of components you can think of to communicate with each other. The value of the button is passed to the rosette graph, and the rosette graph determines the location of the panel indicator based on the value passed in.

It’s perfectly possible to do this, and in fact we’ve all done this before.

But there are two disadvantages to this implementation:

encapsulation

The four values of the four buttons seem to only control the panel indicator, it does not control anything else on the page, that is, its values are only associated with the panel indicator.

And if you have several rounds, each of which is controlled by a different set of buttons, there will be many, many components communicating with each other.

On the one hand, define as few states as possible in Vuex. On the other hand, even if Vuex is not used, it is too cumbersome to emit events and then listen for events on the parent or ancestor component and pass them down the hierarchy. Other communication methods are not much better.

So in terms of encapsulation, the two should be one:

The two should be packaged into one component.

reusability

If there is more than this one in your project, there are also some that do not require panel Pointers. And it’s not just a rotation diagram. What if there were other divs or other elements that needed a panel pointer that could go up, down, left, or right, and a row of buttons that could control the position?

Encapsulate the button component, then the panel indicator component, then the carousel diagram component (introducing the panel indicator component into the carousel component), then a carousel component without the panel indicator, then several other components that require the panel…

Does it feel cumbersome, poorly reusable, and coupled? The current situation is caused by the inability to encapsulate them as a single component:

So what’s keeping these two from getting together?

The answer is the DOM structure

DOM structure

If they were packaged together, it would look like this:

<template>
  <div>
    <! -- Button Component -->
  	<Btns/>
    
    <! -- Panel Components -->
    <Points/>
  </div>
</template>

<style>
  .points {
  	position: absolute;
  }
</style>
Copy the code

Although we set absolute positioning for the panel component, it is not relative to the DOM element we want it to be relative to. The best way to position a DOM element relatively specifically is to be its descendant (and, of course, to set a nonstatic position on the ancestor element).

But now <Points> is restricted to this component and cannot be descendants of others, so DOM portal was created to address this requirement!

Is this where I start to see the DOM portal? A DOM portal is the ability to transfer a DOM element from a component to another location.

Its significance lies in:

  • From the component’s point of view, they are still the same component, and the variables and logic defined within the component are still valid
  • In terms of the DOM structure, the DOM structure of the panel control point has become a child element of someone else

usage

First of all, let’s build a project to support VUE 3 based on the article “Vue3 beta was released in the early hours of this morning, and the scaffolding project was openly supported”.

@vue/cli: @vue/cli: @vue/cli: @vue/cli: @vue/cli

Look! The preview version of Vue 3 is now available!

The first thing to note after building the project is that the portal is a component called the Teleport:

Then we want to send the images from the App component away:

So we just wrap a teleport component around the img tag:

The ⚠️ teleport component must have a TO property that passes a CSS selector that corresponds to the destination of the portal

You can see that img is currently at the bottom of the body, presumably using syntax like dom.appendChild() at the bottom.

What’s surprising is that img was teleported outside the #app that Vue represents:

It used to be new Vue(), and then Vue is mounted to this #app element. Now that it’s been teleported to the outside world, does it still belong to Vue? Try it out:

You can see that the variables and logic defined in the component still apply to the DOM element!

What about the style? Will the style work? Try it again:

This is great!

But what I just passed is a DOM element. Can I pass a component? <HelloWorld/>

Still fine!

But when you pass a string to the teleport, the underlying element of it calls the document.querySelector() method. This method will only match the first element that matches the selector, so try to use a more precise selector such as ‘#id’.

In addition to the TO attribute, teleports also support passing a disabled attribute, which requires passing a Boolean value.

If v-if is false, it will not be transmitted, but it will not appear in its original position. This is where disabled comes in.

Disabled literally means to invalidate. It defaults to false, meaning that teleport is not invalidated. Let’s give it a true value to disable the teleport:

You can see that it is not transferred to the body, but remains in its original position, and if you look closely you will notice this comment:

It’s not that you didn’t write teleport, it’s that it’s disabled!

inspiration

If you’ve ever learned the React language, you’ll probably know where the idea came from. If you’ve ever learned the React language, you’ll probably find this teleport a little familiar.

Yes, it was inspired by React’s createPortal, but Vue’s design is more of a componentize intuition. Here’s a comparison:

The word ‘Portal’ actually means’ Portal ‘:

Of course, the translator doesn’t translate as portal, but it does. The key is that the word is a noun, and that’s what component names are supposed to be.

It is said that Yuyuxi originally named it Portal, but I heard that Chrome is working on a < Portal > component, and if it is successful, it may be deployed in the browser. To avoid future conflicts, it renamed the verb teleport.

conclusion

So, is this new feature both useful and fun?

If you still feel more than enough, you can check out the previous excellent articles:

  • Microsoft launches comments section on GitHub
  • Vue 3.0.3: New CSS variable passing and the latest Ref Proposal
  • You Yuxi: Ref Grammar Sugar Proposal
  • “Double 11 small black box is cool? Let’s use CSS variables to improve!”
  • “Don’t underestimate the nine grid, one question can let a candidate reveal his true colors!”
  • “Mobile Layout Interview Questions to test your CSS Skills (Center)”
  • A fun new feature of Vue: Introducing JS variables into CSS
  • Create your own Visual Data Map without any libraries
  • “Use of React’s Super-popular CSS-in-JS Library in the Vue Project: Styled – Components”
  • Is It Finally Vue’s Turn to Inspire React?
  • A Small Pit in Vue3 on IOS
  • Upgrade your React project to Immer instead of Immutable by 2020
  • “Soul Interrogation from the Author of React Hooks and Immutable”
  • Good news, Vue3 official document is available in Chinese!
  • Hooks use of the New VUe-Router
  • Vue 3:20 Years of Status Updates
  • React 17 is officially a transition version!
  • Yu Yuxi: The Design Process of Vue3
  • The Father of Node’s refactoring Deno is finally released. Will it Replace Node after all?
  • The Vue3 beta was released early this morning and openly supports scaffolding!