12
Author: Matt Maribojoc
Translator: Front-end Xiaozhi
Source: medium

If you have dreams, you have dry goods, World] Follow this brush bowl wisdom who is still washing dishes in the early morning.

This article https://github.com/qq449245884/xiaozhi . There are complete test sites, materials and my series of articles for interviews with first-tier manufacturers.

VueUse is Anthony Fu , which provides Vue developers with a lot of basic Composition API utility functions for Vue2 and Vue3.

It has dozens of solutions for common developer use cases like tracking ref changes, detecting element visibility, simplifying common Vue patterns, keyboard/mouse input, and more. This is a great way to really save development time, because we don't have to add all these standard features ourselves, just use it and just use it (thanks again, big guy).

I like the VueUse library because it really puts the developer first when deciding what utilities to provide, and it's a well-maintained library because it's kept up to date with the current version of Vue.

What utility methods does VueUse have?

If you want to see a full list of each utility, it is recommended to take a look at the official documentation . But to summarize, there are 9 types of functions in VueUse.

  • Animation - Contains easy-to-use transitions, timeouts and timing functions
  • Browser - can be used for different on-screen controls, clipboard, preferences, etc.
  • Component - provides shorthands for different component methods
  • Sensors - used to listen to various DOM events, input events and network events
  • State - Manage user state (global, local storage, session storage)
  • Utility - Different utility methods like getters , conditionals , ref synchronization etc.
  • Watch -- more advanced watcher types like pauseable watchers, abandoned watchers, and conditional watchers
  • Miscellaneous - Events, WebSockets, and different types of functionality for Web workers

Install Vueuse into the Vue project

One of the best features of VueUse is that it is compatible with Vue2 and Vue3 in just one package!

There are two options for installing VueUse: npm or CDN

npm i @vueuse/core # yarn add @vueuse/core
<script src="https://unpkg.com/@vueuse/shared"></script>
<script src="https://unpkg.com/@vueuse/core"></script>

NPM is recommended as it is easier to understand, but if we use a CDN, it may be accessed via window.VueUse .

Using npm, you can get the desired method by destructuring:

import { useRefHistory } from '@vueuse/core'

useRefHistory to track changes in responsive data

useRefHistory keeps track ref and stores it in an array. This way we can easily provide the application with undo and redo functionality.

Let's look at an example where we make a text area that can be undone

The first step is to create our base component without VueUse -- using ref , textarea , and buttons for undo and redo.

<template>
  <p> 
    <button> Undo </button>
    <button> Redo </button>
  </p>
  <textarea v-model="text"/>
</template>

<script setup>
import { ref } from 'vue'
const text = ref('')
</script>

<style scoped>
  button {
    border: none;
    outline: none;
    margin-right: 10px;
    background-color: #2ecc71;
    color: white;
    padding: 5px 10px;;
  }
</style>

Next, import useRefHistory , and then extract the history , undo and redo attributes from text useRefHistory

import { ref } from 'vue'
import { useRefHistory } from '@vueuse/core'

const text = ref('')
const { history, undo, redo } = useRefHistory(text)

Whenever our ref changes, updating the history property, a listener is fired.

To see what the bottom layer is doing, we print the contents of history undo and redo functions when the corresponding button is clicked.

<template>
  <p> 
    <button @click="undo"> Undo </button>
    <button @click="redo"> Redo </button>
  </p>
  <textarea v-model="text"/>
  <ul>
    <li v-for="entry in history" :key="entry.timestamp">
      {{ entry }}
    </li>
  </ul>
</template>

<script setup>
import { ref } from 'vue'
import { useRefHistory } from '@vueuse/core'
const text = ref('')
const { history, undo, redo } = useRefHistory(text)
</script>

<style scoped>
  button {
    border: none;
    outline: none;
    margin-right: 10px;
    background-color: #2ecc71;
    color: white;
    padding: 5px 10px;;
  }
</style>

Directly, run, the effect is as follows:

There are also different options that add more functionality to this feature. For example, we can drill down to the reactive object and limit the number of history

const { history, undo, redo } = useRefHistory(text, {
  deep: true,
  capacity: 10,
})

onClickOutside closes the modal

