<![CDATA[王小明博客]]>https://16px.cc/RSS for NodeSat, 27 Jul 2024 08:45:10 GMT60<![CDATA[ffmpeg 学习笔记]]>-f 强制格式(一般能自动识别, 无须指明)

-i 输入

-y 覆盖

-stream_loop 循环次数(0 表示不循环, -1 表示无限循环)

-c -codec 编解码器

-t duration(和 -to 互斥, 且优先级比 -to 高)

-to 到某个时间为止

-ss-to 相反, 从某个时间开始

-sseof 输入参数, 相对于文件结尾的相对位置, 负值

-r frame rate 帧率(作为输入参数时请使用 -framerate)

-s frame size 输出帧尺寸

-aspect 视频尺寸比例

-frames:v 输出帧

-codec:v 视频编码

-filter:v 视频滤镜

-vf scale=960:-1 将视频scale

-pattern_type glob 可以设置输入文件名的匹配模式为glob模式, 例如 ffmpeg -pattern_type glob -framerate 12 -i "foo-*.jpg" -s WxH foo.mp4

]]>
https://16px.cc/blog/fpID-q1NVAXWhttps://16px.cc/blog/fpID-q1NVAXWSat, 15 Jun 2024 05:57:18 GMT
<![CDATA[nginx 学习笔记]]>location

location 文档

syntax: location [ ~ | ~* | ^~ | = ]  /uri/ { ... }
  1. 无前缀

    • literal string 匹配
    • 匹配成功后仍会进行后续匹配, 如果后续存在优先级更高的匹配, 则会采用优先级高的匹配, 不存在才会采用该匹配
    • 匹配优先级见官网文档 ngxhttpcore_module #location
  2. ~~*

    • 正则匹配
    • 匹配成功后仍会进行后续匹配, 如果后续存在优先级更高的匹配, 则会采用优先级高的匹配, 不存在才会采用该匹配
    • ~: 大小写敏感
    • ~*: 大小写敏感
  3. ^~

    • 区别于 ~, 匹配成功则立即终止匹配
  4. =

    • 仅匹配 exact query
    • 匹配成功则立即终止匹配

alias

alias 文档

location /i/ {
  alias  /path/to/images/;
}

# 剩余 location 直接拼接到 alias
# request /i/top.gif
# return  /path/to/images/top.gif

alias 指令不能用在指定正则的 location 中; 指定正则的 location 中需要使用 rewrite + root;

root

root 文档

location /i/ {
  root /path/to/images;
}

# 整个 location 直接拼接到 root
# request /i/top.gif
# return  /path/to/images/i/top.gif

rewrite

rewrite 文档

  1. rewrite 位于 server 下时, 可以使用 last 标记来中止 rewrite; nginx server { # ... rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last; rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last; return 403; # ... }
  2. rewrite 位于 location 下时, 需要把 last 换成 break; nginx location /download/ { rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break; rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break; return 403; }
  3. replacement 包含新的 arguments 时, 需要在结尾添加 ?, 因为原 arguments 会直接拼接到 replacement 后面 nginx rewrite ^/users/(.*)$ /show?user=$1? last;

proxy_pass

proxy_pass 文档

  1. proxypass 最后有 "/", 则将 剩余 location 拼接到 proxypass
  2. proxy_pass 最后没有 "/":
    • 如果结尾是 host, 则将 整个 location 拼接到 proxy_pass
    • 如果结尾是 path, 则将 剩余 location 拼接到 proxy_pass

try_files

try_files 文档

location / {
  try_files index.html index.htm @whatever_fallback;
}

location @whatever_fallback {
  root /var/www/error;
  index index.html;
}
  1. @whatever_fallback 是具名location(named location)
  2. 尝试检测指定文件是否存在, 返回第一个存在的文件;
  3. 如果都不存在, 将会调用 @fallback location;

部分内置变量

部分内置变量 文档

  1. $args(等同于 $query_string) > 请求参数
  2. $request_filename > 基于 root / aliasrequest URI 的当前 file path
  3. $request_uri > 包括 arguments 的完整初始 uri(complete initial URI)
  4. $uri > 当前 uri > 不同于initial uri, 因为可能经过了内部重定向

tips

  1. It is important to know that nginx does the comparison against decoded URIs. For example, if you wish to match /images/%20/test, then you must use /images/ /test to determine the location.
]]>
https://16px.cc/blog/maRde2B9KnaQhttps://16px.cc/blog/maRde2B9KnaQWed, 17 Jul 2024 13:24:34 GMT
<![CDATA[昨天突然接到一个私人电话,说是网安大队的]]>昨天突然接到一个私人电话,说是网安大队的,单纯跟我确认我有没有备案、以及服务器在哪里。是准备万一我说了什么不合适的,直接就给我一锅烩了吗。。。我这么单纯的一个技术分享网站。。。

]]>
https://16px.cc/blog/ilYGuH_PAYxthttps://16px.cc/blog/ilYGuH_PAYxtThu, 23 May 2024 05:39:48 GMT
<![CDATA[竟然会有人,宁愿相信人,也不相信程序]]>是人就会犯错,而且可能会一遍一遍地犯同一个错误。

