必知必会的10个Vue3钩子函数

举报
搞前端的半夏 发表于 2022/03/31 22:13:10 2022/03/31
【摘要】 hook function什么是hook,顾名思义钩子,他的作用就像是一个挂钩,在我们需要的时候把我们实现的钩子函数-hook function,挂在挂钩上。用过Vue的同学,想必都很熟悉Vue的生命周期。例如create,mounted,其实这些都是生命周期钩子。我们可以在这些钩子调用我们实现的函数。、本文就是介绍10个在Vue项目开发过程,经常会用到的函数,请注意,这里是Vue3的写法...

hook function

什么是hook,顾名思义钩子,他的作用就像是一个挂钩,在我们需要的时候把我们实现的钩子函数-hook function,挂在挂钩上。

image-20220330173822568

用过Vue的同学,想必都很熟悉Vue的生命周期。例如createmounted,其实这些都是生命周期钩子。我们可以在这些钩子调用我们实现的函数。

本文就是介绍10个在Vue项目开发过程,经常会用到的函数,请注意,这里是Vue3的写法!!!

1. 窗口大小

这个函数,我在使用Vue+Electron会经常用到,主要是用来监听窗口的变化,获取当前窗口的宽高。

实现

import { ref, onMounted, onUnmounted } from 'vue';

export function useWindowResize() {
  const width = ref(window.innerWidth);
  const height = ref(window.innerHeight);
  const handleResize = () => {
    width.value = window.innerWidth;
    height.value = window.innerHeight;
  }

  onMounted(() => {
    window.addEventListener('resize', handleResize)
  });

  onUnmounted(() => {
    window.removeEventListener('resize', handleResize)
  })

  return {
    width,
    height
  }
}

调用

setup() {
    const { width, height } = useWindowResize();
}}

2. 本地存储

想通过将数据值存储在会话存储-sessionStorage本地存储-localStorage*中并将该值绑定到视图来持久化数据吗?只需要创建一个钩子,返回一个从存储中获取的数据,以及一个在我们想要更改数据时将数据存储在存储中的函数。

代码

import { ref } from 'vue';

const getItem = (key, storage) => {
  let value = storage.getItem(key);
  if (!value) {
    return null;
  }
  try {
    return JSON.parse(value)
  } catch (error) {
    return value;
  }
}

export const useStorage = (key, type = 'session') => {
  let storage = null;
  switch (type) {
    case 'session':
      storage = sessionStorage;
      break;
    case 'local':
      storage = localStorage;
      break;
    default:
      return null;
  }
  const value = ref(getItem(key, storage));
  const setItem = (storage) => {
    return (newValue) => {
      value.value = newValue;
      storage.setItem(key, JSON.stringify(newValue));
    }
  }
  return [
    value,
    setItem(storage)
  ]
}

调用

const [token, setToken] = useStorage('token');
setToken('new token');

3. 网络状态

我们需要为“online”和“offline”的事件添加事件监听器。在事件中,我们只是调用一个回调函数,参数为网络状态,支持检查网络连接的状态。

代码

import { onMounted, onUnmounted } from 'vue';

export const useNetworkStatus = (callback = () => { }) => {
  const updateOnlineStatus = () => {
    const status = navigator.onLine ? 'online' : 'offline';
    callback(status);
  }

  onMounted(() => {
    window.addEventListener('online', updateOnlineStatus);
    window.addEventListener('offline', updateOnlineStatus);
  });

  onUnmounted(() => {
    window.removeEventListener('online', updateOnlineStatus);
    window.removeEventListener('offline', updateOnlineStatus);
  })
}

调用

