【vue自定义指令】骨架屏指令

news2024/11/20 15:30:41

场景

预加载的过程中,数据还未请求到,dom已经渲染出来了?

展示效果


 

实现

封装指令(代码块1)
  1. app引入(代码块2)
  2. 使用(代码块3)

代码

封装

​
import { reactive, watchEffect, h, render } from 'vue';


  const state = reactive({
    loading: false,
    list: []
  });

  // 动态插入 CSS 样式
  const insertStyles = () => {
    const style = document.createElement('style');
    style.textContent = `
    @keyframes fadeIn {
      from { opacity: 0; }
      to { opacity: 1; }
    }
    
    @keyframes fadeOut {
      from { opacity: 1; }
      to { opacity: 0; }
    }
    
    .frame-container {
      animation: fadeIn 0.5s ease-in-out;
    }
    
    .frame-container.fade-out {
      animation: fadeOut 0.5s ease-in-out;
    }
    
    .frame-item {
      background: #e5e5e5;
      border-radius: 4px;
    }
  `;
    document.head.appendChild(style);
  };


  insertStyles(); // 执行插入样式

  watchEffect(() => {
    const children = state.list.map((el) => {
      const rect = el.getBoundingClientRect();
      return h('div', {
        class: 'frame-item',
        style: {
          position: 'absolute',
          top: rect.top + 'px',
          left: rect.left + 'px',
          width: '0px',  // 初始化宽度为0
          height: rect.height + 'px',
          borderRadius: getComputedStyle(el).borderRadius,
          maxWidth: rect.width + 'px',  // 确保动画结束时的最大宽度
        },
      });
    });

    const container = h('div', { class: 'frame-container' }, children);

    if (state.loading) {
      render(container, document.body);

      // 动态触发动画
      requestAnimationFrame(() => {
        state.list.forEach((el, index) => {
          const rect = el.getBoundingClientRect();
          const frameItem = document.querySelectorAll('.frame-item')[index];
          frameItem.style.width = rect.width + 'px';  // 动态设置最终宽度
          frameItem.style.transition = 'width 1.5s ease-in-out';  // 过渡动画
        });
      });
    } else {
      const existingContainer = document.querySelector('.frame-container');
      if (existingContainer) {
        existingContainer.classList.add('fade-out');
        setTimeout(() => {
          render(null, document.body);
        }, 300);
      }
    }
  });


  const Frame = {
    mounted(el, binding) {
      state.loading = binding.value;
    },
    updated(el, binding) {
      state.loading = binding.value;
    },
    unmounted(el) {
      state.loading = false;
    }
  };

  const FrameItem = {
    mounted(el) {
      state.list.push(el);
    },
    unmounted(el) {
      const i = state.list.indexOf(el);
      if (i !== -1) {
        state.list.splice(i, 1);
      }
    }
  };

  const vFrame = {
    install: (app) => {
      app.directive('frame', Frame);
      app.directive('frame-item', FrameItem);
    }
  };

  export default vFrame;

​

使用

<template>
  <div class="mb100" v-frame="frameLoading" :style="{position:'relative',display:'flex',flexDirection:'column',rowGap:'10px'}">
    <div :style="{width:'600px'}">
      <div v-frame-item>
        91273123812738127831738127381273812
      </div>
    </div>
    <div :style="{width:'200px'}">
      <div v-frame-item>
        012931293
      </div>
    </div>
    <div :style="{width:'300px'}">
      <div v-frame-item>
        012931293
      </div>
    </div>
    <div :style="{width:'400px'}">
      <div v-frame-item>
        012931293
      </div>
    </div>
  </div>
</template>

<script setup>
  const frameLoading = ref(true)
</script>


 


 


 


 


 


 


 


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2213944.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spark全网最全总结

Spark 产生之前&#xff0c;已经有 MapReduce 这类非常成熟的计算系统存在了&#xff0c;并提供 了高层次的 API(map/reduce)&#xff0c;把计算运行在集群中并提供容错能力&#xff0c;从而实现 分布式计算。 虽然 MapReduce 提供了对数据访问和计算的抽象&#xff0c…

一个月学会Java 第13天 抽象类与接口

Day13 抽象类与接口 通过了前面的学习&#xff0c;我们已经掌握了面向对象的基础 继承 封装 多态 第一章 抽象类 接下来&#xff0c;我们要对面向对象学习高级的部分&#xff0c;我们先要学到的就是抽象类&#xff0c;听名字也能想到&#xff0c;肯定很抽象&#xff0c;那我们先…

电力电子技术(二)

三相可控整流电路&#xff1a;&#xff08;主要包括三相半波和三相桥式&#xff09; &#xff08;一&#xff09;三相半波&#xff1a; &#xff08;1.1电阻性负载&#xff09; 右侧第三个图代表VT1晶闸管的流经电流波形&#xff0c;一个周期仅导通一次&#xff1a;晶闸管导…

Netty讲解与案例

1.Netty简介&#xff1a; 官网&#xff1a;https://netty.io/ Netty 是一个 NIO 客户端服务器框架&#xff0c;可以快速轻松地开发协议服务器和客户端等网络应用程序。它极大地简化和精简了 TCP 和 UDP 套接字服务器等网络编程。 “快速简便”并不意味着最终的应用程序会存在…

Halcon 使用二维像素分类对图像进行分割

文章目录 算子histo_2dim 计算双通道灰度值图像的直方图class_2dim_sup 使用二维像素分类对图像进行分割 示例 算子 histo_2dim 计算双通道灰度值图像的直方图 histo_2dim(Regions, ImageCol, ImageRow : Histo2Dim : : )Regions (输入对象)&#xff1a;在此区域内计算直方图…