固然程序也会犯错,但是程序的错误是可以复现且修复的,而且,修复后,它就不会再犯了。所以能用程序的,我都会用程序实现/自动处理。我不相信人,不单他人,包括自己。

]]>
https://16px.cc/blog/nIAfNN-fpt7fhttps://16px.cc/blog/nIAfNN-fpt7fWed, 22 May 2024 11:39:15 GMT
<![CDATA[使用 scroll-margin 优化页面内滚动]]>问题

当需要某个元素平滑滚动到顶部时,我们会使用:

targetElement.scrollIntoView({ behavior: 'smooth' })

然而,当我们有一个固定的头部时,这样就有问题了——元素确实滚动到顶部了,可是,被头部遮挡了。

解决方案:scroll-margin

这时候,我们就需要 css 的 scroll-margin 来帮忙了。

/* css */
targetElement {
  /* 假设头部的高度为 40px */
  scroll-margin: 40px;
}

这时候再调用 element.scrollIntoViewelement 会自动停到距离顶部 40px(上面声明的值)的位置,问题解决。

兼容性

Can I use: scroll-margin?


扩展

以下内容需要配合 scroll-snap-type 使用,建议先了解 scroll-snap-type

下面的各个属性,建议直接浏览对应的 MDN 文档,毕竟人家还有在线 demo。

scroll-padding

看名字就知道,scroll-margin 用于目标元素上,指示元素滚动到目标位置且保留 "margin"。我们看到 margin 就会想到 padding,确实,还有 scroll-paddingscroll-padding 如其名,用于滚动容器上。

我们知道,当我们的滚动容器设置 scroll-snap-typemandatory 时[^1],滚动起来就像轮播一样,会“吸附”。这时候我们在滚动容器上定义一个 scroll-padding,效果就如同在子元素上定义了 scroll-margin 一样了。

[^1]: 子元素需要设置 scroll-snap-align

scroll-x-inline & scroll-x-block

scroll-x-inline

scroll-snap-typemandatory 且子级为表现为 inline 时,使用 scroll-x-inline,即:

  • scroll-margin-inline
  • scroll-padding-inline

scroll-x-block

scroll-snap-typemandatory 且子级为表现为 block 时,使用 scroll-x-block,即:

  • scroll-margin-block
  • scroll-padding-block

scroll-xx-direction

  • scroll-xx-start
  • scroll-xx-end
  • scroll-xx-top
  • scroll-xx-bottom
  • scroll-xx-left
  • scroll-xx-right
]]>
https://16px.cc/blog/XhMYxwOtfix5https://16px.cc/blog/XhMYxwOtfix5Mon, 06 May 2024 16:21:17 GMT
<![CDATA[[译文] React 19 Beta 中文翻译]]>

原文链接:React 19 Beta

该文在一些难翻译的细节用词上会采用意译,其中会掺杂一些译者的个人理解,建议阅读原文,以获得更准确的信息。

以下为译文


React 19 Beta 现已在 npm 上发布!这篇文章概述 React 19 中的新功能及其使用。

2024 年 4 月 25 日,React 团队

注意

该 Beta 版本是为了让包开发者(libraries)为 React 19 做准备。普通开发者(App developers)应当升级 18.3.0 并等待 React 19 稳定,因为我们会跟包开发者(libraries)合作并根据反馈进行更改。

React 19 Beta 现已在 npm 上发布!

在我们的 React 19 Beta 升级指南 中,我们分享了将应用程序升级到 React 19 Beta 的分步说明。在这篇文章中,我们将概述 React 19 中的新功能及其使用。

破坏性更新(breaking changes)列表,请查看React 19 Beta 升级指南:Breaking changes

