• What Hooks Mean for Vue
  • By Sarah Drasner
  • Translation from: The Gold Project
  • This article is permalink: github.com/xitu/gold-m…
  • Translator: Ivocin
  • Proofreader: LeoYang, TUARAN

Not to be confused with Vue’s Lifecycle Hooks, which were introduced by React in V16.7.0-alpha and Vue released their proof-of-concept version a few days later. Although Hooks are introduced by React, they are an important combinational mechanism that is valuable to every JavaScript framework ecosystem, so we’ll spend a little time today talking about what they mean.

Hooks provide a more explicit idea of pattern reuse — avoid overwriting the components themselves, and allow different parts of stateful logic to work together seamlessly.

The original question

The problem with React is that classes are the most common form of component for expressing the concept of state. Stateless components are also very popular, but because they can only be rendered purely, their use is limited to presentation tasks.

The class itself has some problems. For example, as React has become more popular, class problems have generally become a barrier for newcomers. In order to understand React, developers must also understand the classes. The binding makes the code long and unreadable, and requires understanding this in JavaScript. Some of the optimization hurdles associated with using classes are also discussed.

For logical reuse, we typically use patterns such as Render props and high-level components. But using these patterns can find yourself in a similar “pyramid of doom” — style implementation hell, where overuse of nesting can make components difficult to maintain. It made me want to yell at Dan Abramov like he was drunk, and no one wants that.

Hooks solve these problems by allowing us to define stateful logic for components using function calls. These function calls become more composable, reusable, and allow us to access and maintain state while using functional components. When React released Hooks, there was a lot of excitement — here you can see some of the advantages that Hooks show, how they reduce code and duplication:

