分类 技术教程 下的文章 - 易航博客
首页
文章分类
源码资源
技术教程
程序软件
文创娱乐
玄学修炼
关于我们
其他页面
网站统计
友情链接
用户留言
高清壁纸
关于易航
热门文章
Joe再续前缘主题 - 本站同款
易航网址导航系统 – 功能强大,轻量易用
Js自动播放HTML音乐(不受浏览器限制,无需先与浏览器交互,无需对浏览器进行修改)
JsonDb-PHP轻量级文件数据库系统
Typecho一键调整网站为冬天情景插件
标签搜索
PHP
网站源码
Web前端
PHP源码
Typecho
课程资料
HTML源码
Typecho插件
武术内功
Joe主题
Web
Android软件
国漫
网络协议
Windows程序
MySQL
Windows
小说
Linux程序
Java源码
发布
登录
注册
找到
90
篇与
技术教程
相关的结果
2024-12-04
PHP 纤程:它真的能实现异步执行吗?
图片图片 PHP 8.1 引入了 Fibers,这让许多开发者好奇:它能否打破 PHP 作为单线程同步语言的固有局限,让它像 JavaScript 和 Node.js 那样实现异步操作?答案并非简单的肯定或否定:Fibers 本身并不提供真正的异步执行,但它为更高效的任务管理提供了强大的机制。下文将深入探讨这一概念。 什么是 PHP 纤程? PHP 纤程是一种协作式多任务处理机制。它允许你暂停和恢复代码的特定部分,而不会阻塞整个 PHP 进程。你可以把纤程想象成一种特殊的函数,它能够将执行控制权交回主程序,并在需要时从之前暂停的地方继续执行。 纤维的主要特点 可启动、暂停和恢复执行。 在单一的 PHP 进程内运行,不涉及多线程。 尤其适用于构建非阻塞代码。 当纤程暂停时会发生什么? 当使用 Fiber::suspend() 暂停纤程时,执行控制权会返回主 PHP 脚本。这意味着: 主程序可以继续执行其他部分。 纤程的执行暂停,直到被 resume() 唤醒。 例如: $fiber = new Fiber(function () { echo "Fiber started\n"; Fiber::suspend(); echo "Fiber resumed\n"; }); echo "Before Fiber\n"; $fiber->start(); echo "After Fiber Start\n"; $fiber->resume(); echo "After Fiber Resume\n";输出: Before Fiber Fiber started After Fiber Start Fiber resumed After Fiber Resume以下是具体情况 1、Fiber::suspend() 暂停纤程,并将执行控制权返回到启动纤程的主脚本 ($fiber->start() 之后的代码)。 2、主脚本继续执行。 3、当调用 resume() 时,纤程从暂停处恢复执行,直至完成。 恢复纤程是否会阻塞主进程? 调用 Fiber::resume() 恢复纤程会暂时阻塞主进程。这意味着: 在纤程完成或再次暂停之前,脚本的其他部分(或其他纤程)无法执行。 由于 PHP 的单线程特性,纤程的执行仍然是阻塞式的。 尽管纤程提供了更灵活的控制,但它并没有改变 PHP 的底层执行模型。 例如: $fiber = new Fiber(function () { echo "Processing Fiber...\n"; sleep(2); // Simulates a blocking task echo "Fiber Done\n"; }); echo "Before Fiber\n"; $fiber->start(); echo "Between Fiber Start and Resume\n"; $fiber->resume(); echo "After Fiber\n";输出: Before Fiber Processing Fiber... Fiber Done Between Fiber Start and Resume After Fiber在此示例中,纤程在调用 sleep(2) 期间会阻塞主进程。 因此,尽管纤程提供了一种更有效地组织代码的方式,但它们并不会神奇地实现并行处理或真正的异步执行。 它们只是提供了一种在单线程环境下更精细地控制执行流程的机制。 光纤如何仍然“不阻塞”? 纤程的“非阻塞”并非指并行执行,而是指其更优的任务管理能力。纤程暂停时不会阻塞主进程,而是将控制权交还给主脚本或事件循环。 这在基于事件驱动的库或框架(如 ReactPHP 或 Amp)中尤为有用: 长时间运行或等待的任务(例如数据库查询、API 调用)可以被暂停。 其他任务可以同时进行。 当任务准备好后,纤程会被恢复并继续执行。 这使得在单线程环境下能够模拟异步行为,从而提升效率。 事件循环和纤程 纤程通常与事件循环结合使用才能实现真正的非阻塞操作。事件循环负责跟踪多个任务并决定下一步执行哪个任务。其工作原理如下: 当遇到阻塞任务(例如数据库查询)时,纤程自动暂停。 事件循环选择并处理其他任务。 阻塞任务完成后,事件循环恢复相应的纤程。 像 Amp 和 ReactPHP 这样的库正是利用纤程和事件循环来实现异步任务处理。 为什么 Fiber 不是真正异步的 与 JavaScript 或 Node.js 中的异步编程(任务可以通过线程或事件循环并行运行)不同,PHP 纤程: 在单个 PHP 进程内同步执行。 通过允许开发者手动控制任务的暂停和恢复来实现协作式多任务处理。 换句话说: 纤程不引入并行性(任务仍然按顺序逐个执行)。 它们是一种更有效地管理和构建非阻塞代码的工具,而非真正的并行机制。 它们提供了一种在单线程环境下模拟异步行为的方式。 尽管 PHP 纤程本身并不能使 PHP 真正实现异步,但它们仍然是该语言的有力补充。原因如下: 1、改进的任务管理:纤程允许暂停和恢复任务,从而释放主进程去处理其他工作。 2、非阻塞工作流: 与事件循环结合使用时,纤程可以实现非阻塞任务处理,提升程序的并发性能。 3、同步执行的便利性: 恢复时,纤程同步执行,简化了代码逻辑,尽管会暂时阻塞进程。 这使得开发者无需处理复杂的回调或 Promise,就能以更线性的方式编写异步代码。 对于需要高效多任务处理的 PHP 应用(例如实时应用、后台作业或 API),纤程是一项重要的改进。它能够更好地管理任务并模拟异步行为。 然而,要实现真正的并行处理,仍然需要依赖外部解决方案,例如扩展或单独的进程来实现多线程。
技术教程
# PHP
易航
2天前
0
5
0
2024-12-03
Bing搜索引擎爆出严重XSS漏洞
最近在 Bing.com 上发现的跨站点脚本 (XSS) 漏洞引发了严重的安全问题,可能允许攻击者在 Microsoft 的互连应用程序之间发送精心设计的恶意请求。此漏洞在 Bing 的主域上发现,突显了与广泛的 Web 服务集成相关的风险,并突出了大规模利用的可能性。 该漏洞是在对 Bing 的 API 攻击面进行详细检查时发现的,特别关注 Bing 的主域如何与其他 Microsoft 服务交互。 研究表明,XSS 漏洞可用于在 Bing 的主域“www.bing.com”上执行任意 JavaScript。 研究人员“pedbap”观察到,然后可以利用此执行来制作针对用户默认登录的其他 Microsoft 应用程序(例如 Outlook、Copilot 和 OneDrive)的恶意请求。 攻击机制 攻击首先利用XSS 漏洞创建恶意链接。此链接允许攻击者在 Bing 的主域上下文中执行 JavaScript。鉴于 Bing 与其他 Microsoft 服务的集成,恶意脚本可以发送触发这些平台敏感操作的请求。 Bing 的广泛使用增强了攻击的潜在影响,每天有数百万用户与 Bing 的功能进行交互。一旦执行,恶意 JavaScript 就可以跨多个 Microsoft 服务访问用户数据。 这包括在 Outlook 中阅读电子邮件、访问 OneDrive 中的文件,以及可能在其他连接的应用程序中操作数据。Microsoft 生态系统的互连性质意味着一项服务中的漏洞可能会对其他服务产生级联影响。 这一发现凸显了对用户和 Microsoft 的重大安全影响。从 Bing 等受信任域执行 XSS 攻击的能力构成了严重威胁,因为它可能导致未经授权的数据访问和操纵。 图片图片 此外,此类漏洞可能是“可蠕虫的”(无需用户交互即可自动传播)增加了被广泛利用的风险。 Microsoft 已收到此漏洞的警报,预计将迅速采取措施修补受影响的系统。 建议用户在点击来自不受信任的来源的链接时要小心,并确保他们的浏览器和安全软件是最新的。 作为更广泛的安全措施的一部分,使用 Microsoft 服务的组织应检查其配置和访问控制,以防止未经授权的访问。 Bing.com 上的 XSS 漏洞严重提醒我们强大的 Web安全实践的重要性,尤其是在互连的数字生态系统中。 漏洞原理:https://medium.com/@pedbap/wormable-xss-www-bing-com-7d7cb52e7a12 演示视频:https://www.youtube.com/watch?v=_brKdFmYGdI8606cd0cff80fbea91699ce6bba7eda48embeds_widget_referrer=https%3A%2F%2Fmedium.com%2F%40pedbap%2Fwormable-xss-www-bing-com-7d7cb52e7a128606cd0cff80fbea91699ce6bba7eda49embeds_referring_euri=https%3A%2F%2Fcdn.embedly.com%2F8606cd0cff80fbea91699ce6bba7eda410embeds_referring_origin=https%3A%2F%2Fcdn.embedly.com8606cd0cff80fbea91699ce6bba7eda411source_ve_path=OTY3MTQ
技术教程
# 网络安全
易航
3天前
2
15
0
2024-12-03
PHP 8.4 正式发布!🧨
图片 PHP 8.4 第一个正式发布版本今天发布。PHP 8.4 在很大程度上向后兼容 PHP 8.0 到 8.4,并带来了一些新功能。 PHP 8.4 新增/变更功能 curl_getinfo 支持 CURLINFO_POSTTRANSFER_TIME_T curl_version() 支持 feature_list 新增 http_(get|clear)_last_response_headers 函数 新增 CURLOPT_PREREQFUNCTION 选项 新增 CURLOPT_DEBUGFUNCTION 选项 新增 CURLOPT_SERVER_RESPONSE_TIMEOUT 选项,以替换 CURLOPT_FTP_RESPONSE_TIMEOUT 新增 CURLOPT_TCP_KEEPCNT 选项 新增round()函数 新增 mb_trim、mb_ltrim 和 mb_rtrim 函数 DateTime(Immutable) 类新增 createFromTimestamp 方法 phpinfo 显示 PHP 整数大小信息 DateTime(Immutable) 类新增 get/setMicrosecond 方法 新增函数 request_parse_body PCRE2 升级及相关正则表达式变化 PHP 8.4 语法/功能变更 OpenSSL:最低要求的 OpenSSL 版本提升至 1.1.1 MBString:Unicode 字符数据库更新至版本 16 exit/die 从语言构造变为函数 CURLOPT_DNS_USE_GLOBAL_CACHE 不再有效 密码哈希:默认 Bcrypt 成本从 10 变为 12 PHP_ZTS 和 PHP_DEBUG 常量值类型从 int 变为 bool Opcache:JIT 启用方式的 INI 变更 round() 函数:无效的舍入模式将抛出 \ValueError 异常 Curl:最低要求的 libcurl 版本提升至 7.61.0 PHP 8.4 弃用功能 隐式可为空的参数声明被弃用 E_STRICT 常量被弃用 调用 session_set_save_handler() 时使用超过 2 个参数被弃用 CSV:必须提供 $escape 参数 CURLOPT_BINARYTRANSFER 被弃用 PHP 8.4 移除功能 Pspell 扩展从 PHP 核心移至 PECL IMAP 扩展从 PHP 核心移至 PECL OCI8 和 PDO-OCI 扩展从 PHP 核心移至 PECL
技术教程
# PHP
易航
3天前
0
20
0
2024-11-30
PHP 8.4 新功能
图片图片 PHP 8.4 的正式发布计划于下周,即 2024 年 11 月 21 日发布。在此次发布之前,一系列预发布版本(Alpha、Beta 和候选版本)允许社区测试新功能并进行最后一刻的调整。PHP 8.4 引入了多项改进,包括用于操作数组的新功能、受其他语言启发的属性钩子以及简化的语法。让我们一起回顾一下此版本中要记住的新功能。 Property Hooks Property Hooks 是 8.4 版中引入的主要功能之一。PHP 实现的灵感来自其他语言(如 Kotlin、C#、Swift、Javascript 或 Python)中的现有实现。让我们举几个例子来说明 Property Hooks 的用途以及如何使用它们: <?php declare(strict_types=1); class Foo { private string $id; public function getId(): string { return $this->id; } public function setId(string $id): void { $this->id = $id; } }从 PHP 8 开始,由于 Constructor Property Promotion,可以通过以下方式进行简化: <?php class Foo { function __construct(public string $id) {} }在我们必须保留访问器 (getter/setter) 的情况下,我们会考虑包含业务逻辑的丰富模型,我们失去了更轻量级语法的优势。PHP 版本 8.4 和引入的 Property Hooks 修复了这个问题: <?php class Foo { public function __construct( public string $id { get { return '#' . $this->id; } set(string $id){ $this->id = mb_strtoupper($id); } }, ){} }乍一看,语法似乎令人困惑,但就像任何语法演变一样,随着时间的推移,您会习惯它。 Property Hooks 引入的另一种可能性是能够在 property 上定义接口。 使用这个新版本的 PHP,我们可以编写以下定义: <?php interface HasId { public string $id { get; set; } } // Les fonction fléchées peuvent être aussi utilisées pour raccourcir la syntaxe class Foo implements HasId { function __construct( public string $id { get => '#' . $this->id; set (string $id) => $this->id = mb_strtoupper($id); }, ) {} } // Le contrat d’interface est également respecté sans l’utilisation des Property Hooks en déclarant publiquement la propriété class Bar implements HasId { function __construct(public string $id) {} }一个完整的案例 <?php declare(strict_types=1); interface HasId { public string $id { get; set; } } class Foo implements HasId { function __construct( public string $id { get => '#' . $this->id; set (string $id) => $this->id = mb_strtoupper($id); }, ) {} } class Bar implements HasId { function __construct(public string $id) {} } class Baz { public function display(HasId $object): void { echo $object->id . PHP_EOL; } public function update(HasId $object, string $id): void{ $object->id = $id; $this->display($object); } } $foo = new Foo(id: 'FOO'); $bar = new Bar(id: 'BAR'); $baz = new Baz(); $baz->display($foo); $baz->update($foo, 'foo'); $baz->display($bar); $baz->update($bar, 'bar');设置具有非对称可见性的类属性的可见性 非对称可见性 允许您根据相关操作是读取还是写入属性,对同一属性设置不同的可见性。然后,可以定义读取访问的公共可见性和写入访问的更受限的可见性(受保护或私有)。接下来的两个类是等效的,随着非对称可见性的引入,语法更加简洁。 <?php class Foo { function __construct(private string $id,) { // } public function getId(): string { return $this->id; } } class Bar { function __construct( public private(set) string $id, ) {} }不对称可见性附带一些规则,这些规则很容易理解: 属性必须被类型化(来自 PHP 实现的约束) 只关注对象属性,静态属性不能从中受益(这也是 PHP 实现产生的约束)。 对于对象属性,如果该属性设置为 private(set),则不能在与当前类不同的范围内修改链接对象。但是,如果链接对象的属性被定义为 Properties,则可以对其进行修改。 对于数组类型属性,如果该属性已设置为 private(set),则无法在当前类的范围之外操作数组(添加元素、删除元素等)。 set 的可见性不能比 get 的可见性更宽。 对于类继承或接口协定,可见性不能更严格,也可以更广泛。 在 readonly中定义的属性(在 PHP 8.1 中引入)和 public private(set) 中定义的属性之间的差异非常小,但值得一提。上面定义的不对称可见性将具有相同的效果,只是它允许内部更改。换句话说, readonly 限制了 mutation,并且在实例化期间还具有唯一写入的效果。 管独立于 Property Hook 运行,但这两种机制可以结合使用。此处提供了这两种功能的示例。 对惰性对象的原生支持 惰性对象 是其实际实例化将被推迟到实际需要的时间(因为它们的实例化通常很昂贵)的对象。出于性能原因,它们在 Doctrine 和 Symfony 中被大量使用。 Martin Fowler 在他的理论定义中建立了四种可能的实现。其中两个是不需要修改现有对象的实现:Ghost 和 Proxy。这些是通过在 PHP Reflection API 中添加方法保留和访问的。 在这两种情况下,都会创建一个初始化函数。对于 Ghosts,该函数将直接作用于对象。对于 Proxy,它是实例化惰性对象的函数,然后将交互反馈给真实实例。 在这两种情况下,实例化机制都是通过访问真实对象的 state 来触发的:读取或写入属性、测试属性是否具有值、克隆等。可以通过特定函数对特定属性禁用此行为,在某些情况下,可以定义或参数化,例如用于调试或序列化。 由于它是为非常有限且根据定义相当抽象的用例保留的,因此我们邀请您阅读 RFC 以发现代码示例和两种不同实现的详细功能。 不带括号的类实例化 更有趣的是,这种演变通过在实例化新对象时使括号变得多余,从而减轻了语法的负担。 <?php // Avant et toujours valide $o = (new Operation(0))->add(10)->multiply(2); // Depuis PHP 8.4 $o = new Operation(0)->add(10)->multiply(2);解析 HTML5 创建了一个新的 DOM\HTMLDocument 类来允许 HTML5 解析,为了确保与 HTML4 的向后兼容性,当前类将保持不变。这两个类保持相同的 API,因此可以以相同的方式使用。只有构造逻辑已更改,并且需要使用其中一个可用的工厂。用 C 语言编写的底层库是 Lexbor。 新的函数 添加了四个作用于数组的新函数,它们补充了现有函数。 array_find array_find 将返回传递给它的回调函数的第一个匹配项 <?php $array = ['A', 'AA', 'AAA']; $arrayWithKeys = ['A' => 1, 'AA' => 2, 'AAA' => 3]; array_find($array, static fn(string $value): bool => strlen($value) > 2);// returns AAA array_find($array, static fn(string $value): bool => strlen($value) > 3);// returns null array_find($arrayWithKeys, static fn(int $value, string $key): bool => $value === strlen($key)); // returns 1array_find_key array_find_key 的工作方式与上一个函数相同,但返回 key 而不是 value: <?php $array = ['A', 'AA', 'AAA']; $arrayWithKeys = ['A' => 1, 'AA' => 2, 'AAA' => 3]; array_find_key($array, static fn(string $value): bool => strlen($value) > 2); // returns 2 array_find_key($array, static fn(string $value): bool => strlen($value) > 3); // returns null array_find_key($arrayWithKeys, static fn(int $value, string $key): bool => $value === strlen($key)); // returns Aarray_any 如果数组中至少有一个元素与回调函数匹配,array_any 将返回布尔值 true: <?php $array = ['A', 'AA', 'AAA']; $arrayWithKeys = ['A' => 1, 'AA' => 2, 'AAA' => 3]; array_any($array, static fn(string $value): bool => strlen($value) > 2)); // returns true array_any($arrayWithKeys, static fn(int $value, string $key): bool => $value === strlen($key)); // returns truearray_all 如果数组中的所有元素都与回调函数匹配,array_all 将返回布尔值为 true <?php $array = ['A', 'AA', 'AAA']; $arrayWithKeys = ['A' => 1, 'AA' => 2, 'AAA' => 3]; array_all($array, static fn(string $value): bool => strlen($value) < 4)); // returns true array_all($arrayWithKeys, static fn(int $value, string $key): bool => $value === strlen($key)); // returns true改进和错误修复 除其他事项外,我们保留了以下更改: 添加了新的多字节函数来操作字符串 mb_trim、mb_ltrim、mb_rtrim、mb_ucfirst mb_lcfirst。 添加了用于从时间戳创建 DateTime 对象的新函数。 exit 和 die 的元素失去了它们的地位,取而代之的是特殊功能。在不破坏向后兼容性的情况下,这允许对函数进行类似的操作,例如,更精确地键入输入参数。 以下扩展正在从核心中移出以加入 PECL:Pspel、IMAP、OCI8 和 PDO-OCI。 为舍入功能添加了四种新的舍入模式 在 Sodium 中添加了两种新的加密算法,并升级了 OpenSSL。 添加了 cURL 的新选项。 完整的更新日志:https://www.php.net/ChangeLog-8.php
技术教程
# PHP
易航
6天前
0
21
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前端
易航
11月23日
0
40
0
2024-11-23
身体出现这3个高危迹象,说明你真的累过头了!
图片 图片 图片 图片 图片 图片 图片 图片 图片
技术教程
易航
11月23日
0
35
2
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前端
易航
11月22日
0
34
0
2024-11-20
提升PHP技术:18个实用高级特性
掌握PHP基础知识只是第一步。 深入了解这18个强大的PHP特性,将显著提升您的开发效率和代码质量。 超越 __construct() 的魔法方法 虽然 __construct() 为大多数开发者所熟知,PHP 却提供了更多强大的魔术方法,例如: class DataObject { private array $data = []; // 设置不可访问的属性时调用 public function __set($name, $value) { $this->data[$name] = $value; } // 获取不可访问的属性时调用 public function __get($name) { return $this->data[$name] ?? null; } // 对不可访问的属性使用 isset() 时调用 public function __isset($name) { return isset($this->data[$name]); } // 序列化对象时调用 public function __sleep() { return ['data']; } }生成器和收益 使用生成器迭代大型数据集,显著降低内存消耗 function readHugeFile($path) { $handle = fopen($path, 'r'); while (!feof($handle)) { yield trim(fgets($handle)); } fclose($handle); } // 用法 foreach (readHugeFile('large.txt') as $line) { echo $line . PHP_EOL; }匿名类 可以使用匿名类创建无需正式声明的单例实例 $logger = new class { public function log($message) { echo date('Y-m-d H:i:s') . ": $message\n"; } }; $logger->log('发生了一些事');属性(PHP 8+) 代码的元数据注释: #[Route("/api/users", methods: ["GET"])] #[Authentication(required: true)] class UserController { #[Inject] private UserService $userService; #[Cache(ttl: 3600)] public function getUsers(): array { return $this->userService->getAllUsers(); } }纤程并发 PHP 8.1+中的协作式多任务处理: $fiber = new Fiber(function(): void { $value = Fiber::suspend('suspended'); echo "Value: $value\n"; }); $value = $fiber->start(); echo "Fiber suspended with: $value\n"; $fiber->resume('resumed');带有空合并的方法链 优雅地处理可能返回 null 的方法链调用 class User { public function getProfile() { return new Profile(); } } $user = null; $result = $user?->getProfile()?->getName() ?? 'Anonymous';动态属性访问 变量属性和方法名称: class DataAccess { private $name = 'John'; private $age = 30; public function getValue($property) { $getter = 'get' . ucfirst($property); return $this->$getter(); } public function getName() { return $this->name; } }可调用函数和闭包 高级功能处理: $multiply = Closure::bind( function($x) { return $x * $this->multiplier; }, new class { public $multiplier = 2; } ); echo $multiply(5); // 输出: 10特征组成 在类之间复用复杂的业务逻辑 trait Timestampable { private $createdAt; private $updatedAt; public function touch() { $this->updatedAt = new DateTime(); } } trait SoftDeletable { private $deletedAt; public function softDelete() { $this->deletedAt = new DateTime(); } } class User { use Timestampable, SoftDeletable { Timestampable::touch insteadof SoftDeletable; } }命名参数 使用PHP 8更清晰的函数调用: function createUser( string $name, string $email, ?string $role = null, bool $active = true ) { // 实现 } createUser( email: 'john@example.com', name: 'John', active: false );一等可调用函数 PHP 8.1 的简化调用语法: class Math { public function add($a, $b) { return $a + $b; } } $math = new Math(); $add = $math->add(...); echo $add(5, 3); // 输出: 8枚举 PHP 8.1中的类型安全枚举: enum Status: string { case DRAFT = 'draft'; case PUBLISHED = 'published'; case ARCHIVED = 'archived'; public function color(): string { return match($this) { Status::DRAFT => 'gray', Status::PUBLISHED => 'green', Status::ARCHIVED => 'red', }; } }属性类型强制转换 自动类型转换: class Config { private int $timeout = '60'; // 自动将字符串转换为 int private float $rate = '0.5'; // 自动将字符串转换为浮点数 }引用返回值 通过函数返回修改值: class Collection { private array $items = []; public function &getItem($key) { return $this->items[$key]; } } $collection = new Collection(); $item = &$collection->getItem('key'); $item = 'new value'; // 修改原始数组后期静态绑定 静态调用的正确继承: class Parent { public static function who() { return static::class; } } class Child extends Parent { } echo Child::who(); // 输出: Child操作码缓存 通过字节码缓存进行性能优化: // php.ini configuration opcache.enable=1 opcache.memory_consumption=128 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=4000 opcache.validate_timestamps=0预加载 永久内存类加载(PHP 7.4+): // preload.php opcache_compile_file(__DIR__ . '/vendor/autoload.php'); opcache_compile_file(__DIR__ . '/app/Models/User.php');反射API 运行时代码检查与修改: class Inspector { public static function getPropertyTypes($class) { $reflection = new ReflectionClass($class); $properties = []; foreach ($reflection->getProperties() as $property) { $type = $property->getType(); $properties[$property->getName()] = $type ? $type->getName() : 'mixed'; } return $properties; } }结论 掌握这些高级PHP特性,将显著提升您的代码质量、开发效率和问题解决能力,从而构建更优雅、高效且易于维护的PHP应用程序。
技术教程
# PHP
易航
11月20日
0
25
0
2024-11-17
Joe再续前缘编辑器功能演示 - Typecho主题
文字加粗 文字加粗 文字倾斜 文字倾斜 文字删除 文字删除 文字居中 文字居中文字居右 文字居右文字颜色 文字红色 文字大小 文字大小 行内代码 行内代码 横线 引用 引用标题 H1 H2 H3 H4 H5 H6 有序列表 有序列表 有序列表 有序列表 无序列表 无序列表 无序列表 无序列表 超链接 超链接 插入图片 易航博客图片 表格 表头表头表头表格表格表格表格表格表格表格表格表格代码块 <?php ehco "Hello world!" ?>原生HTML 居中 居右 颜色大小当前时间 2024-11-17 07:14:37 星期日 实体符号 包含99%的特殊标点符号 表情符号 包含99%的表情符号 图片表情 Joe再续前缘经典表情包大全图片 任务 居中标题 居中标题 M3U8/MP4视频 哔哩哔哩视频 正常可用,影响UI,暂不展示 网易云列表 网易云单首 多彩按钮 多彩按钮 便条按钮 次要按钮 成功按钮 警告按钮 错误按钮 信息按钮 彩色虚线 隐藏内容 隐藏内容,请前往内页查看详情 默认卡片 {card-default label="卡片标题" width="100%"} 卡片内容 {/card-default} 消息提示 消息提示:成功! 消息提示:信息! 消息提示:警告! 消息提示:错误! 进度条 {progress percentage="100%" color="#ff6c6c"/} 标注 f0ad4e 外部音乐 滕王阁序 - 王勃 标签页 标签一 标签一内容 标签二 标签二内容 卡片列表 列表一内容 列表二内容 时间轴 19be6b ed4014 复制文本 点击复制 复制成功 描述卡片 卡片描述 - 卡片内容 跑马灯 折叠面板 折叠标题一 - 折叠内容一 折叠标题二 - 折叠内容二 云盘下载 默认云盘 下载地址:https://gitee.com/yh-it/Joe 提取码:6666 360网盘 下载地址:https://gitee.com/yh-it/Joe 提取码:6666 百度云盘 下载地址:https://gitee.com/yh-it/Joe 提取码:6666 天翼云盘 下载地址:https://gitee.com/yh-it/Joe 提取码:6666 城通网盘 下载地址:https://gitee.com/yh-it/Joe 提取码:6666 腾讯微云 下载地址:https://gitee.com/yh-it/Joe 提取码:6666 夸克云盘 下载地址:https://gitee.com/yh-it/Joe 提取码:6666 Github仓库 下载地址:https://gitee.com/yh-it/Joe 提取码:6666 Gitee仓库 下载地址:https://gitee.com/yh-it/Joe 提取码:6666 蓝奏云网盘 下载地址:https://gitee.com/yh-it/Joe 提取码:6666 宫格 宫格内容1 宫格内容2 宫格内容3 提示 信息提示 成功提示 警告提示 错误提示
付费阅读
¥
0.1
技术教程
# Joe主题
易航
11月17日
3
234
5
1
2
...
10
下一页
易航博客