React 19 的新增功能

Actions

React 应用程序中的一个常见用例是,数据变更(mutation),驱动状态更新[^1]。例如,当用户提交表单更新姓名时,你会发送 API 请求,然后处理响应。过去,你需要手动处理 pending、errors、乐观更新(optimistic updates)和顺序请求(sequential requests)。

[^1]: 原文 perform a data mutation and then update state in response.

例如,你可能会使用 useState 来处理 pending 和 errors:

```jsx {5,8,10} // 有 Actions 之前 function UpdateName({}) { const [name, setName] = useState(""); const [error, setError] = useState(null); const [isPending, setIsPending] = useState(false);

const handleSubmit = async () => { setIsPending(true); const error = await updateName(name); setIsPending(false); if (error) { setError(error); return; } redirect("/path"); };

return (

setName(event.target.value)} /> {error &&

{error}

}
); }

在 React 19 中,我们支持在 transitions 中使用异步函数,以自动处理 pending、errors、表单和乐观更新。

例如,你可以使用 `useTransition` 来处理 pending:

jsx {5,8,15} // 使用 Actions 更新 pending function UpdateName({}) { const [name, setName] = useState(""); const [error, setError] = useState(null); const [isPending, startTransition] = useTransition();

const handleSubmit = () => { startTransition(async () => { const error = await updateName(name); if (error) { setError(error); return; } redirect("/path"); }) };

return (

setName(event.target.value)} /> {error &&

{error}

}
); }

异步 transition 会立即将 `isPending` 状态设置为 true,发送异步请求,并在任何 transitions 后将 `isPending` 切换为 false。这样可以在数据更改时,保持当前 UI 的响应能力和交互性。

> 译者注:其实这个例子看不出和 `useState` 相比的优势。建议浏览 [useTransition](https://zh-hans.react.dev/reference/react/useTransition) 查看 `useTransition` 的应用。

> 注意
>
> 按照惯例,使用异步 transitions 的函数称为“Actions”。
> Actions 会自动管理提交数据(submitting data):
> - pending 状态:Actions 提供 pending 状态,该状态在请求开始时启动(`译者注:置为 true`),并在所有状态更新都提交(committed)后自动重置。
> - 乐观更新:Actions 支持新的 [useOptimistic](#user-content-新-hook-useOptimistic) hook,你可以在提交请求时给用户即时反馈。
> - 错误处理:Actions 提供错误处理,以便你可以在请求失败时展示 Error Boundaries,并自动将“乐观更新”恢复为其原始值。
> - 表单:`<form>` 的 action 和 formAction 属性现在支持函数了。将函数传递给 action 属性会默认使用 Actions,并在提交后自动重置表单。

React 19 构建于 Actions 之上,引入了 [useOptimistic](#user-content-新-hook-useOptimistic) 来管理乐观更新,并引入了新 hook [React.useActionState](#user-content-新-hook-useActionState) 来处理 Actions 的常见情况。在 `react-dom` 中,我们添加了 [\<form\> Actions](#user-content-React-DOM-form-Actions) 来自动管理表单,并添加了 [useFormStatus](#user-content-React-DOM-新-hook-useFormStatus) 来支持表单中操作的常见情况。

在 React 19 中,上面的例子可以简化为:

jsx // 使用

Actions and useActionState function ChangeName({ name, setName }) { const [error, submitAction, isPending] = useActionState( async (previousState, formData) => { const error = await updateName(formData.get("name")); if (error) { return error; } redirect("/path"); return null; }, null, );

return ( {error &&

{error}

}
); }

在下一节中,我们将详细介绍 React 19 中的每个新 Action 功能。

### 新 hook:useActionState

为了使 Actions 易于处理常见情况,我们添加了一个名为 `useActionState` 的新 hook:

jsx const [error, submitAction, isPending] = useActionState( async (previousState, newName) => { const error = await updateName(newName); if (error) { // 该 action 你可以返回任何结果 // 该示例我们只返回一个 error return error; }

// 此处可以处理成功的情形
return null;

}, null, );

`useActionState` 接受一个函数(即 “Action”),并返回一个包装过的 Action 来用于调用(译者注:即上面示例中的 `submitAction`)。`This works because Actions compose.` 当调用包装过的 Action 时, `useActionState` 将返回 Action 的最后结果作为 data ,并将 Action 的挂起状态返回作为 pending 。

> 注意
>
> `React.useActionState` 在之前的 Canary 版本中称为 `ReactDOM.useActionState`,但我们已经重命名并弃用了 `ReactDOM.useActionState`。
>
> 更多详细信息,请参阅 [#28491](https://github.com/facebook/react/pull/28491)。

### React DOM: \<form\> Actions

Actions 还集成到了 React 19 的 `react-dom` 新 `<form>`中。 `<form>` 、`<input>` 和 `<button>` 的 `action` 和 `formAction` 属性,支持传递函数,以使用 Actions 自动提交表单。

jsx

当 `<form>` Action 成功时,React 会自动重置[非受控表单组件](https://zh-hans.react.dev/learn/sharing-state-between-components#controlled-and-uncontrolled-components)。如果你需要手动重置 `<form>` ,可以调用新的 `requestFormReset` React DOM API。

> 译者注:没找到 `requestFormReset` 这个 React DOM API,可能是指 [form.reset()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reset)?

更多详细信息,请参阅 react-dom 文档中的 [\<form\>](https://zh-hans.react.dev/reference/react-dom/components/form)、[\<input\>](https://zh-hans.react.dev/reference/react-dom/components/input) 和 `<button>`。

### React DOM: 新 hook:useFormStatus

在系统设计时,我们通常会设计,使得组件能直接访问当前所处的 `<form>` 的信息,而无需使用 props 逐层传递。这可以通过 Context 来完成,但为了简化该常见情形,我们添加了一个新的 hook `useFormStatus`:

jsx import {useFormStatus} from 'react-dom';

function DesignButton() { const {pending} = useFormStatus(); return }

实现不复杂,直接看**全部代码**

tsx import { clamp } from 'lodash-es' import { useCallback, useState } from 'react'

const InfiniteTimeout = 2 ** 31 - 1

/**

  • 同一个 withLoading 可以包装多个函数,

  • 同一个 withLoading 包装的所有函数全部执行完毕后才会关闭 loading; *

  • @usage

  • ```tsx

  • function Comp() {

  • const [ loading, withLoading ] = useLoading() *

  • const { data } = useSWR('xxx', withLoading(asyncTask1)) *

  • return <>

  • *

  • <Button

  • onClick={withLoading(asyncTask2)}

  • >

  • async task

  • }

  • ``` */ export function useLoading() { const [flag, setFlag] = useState(0)

    /**

  • @param fn 需要包装的函数

  • @param delayMs 延迟显示 loading (!!! 而非延迟执行函数) */ const withLoading = useCallback( ( fn: (…args: Arg) => Res | Promise, delayMs = 500 ) => async (…args: Arg) => { let timer = -1 if (delayMs > 0) { timer = +setTimeout(() => { timer = -1 setFlag((prev) => prev + 1) }, clamp(delayMs, 0, InfiniteTimeout)) } else { setFlag((prev) => prev + 1) } try { return await fn(…args) } finally { clearTimeout(timer) if (timer < 0) { setFlag((prev) => prev - 1) } } }, [] )

    return [ loading: flag > 0, withLoading, ] as const }

```