By visualizing @dan_Abramov’s code (from #ReactConf2018), you can see the benefit of the React Hooks. pic.twitter.com/dKyOQsG0Gd

— Pavel Prichodko (@prchdk) October 29, 2018

In terms of maintenance, simplicity is key, and Hooks provide a single, functional way to share logic with potentially smaller code volumes.

Why do I need Hooks in Vue?

By this point you must be wondering what Hooks must provide in Vue. This seems like a problem that doesn’t need solving. After all, classes are not the predominant pattern used by Vue. Vue provides stateless functional components (if they are needed), but why do we need to carry state in functional components? We have mixins for composing the same logic that can be reused across multiple components. Problem solved.

I was thinking the same thing, but after talking to Evan You, he pointed out a major use case THAT I had overlooked: Mixins can’t consume and use states with each other, but Hooks can. This means that if we need chained encapsulation logic, we can use Hooks.

Hooks implement the functionality of mixins, but avoid the two main problems that mixins cause:

  • Allows state transfer to each other.
  • Be clear about where the logic comes from.

If multiple mixins are used, it is not clear which attribute is provided by which mixins. With Hooks, the return value of the function records the value consumed.

So, how does this work in Vue? As we mentioned earlier, with Hooks, the logic is expressed during function calls and therefore reusable. In Vue, this means that we can wrap data calls, method calls, or computed property calls into another custom function and make them freely combined. Data, methods, and computed properties are now available for functional components.

example

Let’s look at a very simple hook so we understand the building blocks before we move on to the combination examples in Hooks.

useWat?

Okay, there’s a cross between the Vue Hooks and the React Hooks. Use is the React convention, so if you look for Hooks in React, you’ll find Hooks with names like useState, useEffect, etc. More information can be found here.

In Evan’s online demo, you can see where he is accessing useState and useEffect and using the Render function.

If you are not familiar with the render function in Vue, it may be helpful to take a look at the official documentation.

But when we use Vue style Hooks, what do we call them — you guessed it — useData, useComputed, etc.

So, to give us a look at how to use Hooks in Vue, I created a sample application for us to explore.

See the video demo: css-tricks.com/wp-content/…

Demo site

Making the warehouse

In the SRC /hooks folder, I created a hook that blocks scrolling on the useMounted hook and re-enables scrolling on useDestroyed. This helps me pause page scrolling when the viewing dialog opens and allow scrolling again when the viewing dialog ends. This is a good abstraction because it is likely to be used multiple times throughout the application.

import { useDestroyed, useMounted } from "vue-hooks";

export function preventscroll() {
  const preventDefault = (e) => {
    e = e || window.event;
    if (e.preventDefault)
      e.preventDefault();
    e.returnValue = false;
  }

  // keycodes for left, up, right, down
  const keys = { 37: 1, 38: 1, 39: 1, 40: 1 };

  const preventDefaultForScrollKeys = (e) => {
    if (keys[e.keyCode]) {
      preventDefault(e);
      return false;
    }
  }

  useMounted(() => {
    if (window.addEventListener) // older FF
      window.addEventListener('DOMMouseScroll', preventDefault, false);
    window.onwheel = preventDefault; // modern standard
    window.onmousewheel = document.onmousewheel = preventDefault; // older browsers, IE
    window.touchmove = preventDefault; // mobile
    window.touchstart = preventDefault; // mobile
    document.onkeydown = preventDefaultForScrollKeys;
  });

  useDestroyed(() => {
    if (window.removeEventListener)
      window.removeEventListener('DOMMouseScroll', preventDefault, false);

    //firefox
    window.addEventListener('DOMMouseScroll', (e) => {
      e.stopPropagation();
    }, true);

    window.onmousewheel = document.onmousewheel = null;
    window.onwheel = null;
    window.touchmove = null;
    window.touchstart = null;
    document.onkeydown = null;
  });
} 
Copy the code

We can then call it in a Vue component like AppDetails.vue:

<script>
import { preventscroll } from ". /.. /hooks/preventscroll.js"; .export default {
  ...
  hooks() {
    preventscroll();
  }
}
</script>
Copy the code

Not only can we use it in this component, we can use the same functionality throughout the entire application!

Two Hooks that understand each other

As we mentioned earlier, one of the main differences between Hooks and mixins is that Hooks can actually pass values to each other. Let’s take a look at this simple but slightly unnatural example.

In our application, we need to do the calculation in a reusable hook, and something else that needs to use the result of the calculation. In our example, we have a hook that takes the window width and passes it to the animation, letting it know that it will only fire if we are on a larger screen.

See the video demo: css-tricks.com/wp-content/…

The first hook:

import { useData, useMounted } from 'vue-hooks';

export function windowwidth() {
  const data = useData({
    width: 0
  })

  useMounted(() => {
    data.width = window.innerWidth
  })

  // this is something we can consume with the other hook
  return {
    data
  }
}
Copy the code

Then, in the second hook, we use it to create a condition that triggers the animation logic:

// the data comes from the other hook
export function logolettering(data) {
  useMounted(function () {
    // this is the width that we stored in data from the previous hook
    if (data.data.width > 1200) {
      // we can use refs if they are called in the useMounted hook
      const logoname = this.$refs.logoname;
      Splitting({ target: logoname, by: "chars" });

      TweenMax.staggerFromTo(".char", 5,
        {
          opacity: 0,
          transformOrigin: "50% 50% -30px",
          cycle: {
            color: ["red"."purple"."teal"],
            rotationY(i) {
              return i * 50
            }
          }
        },
        ...
Copy the code

Then, within the component, we pass a hook as a parameter to another hook:

<script>
import { logolettering } from ". /.. /hooks/logolettering.js";
import { windowwidth } from ". /.. /hooks/windowwidth.js";

export default {
  hooks() { logolettering(windowwidth()); }}; </script>Copy the code

Now we can use Hooks to write logic throughout the application! Again, this is not a natural example for demonstration purposes, but you can see that it works for large applications to keep the logic in smaller, reusable functions.

Future plans

Vue Hooks are now available in conjunction with Vue 2.x, but are still experimental. We plan to integrate Hooks into Vue 3, but may deviate from the React API in our own implementation. We found the React Hooks very encouraging and are considering how to introduce them to Vue developers. We want to do it in a way that’s consistent with the Vue idiom, so there’s a lot of experimentation to do.

You can check out this warehouse as a start. Hooks may become an alternative to Mixins, so while it’s still early days for this feature, it’s good to explore the concepts in the meantime.

(Sincere thanks to Evan You and Dan Abramov for reviewing this article.)

If you find any errors in the translation or other areas that need improvement, you are welcome to revise and PR the translation in the Gold Translation program, and you can also get corresponding bonus points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


Diggings translation project is a community for translating quality Internet technical articles from diggings English sharing articles. The content covers the fields of Android, iOS, front end, back end, blockchain, products, design, artificial intelligence and so on. For more high-quality translations, please keep paying attention to The Translation Project, official weibo and zhihu column.