前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >10个有用的自定义钩子vue.js

10个有用的自定义钩子vue.js

作者头像
前端小智@大迁世界
发布于 2022-04-14 00:30:38
发布于 2022-04-14 00:30:38
42300
代码可运行
举报
文章被收录于专栏:终身学习者终身学习者
运行总次数:0
代码可运行

作者:Sang Nguyen 译者:前端小智 来源:medium 本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。

Vue 是我使用的第一个 JS 框架。可以说,Vue 是我进入JavaScript世界的第一道门之一。目前,Vue 仍然是一个很棒的框架。随着 composition API 的出现,Vue 只会有更大的发展。在这篇文章中,我将介绍 10 个有用的自定义钩子,让我们的代码更加好看。

useWindowResize

这是一个基本的钩子,因为它被用在很多项目中.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
  }
}

使用就更简单了,只需要调用这个钩子就可以获得 window 的宽度和高度。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
setup() {
    const { width, height } = useWindowResize();
}

useStorage

你想通过在 session storage 或 local storage 中存储数据的值来持久化数据,并将该值绑定到视图?有了一个简单的钩子--useStorage,这将变得非常容易。我们只需要创建一个钩子来返回从存储空间得到的数据,以及一个函数来在我们想要改变数据时将其存储在存储空间。下面是我的钩子。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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)
  ]
}

在我的代码中,我使用 JSON.parse JSON.stringify 来格式化数据。如果你不想格式化它,你可以删除它。下面是一个如何使用这个钩子的例子。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const [token, setToken] = useStorage('token');
setToken('new token');

useNetworkStatus

这是一个有用的钩子,支持检查网络连接的状态。为了实现这个钩子,我们需要为事件 "在线"和 "离线"添加事件监听器。在事件中,我们只是调用一个回调函数,参数为网络状态。下面是我的代码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);
  })
}

调用方式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
useNetworkStatus((status) => { 
    console.log(`Your network status is ${status}`);
}

useCopyToClipboard

剪切板是一个比较常见的功能,我们也可以将它封装成 hook,代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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;
  }
}

使用如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const copyToClipboard = useCopyToClipboard();
copyToClipboard('just copy');

useTheme

只是一个简短的钩子来改变网站的主题。它可以帮助我们轻松地切换网站的主题,只需用主题名称调用这个钩子。下面是一个我用来定义主题变量的CSS代码例子。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
html[theme="dark"] {
   --color: #FFF;
   --background: #333;
}
html[theme="default"], html {
   --color: #333;
   --background: #FFF;
}

要改变主题,只需要做一个自定义的钩子,它返回一个函数来通过主题名称改变主题。代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
export const useTheme = (key = '') => {
  return (theme) => {
    document.documentElement.setAttribute(key, theme);
  }
}

使用如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const changeTheme = useTheme();
changeTheme('dark');

usePageVisibility

有时,当客户不专注于我们的网站时,我们需要做一些事情。要做到这一点,我们需要一些东西,让我们知道用户是否在关注。这是一个自定义的钩子。我把它叫做 PageVisibility,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { onMounted, onUnmounted } from 'vue';

export const usePageVisibility = (callback = () => { }) => {
  let hidden, visibilityChange;
  if (typeof document.hidden !== "undefined") {
    hidden = "hidden";
    visibilityChange = "visibilitychange";
  } else if (typeof document.msHidden !== "undefined") {
    hidden = "msHidden";
    visibilityChange = "msvisibilitychange";
  } else if (typeof document.webkitHidden !== "undefined") {
    hidden = "webkitHidden";
    visibilityChange = "webkitvisibilitychange";
  }

  const handleVisibilityChange = () => {
    callback(document[hidden]);
  }

  onMounted(() => {
    document.addEventListener(visibilityChange, handleVisibilityChange, false);
  });

  onUnmounted(() => {
    document.removeEventListener(visibilityChange, handleVisibilityChange);
  });
}

用法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
usePageVisibility((hidden) => {
   console.log(`User is${hidden ? ' not' : ''} focus your site`);
});

useViewport