后记:代码的实现很简单,但我感觉从代码风格上来说,由原来的命令式,改为了声明式,更 "react" 了,所以感觉很有意义,就此记录。~~(当然不会说是为了水一篇文了)~~

]]>
https://16px.cc/blog/rhCL8zAniBX_https://16px.cc/blog/rhCL8zAniBX_Fri, 12 Jan 2024 01:29:58 GMT
<![CDATA[极简 js 入门]]>需要下载的东西:

编辑器, 写代码用的
sublime / notepad++ 等现代编辑器都行
windows 自带的记事本不行

  • node js 的环境, 是一个命令行工具

起步

  1. 新建一个项目目录

最好起全英文名, 别带中文, 别带空格
例如 hello-worldjs-testhello (分割单词使用中划线 下划线都行, 看自己喜好)

  1. 在刚刚那个目录里面新建一个 js 文件

一般叫 index.js 或者 main.js
用上面下载的 vscode, 别用 windows 自带的记事本

  1. 在里面写些代码并保存

比如说

   console.log('hello world')
  1. 执行

在项目目录下打开命令行工具, 执行 node index.js, 应该就能看到打印出来的 hello world

进阶

  • 去网上找些案例, 跟着做一做
  • 把项目保存到 github(或 gitee), 并使用 git 管理项目
  • 使用 typescript