onClickOutside Detects any click outside of an element. In my experience, the most common use case for this feature is to close any modal or popup.

Often, we want our modals to block the rest of the web page to attract the user's attention and limit errors. However, if they do click outside the modal, we want it to close.

To do this, there are only two steps.

  • Create a template reference for the element to detect
  • Use this template ref run onClickOutside

This is a simple component that uses onClickOutside pop up a window.

<template>
  <button @click="open = true"> Open Popup </button>
  <div class="popup" v-if='open'>
    <div class="popup-content" ref="popup">
      Lorem ipsum dolor sit amet consectetur adipisicing elit. Corporis aliquid autem reiciendis eius accusamus sequi, ipsam corrupti vel laboriosam necessitatibus sit natus vero sint ullam! Omnis commodi eos accusantium illum?
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { onClickOutside } from '@vueuse/core'
const open = ref(false) // state of our popup
const popup = ref() // template ref
// whenever our popup exists, and we click anything BUT it
onClickOutside(popup, () => {
  open.value  = false
})
</script>

<style scoped>
  button {
    border: none;
    outline: none;
    margin-right: 10px;
    background-color: #2ecc71;
    color: white;
    padding: 5px 10px;;
  }
  .popup {
    position: fixed;
    top: ;
    left: ;
    width: 100vw;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(, , , 0.1);
  }
  .popup-content {
    min-width: 300px;
    padding: 20px;
    width: 30%;
    background: #fff;
  }
</style

The result is that we can open the popup with our button and then close it with a click outside the popup content window.

useVModel simplifies v-model binding.

A common use case for Vue developers is to create a custom v-model binding for a component. This also requires our component to accept a value as a prop, and whenever this value is modified, our component will emit a update event to the parent class.

image.png

useVModel function simplifies this to just the standard ref syntax. Suppose we have a custom text input trying to create a v-model for the value of its text input. Normally, we have to accept a value and then emit a change event to update the data value in the parent component.

We can use useVModel , treat it as an ordinary ref , instead of using ref and call props.value and update:value . This helps reduce the number of different syntaxes we need to remember!

<template>
    <div>
        <input 
            type="text" 
            :value="data"
            @input="update"
        />
    </div>
</template>

<script>
import { useVModel } from '@vueuse/core'
export default {
  props: ['data'],
  setup(props, { emit }) {
    const data = useVModel(props, 'data', emit)
    console.log(data.value) // equal to props.data
    data.value = 'name' // equal to emit('update:data', 'name')
    const update = (event) => {
        data.value = event.target.value
    }
    return {
        data,
        update
    }
  },
}
</script>

Whenever we need to access value we just call .value and useVModel will give us the value from our component props. And whenever the value of the object is changed, useVModel will emit an update event to the parent component.

Here is a simple example of a parent component

<template>
  <div>
    <p> {{ data }} </p>
    <custom-input 
      :data="data" 
      @update:data="data = $event"
    />
  </div>
</template>

<script>
import CustomInput from './components/CustomInput.vue'
import { ref } from 'vue'
export default {
  components: {
    CustomInput,
  },
  setup () {
    const data = ref('hello')
    return {
      data
    }
  }
}

The result of the operation is as follows, the value of the parent is always in sync with the input of the child:

Track element visibility with intersectionobserver

useIntersectionObserver is very powerful when determining whether two elements overlap. A good use case for this is to check if an element is currently visible in the viewport.

Basically, it checks the percentage of intersection of the target element with the root element/document. If this percentage exceeds a certain threshold, it calls a callback to determine if the target element is visible.

useIntersectionObserver provides a simple syntax to use IntersectionObserver API . All we need to do is provide a template ref for the element we want to inspect.

By default, IntersectionObserver will be based on the document's viewport, with a threshold of 0.1 -- so when this threshold is crossed in either direction, our intersection observer will fire.

Example: We have a fake paragraph that just takes up space in our viewport, the target element, and then a print statement that prints the visibility of our element.


<template>
  <p> Is target visible? {{ targetIsVisible }} </p>
  <div class="container">
    <div class="target" ref="target">
      <h1>Hello world</h1>
    </div>
  </div>
</template>

