REC
首页
文章分类
源码资源
技术教程
程序软件
文创娱乐
玄学修炼
关于我们
其他页面
网站统计
友情链接
用户留言
高清壁纸
关于易航
热门文章
Joe再续前缘主题 - 本站同款
易航网址导航系统 – 功能强大,轻量易用
Js自动播放HTML音乐(不受浏览器限制,无需先与浏览器交互,无需对浏览器进行修改)
网易云官方歌曲解析接口
JsonDb-PHP轻量级文件数据库系统
标签搜索
PHP
Web前端
网站源码
PHP源码
Typecho
课程资料
武术内功
HTML源码
Windows程序
Web
Android软件
Typecho插件
Joe主题
国漫
网络协议
MySQL
Python
NodeJs
Windows
小说
发布
登录
注册
找到
40
篇与
Web前端
相关的结果
- 第 2 页
2024-12-19
一个兼容 OneBot 协议的非官方 QQ 客户端实现,支持网页及 electron 客户端
Stapxs-QQ-Lite-2.0 一个兼容 OneBot 协议的非官方 QQ 客户端实现,支持网页及 electron 客户端Github地址:隐藏内容,请前往内页查看详情 在线体验:隐藏内容,请前往内页查看详情 图片 ✨ 特性支持 ✅ 使用 Vue.js 全家桶开发,快乐前后端分离 🎨 自适应布局,竖版也能使用 🖥️ 支持 PWA(都有 Electron 了(小声)) 🌚 Light/Dark Mode 自动切换 🍱 该有的都有(虽然比不过官方端) 复杂消息显示、转发、回复、撤回 群文件、群公告、群设置(一小部分)、精华消息 图片、收藏表情、文件发送 📦️ 支持多种 bot,我就是要用! 🔥 水深火热但是更好看的 Electron 客户端 🥚 彩蛋!来更多的彩蛋! 🛠 更多特性开发中 💬 提醒和问题 > 关于不安全连接 当使用 https 页面连接 ws 服务(反之相同)的情况下,连接将会失败;这是由于其中某一者是不安全的。在这种情况下,你可以选择将 ws 提升为 wss 或者将 https 降级为 http(不安全)来解决问题,此处不提供解决方案。>> Stapxs-QQ-Lite#32 > 我能使用其他 QQ Http Bot 吗 如果它兼容 OneBot 11 协议, 你可以尝试连接它, 但是由于消息体格式和接口扩展的差异,大部分情况下都不能完全正常使用。 已经兼容的 Bot 都写在了文档里,可以去 这里 查看。 > 使用 Bot 是否有风险 如果你使用的是 oicq-http, 可以查看此处了解 如果你尝试使用其他 QQ Bot (参见上一条问题), 请自行参考它的文档。 使用风险:https://github.com/takayama-lily/oicq/wiki/98.%E5%85%B3%E4%BA%8E%E8%B4%A6%E5%8F%B7%E5%86%BB%E7%BB%93%E5%92%8C%E9%A3%8E%E6%8E%A7
程序软件
# 网站源码
# Web前端
# HTML源码
# Windows程序
易航
1年前
2
36
0
2024-12-19
不要过度使用 console.log 啦!我们有更好的调试方式!
Hello,大家好,我是 Sunday。 在日常的工作中,我经常会帮同学【远程调试代码】。在远程时,我发现 很多同学会大量使用 console.log 进行打印调试。打印的数量之多,让同学自己都摸不清哪个打印对应哪个内容了😂。 毫无疑问,console.log 是一个很好的调试方式。但是 如果我们滥用它,效果反而会适得其反!大量打印信息堆积如山,反倒使得我们难以理清各条输出的对应逻辑! 因此,我们可以寻找可好的调试方案,来解决 console.log 过多而导致的混乱问题。 console 不止 log 没错!console 不止 log ,console 对象内部提供了很多的方法。在之前的文章中,我们提到过这一点:调试只会console.log?来看一看这 6 种惊艳的调试技巧! 使用更多的 console 方法配合可以帮助我们大幅提升调试的效率。 1. 使用 console.dir() 打印对象 console.dir() 是一个专门打印 对象 的 API。 console.dir() 方法可以显示指定 JavaScript 对象的属性列表,并以交互式的形式展现。输出结果呈现为分层列表,包含展开/折叠的三角形图标,可用于查看子对象的内容。因此,当我们打印对象时,可以使用 dir 代替 log 2. 使用 console.table() 打印数组 如果想要打印数组的话,那么 table() 是首选方法: const users = [ { id: 1, name: '张三', age: 25 }, { id: 2, name: '李四', age: 30 }, { id: 3, name: '王五', age: 35 }, ]; console.table(users);一句话:贼清晰! 图片 3. 使用 console.clear() 清理控制台 这个 API 可以帮我们解决控制台打印过多的问题。 如果我们要开启一轮新的调试,那么可以在开始前执行 console.clear(),清空之前的控制台打印。 这样,可以帮我们更加专注的针对本次的调试,而不需要被之前的打印信息所误导! 4. 使用 console.group() 控制打印组 这在 嵌套函数、递归 中非常有用,配合 console.groupEnd() 可以帮助我们完成分组打印。 比如下面的场景: function factorial(n) { console.group(`方法开始,长度(${n})`); if (n <= 1) { console.log("执行 1"); console.groupEnd(); return 1; } else { let result = n * factorial(n - 1); console.log(`执行 ${result}`); console.groupEnd(); return result; } } factorial(3);最终,打印结果如下: 图片 5. 使用 console.time() 完成计时 console.time() 配合 console.timeEnd() 经常用来处理 计时操作。 比如,我们想要测试一个函数的执行耗时,那么就可以通过这种方式完成: function processLargeData() { console.time("time"); // 模拟耗时操作 for (let i = 0; i < 1000000; i++) { Math.sqrt(i); } console.timeEnd("time"); } processLargeData();计时结果如下: 图片
技术教程
# Web前端
易航
1年前
0
39
0
2024-12-19
免费的轻量级代码编辑器 HBuilderX
HBuilderX 是由DCloud开发的一款面向Web前端开发者的集成开发环境(IDE),它是HBuilder的下一代产品,继承了HBuilder的诸多优点,并在此基础上进行了全面的升级。HBuilderX旨在提供更加强大、高效的开发体验,支持多种前端技术栈,包括但不限于HTML5、CSS3、JavaScript、Vue.js、React、Angular等。 功能特点 快速启动:启动速度快,能够在几秒内启动,这对于频繁切换任务的开发者来说是非常有用的特性。 智能提示:提供了丰富的代码补全和提示功能,能够提高编写代码的速度和准确性。 实时预览:支持实时预览功能,开发者可以直接在编辑器中看到代码修改的效果,无需频繁切换浏览器。 多页面编辑:支持多页面同时编辑,可以在同一个窗口中打开多个文件,方便进行对比和同步修改。 多光标操作:支持多光标编辑,允许用户一次编辑多处相同代码,提高编码效率。 HTML5/CSS3支持:内置对HTML5和CSS3的支持,包括新特性的语法高亮和代码提示。 Git集成:内置Git支持,方便开发者进行版本控制和团队协作。 代码美化:提供代码格式化功能,帮助开发者保持代码整洁。 文件压缩打包:支持JavaScript、CSS文件的压缩合并,减少HTTP请求次数,提高网页加载速度。 调试工具:拥有内置的调试工具,便于开发者进行前端代码的调试。 扩展插件:支持插件扩展,用户可以根据需要安装额外的插件来增强IDE的功能。 模板支持:内置了多种模板,包括常用的框架模板,方便快速搭建项目。 下载及安装 HBuilderX官网下载地址:https://www.dcloud.io/hbuilderx.html,可以在下载页面选择Windows或MacOS平台,Windows平台压缩包下载后解压即可运行。 HBuilderX首次运行时会出现主题和快捷键选择窗口,可以选择喜欢的主题和习惯的操作方式。点击【开始体验】按钮后,可以在HBuilderX自述文件中查看HBuilderX的特性。 图片 基本操作 语法提示:工具提供多种框架语法提示库,可以在窗口右下角进行选择。 图片 代码助手:工具提供智能的代码提示助手,可按【ctrl+I】打开代码助手,代码提示后可以按【alt+数字】选择直接选择某个项目。 图片 语法帮助:在编辑区域鼠标悬停会自动弹出语法或说明提示,按下【F1】键可以跳转到官方手册(2.5.7以上版本会在外部浏览器打开说明文档)。 图片 多光标操作:在编辑区域按【ctrl+鼠标左键】可增加一个光标,【ctrl+鼠标右键】可取消一个光标或选区。 图片 相同词操作:在编辑区域按【ctrl+shift+L】可以选择和光标位置相同的所有词同时进行编辑。 列选择:在编辑区域使用【alt+鼠标拖选】进入列选择编辑方式。 图片 Emmet支持:Emmet语法可以用缩写来动态生成所需要的结构及样式,从而极大改善HTML和CSS的编写流程。 图片 智能双击: 双击引号/括号内侧,选中引号/括号内的内容 双击逗号两侧,选择逗号前一段或后一段 双击行尾,选中该行(不含回车符) 双击连词符(-_)选中整个词 双击折叠行首内容开头,选择折叠段落 双击行首缩进,选择相同缩进的段落 双击列表符号,选择列表段落 双击Tag开头或结尾,选择整段Tag 双击属性赋值等号=,选择Html属性 双击if、function等关键字,选择整段包围区域 双击分号,选择js等语言的;分号前段落 双击css类名左侧,选择Css类 双击注释符选择注释区域 双击#选择markdown标题段落 双击语法定义符开头选择markdown图片、超链接、加粗、倾斜、代码等语法区 还有更多的操作和编辑技巧可以查看官方文档:https://hx.dcloud.net.cn 另外,软件对vue开发做了大量优化,新版本仅支持uni-app、uni-app cli、vue2-cli、vue3-cli项目中可以切换vue语法提示库;对Markdown文件编辑提供了强大支持,支持Emmet、快捷键编辑、智能粘贴、路径提示、Mermaid流程图等;对Json编辑进行了优化;支持开发小程序;可以创建uni-app项目;支持java插件、nodejs插件,并兼容了很多vscode的插件及代码块。 总之,HBuilderX非常适用于Web前端开发人员,特别是在进行HTML5相关的项目开发时非常高效。此外,由于其对多种语言的支持,也可以作为通用的轻量级开发工具使用。
程序软件
# Web前端
# Windows程序
易航
1年前
0
31
0
2024-12-19
你不知道的 7 项 CSS 新功能
CSS 一直在进步,不断推出新的功能,让开发更加强大、简单、有趣。以下是一些最新的 CSS 更新,它们不仅能优化你的工作流程,还会改变你对 CSS 的使用方式。我们也会通过一些示例帮助你理解这些功能的应用场景。 1. 无需 Flexbox 或 Grid 的快速居中对齐 还记得以前用 CSS 居中元素的“痛苦”吗? 现在,有了 align-content 属性,居中对齐变得轻松无比,无需额外的容器。 .my-element { display: block; align-content: center; }再也不用纠结是选 flexbox 还是 grid 了。 2. 更智能的 CSS 变量:@property CSS 变量非常灵活,但也存在缺陷,比如缺乏类型约束和默认值支持。 现在,@property 规则让你可以定义具有特定类型、继承规则和初始值的自定义属性。 传统做法: :root { --rotation: 45deg; } div { transform: rotate(var(--rotation)); }如果意外赋值 --rotation: blue;,代码可能会报错或行为异常。 新方法: @property --rotation { syntax: '<angle>'; inherits: false; initial-value: 0deg; } div { transform: rotate(var(--rotation)); } syntax: 限定变量值类型,比如 <angle> 表示角度。 inherits: 决定变量是否继承父级值。 initial-value: 定义默认值(这里是 0deg)。 这不仅提升了代码的健壮性,也减少了意外错误。 3. @starting-style:解决页面加载时样式闪烁问题 开发者经常遇到页面加载时内容闪烁的问题(FOUC)。 @starting-style 提供了解决方案,可以为元素设置初始样式,避免布局错乱。 @starting-style { .modal { opacity: 0; visibility: hidden; } } .modal { opacity: 1; visibility: visible; transition: opacity 0.3s ease, visibility 0.3s ease; }这样,即使在页面加载时,也能保证模态框的显示效果流畅自然,无需繁琐的内联样式。 4. 数学功能升级:更多强大的计算方法 以前,calc() 是 CSS 唯一的数学函数,但功能有限。 现在,新增了 round()、mod() 和 rem() 等强大函数,大幅扩展了计算能力。 传统方式: .element { width: calc(100% - 50px); }新功能: .box { /* 四舍五入为 3px */ margin: round(2.5px); } .stripe:nth-child(odd) { left: calc(var(--index) * 50px mod 200px); } .circle { /* 输出 1px */ width: rem(10px, 3px); }这些新增函数让复杂的布局计算变得更加灵活且直观。 5. 光明与黑暗的完美切换:light-dark() 定义明暗主题的样式曾经需要依赖媒体查询,容易导致代码重复。 现在,light-dark() 函数简化了这一过程。 传统方法: body { background-color: white; color: black; } @media (prefers-color-scheme: dark) { body { background-color: black; color: white; } }新方法: body { background-color: light-dark(white, black); color: light-dark(black, white); } 第一个值是浅色模式的样式。 第二个值是深色模式的样式。 再也不用重复代码,主题切换更加高效。 6. 表单验证新伪类::user-valid 和 :user-invalid 以前,:valid 和 :invalid 的表单验证伪类会在页面加载时触发,导致样式误判。 新伪类 :user-valid 和 :user-invalid 专注于用户交互后的状态,大幅提升体验。 新方法: input:user-valid { border-color: green; } input:user-invalid { border-color: red; }这避免了未交互前就出现错误提示的问题,让表单验证更贴合实际需求。 7. interpolate-size:更顺滑的尺寸动画 CSS 一直以来对高度、宽度等尺寸的动画支持不够友好。 现在,有了 interpolate-size 属性,尺寸动画变得更加平滑自然。 传统方法: .collapsible { overflow: hidden; max-height: 0; transition: max-height 0.3s ease-out; } .collapsible.open { max-height: 500px; }新方法: .panel { interpolate-size: height 0.5s ease; } .panel.open { height: auto; }浏览器会动态计算起始和结束尺寸,无论内容多少,动画都能流畅衔接。 总结 这些 CSS 新功能都得到了主流浏览器的支持,无论是 Chrome、Firefox 还是 Safari,都可以立即开始使用。掌握这些特性不仅能提升你的工作效率,还能让代码更加简洁优雅。
技术教程
# Web前端
易航
1年前
0
20
0
2024-12-08
CSS奇思妙想:动态点亮文本下划线
一、简介 在现代网页中,为用户提供流畅且具有吸引力的交互体验至关重要。本文分享了一种纯CSS实现的动态文本下划线效果。当鼠标悬停在文本上时,无论文本的宽度如何、有多少行、行中有多少字,下划线都会以从左到右、从上到下的顺序,自适应的在文本底部动态、平滑地显示出来。而当鼠标移出时,下划线则按照相反的方向,逐行动态、平滑地隐藏,直到恢复至最初状态。具体效果如下: 案例效果 图片 该动画效果看起来很简单,具体实现也确实不难,难的是实现思路,需要扎实的前端CSS基础和很大的脑洞。该动画效果中利用到了:行内元素的基础特性、元素背景特性、trasition过渡等CSS的基础知识。 该动画可用于资料列表、新闻列表等页面场景中,可以突出显示鼠标所聚焦的文本内容,提升用户的视觉交互体验。 二、具体实现 1、实现思路 ① 看到文本下划线,我们首先会考虑通过text-decoration属性来实现,将文本的该属性默认状态设置为none,然后在hover的时候将其设置为underline,使文本出现下划线。但仔细想想,会发现这个方案并不可取,因为text-decoration是一个离散属性,只能在不同属性值状态之间切换,无法通过trasition过渡实现平滑动画。 ② 排除掉text-decoration属性之后,我们继续思考还有什么样式属性可以实现类似下划线的效果。此时应该想到两个属性:border和background。然后进一步思考,发现border只能控制宽度或者颜色,而且每一行的border只能同时显示,或者同时隐藏,无法实现逐行按序显示/隐藏下划线的效果。排除掉border后,最终确定需要依赖background属性来实现目标效果。 ③ 确定属性之后,首先我们要使用行内元素(或设置display: inline;的其他元素)来承载文本内容。因为行内元素具有一个重要的特性:元素的宽度和高度由其内容决定,当文本内容换行时,从布局角度看,每个换行后的文本片段会被视为单独的内联内容部分,而不是一个整体的块级元素那样有明确的整体宽度和高度概念。这一点特性,在后面通过背景实现下划线效果时将会起到关键作用。 ④ 接下来思考应该如何设置背景属性。目标效果中下划线是纯色的,首先想到的应该是设置背景颜色,但这种想法是错误的。因为设置背景颜色会直接应用到整个行内元素内容区域,而不是对每行的内联文本片段进行单独设置,且无法控制尺寸和位置。但如果给行内元素设置的背景图片,则会基于每行的内联文本片段来进行处理,而非整体内容区域,并且可以通过 background-size 和 background-position 属性进行精确控制。简单来说:我们给换行的行内元素设置背景图片时,其实际效果并非给整个内容块设置背景,而是给每行的内联文本片段设置背景。 ⑤ 经过前面四步的思考,我们已经明确了实现目标效果的关键,接下来只需按部就班设置相关样式即可。首先通过linear-gradient生成一张纯色图片作为元素的背景图片,并设置为不允许重复;其次设置background-size属性,设置初始宽高,使其看起来为一条线;然后通过background-position将背景定位在元素底部,变为下划线。此时查看页面样式,发现每行文本底部的下划线效果已经实现。 ⑥ 最后我们实现平滑动画效果。首先设置background-size属性,将初始宽度设置为0,将背景隐藏;然后在元素hover的时候,将背景宽度恢复为100%,显示背景;再然后借助transition属性,实现平滑的过渡效果,使得背景能逐行动态平滑的显示。 2、具体代码 HTML <div class="title-box"> <span> 有志者,事竟成。破釜沉舟,百二秦关终属楚。苦心人,天不负。卧薪尝胆,三千越甲可吞吴。有志者,事竟成。破釜沉舟,百二秦关终属楚。苦心人,天不负。卧薪尝胆,三千越甲可吞吴。 </span> </div>CSS .title-box { /* 父级盒子设置宽度 限制内部文本宽度 使其换行 */ width: 336px; margin: 50px auto; } .title-box span { color: #333; /* 通过渐变设置图片背景 且不允许重复 */ background: linear-gradient(to right, #333, #333) no-repeat; /* 背景初始宽度为0 高度为2px */ background-size: 0 2px; /* 背景位置在文字底部 */ background-position: left bottom; /* 设置平滑过渡效果 */ transition: background-size 1.5s ease-in-out; cursor: pointer; } /* hover时触发动画 */ .title-box span:hover { /* 背景宽度变为100% 高度不变 */ background-size: 100% 2px; /* 可以通过改变背景位置 改变下划线出现和消失的方向 */ /* background-position: right bottom; */ }三、相似扩展 1、效果1 图片 2、效果2 图片
技术教程
# Web前端
易航
1年前
0
39
0
2024-12-08
揭开迷雾:全面解析 JS 中的 this 指向问题
一、简介 身为一个使用JavaScript的开发者,我们或多或少在开发中都遇到过因 this 指向不明导致的代码错误。函数中this 关键字的指向是一个复杂但又关键的概念,大多数时候它的指向不是在编写时确定的,而是在代码执行时根据函数的调用方式来决定,简单来说,this 的指向取决于函数的调用者(箭头函数除外)。 本文将全面详细的讲解this的指向规则,让你能够清晰理解并正确使用 this,避免由于错误的指向导致的程序异常,并提升对JavaScript的整体理解。 二、详解 1、 全局作用域 在全局作用域下(非严格模式),也就是最外层的JS脚本中,this指向全局对象(浏览器中为window对象)。 <script> console.log(this === window); // 浏览器中输出 true </script>2、普通函数 在调用一个独立的普通函数时(非严格模式),此时相当于通过全局对象来调用函数,this会进行默认绑定,指向全局对象(浏览器中为window对象)。 重点:普通函数中的 this 指向是动态的,取决于函数的调用方式,会因为调用方式的不同而发生改变。 // 非严格模式下 // 两个普通函数 function showThis() { console.log(this); } const showThis2 = function() { console.log(this); } // 调用普通话函数 showThis(); // 输出 window 对象 showThis2(); // 输出 window 对象 // 相当于通过window来调用函数 因此this指向window window.showThis(); // 输出 window window.showThis2(); // 输出 window如果让一个对象内部的方法指向普通函数,并通过该对象来调用函数,则this指向发生改变,指向调用函数的对象,谁进行调用,this就指向谁。 // 普通函数 function showThis() { console.log(this); } // 创建对象 并让对象的方法指向函数 const obj = { getThis: showThis }; // 通过对象调用函数 obj.getThis(); // 输出 obj3、箭头函数 箭头函数不会创建自己的this,其内部的this会继承函数定义时其外层最近的非箭头函数的 this 指向。如果是在全局作用域内使用箭头函数,则this指向全局对象;如果是在构造函数中使用箭头函数,则this指向new出来的新对象... 重点:箭头函数中的 this 指向是静态的,在函数定义时确定,后面不会因为调用方式的不同而发生改变,也无法被call/apply/bind等方法改变。 // 非严格模式下 // 箭头函数 this指向window const showThis3 = () => { console.log(this); } // 调用箭头函数 showThis3(); // 输出 window 对象如果让一个对象内部的方法指向箭头函数,并通过该对象来调用函数,此时虽然函数的调用者发生变化,但this指向不会改变,依旧指向全局对象。 // 箭头函数 const showThis3 = () => { console.log(this); } // 创建对象 并让对象的方法指向函数 const obj = { getThis: showThis3 }; // 通过对象调用函数 但this指向不会改变 obj.getThis(); // 输出 window4、调用对象的方法 在通过对象直接调用其内部的方法时,方法中的this 会进行隐式绑定,指向当前对象。 const obj = { getThis: function() { // 对象的方法中的this 指向当前对象 console.log(this) } }; // 通过对象调用方法 this指向当前对象 obj.getThis(); // 输出 obj如果先用一个变量指向对象的方法,然后再通过变量来调用对应的方法时,this的指向将不再指向对象,而是指向全局对象(浏览器中为window对象)。因为此时相当于进行独立函数调用,遵守独立函数的默认绑定规则。 <script> const obj = { getThis: function () { console.log(this) } }; // 通过对象调用方法 this指向对象本身 obj.getThis(); // 输出 obj // 使用变量指向对象的方法 但不调用 const fun = obj.getThis; // 通过变量调用方法 此时相当于独立函数调用 所以this指向window fun(); // 输出 window </script>如果使用一个对象的方法指向另一个对象的方法,此时两个对象都可以调用该方法,那么具体的this指向取决于调用者,谁进行调用, this就指向谁。 <script> const obj = { getThis: function () { console.log(this) } }; // 通过obj调用方法 this指向obj本身 obj.getName(); // 输出 obj // 在另一个对象中使用属性指向前面对象的方法 const obj2 = { // 指向obj的方法 get2: obj.getThis } // 通过obj2调用方法 此时this指向obj2 obj2.get2(); // 输出 obj2 </script>还存在一种特殊情况:如果对象的方法使用的是箭头函数,那么方法中的 this 将继承定义对象时所在作用域的this指向,而非对象本身,并且后续不会因为调用者改变而改变this指向。 <script> // 如果对象的方法使用的是箭头函数 那么this将继承定义对象时所在作用域的this指向 // 在全局作用域下定义对象 const obj = { getThis2: () => { // 此时箭头函数中的this 指向全局对象window console.log(this) } } // 虽然是通过obj调用的 但是其this还是会指向全局对象window obj.getThis2(); // 输出 window // 使用变量指向对象的方法 但不调用 const fun = obj.getThis2; // 通过变量调用方法 this依旧指向window fun(); // 输出 window // 在另一个对象中使用属性指向对象的方法 const obj2 = { // 指向obj的方法 get2: obj.getThis2 } // 通过obj2调用方法 此时this依旧指向window obj2.get2(); // 输出 window </script>5、调用构造函数 在使用new关键字调用构造函数时,会创建一个新的对象,此时this 会指向被创建的新对象。内部的普通函数和箭头函数内的 this 也都指向被创建的新对象,但后续普通函数的this指向是会根据调用者不同而发生改变,箭头函数则不会改变。 // 构造函数 function Person(name) { // 构造函数中的this指向通过new创建的新对象 this.name = name; // 普通函数 this.getThis = function () { console.log(this) } // 箭头函数 this.getThis2 = () => { console.log(this) } } // 调用构造函数创建新对象 const person = new Person('Bob'); // 通过新对象调用方法 此时this指向新对象 person.getThis(); // 输出 person person.getThis2(); // 输出 person // 在另一个对象中使用属性指向new出来的新对象的方法 const obj = { getThis: person.getThis, getThis2: person.getThis2 } // 通过obj调用方法 此时this指向会根据函数类型不同而不同 obj.getThis(); // 输出 obj obj.getThis2(); // 输出 person 还存在一种特殊情况,就是Function()构造函数,在使用该构造函数创建新函数时,其内部的this指向并非指向新函数本身,而是根据函数被调用的方式来决定this指向,谁调用this就指向谁。 // 非严格模式 // 在全局作用域下 const func = new Function('console.log(this)'); // 相当于通过window来调用函数 因此this指向window func(); // 输出 window 对象 // 在对象中 const p = { name: 'Alice', get: func } // 通过对象中调用函数 对象内的this指向对象本身 p.get(); // 输出 Person { name: 'Alice', get: [Function] }6、事件处理函数 在事件处理函数中,如果绑定的函数是普通函数,则相当于由DOM元素调用函数,则函数内的this指向触发事件的DOM元素;如果绑定的是箭头函数,则函数内的this会继承绑定事件处理函数所在作用域的this指向。 <button id="btn">Click me</button> <!-- 内联的事件处理器也一样 --> <button onclick="console.log(this)">Click me</button> <script> const btn = document.getElementById('btn'); // 绑定普通函数 相当于dom调用函数 所以this指向button元素 btn.addEventListener('click', function () { console.log('普通函数this--', this); // 输出 button 元素 }); // 绑定箭头函数 继承绑定事件处理函数所在作用域的this 此时为全局作用域 所以this指向window btn.addEventListener('click', () => { console.log('箭头函数this--', this); // 输出 window }); </script>7、回调函数 当把一个函数作为回调函数传递后,其this指向取决于回调函数的调用方式和函数的类型两者: 如果函数类型为普通函数且被传递后是直接独立调用的,此时相当于独立函数调用,函数内部this指向全局对象(浏览器中为window对象)。 如果函数类型为普通函数且被传递后是通过别的对象进行调用的,此时相当于通过对象调用函数,函数内部的this指向函数的调用者。 如果函数类型为箭头函数,则无论被传递后是如何进行调用的,都不会修改函数内部的this指向,箭头函数内部的this指向在函数定义后确定就不会再被改变。 const obj = { // 普通函数 showThis: function () { console.log(this); }, // 箭头函数 showThis2: () => { console.log(this); } } function fun(fn) { // 直接独立调用回调函数 fn(); } function fun2(fn) { // 通过对象调用回调函数 const a = { getThis: fn, } a.getThis(); } // 对象普通函数中的this指向对象本身 obj.showThis(); // 输出 obj // 对象箭头函数中的this继承定义对象时所在作用域的this指向 此时为window obj.showThis2(); // 输出 window // 传入一个普通函数 并且直接调用函数 相当于独立函数调用 所以this指向window fun(obj.showThis); // 输出 window // 传入一个箭头函数 并且直接调用函数 this指向不受影响 依旧为window fun(obj.showThis2); // 输出 window // 传入一个普通函数 并且通过对象调用函数 this被改变 指向其调用者 fun2(obj.showThis); // 输出调用者对象 a // 传入一个箭头函数 并且通过对象调用函数 this指向不受影响 依旧为window fun2(obj.showThis2); // 输出 window数组提供的内置方法中,除了传递回调函数之外,还可以通过第二个参数指定回调函数的this指向。如果未指定this的指向,则取决于函数的调用环境内的this指向。 // 创建对象 const obj = { multiplier: 2 }; // 创建数组 const numbers = [1, 2, 3]; // 使用数组提供的map方法 第一个参数是回调函数 第二个参数是指定回调函数的this指向 const doubled = numbers.map(function (number) { // 回调函数中的this指向obj 所以this.multiplier指向obj.multiplier 值为2 return number * this.multiplier; }, obj); // 最终运算结果为[2, 4, 6] console.log(doubled); // 未指定this指向 回调函数中的this指向window const doubled2 = numbers.map(function (number) { return this; }); // 最终运算结果为[window, window, window] console.log(doubled2);8、call/apply/bind 显式指定 call()、apply()、bind()三个方法都可以显式的指定函数的this指向,只是在一些具体细节上有所不同。例如:call() 和 apply() 方法会在改变函数内部this指向的同时,调用函数执行一次。而bind() 不会调用函数执行,仅改变函数的this指向;在向函数传递参数时,call() 和 bind() 传递的参数都是用逗号隔开的独立参数,而apply()是以数组的形式来传递参数。 // call方法 function greet(text) { console.log(`${text}, ${this.name}`); } const user = { name: 'Charlie' }; // 使函数的this指向user 且会调用执行一次 greet.call(user, 'Hello'); // 输出 'Hello, Charlie' // apply方法 function introduce(age, gender) { console.log(`Name: ${this.name}, Age: ${age}, Gender: ${gender}`); } const user2 = { name: 'Dana' }; // 使函数的this指向user 且会调用执行一次 introduce.apply(user2, [25, 'Female']); // 输出 'Name: Dana, Age: 25, Gender: Female' // bind方法 const module = { x: 42, getX: function () { return this.x; } }; // 此时指向对象的方法 但不调用执行 const retrieveX = module.getX; // 调用执行 此时的 this 指向window 因为相当于独立函数调用 console.log(retrieveX()); // 输出 undefined // 修改this指向 使函数的this指向module 且不会调用执行 const boundGetX = retrieveX.bind(module); // 手动调用执行一次 console.log(boundGetX()); // 输出 42三、课后练习 1、下面代码的执行结果是什么? // 全局作用域 且非严格模式 [1, 2, 3].forEach(function (item) { console.log(this); });2、下面代码的执行结果是什么? // 全局作用域 且非严格模式 const obj = { a: () => { console.log(this); }, b: function () { console.log(this); } }; obj.a(); obj.b();3、下面代码的执行结果是什么? // 全局作用域 且非严格模式 function Person(name) { this.name = name; this.getName = () => { return this.name; }; } const person1 = new Person('Alice'); const person2 = { name: 'Bob' }; person2.getName = person1.getName; console.log(person2.getName());欢迎大家在评论区揭晓答案
技术教程
# Web前端
易航
1年前
0
23
0
2024-11-23
15 分钟带你感受 CSS :has() 选择器的强大
最近看到了许多关于 :has() 选择器的知识点,在此总结下来。 MDN 对 :has() 选择器 的解释是这样的: CSS 函数式 伪类 :has() 表示一个元素,如果作为参数传递的任何 相对选择器 在锚定到该元素时,至少匹配一个元素。这个伪类通过把 可容错相对选择器列表 作为参数,提供了一种针对引用元素选择父元素或者先前的兄弟元素的方法。下面一起来感受下 :has() 选择器的强大之处吧。 :has() 选择器选择父元素和前面的兄弟元素 邻接兄弟选择器(+)用来选中恰好处于另一个在继承关系上同级的元素旁边的物件。例如,选中所有紧随<p>元素之后的<img>元素: p + img { }通用兄弟关系选择器(~)用来选中一个元素后面的所有兄弟元素。例如,选中<p>元素之后的所有的<img>元素: p ~ img { }css 并没有提供直接选择父元素或者前面的兄弟元素的选择器,但 :has() 可以做到这点。 1、比如选择所有包含 <p>元素的父元素: :has(p) { }2、选择直接后代元素包含 <p>元素的父元素: :has(> p) { }3、选择直接后代元素包含 <p>元素的父级标签名是 div父元素: div:has(> p) { }4、选择 <p>元素的相邻的前一个标签名是 div的兄弟元素: div:has(+ p) { }5、选择 <p>元素的前面所有标签名是 div的兄弟元素: div:has(~ p) { }:has() 选择器中的 且 和 或 在 :has() 选择器中表示 且 和 或 很简单,例如: p:has(.a):has(.b) 表示选择同时包含子元素 a 和 子元素 b 的 元素 p p:has(.a, .b) 表示选择包含子元素 a 或者包含子元素 b 的 元素 p :has() 选择器选择一个范围内的元素 现在有如下元素 <div> <h2>标题开始(选择第一行字体为绿色,最后一行字体为红色)</h2> <p>h2中间第一行</p> <h4>h2中间第二行</h4> <h5>h2中间最后一行</h5> <h2>标题结束</h2> </div>要求选择第一行字体为绿色,最后一行字体为红色。需要注意的是,中间元素可以是任意的。 cc.png图片 使用 :has() 实现上面效果,可以这么做 /* 选择 h2 中间第一行 */ h2+ :has(~ h2) { color: green; } /* 选择 h2 中间最后一行 */ h2~ :has(+ h2) { color: red; }h2 + :has(~ h2) 表示选择紧跟着 h2 的并且后面还有 h2 元素的兄弟元素。也就选择到了 h2 范围内的第一个元素。 h2 ~ :has(+ h2) 表示选择 h2 后面的兄弟元素,并且该兄弟元素的下一个兄弟元素是 h2,也就选择到了 h2 范围内最后一个元素 那如果要选择中间所有元素呢,可以这样做 dd.png图片 /* 选择 hr 中间所有行 */ hr~ :has(~ hr) { color: blue; }:has()选择器的应用 1、CSS :has() 选择器之星级评分 关于星级评分,之前写过一篇文章分享过三种方式使用纯 CSS 实现星级评分。 这里介绍下使用 :has() 选择器 + :not() 选择器 实现星级评分的方式。 星级评分效果包括鼠标滑入和点击,滑入或点击到第几颗星的位置,该位置之前的星高亮,之后的星不高亮或者有高亮的则取消高亮; star.webp图片 html 结构 <div> <input type="radio" name="radio" id="radio1"> <label for="radio1"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> <path fill="currentColor" d="M283.84 867.84 512 747.776l228.16 119.936a6.4 6.4 0 0 0 9.28-6.72l-43.52-254.08 184.512-179.904a6.4 6.4 0 0 0-3.52-10.88l-255.104-37.12L517.76 147.904a6.4 6.4 0 0 0-11.52 0L392.192 379.072l-255.104 37.12a6.4 6.4 0 0 0-3.52 10.88L318.08 606.976l-43.584 254.08a6.4 6.4 0 0 0 9.28 6.72z"> </path> </svg> </label> <input type="radio" name="radio" id="radio2"> <label for="radio2"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> <path fill="currentColor" d="M283.84 867.84 512 747.776l228.16 119.936a6.4 6.4 0 0 0 9.28-6.72l-43.52-254.08 184.512-179.904a6.4 6.4 0 0 0-3.52-10.88l-255.104-37.12L517.76 147.904a6.4 6.4 0 0 0-11.52 0L392.192 379.072l-255.104 37.12a6.4 6.4 0 0 0-3.52 10.88L318.08 606.976l-43.584 254.08a6.4 6.4 0 0 0 9.28 6.72z"> </path> </svg> </label> <input type="radio" name="radio" id="radio3"> <label for="radio3"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> <path fill="currentColor" d="M283.84 867.84 512 747.776l228.16 119.936a6.4 6.4 0 0 0 9.28-6.72l-43.52-254.08 184.512-179.904a6.4 6.4 0 0 0-3.52-10.88l-255.104-37.12L517.76 147.904a6.4 6.4 0 0 0-11.52 0L392.192 379.072l-255.104 37.12a6.4 6.4 0 0 0-3.52 10.88L318.08 606.976l-43.584 254.08a6.4 6.4 0 0 0 9.28 6.72z"> </path> </svg> </label> <input type="radio" name="radio" id="radio4"> <label for="radio4"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> <path fill="currentColor" d="M283.84 867.84 512 747.776l228.16 119.936a6.4 6.4 0 0 0 9.28-6.72l-43.52-254.08 184.512-179.904a6.4 6.4 0 0 0-3.52-10.88l-255.104-37.12L517.76 147.904a6.4 6.4 0 0 0-11.52 0L392.192 379.072l-255.104 37.12a6.4 6.4 0 0 0-3.52 10.88L318.08 606.976l-43.584 254.08a6.4 6.4 0 0 0 9.28 6.72z"> </path> </svg> </label> <input type="radio" name="radio" id="radio5"> <label for="radio5"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"> <path fill="currentColor" d="M283.84 867.84 512 747.776l228.16 119.936a6.4 6.4 0 0 0 9.28-6.72l-43.52-254.08 184.512-179.904a6.4 6.4 0 0 0-3.52-10.88l-255.104-37.12L517.76 147.904a6.4 6.4 0 0 0-11.52 0L392.192 379.072l-255.104 37.12a6.4 6.4 0 0 0-3.52 10.88L318.08 606.976l-43.584 254.08a6.4 6.4 0 0 0 9.28 6.72z"> </path> </svg> </label> </div>为了使星星有点击效果,利用 radio + label 的方式实现点击效果;label 代表星星。 当点击星星时,高亮当前星星 input:checked+label { color: gold; }当鼠标移入星星时,高亮当前星星,并且该位置之后的星星取消高亮; label:hover { color: gold; &~label { color: #ccc !important; } }让当前位置之前的所有星星也高亮,可以利用 :not ,排除掉当前位置和当前位置之后的星星。 label:not(:hover, :hover ~ *) { color: gold; }并且只有鼠标滑入时添加这些效果。 div:has(label:hover) label:not(:hover, :hover ~ *) { color: gold; }同样,当点击星星时,点亮当前选择的之前所有的星星也如此 div:has(input:checked) label:not(input:checked ~ label) { color: gold; }完整示例 2、CSS :not 和 :has() 模拟 :only-of-type 有下面的 html 结构 <div> <p>第一页</p> <p class="this">第二页</p> <p>第三页</p> <p>第四页</p> </div>要选择类名为 this 的元素,并设置颜色为红色,使用 .this{color:red;} 可以轻松做到。 aa.png图片 如果现在有两个 div 元素块 <div> <p>第一页</p> <p class="this">第二页</p> <p>第三页</p> <p>第四页</p> </div> <div> <p>第一页</p> <p class="this">第二页</p> <p class="this">第三页</p> <p>第四页</p> </div>现要求选择 div 的子元素中只有含有一个类名为 this 的元素(也就是第一个 div 元素块),并且设置其颜色为红色,该怎么做呢? :only-of-type 代表了任意一个元素,这个元素没有其他相同类型的兄弟元素。 但 :only-of-type 判断是否有相同类型的依据是标签名,而不是类名。所以并不能达到想要的效果。 /* 这种写法是无效的,无法判断元素有没有其他相同的类名。 */ .this:only-of-type { color: red; } /* 这种写法是有效的,但判断的是没有相同的 p 的元素,显然无法满足上面的要求,但能匹配下面 ul 中的 p */ p:only-of-type { color: red; }<ul> <li>第一页</li> <li class="this">第二页</li> <li class="this">第三页</li> <p>第四页</p> </ul>而 :has 能做到,要选择前后没有相同类名的元素 ,也就是排除前后的 .this 。 排除前面的 .this /* 表示选择前面没有 .this 的 .this */ .this:not(.this ~) { }排除后面的 .this, /* 表示排除后面有 .this 的 .this */ .this:not(:has(~ .this)) { }两个做并集,也就选择到了唯一的 .this .this:not(:has(~ .this)):not(.this ~ *) { color: red; }bb.png图片 完整示例 3、CSS :has() 选择器之模仿 mac 电脑 dock 栏 利用 :has() 可以选择到前面的兄弟元素的特点,还能做出下面的动画效果 aa.gif图片 当鼠标滑入到一个元素时,该元素放大,该元素的前一个元素和后一个元素缩小,除了这三个元素之外的其他元素缩的更小并且有一定透明度; html 结构如下 <div class="box"> <div class="son">乔丹</div> <div class="son">科比</div> <div class="son">詹姆斯</div> <div class="son">奥尼尔</div> <div class="son">邓肯</div> <div class="son">卡特</div> <div class="son">麦迪</div> <div class="son">艾弗森</div> <div class="son">库里</div> <div class="son">杜兰特</div> </div>关键 css 代码 .son { ... ... ... &:hover { background-color: #67c23a; transform: scale(1.4); &+.son { transform: scale(1.1); // 后一个相邻的兄弟元素 } } }让前一个元素也缩放为原来的 1.1 /* 选择存在 后一个相邻的被hover的兄弟元素 的元素 */ .son:has(+ .son:hover) { transform: scale(1.2); }然后对这三个元素之外的其他元素缩放为原来的 0.8 .box:has(.son:hover) .son:not(:hover, :has(+ :hover), .son:hover + *) { transform: scale(0.8); opacity: 0.7; }.box:has(.son:hover) 表示选择子元素 son 被 hover 时的 .box .son:not(:hover, :has(+ :hover), .son:hover + *) 表示排除 son 元素里面被 hover 的元素,被 hover 的元素的前一个邻接的兄弟元素,被 hover 的元素的后一个邻接的兄弟元素; 完整示例 4、CSS :has() 选择器之单选题 bb.gif图片 这是个有趣的应用,当选择的是错误的选项时,选择题的标题和当前选择项标红。并且会给正确的选项添加动画效果提示用户这才是正确选项。 这里用 data-correct="false" 表示错误的选项,data-correct="true" 表示正确的选项。 <input type="radio" name="option" data-correct="false" id="option1" /> <label for="option1">Responsive design</label> <input type="radio" name="option" data-correct="true" id="option2" /> <label for="option2">Responsive design</label> <input type="radio" name="option" data-correct="false" id="option3" /> <label for="option3">Responsive design</label>选择错误选项时,标红当前选项。选择正确选项时标绿当前选项。 .question { --correct: #5ed235; /* 正确选项的颜色 */ --wrong: #f83d56; /* 错误选项的颜色 */ --wrong-bg: rgba(248, 61, 86, 0.8); --correct-bg: rgb(94, 210, 53, 0.8); } input[data-correct="false"]:checked+label { color: #fff; background-color: var(--wrong); border-color: var(--wrong); } input[data-correct="true"]:checked+label { color: #fff; background-color: var(--correct); border-color: var(--correct); }选择错误选项时,标红标题; 这里用 :has 选择器获取子元素中有错误选项选中时。 .question:has(input[data-correct="false"]:checked) { .questionHeader { box-shadow: inset 0 7px 0 0 var(--wrong); background-color: var(--wrong-bg); } }并且给正确选项增加提示动画 .question:has(input[data-correct="false"]:checked) { input[data-correct="true"]+label { animation: flash 2s infinite; } } @keyframes flash { 0% { background-color: white; } 25% { background-color: #5ed235; } 50% { background-color: white; } 75% { background-color: #5ed235; } 100% { background-color: white; } }选择正确选项时,标绿标题; .question:has(input[data-correct="true"]:checked) { .questionHeader { box-shadow: inset 0 7px 0 0 var(--correct); background-color: var(--correct-bg); } }完整示例 总结 本文介绍了 :has()选择器的基本用法以及四个实际应用; 选择父元素和前面的兄弟元素 :has() 选择器中的 且 和 或 选择一个范围内的元素 在 :has()选择器出来之前,使用 CSS 是无法直接选择到父级元素和前面的兄弟元素的,但 :has()选择器的出现使这个变成了可能; 如果对本文感兴趣或对你有帮助,麻烦动动你们的发财手,点点赞~
技术教程
# Web前端
易航
1年前
0
64
0
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
134
0
2024-11-13
一款功能丰富、界面美观的OA办公系统
介绍 OA-System Vue 开发的OA系统 具有工作流动态审批、加签、会签等工作流功能 具有文档预览、图片预览等功能 具有博客编写、预览、查看、搜索等功能 具有社区、问答等功能 具有OA系统常用功能 具有在线网盘等功能 支持审批流程、自由流程,审批日志,我的待办,我的已办,行政公告,Office文档预览,文档转PDF,图片压缩。 功能一览 具有工作流动态审批、加签、会签等工作流功能,可以对工作流程的审批业务进行评论/讨论 具有文档预览、图片预览等功能 具有博客编写、预览、查看、搜索等功能 具有社区、问答等功能 具有OA系统常用功能 具有在线网盘等功能 具有OA的移动端应用 工作流引擎完全手写且开源,可以类似钉钉/飞书那样,动态选择审批人员。 项目截图 图片 图片 图片 图片 图片 图片 图片 图片 图片 源码下载 隐藏内容,请前往内页查看详情
源码资源
# 网站源码
# Web前端
# NodeJs
易航
1年前
15
216
0
上一页
1
2
3
...
5
下一页