腾讯云视立方开通各项云服务相关

云直播 如何开通云直播服务&#xff1f; 进入 云直播管理控制台&#xff0c;进入腾讯云直播服务开通页&#xff0c;查看相关协议并勾选同意&#xff0c;单击申请开通即可开通云直播服务。 。 如何开启流防盗链 KEY&#xff1f; 推流防盗链 KEY 是为了确保只有您的 App 用户…

dockerfile 用法全解析

FROM 构建基于alpine的镜像&#xff0c;单条执行就是复制了一个apline镜像(除了FROM其他都是非必须的) WORKDIR 是之指定接下来的shell语句是运行在哪个路径下&#xff0c;没有就会创建目录 COPY 将宿主机指定目录的文件拷贝到镜像指定目录 &#xff08;ADD 源地址还可以url…

[LeetCode] 662. 二叉树最大宽度

题目描述&#xff1a; 给你一棵二叉树的根节点 root &#xff0c;返回树的 最大宽度 。 树的 最大宽度 是所有层中最大的 宽度 。 每一层的 宽度 被定义为该层最左和最右的非空节点&#xff08;即&#xff0c;两个端点&#xff09;之间的长度。将这个二叉树视作与满二叉树结…

【C语言刷力扣】2206.将数组划分成相等数对

题目&#xff1a; 解题思路&#xff1a; 题目中要求元素成数对出现&#xff0c;即每个元素出现偶数次。用哈希表存放每个数出现的次数&#xff0c;再循环查看每个数的次数是否位偶数。 typedef struct {int key;int count;UT_hash_handle hh; } hashEntry;bool divideArray(int…

IDEA下载安装

文章目录 1、下载安装包2、安装IDEA3、全局配置4、安装插件 1、下载安装包 IDEA官网下载最新IDEA。 上面的ULtimate是旗舰版&#xff0c;试用30天&#xff0c;之后是需要收费的&#xff0c;下面黑色区域的Community是社区版&#xff0c;功能不如旗舰版丰富&#xff0c;但是好在…

文件的二维码怎么做成?简单的3步生成二维码技巧

数字化时代的到来&#xff0c;用来将内容分享给其他人展示的方式也越来越多。其中二维码就是现在很流行的一种方式&#xff0c;将内容存入二维码后&#xff0c;其他人就可以扫描分享二维码来查看内容&#xff0c;那么文件生成二维码该怎么操作呢&#xff1f; 通过使用文件二维…

如何轻松实现Patreon订阅,获得独家内容

目录 1. 什么是Patreon&#xff1f; Patreon是一个非常流行的在线平台。 它支持内容创作者通过订阅的方式,直接从粉丝那里获取资金支持。无论是艺术家、音乐家,还是作家、视频制作人,都能在这里找到自己的粉丝群体。 简而言之,你可以通过订阅他们定期发布的独家内容,享受到更…

量子噪声与量子操作

由于量子不确定性和量子态的测量过程而引入的随机波动&#xff0c;量子噪声不可避免。 经典噪声 想象一下&#xff0c;一个比特存储在硬盘驱动器上&#xff0c; 它与普通计算机相连&#xff0c;该比特从状态0或1开始&#xff0c;经过长时间&#xff0c;散乱的磁场很可能会导致…

020 elasticsearch7.10.2 elasticsearch-head kibana安装

文章目录 全文检索流程ElasticSearch介绍ElasticSearch应用场景elasticsearch安装允许远程访问设置vm.max_map_count 的值 elasticsearch-head允许跨域 kibana 商品数量超千万&#xff0c;数据库无法使用索引 如何使用全文检索&#xff1a; 使用lucene&#xff0c;在java中唯一…

AI视频监控卫士:一键Docker简易安装,开源技术引领视频监控

AI视频监控卫士的主要应用场景&#xff1a; 我们决定开源的原因&#xff1a; 1. 灵活性与可定制性&#xff1a; 开源产品的代码对用户公开&#xff0c;允许开发者根据特定需求进行自定义和扩展。思通数科AI视频监控卫士作为开源项目&#xff0c;可以灵活适应不同企业或项目的需…

一些NLP代表性模型

&#xff08;一&#xff09;BERT 由Bidirectional Encoder Representations from Transformers的首字母组成&#xff0c;是encoder-only结构类型的代表。 模型分预训练和微调两步&#xff0c;预训练任务有两类&#xff1a;masked language model(MLM)、next sentence predict…

我作为TypeScript开发人员是如何学习Rust的

讲讲我作为TypeScript开发人员学习Rust的经验吧&#xff0c;希望对你有帮助 像许多开发人员一样&#xff0c;我通过专注于网络技术开始了我的编程生涯。我相信这是一个很好的起点&#xff0c;JavaScript&#xff0c;互联网的语言&#xff0c;以及许多&#xff0c;是一个令人难…

Axure原型设计秘籍:解锁高效设计与开发的宝藏工具

​ 在快速迭代的数字时代&#xff0c;原型设计成为了产品开发与用户体验优化的关键环节。Axure&#xff0c;作为一款备受推崇的原型设计工具&#xff0c;凭借其强大的功能、直观的界面和丰富的资源&#xff0c;成为了设计师和产品经理们的得力助手。本文将带你深入探索Axure的原…

JavaScript中的对象,常用内置对象和数据类型

一、对象 1.概念 什么是对象&#xff1f; 在JavaScript中&#xff0c;对象是一组无序的相关属性和方法集合&#xff0c;所有的事物都是对象&#xff0c;例如&#xff1a;字符串、数值、数组和函数等等。 对象是由属性和方法组成的。 属性&#xff1a;事物的特征&#xff0c;在…