有用的站点

可以在 https://github.com 上面新建一个自己的账号, 代码可以保存在里面。上面说的 git 就可以用于管理 github 上的项目的。(如果实在没有梯子, https://gitee.com/ 也勉强能用)

大佬

大佬

脚手架, 能帮助我们更快、更便捷地构建项目
建议学习 js 半个月之后再接触

一个前端的框架
如果想要学习前端就可以学学
建议学习 js 半个月之后再接触

]]>
https://16px.cc/blog/9yQot2vnXJVihttps://16px.cc/blog/9yQot2vnXJViFri, 03 Nov 2023 07:54:41 GMT
<![CDATA[小计一次 CLS 优化]]>网站 CLS(Cumulative Layout Shift) 评分一直在 0.7+, lighthouse 评分一直在 80 分上下, 然后就尝试找哪里有问题。

首先运行 lighthouse 评分, 找到 performance 下的 CLS 选项, 看到主要两处影响了 CLS 评分:

  1. 第一处是所有文章的列表, 是一个 MUI Grid 组件

当初文章列表打算做响应式, 就用了 MUI 的 Grid 组件, 后来决定列表不响应了, 但是感觉 Gird 还能用于纵向的 space, 就懒得换了。 可是这是 MUI 啊, 难道 MUI 还能影响 CLS? 不, 我不相信!!!

然而看 CLS 的截图, 明确指向了 Grid 组件, 之前看过 Grid 组件实现原理就是负 margin, 难道是负 margin的问题? 一搜关键字, "mui Grid CLS", "negative margin CLS", 好几个 issue 指向了它:

  1. 第二处是所有标签(tag)的列表, 是一个 object 元素

由于我希望在任何地方, 标签(tag)都能点击跳转到标签详情页(即使在另一个大的 a 标签下面), & 我希望使用原生的 a 标签, 以保证在禁用 js 的情况下仍能跳转, 然而 a 标签不能嵌套, 查了查, 哦, 可以用一个 object 标签包裹住 Tag 组件, 就用了。

CLS 截图指示 Tag 组件影响了评分, 可是它只是一个行内文本, 带了点 padding 和 margin, 它什么也没干啊, 它也没有负 margin, 为什么说它影响了评分啊, 不, 我不相信!!!

可是突然回想起前些天处理 tailwind preflight.css 时, 发现 tailwind preflight 把 object 和 img 放在了一起, 并将他们的默认样式设置为了 display: block;, 会不会, object 和 img 有差不多的性质?

一看 MDN, 果然:

HTML <object> 元素(或者称作 HTML 嵌入对象元素)表示引入一个外部资源,这个资源可能是一张图片,一个嵌入的浏览上下文,亦或是一个插件所使用的资源。

它引用一个外部资源, 那他必然不知道那个外部资源有多大, 而它里面的文字是标签的 name, 有长有短, 就必然导致 object 产生偏移。是啦, 说干就干, 标签 name 固定一下长度, object 也设置一下宽度, 搞定。

重新跑一下 lighthouse, 99 分, 啊, 多么美丽的绿色(是不是…有哪里不对)

]]>
https://16px.cc/blog/9M7HgvNI--R3https://16px.cc/blog/9M7HgvNI--R3Fri, 28 Jul 2023 17:05:36 GMT
<![CDATA[HTML 邮件需要注意的点]]>优秀参考

XHTML 1 规范与 HTML 4 的差异

翻译自 https://www.w3.org/TR/xhtml1/

  1. 文档格式必须正确

    正确: 嵌套元素

   <p>这是强调 <em>段落</em>。</p>