有时我们会用宽度来检测当前的用户设备,这样我们就可以根据设备来处理对应的内容。这种场景,我们也可以封装成一个 hook,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { ref, onMounted, onUnmounted } from 'vue';

export const MOBILE = 'MOBILE'
export const TABLET = 'TABLET'
export const DESKTOP = 'DESKTOP'

export const useViewport = (config = {}) => {
  const { mobile = null, tablet = null } = config;
  let mobileWidth = mobile ? mobile : 768;
  let tabletWidth = tablet ? tablet : 922;
  let device = ref(getDevice(window.innerWidth));
  function getDevice(width) {
    if (width < mobileWidth) {
      return MOBILE;
    } else if (width < tabletWidth) {
      return TABLET;
    }
    return DESKTOP;
  }

  const handleResize = () => {
    device.value = getDevice(window.innerWidth);
  }

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

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

  return {
    device
  }
}

使用如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const { device } = useViewport({ mobile: 700, table: 900 });

useOnClickOutside

当 model 框弹出时,我们希望能点击其它区域关闭它,这个可以使用 clickOutSide,这种场景我们也可以封装成钩子,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);
  });
}

用法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
    <div ref="container">View</div>
</template>
<script>
import { ref } from 'vue';
export default {
    setup() {
        const container = ref(null);
        useOnClickOutside(container, () => {
            console.log('Clicked outside'); 
        })
    }
}
</script>

useScrollToBottom

除了分页列表,加载更多(或懒惰加载)是一种友好的加载数据的方式。特别是对于移动设备,几乎所有运行在移动设备上的应用程序都在其用户界面中应用了load more。要做到这一点,我们需要检测用户滚动到列表底部,并为该事件触发一个回调。 useScrollToBottom 是一个有用的钩子,支持你这样做。代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);
  });
}

用法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
useScrollToBottom(() => { console.log('Scrolled to bottom') })

useTimer

useTimer 的代码比其他钩子要长一些。 useTimer 支持运行一个带有一些选项的定时器,如开始、暂停/恢复、停止。要做到这一点,我们需要使用 setInterval 方法。在这里,我们需要检查定时器的暂停状态。如果定时器没有暂停,我们只需要调用一个回调函数,该函数由用户作为参数传递。为了支持用户了解该定时器当前的暂停状态,除了action useTimer之外,还要给他们一个变量 isPaused,其值为该定时器的暂停状态。代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
  }
}

用法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function handleTimer(round) {      
    roundNumber.value = round;    
}
const { 
    start,
    stop,
    pause,
    resume,
    isPaused
} = useTimer(handleTimer);

本文分享了10个有用的Vue自定义钩子。希望它们对你有帮助。Vue. 是一个很棒的框架,希望你能用它来构建更多很棒的东西。

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