useNetworkStatus((status) => { 
    console.log(`你的网络状态是 ${status}`); 
}

4. 复制到粘贴板

将文本复制到剪贴板是每个项目中的常用功能。这个钩子非常简单,只需返回一个支持将文本复制到剪贴板的函数。

代码

function copyToClipboard(text) {
  let input = document.createElement('input');
  input.setAttribute('value', text);
  document.body.appendChild(input);
  input.select();
  let result = document.execCommand('copy');
  document.body.removeChild(input);
  return result;
}

export const useCopyToClipboard = () => {
  return (text) => {
    if (typeof text === "string" || typeof text == "number") {
      return copyToClipboard(text);
    }
    return false;
  }
}

调用

const copyToClipboard = useCopyToClipboard();
copyToClipboard('just copy');

5, 主题切换

它可以帮助我们轻松切换网站的主题,只需使用主题名称调用此钩子即可。这是我用来为主题定义变量的示例 CSS 代码。

html[theme="dark"] {
   --color: #FFF;
   --background: #333;
}html[theme="default"], html {
   --color: #333;
   --background: #FFF;
}

要更改主题,我们只需要制作一个自定义钩子,它将返回一个通过主题名称更改主题的函数.

代码

export const useTheme = (key = '') => {
  return (theme) => {
    document.documentElement.setAttribute(key, theme);
  }
}

调用

const changeTheme = useTheme();
changeTheme('dark');

6. ScrollToBottom

除了分页列表,加载更多(或延迟加载)是一种友好的数据加载方式。特别是对于移动设备,几乎运行在移动设备上的应用程序在其 UI 中加载更多。为此,我们需要检测用户滚动到列表底部并触发该事件的回调。

代码

import { onMounted, onUnmounted } from 'vue';

export const useScrollToBottom = (callback = () => { }) => {
  const handleScrolling = () => {
    if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight) {
      callback();
    }
  }

  onMounted(() => {
    window.addEventListener('scroll', handleScrolling);
  });

  onUnmounted(() => {
    window.removeEventListener('scroll', handleScrolling);
  });
}

调用

useScrollToBottom(() => { console.log('滚动到底部') })

7. 点击容器之外

在开发中,我们会经常性的用到模态框。它对许多用例(表单、确认、警告等)非常有帮助。我们经常会用到的一个场景是:响应用户在模态框之外单击时的操作!

代码

import { onMounted, onUnmounted } from 'vue';

export const useOnClickOutside = (ref = null, callback = () => {}) => {
  function handleClickOutside(event) {
    if (ref.value && !ref.value.contains(event.target)) {
      callback()
    }
  }

  onMounted(() => {
    document.addEventListener('mousedown', handleClickOutside);
  })

  onUnmounted(() => {
    document.removeEventListener('mousedown', handleClickOutside);
  });
}

调用

<template>
    <div ref="container">View</div>
</template>
<script>
import { ref } from 'vue';
export default {
    setup() {
        const container = ref(null);
        useOnClickOutside(container, () => {
            console.log('在容器外点击'); 
        })
    }
}
</script>

8. 定时器

实现一个具体开始、暂停/恢复、停止功能的定时器。

代码

import { ref, onUnmounted } from 'vue';

export const useTimer = (callback = () => { }, step = 1000) => {
  let timerVariableId = null;
  let times = 0;
  const isPaused = ref(false);
   
  const stop = () => {
    if (timerVariableId) {
      clearInterval(timerVariableId);
      timerVariableId = null;
      resume();
    }
  }
  
  const start = () => {
    stop();
    if (!timerVariableId) {
      times = 0;
      timerVariableId = setInterval(() => {
        if (!isPaused.value) {
          times++;
          callback(times, step * times);
        }
      }, step)
    }
  }

  const pause = () => {
    isPaused.value = true;
  }

  const resume = () => {
    isPaused.value = false;
  }

  onUnmounted(() => {
    if (timerVariableId) {
      clearInterval(timerVariableId);
    }
  })

  return {
    start,
    stop,
    pause,
    resume,
    isPaused
  }
}

调用

function handleTimer(round) {      
    roundNumber.value = round;    
}
const { 
    start,
    stop,
    pause,
    resume,
    isPaused
} = useTimer(handleTimer);
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。