错误: 重叠元素

   <p>这是强调 <em>段落</p>。</em>
  1. 元素名和属性名必须小写

    li 而非 LI

  2. 非空元素必须要结束标签

    正确

    <p>这是一段。</p><p>这是另一段。</p>
    

    错误

    <p>这是一段。<p>这是另一段。
    
  3. 所有属性值必须使用引号

    正确

    <td rowspan="3">
    

    错误

    <td rowspan=3>
    
  4. 不支持属性最小化(Attribute Minimization)

    正确

    <input checked="checked" />
    

    错误

    <input checked />
    
  5. 空元素必须有结束标签

    正确

    <br /><hr />
    

    错误

    <br><hr>
    
  6. 处理属性值中的空白

    根据 XML 属性值归一化 的标准:

    • 去除前导和尾随空白字符
    • 词间的一个或多个空白字符(包括换行符)将替换为一个 space
  7. script 和 style 元素(其实在邮件中是用不上 script 的)

    在 XML 中, <& 被视为标记的开始, 而 &lt;&amp; 会被转义为 <&. 所以如果你不希望他们被转义, 可以用 CDATA 包裹他们, 或者引用外部文档

    <script type="text/javascript">
      <![CDATA[
      ... unescaped script content ...
      ]]>
    </script>
    
  8. SGML 排除项

    SGML 禁止某些元素嵌套, XML 中没有这些禁令, 但仍表示这些元素不应嵌套

    • a 禁止包含其他 a
    • pre 禁止包含其他 img, object, big, small, sub, sup
    • button 禁止包含其他 input, select, textarea, label, button, form, fieldset, iframe, isindex
    • label 禁止包含其他 label
    • form 禁止包含其他 form
  9. 元素的 idname 属性

    HTML 4 为 a, applet, form, frame, iframe, img, map 定义了 name 属性, 同时也有 id 属性, nameid 都是用作片段标识符

    而 XML 仅使用 id 作为标识符, 且必须文档内唯一(id不能重复), 因此出于兼容性考虑, 当上述元素需要定义标识符时, 必须使用 id(而非 name)

    同时需要注意, 上述元素的 name 属性在 XHTML 1.0 中已被正式弃用, 并将在 XHTML 的后续版本中删除。

  10. 属性枚举值

    HTML 4 中, 属性枚举值不区分大小写(如 inputtype 属性, 值 TEXT 等同于 text), 但在 XML 中区分大小写, XHTML 1 中定义为小写

  11. 16 进制实体引用(Entity references)必须使用小写

    &#xnn; 而非 &#XNN;

  12. 空元素的尾随 / 前面要加一个空格

    • <br /> 而非 <br/>
    • 使用 <br /> 而非 <br></br> (因为后者, 用户代理可能给出不确定的结果, 即不同浏览器的解析结果可能不一致)
  13. 内容模型(content model)非空的元素, 别使用 minimized form

    <p> </p> 而非 <p />

  14. 如果 scripts or style sheets 脚本中有用到 <, &, ]]>, -- 时, 使用外部脚本

    XML 允许用户代理删除注释, 因此你想将他们放在注释中来做兼容也是行不通的

  15. 避免在属性值中使用换行符和多个空白字符, 用户代理处理这些情况是不一致的

  16. 同时使用 langxml:lang 时, xml:lang 的优先级更高

  17. 片段标识符

    标识符用于在 URI 结尾来引用元素, 如 #foo 会引用到 标识符的值为 foo 的元素。

    • XML 中以 id 作为标识符, HTML 4 以 name 作为标识符, 建议对支持的元素, 同时使用 idname, 以做到最大兼容。
    • 需要注意, XHTML 1.0 中 a, applet, form, frame, iframe, img, mapname 属性已弃用, 并将在 XHTML 的后续版本中删除。
  18. 在属性值(和其他地方)中使用 & 符号需要转义 (存疑)

    文档表示, 当元素 href 属性带有 & 符号时, 需要转义, 如:

    • 正确: http://my.site.dom/cgi-bin/myscript.pl?class=guest&amp;name=user
    • 错误: http://my.site.dom/cgi-bin/myscript.pl?class=guest&name=user

    我是有些存疑的, 那样还能访问到正确的地址吗? 待测试

  19. 一些在 HTML 文档中合法的字符, 在 XML 文档中是非法的。

    例如, 在 HTML 中, Formfeed 字符 (U+000C) 被视为空白, 在 XHTML 中, 由于 XML 对字符的定义, 它是非法的。

  20. 撇号 不应该使用 &apos; 而应该使用 &#39; > - 命名字符引用 &apos; (撇号 U+0027: ') 是在 XML 1.0 中引入的, 但没有出现在 HTML 中。因此, 应该使用 &#39; 而不是 &apos;, 才能在 HTML 4 用户代理中按预期工作。 > - 我就遇到过, 产品表示部分用户收到的邮件标题直接出现了 &apos;, 体验非常不好, 而 &#39; 是否可以避免这个问题? 待测试

]]>
https://16px.cc/blog/mz9sNneP9r8chttps://16px.cc/blog/mz9sNneP9r8cFri, 28 Jul 2023 17:04:18 GMT