REC
首页
文章分类
源码资源
技术教程
程序软件
文创娱乐
玄学修炼
关于我们
其他页面
网站统计
友情链接
用户留言
高清壁纸
关于易航
热门文章
Joe再续前缘主题 - 搭建本站同款网站
易航网址导航系统 – 功能强大,轻量易用
JsonDb-PHP轻量级文件数据库系统
Typecho一键调整网站为冬天情景插件
V免签全开源免签约码支付系统(支持:支付宝 微信 QQ)
标签搜索
PHP
Web前端
网站源码
PHP源码
Typecho
Typecho插件
课程资料
Windows程序
Android软件
武术内功
HTML源码
Web
Joe主题
Python
Windows
国漫
网络协议
MySQL
NodeJs
小说
发布
登录
注册
找到
42
篇与
Web前端
相关的结果
- 第 3 页
2024-11-22
浏览器Audio音频自动播放为什么会失效
背景 某天客户报了一个问题,说是大屏的声音不能自动播放了,我们的大屏应用是有报警的,当有报警的时候,会自动播放报警的声音 复线步骤 测试结果如下 当浏览页面后,音频不会自动播放 当从另外的一个页面进入到当前页面,可以直接播放声音 如果你想测试,可以点我进行测试 你可以先点击上面链接的 「尝试一下」,下面为截图 图片 这个时候你会听到一声马叫声 然后,你刷新下一个马叫声的页面,这个时候声音的自动播放将不会生效 图片 报错问题排查 打开控制台,无法意外看到一个报错信息。 图片 翻译为中文的意思为允许的错误。播放失败,因为用户没有先与文档交互。https\://goo.gl/xX8pDD 尝试解决 那我就通过给body添加点击事件,自动触发点击事件,在点击的事件后自动播放声音。(当是我的想法是,这个大概率是不行的,chrome应该不会这个忽略点,不然这个功能就外表不存在) 经过测试后,发现确实还不行,在意料中。 参考别人的网站,用抖音测试 点击我跳转抖音 想到了我们可以参考抖音,我用抖音进行测试,当你不应该做任何操作时,页面如下 图片 我们从这里总结得出的结论,这应该是浏览器的,需要查看官方文档,看看原因 刊物 点我查看chrome的官方文档 「我截取了一些关键信息」 图片 注意浏览器有一个「媒体互动指数」,这是浏览器自动计算的,该分结果,才会触发自动播放 「查看电脑的媒体互动指数」 在url上输入about://media-engagement,你会看到如下的截图, 图片 「经过测试后」当网站变成了「High」,音频会自动播放,不会播放失败。 这里解释了为什么有的网站可以自动播放声音,有的网站不可以自动播放声音 好吧,我们继续往下看,这个时候看到了一些关键的信息。 「作为人,我们不应该相信音频开发/视频播放会成功,要始终在播放的回落中来进行判断」 图片 看到这些,我们来修改抖音的实现。在播放声音的catch的时候,显示一个错误的弹窗,提示用户,当用户点击的时候,自动播放声音 this.alarmAudio = new Audio(require("@/assets/sound/alarm.mp3")); this.alarmAudio .play() .then(() => { this.notifyId && this.notifyId.close(); }) .catch((error) => { if (error instanceof DOMException) { // 这里可以根据异常类型进行相应的错误处理 if (error.name === "NotAllowedError") { if (this.notifyId) return; this.notifyId = Notification({ title: "", duration: 0, position: "bottom-left", dangerouslyUseHTMLString: true, onClick: this.onAudioNotifyConfirm, showClose: false, customClass: "audio-notify-confirm", message: "<div style='color:#fff;font-size:18px;cursor:pointer'>因浏览器限制,需<span style='color:#ff2c55'>点击打开声音</span></div>", }); } } });实现效果如下 图片 总结 在启用视频或者音频的时候,要始终不相信他会播放声音成功,并且添加catch处理异常场景,给用户友好的提示 或者视频音频的自动播放跟媒体互动指数有关(MEI),当媒体指数高,会自动播放,否则需要用户先交互后,音频才可以自动播放。 从一个页面window.打开另外一个页面可以自动播放声音,当刷新页面后,需要有高的MEI,音频才会自动播放,如果你需要在后台打开一个大屏的页面,正好可以这样设计,不要用页面跳转
技术教程
# Web前端
易航
1年前
0
145
0
2024-11-13
一款功能丰富、界面美观的OA办公系统
介绍 OA-System Vue 开发的OA系统 具有工作流动态审批、加签、会签等工作流功能 具有文档预览、图片预览等功能 具有博客编写、预览、查看、搜索等功能 具有社区、问答等功能 具有OA系统常用功能 具有在线网盘等功能 支持审批流程、自由流程,审批日志,我的待办,我的已办,行政公告,Office文档预览,文档转PDF,图片压缩。 功能一览 具有工作流动态审批、加签、会签等工作流功能,可以对工作流程的审批业务进行评论/讨论 具有文档预览、图片预览等功能 具有博客编写、预览、查看、搜索等功能 具有社区、问答等功能 具有OA系统常用功能 具有在线网盘等功能 具有OA的移动端应用 工作流引擎完全手写且开源,可以类似钉钉/飞书那样,动态选择审批人员。 项目截图 图片 图片 图片 图片 图片 图片 图片 图片 图片 源码下载 隐藏内容,请前往内页查看详情
源码资源
# 网站源码
# Web前端
# NodeJs
易航
1年前
15
224
0
2024-11-12
CSS 让 height 高度属性完美支持 auto 过渡动画
众所周知,有些属性是不支持过渡动画的,比如高度 auto div{ height: 0; transition: 1s } .wrap:hover div{ height: auto }效果如下 图片 要实现过渡效果,之前提供过一个 grid 布局方式,原理是利用 grid 的尺寸单位 1fr 支持过渡的特性 一、calc-size 函数 现在要实现 auto 的过渡效果,需要用到一个全新的 calc-size 函数 图片 看到这个函数,是不是和 calc 比较类似?没错,这是一个可以将一些关键词转换成具体尺寸的函数。 回到上面这个例子,只需要将高度改成 calc-size(auto) ,如下 div{ height: 0; transition: 1s } .wrap:hover div{ height: calc-size(auto) }现在就有过渡效果了(Chrome 129+ 或者 Chrome 127+开启实验属性) 图片 其实除了 auto ,还支持其他尺寸关键词,比如 height: calc-size(min-content) height: calc-size(max-content) height: calc-size(fit-content)也支持混合计算,如下 height: calc-size(auto + 10px) height: calc-size(max-content - 10px)二、interpolate-size 属性 前面的例子,为了兼容之前的浏览器,还必须保留 height: auto 的写法 div{ height: 0; transition: 1s } .wrap:hover div{ height: auto; height: calc-size(auto) }如果是已经存在的项目,可能会有很多地方需要都要改成这种写法,有一定的侵入性。 为此,浏览器还提供了一个 interpolate-size 属性,这个属性可以设置插值计算的规则,有两个关键词 interpolate-size: numeric-only;/*默认值*/ interpolate-size: allow-keywords;其中第一个 numeric-only ,表示仅限数值,也就是只有真实的数值才会有过渡效果(目前浏览器的默认效果),第二个 allow-keywords 表示允许所有关键词,当然包括 auto 属性 有了这个属性,要做的事情就更简单了,只需要在全局 :root 加上这个属性 :root{ interpolate-size: allow-keywords; } div{ height: 0; transition: 1s } .wrap:hover div{ height: auto; }这样就全局生效了,无需在每个地方就加上 calc-size(auto) ,是不是非常方便呢? 图片 三、也支持 detail 展开过渡 大家可能都知道,detail 配合 summary 可以实现展开折叠效果 <div class="con"> <details name="a"> <summary>分组A</summary> <p>这是第一个分组 name="a"</p> </details> <details name="a"> <summary>欢迎</summary> <p>最近 details元素新增了一个name属性</p> </details> <details name="a"> <summary>关注</summary> <p>别看这只是一个普普通通的属性,这可是带来了一个全新的模式,一起了解一下吧</p> </details> </div>效果如下 图片 当然默认展开折叠是没有过渡效果的 利用 calc-size 或者 interpolate-size 也可以很轻松的实现过渡动画,关键实现如下 :root { interpolate-size: allow-keywords; } ::details-content{ content-visibility: visible; height: 0; transition: .3s; overflow: hidden; } details[open]::details-content{ height: auto; }这样就有过渡效果了,非常丝滑 图片 这是一段通用代码,可以用在任何地方 四、现在其实可以用起来了 虽然说兼容性很差(Chrome 129+),但这是一个渐进增强属性,不会影响现有功能,也无需修改已有结构,只需要全局增加这样一行就行了 :root { interpolate-size: allow-keywords; }这样能支持的浏览器自然就会有过渡动画了,完全不用担心是否兼容。 总结一下,其实就两点 calc-size 可以将非数值类型的单位转换成支持过渡的尺寸单位,包括 auto interpolate-size 可以从全局范围允许任意关键词支持过渡
技术教程
# Web前端
易航
1年前
0
192
2
2024-11-09
Three.js 可滑动魔方源码
图片 html 部分 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>魔方</title> <meta name="viewport" content="width=device-width,height=device-height,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0"> <link rel="stylesheet" href="css/style.css"> </head> <body> <div class="mofang"> <div class="mofang__background"></div> <div class="mofang__game"></div> <div class="mofang__texts"> <h1 class="text text--title"> <span>魔方</span> </h1> <div class="text text--note"> 双击即可开始 </div> <div class="text text--timer"> 0:00 </div> <div class="text text--complete"> <span>完成!</span> </div> <div class="text text--best-time"> <icon trophy></icon> <span>最佳时间!</span> </div> </div> <div class="mofang__prefs"> <range name="flip" title="翻转类型" list="迅速的 ,平滑的,弹起"></range> <range name="scramble" title="扰乱长度" list="20,25,30"></range> <range name="fov" title="摄像机角度" list="摄影,透视的"></range> <range name="theme" title="配色方案" list="灰色,浅蓝色,浅黄色,脏黄色,淡青色"></range> </div> <div class="mofang__stats"> <div class="stats" name="total-solves"> <i>全部解决:</i><b>-</b> </div> <div class="stats" name="best-time"> <i>最佳时间:</i><b>-</b> </div> <div class="stats" name="worst-time"> <i>最差时间:</i><b>-</b> </div> <div class="stats" name="average-5"> <i>平均值 5:</i><b>-</b> </div> <div class="stats" name="average-12"> <i>平均值 12:</i><b>-</b> </div> <div class="stats" name="average-25"> <i>平均值 25:</i><b>-</b> </div> </div> <div class="mofang__buttons"> <button class="btn btn--bl btn--stats"> <icon trophy></icon> </button> <button class="btn btn--bl btn--prefs"> <icon settings></icon> </button> <button class="btn btn--bl btn--back"> <icon back></icon> </button> <a href="#" class="btn btn--br btn--pwa"> </button> </div> </div> <script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/95/three.min.js'></script> <script src="js/common.js"></script> </body> </html>完整项目地址 隐藏内容,请前往内页查看详情
免费资源
源码资源
# Web前端
易航
1年前
3
71
0
2024-11-08
JavaScript逆向系列 09-Js Hook
0x00 前言 缘起是我前两天看了一篇逆向文章,里面用到了一段hook脚本,在这之前我是不理解hook是什么东西,看了那段脚本后我突然就悟了,遂写下这篇文章分享一下个人心得。 注:本文不会太深入js hook。 0x01 Intro 首先我需要明确一点,我们在浏览网站时,由于js是在客户端上执行的,所以我们有最高的权限,这也就方便我们去对js进行一些操作,例如hook。我个人认为的js hook技术就是我们去修改函数或方法内部的实现过程,也就是重写方法,以便我们去利用它去实现一些我们想要的效果。 接下来我会通过一个小demo简单演示一下js hook脚本该如何编写。 0x02 Demo console.log = function (message) { alert(message); }效果: 图片 console是内置对象,不需要实例化即可使用,所以我们可以直接修改它的方法,例如log方法。代码中我将log方法的内部实现过程改成了将传入的参数进行alert。不过这个脚本其实还是有缺陷的,一般情况下我们改写某个函数或方法的内部实现过程后,我们还需要将它原本的功能实现了,否则可能会造成意想不到的后果。 改写后的脚本: var test = console.log; console.log = function (message) { alert(message); test(message); }将log方法赋值给test,代码执行完我们想要的效果后就完成它本来的工作,也就是最后执行test函数,相当于执行了log方法。 效果: 图片 图片 现在就是一个比较完善的hook脚本了。 0x03 个人脚本分享 我在看完上文提到的那篇逆向文后,立马就去写了我的第一个hook脚本(注:后文会发全部代码以及讲解如何使用): 图片 就拿上期自动化加解密的案例进行测试: 图片 图片 通过控制台输出的堆栈信息直接定位到解密位置。 我先说明一下我为什么要重写JSON.parse和JSON.stringify这两个方法,可能有看过我的逆向文章或者看过其他js逆向文章的朋友们会发现,这两个方法在加解密操作中出场率极高。一般情况下密文解密后开发可能会选择将json转为object,那么就会用到JSON.parse,JSON.stringify可能就会在加密时用到。 代码的话通过上文的讲解读者应该能看懂大部分,我觉得唯一需要讲的就是new Error().stack,Error是构造函数,需要实例化才能用,以下是MDN介绍的stack方法:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Error/stack 图片 简单来说就是它可以直接输出调用的堆栈,也就是上文演示的效果: 图片 不过我这里还需要提的一点的就是这个方法需要不断的实例化调用,如果只实例化一个对象然后反复调用这个实例的stack方法,只会输出实例化时的那个调用堆栈,例如: 图片 图片 0x04 如何使用js hook脚本 当我们要hook时,一般来说这个脚本一定要是文档中第一个加载执行的js,这样就能拿到函数或方法的控制权,所以我们就需要插件进行帮助。 这里我推荐大家使用油猴插件,直接在google应用商店搜篡改猴即可: 图片 安装后固定到chrome后点击添加新脚本: 图片 将代码写到注释部分即可: 图片 另外我需要提一点,我这个hook脚本一定要是文档中第一个加载的js,所以要修改一下脚本的运行时期。保存代码后点击设置: 图片 图片 修改运行时期即可,document-start是我们需要设置的: 图片 具体为什么可查看油猴中文文档(https://www.cnblogs.com/grubber/p/12560522.html): 图片 hook_JSON: // ==UserScript== // @name hook_JSON // @namespace http://tampermonkey.net/ // @version 2024-10-29 // @description try to take over the world! // @author 0xsdeo // @match http://*/* // @icon https://www.google.com/s2/favicons?sz=64&domain=csdn.net // @grant none // ==/UserScript== (function() { 'use strict'; var json_p = JSON.parse; JSON.parse = function(str){ console.log(str); console.log(new Error().stack); console.log("-----------------------------------------------------------------------------------------------------") return json_p(str); } var json_s = JSON.stringify; JSON.stringify = function(obj){ console.log(obj); console.log(new Error().stack); console.log("-----------------------------------------------------------------------------------------------------") return json_s(obj); } })();最后提一点,脚本需要指定一下要执行脚本的网站,匹配到的网站才会执行脚本,也是在设置里改: 图片 这里我设置的*,意为所有网站都执行该脚本。
技术教程
# Web前端
易航
1年前
0
59
0
2024-11-04
20个超好看又开源的落地页/首页模板(附源码)
分享 20 个超好看的落地页/首页模板。 模板预览 nefa 图片 trippi 图片 tailwind-landing-page-template 图片 vivid-landing-template 图片 shadcn-landing-page 图片 open-react-template 图片 skilline-landing-page 图片 template-landing-page 图片 SaaS-Boilerplate 图片 nextly-template 图片 fresh 图片 landing 图片 nutritrack 图片 mylandingpage 图片 React-Landing-Page-Template 图片 landy-react-template 图片 landing-template-nextui 图片 next-saas-starter 图片 daisyui-nextjs-landing-page 图片 react-landing-page-template-2021 图片 源码下载 隐藏内容,请前往内页查看详情
免费资源
源码资源
# 网站源码
# Web前端
# HTML源码
易航
1年前
6
309
0
2024-10-30
HTML+CSS实现太极八卦加载动画
动画效果预览 HTML部分 <html> <head> <meta charset="utf-8"> <title>太极八卦</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="./55-太极八卦.css"> </head> <body> <div class="table"> <div class="table-cell"> <svg width="470px" height="470px" viewBox="0 0 470 470" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs> <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-1"> <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> <feGaussianBlur stdDeviation="25" in="shadowOffsetOuter1" result="shadowBlurOuter1"> </feGaussianBlur> <feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.63 0" in="shadowBlurOuter1" type="matrix" result="shadowMatrixOuter1"></feColorMatrix> <feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetInner1"></feOffset> <feGaussianBlur stdDeviation="25" in="shadowOffsetInner1" result="shadowBlurInner1"> </feGaussianBlur> <feComposite in="shadowBlurInner1" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowInnerInner1"></feComposite> <feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.7 0" in="shadowInnerInner1" type="matrix" result="shadowMatrixInner1"></feColorMatrix> <feMerge> <feMergeNode in="shadowMatrixOuter1"></feMergeNode> <feMergeNode in="SourceGraphic"></feMergeNode> <feMergeNode in="shadowMatrixInner1"></feMergeNode> </feMerge> </filter> <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-2"> <feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> <feGaussianBlur stdDeviation="22.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"> </feGaussianBlur> <feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.7 0" in="shadowBlurOuter1" type="matrix" result="shadowMatrixOuter1"></feColorMatrix> <feMerge> <feMergeNode in="shadowMatrixOuter1"></feMergeNode> <feMergeNode in="SourceGraphic"></feMergeNode> </feMerge> </filter> <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-3"> <feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> <feGaussianBlur stdDeviation="20" in="shadowOffsetOuter1" result="shadowBlurOuter1"> </feGaussianBlur> <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.7 0" in="shadowBlurOuter1" type="matrix" result="shadowMatrixOuter1"></feColorMatrix> <feMerge> <feMergeNode in="shadowMatrixOuter1"></feMergeNode> <feMergeNode in="SourceGraphic"></feMergeNode> </feMerge> </filter> <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-4"> <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> <feGaussianBlur stdDeviation="25" in="shadowOffsetOuter1" result="shadowBlurOuter1"> </feGaussianBlur> <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.63 0" in="shadowBlurOuter1" type="matrix" result="shadowMatrixOuter1"></feColorMatrix> <feMerge> <feMergeNode in="shadowMatrixOuter1"></feMergeNode> <feMergeNode in="SourceGraphic"></feMergeNode> </feMerge> </filter> <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-5"> <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> <feGaussianBlur stdDeviation="15" in="shadowOffsetOuter1" result="shadowBlurOuter1"> </feGaussianBlur> <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.23 0" in="shadowBlurOuter1" type="matrix" result="shadowMatrixOuter1"></feColorMatrix> <feMerge> <feMergeNode in="shadowMatrixOuter1"></feMergeNode> <feMergeNode in="SourceGraphic"></feMergeNode> </feMerge> </filter> <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-6"> <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> <feGaussianBlur stdDeviation="25" in="shadowOffsetOuter1" result="shadowBlurOuter1"> </feGaussianBlur> <feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.63 0" in="shadowBlurOuter1" type="matrix" result="shadowMatrixOuter1"></feColorMatrix> <feMerge> <feMergeNode in="shadowMatrixOuter1"></feMergeNode> <feMergeNode in="SourceGraphic"></feMergeNode> </feMerge> </filter> <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-7"> <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> <feGaussianBlur stdDeviation="15" in="shadowOffsetOuter1" result="shadowBlurOuter1"> </feGaussianBlur> <feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.23 0" in="shadowBlurOuter1" type="matrix" result="shadowMatrixOuter1"></feColorMatrix> <feMerge> <feMergeNode in="shadowMatrixOuter1"></feMergeNode> <feMergeNode in="SourceGraphic"></feMergeNode> </feMerge> </filter> </defs> <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Artboard-1"> <ellipse id="Oval-1" fill="#485d51" cx="237" cy="228" rx="111" ry="111"></ellipse> <circle id="Oval" fill="#0E7CFE" filter="url(#filter-1)" cx="237" cy="228" r="39"></circle> <path d="M237.737045,228.155741 C206.543902,228.155741 181.166785,253.532859 181.166785,284.726749 C181.166785,312.174294 200.823516,335.102165 226.795386,340.215844 C169.77682,334.873529 125,286.749357 125,228.358226 C125,166.403809 175.404556,116 237.357479,116 C241.130723,116 242.479377,116.122537 242.479377,116.122537 C271.062631,118.710011 293.460007,142.732496 293.460007,171.989704 C293.460007,227.891241 237.737045,228.155741 237.737045,228.155741 L237.737045,228.155741 Z" id="Path1" fill="#FFFFFF" filter="url(#filter-2)"></path> <g id="Group" transform="translate(264.500000, 228.500000) scale(-1, -1) translate(-264.500000, -228.500000) translate(180.000000, 116.000000)" filter="url(#filter-3)" fill="#000000"> <path d="M112.737045,112.155741 C81.5439023,112.155741 56.1667848,137.532859 56.1667848,168.726749 C56.1667848,196.174294 75.8235156,219.102165 101.795386,224.215844 C44.7768195,218.873529 0,170.749357 0,112.358226 C0,50.403809 50.4045562,-2.84217094e-14 112.357479,-2.84217094e-14 C116.130723,-2.84217094e-14 117.479377,0.122537018 117.479377,0.122537018 C146.062631,2.71001075 168.460007,26.7324965 168.460007,55.9897038 C168.460007,111.891241 112.737045,112.155741 112.737045,112.155741 L112.737045,112.155741 Z" id="Path2"></path> </g> <circle id="Oval-3" fill="#000000" filter="url(#filter-4)" cx="164" cy="156" r="39"></circle> <circle id="Oval-3-2" fill="#000000" filter="url(#filter-5)" cx="187" cy="83" r="16"></circle> <circle id="Oval-4" fill="#FFFFFF" filter="url(#filter-6)" cx="309" cy="300" r="39"></circle> <circle id="Oval-4-2" fill="#FFFFFF" filter="url(#filter-7)" cx="286" cy="373" r="16"></circle> </g> </g> </svg> </div> </div> <a class="box-item" href="https://codepen.io/LOverride/" target="_blank"> </a> </body> </html>CSS部分 隐藏内容,请前往内页查看详情
技术教程
# Web前端
易航
1年前
2
67
1
2024-10-30
2024 年最前沿的 5 大 CSS 功能 | 高级 CSS
CSS作为Web设计的基石,一直在不断进化,以应对现代设计的挑战。2024年,CSS引入了一系列令人惊叹的新特性,大大拓展了Web设计的可能性。本文将深入探讨五个最具革命性的CSS新特性,这些特性正在彻底改变前端开发的方式。 1.CSS容器查询(Container Queries) 容器查询允许基于元素的容器大小而非视口来设置样式,这对响应式设计是一个巨大的突破。 示例: 图片 这种方法使得组件级别的响应式设计成为可能,大大提高了代码的可维护性和模块化程度。 2.CSS子网格(Subgrid) 子网格是CSS网格布局的扩展,允许网格项继承其父元素的网格定义。这对于复杂的嵌套布局特别有用。 在 subgrid 出现之前,我一直在为嵌套网格而苦苦挣扎,这往往会导致 CSS 变得复杂冗长。 子网格允许子元素与父网格无缝对齐,从而简化了这一过程。 示例: 图片 子网格简化了复杂布局的创建,减少了冗余代码,提高了网格设计的一致性。 3.@property规则定义的CSS自定义属性 @property规则允许定义具有类型检查、初始值和继承特性的自定义属性(CSS变量)。 示例: 图片 这种方法增强了CSS变量的能力,提供了更多对其行为的控制,确保了它们的正确使用。 4.CSS嵌套 CSS嵌套允许以反映HTML结构的方式嵌套CSS选择器,提高了CSS的可读性和可维护性。 示例: .card { background: white; & .title { color: black; } & .content { font-size: 0.9em; } }这种特性使CSS更加组织化,简化了样式的编写和维护过程,特别是在大型项目中。 5.CSS滚动链接动画 滚动链接动画允许创建响应用户滚动位置的动画,为网站增添了新的交互维度。 示例: @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } } #box { animation: linear fade-in; animation-timeline: scroll(); }这种动画可以使网站更加动态和吸引人,增强用户体验。 结语 2024年的这些CSS新特性为创建更具响应性、组织性和吸引力的Web设计提供了强大的工具。通过在工作流程中incorporate这些前沿特性,开发者可以显著提升项目质量并简化开发过程。 这些新特性不仅提高了开发效率,还开启了Web设计的新可能性。例如,容器查询使得真正的组件级响应式设计成为现实,而滚动链接动画则为用户交互带来了新的维度。随着这些特性的广泛采用,Web开发的未来将更加灵活、高效且富有创意。 掌握这些新特性,将有助于开发者在不断演进的Web开发世界中保持领先地位。通过实践和探索这些新工具,开发者可以创造出更加动态、响应迅速且视觉吸引的Web体验。
技术教程
# Web前端
易航
1年前
0
87
0
2024-10-19
JavaScript代码的简洁之道
1、条件判断赋值布尔值 不推荐: if (a === 'a') { b = true; } else { b = false; }推荐: b = a === 'a';通过直接将条件判断的结果赋值给变量,可以简化代码,提高可读性。 2、使用三元运算符 不推荐: if (a > b) { c = a; } else { c = b; }推荐: c = a > b ? a : b;三元运算符是处理简单条件赋值的一种更简洁的方式。 3、合并重复的代码块 不推荐: function processValue(value) { if (value > 10) { console.log('Value is greater than 10'); // 其他操作 } else { console.log('Value is 10 or less'); // 其他操作 } // 重复的代码块 performAdditionalOperations(); }推荐: function processValue(value) { console.log(value > 10 ? 'Value is greater than 10' : 'Value is 10 or less'); performAdditionalOperations(); }将重复的代码块提取到条件判断之外,可以减少不必要的重复,提高代码的可读性。 4、使用数组方法代替循环 不推荐: let sum = 0; for (let i = 0; i < numbers.length; i++) { sum += numbers[i]; }推荐: let sum = numbers.reduce((acc, num) => acc + num, 0);使用数组的内置方法(如 reduce 、map 、filter 等)可以简化代码,同时提高性能,因为这些方法通常被高度优化。 5、使用模板字符串 不推荐: let greeting = 'Hello, ' + name + '!';推荐: let greeting = `Hello, ${name}!`;模板字符串(使用反引号 ` )允许嵌入变量和表达式,使字符串拼接更加简洁和直观。 6、避免不必要的全局变量 不推荐: let counter = 0; function incrementCounter() { counter++; }推荐: function createCounter() { let counter = 0; return { increment: function() { counter++; }, getValue: function() { return counter; } }; } let counterInstance = createCounter(); counterInstance.increment();通过模块或闭包来封装变量,可以避免全局命名空间的污染,提高代码的封装性和可维护性。 7、使用解构赋值 不推荐: let data = { name: 'Alice', age: 25 }; let name = data.name; let age = data.age;推荐: let { name, age } = data;解构赋值可以方便地提取对象中的属性,使代码更加简洁。 8、提前终止循环 不推荐: for (let i = 0; i < array.length; i++) { if (array[i] === target) { found = true; break; } }推荐: let found = array.includes(target);如果不需要在循环中执行其他操作,直接使用数组的内置方法(如 includes )可以提前终止搜索,提高性能。 9、使用箭头函数 不推荐: function add(a, b) { return a + b; }推荐: const add = (a, b) => a + b;箭头函数不仅语法简洁,还能避免 this 绑定的问题,使代码更加清晰。 10、避免使用 with 语句 不推荐: with (obj) { console.log(name); console.log(age); }推荐: console.log(obj.name); console.log(obj.age);with 语句会使代码难以优化,并可能导致性能问题,因此应避免使用。 11、使用 let 和 const 代替 var 不推荐: var count = 0;推荐: let count = 0; // 对于需要重新赋值的变量 const MAX_COUNT = 100; // 对于不需要重新赋值的常量let 和 const 提供了块级作用域(block scope),避免了 var 带来的函数级作用域(function scope)问题,使得代码更加清晰和可预测。 12、避免内联样式和脚本 不推荐: <div style="color: red;">This is red text</div> <script> console.log('Inline script'); </script>推荐: <link rel="stylesheet" href="styles.css"> <script src="script.js"></script>在HTML中,尽量将样式和脚本分离到外部文件,这有助于代码的组织和维护,同时也可能提高加载性能。 13、使用对象字面量进行属性赋值 不推荐: let obj = new Object(); obj.name = 'Alice'; obj.age = 25;推荐: let obj = { name: 'Alice', age: 25 };对象字面量语法更加简洁,易于阅读。 14、使用短路逻辑 不推荐: if (condition1) { doSomething(); } else if (!condition1 && condition2) { doSomethingElse(); }推荐: if (condition1) { doSomething(); } else if (condition2) { // 这里的!condition1已经被短路逻辑隐含 doSomethingElse(); }在第二个条件中,由于 else if 已经隐含了 !condition1 ,因此可以省略这部分判断,提高代码的可读性。不过,要注意这种优化仅在逻辑上确实可行时才进行。 15、避免不必要的计算 不推荐: for (let i = 0; i < array.length; i++) { // 每次循环都计算array.length console.log(array[i]); }推荐: for (let i = 0, len = array.length; i < len; i++) { console.log(array[i]); }将数组长度存储在一个变量中,避免在每次循环迭代时都重新计算它,这可以提高性能,尤其是在处理大型数组时。 16、使用 Object.assign 进行浅拷贝 不推荐: let newObj = {}; for (let key in oldObj) { if (oldObj.hasOwnProperty(key)) { newObj[key] = oldObj[key]; } }推荐: let newObj = Object.assign({}, oldObj);Object.assign 提供了一种更简洁和高效的方法来创建对象的浅拷贝。 17、使用默认参数和剩余参数 不推荐: function add(a, b) { b = b || 0; return a + b; } function sum() { let args = Array.prototype.slice.call(arguments); return args.reduce((acc, num) => acc + num, 0); }推荐: function add(a, b = 0) { return a + b; } function sum(...args) { return args.reduce((acc, num) => acc + num, 0); }默认参数和剩余参数是ES6中引入的语法糖,它们使得函数定义更加清晰和灵活。 18、避免魔法数字 不推荐: function calculateDiscount(price, discountRate) { return price * (1 - discountRate / 100); } // 调用时 let finalPrice = calculateDiscount(100, 20);推荐: const DISCOUNT_RATE_PERCENTAGE = 100; function calculateDiscount(price, discountRate) { return price * (1 - discountRate / DISCOUNT_RATE_PERCENTAGE); } // 或者使用命名参数 function calculateDiscount(price, discountPercentage) { return price * (1 - discountPercentage / DISCOUNT_RATE_PERCENTAGE); } // 调用时 let finalPrice = calculateDiscount(100, 20);通过定义常量或使用命名参数,可以避免在代码中使用难以理解的魔法数字,提高代码的可读性。 这些优化技巧可以帮助你编写出更加简洁、高效和可维护的JavaScript代码。记住,优化是一个持续的过程,随着你对语言和框架的深入理解,你会找到更多适合自己的优化方法。 我们继续深入讨论JavaScript代码优化的其他策略和最佳实践。 19、使用模板字符串 不推荐: let greeting = 'Hello, ' + name + '!';推荐: let greeting = `Hello, ${name}!`;模板字符串(Template Literals)允许你嵌入变量和表达式,使字符串拼接更加直观和易读。 20、使用解构赋值 不推荐: function getPersonInfo() { return { firstName: 'John', lastName: 'Doe' }; } let info = getPersonInfo(); let firstName = info.firstName; let lastName = info.lastName;推荐: function getPersonInfo() { return { firstName: 'John', lastName: 'Doe' }; } let { firstName, lastName } = getPersonInfo();解构赋值(Destructuring Assignment)允许你从数组或对象中提取数据,并将其赋值给不同的变量,使代码更加简洁。 21、使用箭头函数 不推荐: function add(a, b) { return a + b; } let numbers = [1, 2, 3]; let doubled = numbers.map(function(number) { return number * 2; });推荐: const add = (a, b) => a + b; let numbers = [1, 2, 3]; let doubled = numbers.map(number => number * 2);箭头函数(Arrow Functions)提供了更简洁的函数定义方式,并且没有自己的 this 绑定,这有助于避免在回调函数中常见的 this 问题。 22、使用 Promise 和 async/await 处理异步代码 不推荐: function fetchData(url, callback) { // 假设这里有一个异步的fetch操作 setTimeout(() => { callback(null, 'data'); }, 1000); } fetchData('some-url', function(err, data) { if (err) { console.error(err); } else { console.log(data); } });推荐: function fetchData(url) { return new Promise((resolve, reject) => { // 假设这里有一个异步的fetch操作 setTimeout(() => { resolve('data'); }, 1000); }); } // 使用Promise fetchData('some-url').then(data => { console.log(data); }).catch(err => { console.error(err); }); // 或者使用async/await async function getData() { try { let data = await fetchData('some-url'); console.log(data); } catch (err) { console.error(err); } } getData();Promise 和 async/await 提供了更优雅和强大的方式来处理异步代码,避免了回调地狱(Callback Hell)的问题。 23、使用 try...catch 进行错误处理 不推荐: if (someCondition) { // 可能会抛出错误的代码 } else { console.error('An error occurred'); }推荐: try { // 可能会抛出错误的代码 } catch (error) { console.error('An error occurred:', error); }try...catch 语句允许你捕获并处理在代码执行过程中抛出的错误,从而避免程序崩溃并提供更好的用户体验。 24、使用 Map 和 Set 不推荐: let obj = {}; let keys = ['a', 'b', 'c']; keys.forEach(key => { obj[key] = true; });推荐: let set = new Set(['a', 'b', 'c']);Map 和 Set 是ES6中引入的新的数据结构,它们提供了比传统对象更强大和灵活的功能,例如保持插入顺序和检测元素是否存在的时间复杂度更低。 25、避免全局变量污染 不推荐: let globalVar = 'This is a global variable';推荐: (function() { let localVar = 'This is a local variable'; // 你的代码逻辑 })();或者使用 let 和 const 在块级作用域内定义变量,以及使用模块系统(如ES6模块或CommonJS模块)来封装代码。 我们可继续探讨JavaScript代码优化的其他高级策略和最佳实践。以下是一些额外的建议: 26、使用 WeakMap 和 WeakSet WeakMap 和 WeakSet 是ES6中引入的两种新的集合类型,它们的主要特点是“弱引用”。这意味着它们不会阻止垃圾回收器回收其键(或成员)所引用的对象。这对于存储大量临时数据而不担心内存泄漏的情况非常有用。 示例: let obj = {}; let weakMap = new WeakMap(); weakMap.set(obj, 'some value'); // 当没有其他引用指向 `obj` 时,它可以被垃圾回收器回收27、使用 Symbol 类型 Symbol 是ES6中引入的一种新的原始数据类型,它表示唯一的标识符。使用 Symbol 可以避免属性名的冲突,并且可以作为对象的唯一键。 示例: let sym = Symbol('description'); let obj = {}; obj[sym] = 'value'; console.log(obj[sym]); // 输出: value28、优化循环 减少循环内的计算:将可以在循环外部计算的表达式移到外部。 使用 for...of 代替 for...in:当遍历数组时,for...of 通常比 for...in 更快,因为 for...in 还会遍历数组原型链上的属性。 使用 Array.prototype.every 、Array.prototype.some 、Array.prototype.find 等数组方法:这些方法提供了更简洁的语法,并且在某些情况下可能比传统的 for 循环更高效。 29、避免内存泄漏 清理定时器:确保在组件或页面销毁时清理所有的定时器(如 setInterval 和 setTimeout )。 取消事件监听:在不再需要时取消事件监听器。 避免全局变量:全局变量会一直存在于内存中,直到页面被关闭。尽量使用局部变量或模块作用域变量。 30、使用现代JavaScript框架和库的最佳实践 React: 使用纯函数组件和React Hooks来简化状态管理。 避免不必要的重新渲染,通过使用 React.memo 、useCallback 和 useMemo 等优化技术。 优化数据获取,使用React Query或Apollo Client等库来管理异步数据。 Vue: 使用计算属性和侦听器来优化响应式数据的处理。 避免在模板中进行复杂的计算,而是将它们放在计算属性或方法中。 使用Vuex或Pinia等状态管理库来管理全局状态。
技术教程
# Web前端
易航
1年前
0
50
0
上一页
1
2
3
4
5
下一页