原文:https://javascript.plainengli...

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-04-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
聊聊大模型位置编码及其外推性
现如今很多大模型都开始支持超过4096长度的推理,例如GPT-4支持超过30k,ChatGLM2-6B也支持最长为32K的文本。但是由于显存资源的限制,这些大模型在真正在训练过程中不一定要训练这么长的文本,通常在预训练时只会设计到4k左右。
NewBeeNLP
2023/09/15
2K0
聊聊大模型位置编码及其外推性
十分钟读懂旋转编码(RoPE)
旋转位置编码(Rotary Position Embedding,RoPE)是论文 Roformer: Enhanced Transformer With Rotray Position Embedding 提出的一种能够将相对位置信息依赖集成到 self-attention 中并提升 transformer 架构性能的位置编码方式。而目前很火的 LLaMA、GLM 模型也是采用该位置编码方式。
zenRRan
2023/09/11
5.9K0
十分钟读懂旋转编码(RoPE)
Long-Context下LLM模型架构全面介绍
随着ChatGPT的快速发展,基于Transformer的大型语言模型(LLM)为人工通用智能(AGI)铺平了一条革命性的道路,并已应用于知识库、人机界面和动态代理等不同领域。然而,存在一个普遍的限制:当前许多LLM受资源限制,主要是在较短的文本上进行预训练,使它们对现实世界中常见的较长的上下文提示不太有效。本文对基于Transformer的LLM模型架构的进展进行了全面的介绍。
zenRRan
2023/11/29
2K0
Long-Context下LLM模型架构全面介绍
LLM 大模型学习必知必会系列(四):LLM训练理论篇以及Transformer结构模型详解
深度学习领域所谓的“模型”,是一个复杂的数学公式构成的计算步骤。为了便于理解,我们以一元一次方程为例子解释:
汀丶人工智能
2024/05/26
1.4K0
LLM 大模型学习必知必会系列(四):LLM训练理论篇以及Transformer结构模型详解
Llama也中招,混合精度下位置编码竟有大坑,百川智能给出修复方案
位置编码技术是一种能够让神经网络建模句子中 Token 位置信息的技术。在 Transformer 大行其道的时代,由于 Attention 结构无法建模每个 token 的位置信息,位置编码(Position embedding) 成为 Transformer 非常重要的一个组件。研究人员也提出了各种各样的位置编码方案来让网络建模位置信息,Rope 和 Alibi 是目前最被广泛采纳的两种位置编码方案。
机器之心
2023/09/08
6930
Llama也中招,混合精度下位置编码竟有大坑,百川智能给出修复方案
综述:利用位置编码实现长度外推
Transformer自诞生以来就席卷了NLP领域,因为它具有对序列中复杂依赖关系进行建模的优越能力。尽管基于Transformer的预训练语言模型(PLM)在几乎所有NLP任务中都取得了巨大成功,但它们都有预设的长度限制,因此很难将这种成功扩展到见过数据以外的更长的序列,即长度外推问题。为了增强Transformer的长度外推,人们提出了大量的可外推的位置编码。
zenRRan
2024/01/11
8120
综述:利用位置编码实现长度外推
万字长文带你入门Transformer
Transformer在许多的人工智能领域,如自然语言处理(Natural Language Processing, NLP)、计算机视觉(Computer Vision, CV)和语音处理(Speech Processing, SP)取得了巨大的成功。因此,自然而然的也吸引了许多工业界和学术界的研究人员的兴趣。到目前为止,已经提出了大量基于Transformer的相关工作和综述。本文基于邱锡鹏[1]老师团队近日所发表的一篇综述[2]为基础,详细的解读Transformer的来龙去脉,同时为大家介绍近期一些相关工作,中间也会穿插一些笔者的见解。最后,本文也将列出一些可探索的未来研究方向,希望能给予读者一些启发。
AIWalker
2021/07/05
2.3K0
万字长文带你入门Transformer
Bert不完全手册9. 长文本建模 BigBird & Longformer & Reformer & Performer
这一章我们来唠唠如何优化BERT对文本长度的限制。BERT使用的Transformer结构核心在于注意力机制强大的交互和记忆能力。不过Attention本身O(n^2)的计算和内存复杂度,也限制了Transformer在长文本中的应用。
风雨中的小七
2022/10/08
1.9K0
Bert不完全手册9. 长文本建模 BigBird & Longformer & Reformer & Performer
LLM推理技术之StreamingLLM:如何拥有无限长生成能力
MIT,Meta AI,CMU的研究人员最近提出了一种StreamingLLM,声称可以使得经过有限序列长度训练的大型语言模型能够在无需任何微调的情况下,推广到无限序列长度的输入和输出。 不过这里值得强调的是,这个方法并没有增加LLM的对上文的记忆,只是让它输入输出无限长。一个显而易见的好处就是,在对话机器人生成一个很长的回答时,你不需要再输入“继续”了。
NewBeeNLP
2023/10/25
1.8K0
LLM推理技术之StreamingLLM:如何拥有无限长生成能力
层次分解位置编码,让BERT可以处理超长文本
我们知道,BERT无法处理超长文本的根本原因是BERT使用了从随机初始化训练出来的绝对位置编码,一般的最大位置设为了512,因此顶多只能处理512个token,多出来的部分就没有位置编码可用了。当然,还有一个重要的原因是Attention的O(n^2)复杂度,导致长序列时显存用量大大增加,一般显卡也finetune不了
mathor
2021/07/09
2.1K0
HuggingFace工程师亲授:如何在Transformer中实现最好的位置编码
在 Transformer 模型中,位置编码(Positional Encoding) 被用来表示输入序列中的单词位置。与隐式包含顺序信息的 RNN 和 CNN 不同,Transformer 的架构中没有内置处理序列顺序的机制,需要通过位置编码显式地为模型提供序列中单词的位置信息,以更好地学习序列关系。
机器之心
2025/02/14
1450
HuggingFace工程师亲授:如何在Transformer中实现最好的位置编码
LLM-TAP随笔——有监督微调【深度学习】【PyTorch】【LLM】
答案映射 将模型的输出与最终的标签做映射。映射规则是人为制定的,比如,将“太好了”、“好”映射为“正面”标签,将“不好”,“糟糕”映射为“负面”标签,将“一般”映射为“中立”标签。
来杯Sherry
2023/09/26
4520
LLM-TAP随笔——有监督微调【深度学习】【PyTorch】【LLM】
LLM-TAP随笔——大语言模型基础【深度学习】【PyTorch】【LLM】
这个架构常用于编码器-解码器架构是一种常用于序列到序列(Seq2Seq)任务的深度学习架构。序列到序列的问题举例:NLP问题(机器翻译、问答系统和文本摘要)。
来杯Sherry
2023/09/26
6840
LLM-TAP随笔——大语言模型基础【深度学习】【PyTorch】【LLM】
文献阅读:RoFormer: Enhanced Transformer with Rotary Position Embedding
众所周知,transformer的attention机制本身是不带有位置信息的,因此对于文本序列,attention机制本身就会丢失掉原文当中的序列信息,造成信息缺失,影响到模型的效果表达,这个应该已经算是面试中常见的八股文问题了。
codename_cys
2022/05/11
1.1K0
文献阅读:RoFormer: Enhanced Transformer with Rotary Position Embedding
LLM技术探讨(1)---位置编码
这要从Transformer设计之初说起。在人类语言中,单词的位置和顺序定义了语法,也影响着语义,无法捕获单词的顺序,会导致我们很难理解一句话的含义。
DC童生
2023/09/06
6210
LLM技术探讨(1)---位置编码
王小川的大模型打造秘籍首次曝光:五步走,两个月炼成
70亿参数、一经发布就开源可商用,百川智能的中英文大模型baichuan-7B,近期在圈内备受瞩目。
量子位
2023/08/05
3710
王小川的大模型打造秘籍首次曝光:五步走,两个月炼成
深度学习进阶篇-预训练模型[2]:Transformer-XL、Longformer、GPT原理、模型结构、应用场景、改进技巧等详细讲解
在正式讨论 Transformer-XL 之前,我们先来看看经典的 Transformer(后文称 Vanilla Transformer)是如何处理数据和训练评估模型的,如图 1 所示。
汀丶人工智能
2023/10/11
9990
深度学习进阶篇-预训练模型[2]:Transformer-XL、Longformer、GPT原理、模型结构、应用场景、改进技巧等详细讲解
博采众长式的旋转位置编码
上一篇文章中,我们对原始的Sinusoidal位置编码做了较为详细的推导和理解,总的感觉是Sinusoidal位置编码是一种"想要成为相对位置编码的绝对位置编码"。
mathor
2021/05/20
1.7K0
大语言模型中常用的旋转位置编码RoPE详解:为什么它比绝对或相对位置编码更好?
自 2017 年发表“ Attention Is All You Need ”论文以来,Transformer 架构一直是自然语言处理 (NLP) 领域的基石。它的设计多年来基本没有变化,随着旋转位置编码 (RoPE) 的引入,2022年标志着该领域的重大发展。
deephub
2024/04/01
6.8K0
大语言模型中常用的旋转位置编码RoPE详解:为什么它比绝对或相对位置编码更好?
Llama深入浅出
前方干货预警:这可能是你能够找到的最容易懂的最具实操性的学习开源LLM模型源码的教程。
lyhue1991
2023/09/05
2.4K1
Llama深入浅出
推荐阅读
相关推荐
聊聊大模型位置编码及其外推性
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验