<script>
import { ref } from 'vue'
import { useIntersectionObserver } from '@vueuse/core'
export default {
  setup() {
    const target = ref(null)
    const targetIsVisible = ref(false)
    const { stop } = useIntersectionObserver(
      target,
      ([{ isIntersecting }], observerElement) => {
        targetIsVisible.value = isIntersecting
      },
    )
    return {
      target,
      targetIsVisible,
    }
  },
}
</script>

<style scoped>
.container {
  width: 80%;
  margin:  auto;
  background-color: #fafafa;
  max-height: 300px;
  overflow: scroll;
}
.target {
  margin-top: 500px;
  background-color: #1abc9c;
  color: white;
  padding: 20px;
}
</style>

After running, the corresponding value will be updated:

We can also specify more options for our Intersection Observer, such as changing its root element, margins (the offset from the root's bounding box when calculating intersections), and threshold levels.

const { stop } = useIntersectionObserver(
      target,
      ([{ isIntersecting }], observerElement) => {
        targetIsVisible.value = isIntersecting
      },
      {
        // root, rootMargin, threshold, window
        // full options in the source: https://github.com/vueuse/vueuse/blob/main/packages/core/useIntersectionObserver/index.ts
        threshold: 0.5,
      }
)

Just as importantly, this method returns a stop function that we can call to stop observing intersections. This is especially useful if we only want to track when an element is first visible on the screen.

In this code, once targetIsVisible is set to true true even if we scroll away from the target element.

const { stop } = useIntersectionObserver(
      target,
      ([{ isIntersecting }], observerElement) => {
        targetIsVisible.value = isIntersecting
        if (isIntersecting) {
          stop()
        }
      },
    )

Use useTransition to make a digital loading animation

useTransition is one of my favorite functions in the entire VueUse library. It allows us to smoothly transition between values with just one line.

If I use useTransition make an effect like the following, what should I do?

We can do this in three steps.

  • Initialize a ref variable count , the initial value is 0
  • Use useTransition create a variable output
  • change the value of count
import { ref } from 'vue'
import { useTransition, TransitionPresets } from '@vueuse/core'

const count = ref(0)

const output = useTransition(count , {
  duration: 3000,
  transition: TransitionPresets.easeOutExpo,
})

count.value = 5000

</script>

Then display the value of output in the template:

<template>
  <h2> 
    <p> Join over </p>
    <p> {{ Math.round(output) }}+ </p>
    <p>Developers </p>
  </h2>
</template>

<script setup>
import { ref } from 'vue'
import { useTransition, TransitionPresets } from '@vueuse/core'
const count = ref(0)
const output = useTransition(count, {
  duration: 3000,
  transition: TransitionPresets.easeOutExpo,
})
count.value = 5000
</script>

operation result:

We can also convert the entire array of numbers useTransition This is useful when working with position or color. A good trick for working with colors is to use a computed property to RGB value to the correct color syntax.

<template>
  <h2 :style="{ color: color } "> COLOR CHANGING </h2>
</template>

<script setup>
import { ref, computed } from 'vue'
import { useTransition, TransitionPresets } from '@vueuse/core'
const source = ref([, , ])
const output = useTransition(source, {
  duration: 3000,
  transition: TransitionPresets.easeOutExpo,
})
const color = computed(() => {
  const [r, g, b] = output.value
  return `rgb(${r}, ${g}, ${b})`
})
source.value = [255, , 255]
</script>

Summarize

This is not a complete guide to VueUse. These are just the functions that I usually use, and there are many useful functions. You can go to the official website to learn and use them.

~ Finished, I went to wash the dishes, I don't wash the dishes on weekends, I kneel on durian at night.

possible bugs after the code is deployed cannot be known in real time. In order to solve these bugs afterwards, a lot of time is spent on log debugging. By the way, I recommend a useful bug monitoring tool Fundebug .

Original: https://learvue.co/2021/07/5-vueuse-library-functions-that-can-speed-up-development/

comminicate

If you have dreams and dry goods, search on [Moving to the World] still washing dishes in the early morning.

This article https://github.com/qq449245884/xiaozhi . There are complete test sites, materials and my series of articles for interviews with first-tier manufacturers.


王大冶
68k 声望104.9k 粉丝