0%

前言

首先,如果你不知道 Netlify 有一个 CLI,他们知道。我最喜欢的一件事就是在我的静态页面的项目里运行netlify dev命令时看到它检测到它正在做什么并在开发服务器启动站点,进度条慢慢填满。但不仅仅是一个开发服务器,而是复制 Netlify 环境的开发服务器,这意味着你可以在本地运行微服务和使环境变量可用之类的事情。

这里还有五件你可能没有意识到的事情。

1.使用模版创建网页

是的,就一行命令这么简单

1
netlify sites:create-template=

2.管理环境变量

你可以使用netlify env命令(Beta)来管理环境变量。

  • netlify env:list:列出所有环境变量
  • netlify env:get / set:获取设置变量
  • *env:migrate –to *:迁移整个项目的变量到另外一个

3.测试无服务器功能

通过使用 Netlify CLI在本地启动站点,你的微服务器功能将被运行。你可以测试它们是否正常工作并检查网络流量。但是 CLI 也可以帮助您,netlify functions 命令能够在命令行级别测试函数。例如,netlify functions:invoke 可以触发带有模拟数据的函数。

4.直播开发环境

记得之前提到你如何使用 netlify dev 在本地创建一个开发环境吗?这里的诀窍是执行 netlify dev –live。因此,你获得一个全世界都可以看到的特殊 netlify.live URL,而不是localhost URL

5.运行netlify switch在不同的 Netlify 帐户之间切换

比如从你的个人项目到工作项目切换,实际上是使用 CLI 进行身份验证(netlify 登录,想象一下),这样您就可以代表你自己的 Netlify 帐户进行操作。部署网站等等。但是,你拥有多个 Netlify 帐户(如工作帐户和个人帐户)是完全合理的。

BONUS!

推荐一个视频时长 50 秒,展示了如何从在本地城建一些静态文件到使用 CLI 进行部署的过程。

前言

1
2
1) https://website.com/foo/
2) https://websites.com/foo

第一个选项有一个“斜线”。第二个没有。

我一直倾向于这种想法:如果该页面有子页面,则使用尾部斜杠(例如,它是一个目录页面,即使它有自己的独特内容)。如果是行尾(内容),则没有尾随斜杠。

我这么说,但这个网站css-tricks.com并没有使用它。这个网站上的博客文章就像*css-tricks.com/blog-post/*带有斜杠,如果你去掉斜杠,WordPress 将重定然后主动带上斜杠。重定向会带来性能损失,因此最好尽可能少地发生。

性能是一回事,但 SEO 又是另一回事。如果您渲染相同的内容,无论是否带有斜线,这在理论上都是重复的内容惩罚和禁忌。
(虽然这对我来说似乎很奇怪,但我认为百度,谷歌的那个搜索引擎足够聪明,所以无需过分担心。)

资源解析似乎是最重要的。在一些 web hosting 的平台上使用相对路径时,一些资源是无法加载的。

1
<img src="image.avif" />

在 /resource/ 指向 /resource/image.avif

1
<img src="image.avif" />

在 /resource/ 指向 /image.avif

这是一个很大的区别,对我来说,重定向是值得的一个原因。不能因为这么愚蠢的事情让网页找不到资源。更复杂的是,网站建设框架可能对此有意见,而托管服务提供商可能对此有意见。主持人之间存在一些分歧,因此值得关注。

前言

Ahmad Shadeed 的文章css-object-view-box写得很好,他可以让我们对object-view-box属性的有一定的了解,他将其描述为在浏览器中使用 CSS 裁剪图像的原生方式。

如何使用

使用案例呢?好吧,Ahmad 开头展示了如何在没有css-object-view-box的情况下来完成一些图片裁剪需求。

  1. codepan例子1:一个带有隐藏溢出的包装元素,该元素围绕一个尺寸和定位在该元素内的图像或
  2. codepan例子2:背景图background-image

如果使用 object-view-box,我们基本上可以像使用 SVG 的 viewbox 一样绘制图像边界。因此,我们可以使用普通的 <img> 标签并调用 object-view-box 以使用 inset 函数修剪边缘。我把Ahmad的例子放这里。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
img {
width: 220px;
aspect-ratio: 3 / 2;
object-fit: cover;
}

.img-0 {
aspect-ratio: 1 / 2;
}

.img-1 {
object-view-box: inset(0% 19% -33% 57%);
}

.img-2 {
object-view-box: inset(0% 15% -52% 3%);
}

.img-3 {
object-view-box: inset(0% 0% 17% 0%);
}

.group {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 1rem 1.5rem;
}

/* Other styles */
.item {
text-align: center;
margin-bottom: 2rem;

p {
padding: 0.5rem;
}

code {
font-size: 14px;
}
}
.alert {
display: block;
max-width: 70ch;
padding: 1rem;
text-align: center;
margin: 0 auto 1rem;
background-color: #ffeeee;
border: 1px solid red;
border-radius: 5px;
font-size: 0.75rem;
}

@supports (object-view-box: inset(0)) {
.alert {
display: none;
}
}

body {
font-family: "system-ui";
padding: 1rem;
line-height: 1.45;
}

img {
max-width: 100%;
box-shadow: 0 8px 15px 0 rgba(#000, 0.1), 0 2px 5px 0 rgba(#000, 0.2);
border-radius: 12px;
}

*,
*:before,
*:after {
box-sizing: border-box;
}

结尾

可惜css-object-view-box现在只支持Chrome Canary。 但是谷歌计划在[Chrome 104]中(https://chromestatus.com/feature/5213032857731072)支持!

前言

你可能已经习惯了在 React 中使用 axios 或 fetch 来获取数据。处理数据获取的通常方法是:

  • 进行 API 调用。
  • 如果一切按计划进行,使用响应更新状态。
  • 或者,在遇到错误的情况下,会向用户显示一条错误消息。

当通过网络处理请求时,总是会有延迟。当你提出请求并等待回应时,这只是过程的一部分。这就是为什么我们经常使用加载转轮来告诉用户预期的响应正在加载。

例子

所有这些都可以使用一个名为React Async的库来完成。

React Async 是一个基于承诺的库,可以让你在 React 应用程序中获取数据。让我们来看看各种使用组件、钩子和帮助器的例子,看看我们如何在发出请求时实现加载状态。

在本教程中,我们将使用 Create React App。你可以运行以下命令来创建一个项目:

完成后,运行 yarn 或 npm 命令在你的项目中安装 React Async:

1
2
3
4
5
## yarn
yarn add react-async

## npm
npm install react-async --save

组件中的加载器

这个库允许我们在 JSX 中直接使用。因此,组件的示例如下所示;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Let's import React, our styles and React Async
import React from 'react';
import './App.css';
import Async from 'react-async';

// We'll request user data from this API
const loadUsers = () =>
fetch('https://jsonplaceholder.typicode.com/users')
.then((res) => (res.ok ? res : Promise.reject(res)))
.then((res) => res.json());

// Our component
function App() {
return (
<div className="container">
<Async promiseFn={loadUsers}>
{({data, err, isLoading}) => {
if (isLoading) return 'Loading...';
if (err) return `Something went wrong: ${err.message}`;

if (data)
return (
<div>
<div>
<h2>React Async - Random Users</h2>
</div>
{data.map((user) => (
<div key={user.username} className="row">
<div className="col-md-12">
<p>{user.name}</p>
<p>{user.email}</p>
</div>
</div>
))}
</div>
);
}}
</Async>
</div>
);
}

export default App;

首先,我们创建了一个名为 loadUsers 的函数。这将使用 fetch API 进行 API 调用。当它这样做时,它返回一个得到解决的承诺。之后,组件就可以使用所需的包了。

这些包为:

  • isLoading:处理尚未从服务器接收到响应的情况。
  • err:用于遇到错误的情况。您也可以将其重命名为 error 错误.
  • data:这是从服务器获得的预期数据。

正如你在这个例子中看到的,我们要显示一些东西给依赖于包的用户。

示例 2: 钩子上的加载器

如果你喜欢钩子,在使用 React Async 时有一个钩子选项可用。它看起来是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// Let's import React, our styles and React Async
import React from 'react';
import './App.css';
import {useAsync} from 'react-async';

// Then we'll fetch user data from this API
const loadUsers = async () =>
await fetch('https://jsonplaceholder.typicode.com/users')
.then((res) => (res.ok ? res : Promise.reject(res)))
.then((res) => res.json());

// Our component
function App() {
const {data, error, isLoading} = useAsync({promiseFn: loadUsers});
if (isLoading) return 'Loading...';
if (error) return `Something went wrong: ${error.message}`;
if (data)
// The rendered component
return (
<div className="container">
<div>
<h2>React Async - Random Users</h2>
</div>
{data.map((user) => (
<div key={user.username} className="row">
<div className="col-md-12">
<p>{user.name}</p>
<p>{user.email}</p>
</div>
</div>
))}
</div>
);
}

export default App;

这看起来与组件示例类似,但在本场景中,我们使用的是 useAsync 组件,而不是 Async 组件。响应返回一个被解析的承诺,我们也可以访问类似的包,就像我们在上一个例子中做的,然后我们可以返回到渲染的 UI。

示例 3: 帮助程序中的加载器

Helper 组件在提高我们的代码的可读性方面很有帮助。这些帮助程序可以在使用 useAsync 钩子或 Async 组件时使用,这两个都是我们刚刚看到的。下面是一个在 Async 组件中使用 helper 的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// Let's import React, our styles and React Async
import React from 'react';
import './App.css';
import Async from 'react-async';

// This is the API we'll use to request user data
const loadUsers = () =>
fetch('https://jsonplaceholder.typicode.com/users')
.then((res) => (res.ok ? res : Promise.reject(res)))
.then((res) => res.json());

// Our App component
function App() {
return (
<div className="container">
<Async promiseFn={loadUsers}>
<Async.Loading>Loading...</Async.Loading>
<Async.Fulfilled>
{(data) => {
return (
<div>
<div>
<h2>React Async - Random Users</h2>
</div>
{data.map((user) => (
<div key={user.username} className="row">
<div className="col-md-12">
<p>{user.name}</p>
<p>{user.email}</p>
</div>
</div>
))}
</div>
);
}}
</Async.Fulfilled>
<Async.Rejected>
{(error) => `Something went wrong: ${error.message}`}
</Async.Rejected>
</Async>
</div>
);
}

export default App;

这看起来和我们使用包的时候很类似。完成这些之后,你可以将应用程序的不同部分分解成微小的组件。

总结

如果你已经厌倦了走我在本教程开始部分提到的路线,你可以在你正在做的项目中开始使用 React Async。本教程中使用的源代码可以在 GitHub 上的不同分支中找到。

前言

傍晚的阳光透过沙沙作响的树叶照射进来,给人宁静而温暖的感觉。许多艺术家使用斑驳的光来营造一种柔和、催眠的效果。

斑驳效果

我们可以在网页设计中使用同样的斑驳效果。在照片和插图上使用这个效果,可以为原本单调乏味的内容墙增添魔力,让它们恢复生机。有一种只用 CSS 的简单而快速的方法来添加这个效果。

在我们开始谈代码之前,要先了解斑驳光的组成。它是光透过树叶和树枝形成的大光点组成的。因为我们正在谈论的是穿过许多不确定的空间的光,阴影区域有时会有清晰的边缘,但更多时他的边界候是模糊的。当光从更远的距离投射阴影时,会扩散和扭曲光线附近的墙壁,使得阴影的边界变得模糊。
这是有和没有斑驳光照射的白墙的区别:

效果

我将会使用纯文本和有趣的表情符号来创造斑驳的灯光效果,使用 CSS 阴影和混合来模仿自然。我也将会介绍一些其他的方法。

设置场景

我们将使用文本(字母表中的字母、特殊字符、表情符号等)来创建光的形状。我所说的光,是指半透明的乳白色。同时,我们想要的是柔和的灯光效果,而不是那种锐利、清晰或鲜明的效果。

由斑驳的光产生的斑点有多种形状,所以最好的选择是椭圆或长方形的字符。我会使用 🍃和🍂,因为它们是椭圆的、长方形的和倾斜的,有点混乱且难以预测。

我将它们包装在 .backdrop 父元素中包含的段落中:

1
2
3
4
5
<div class="backdrop">
<p class="shapes">🍃</p>
<p class="shapes">🍂</p>
<p class="shapes">\</p>
</div>

我使用父元素作为投射斑驳光影的表面,为其纹理应用背景图像。我不仅给表面一个明确的 width 和 height,而且在它上面设置了隐藏的溢出,这样我就可以投射超出表面的阴影而不暴露它们。由于 CSS 网格,投射出斑驳光效果的对象在背景表面的中间对齐:

1
2
3
4
5
6
7
8
9
10
.backdrop {
background: center / cover no-repeat url('image.jpeg');
width: 400px;
height: 240px;
overflow: hidden;
display: grid;
}
.backdrop > * {
grid-area: 1/1;
}

如果形状没有完全对齐也没有关系,只要它们能够达到你想要的斑驳的效果,就可以了。所以没有必要完全按照我的做法来放置这些东西,你可以尝试调整这些值来获得不同图案的斑驳光!

在 CSS 中设计斑驳的灯光

这些是表情符号应该具有的关键属性——transparent 颜色、黑色半透明背景(使用 alpha 通道 inrgbargba())、font-size 漂亮的模糊白色 text-shadow,最后是 mix-blend-mode 来平滑过渡。
mix-blend-mode 设置元素的颜色与其容器的内容的融合方式。该 multiply 值使元素的背景通过元素的浅色显示并保持深色相同,从而形成更好、更自然的斑驳光效果。

1
2
3
4
5
6
7
.shapes {
color: transparent;
background-color: rgba(0, 0, 0, 0.3); // Use alpha transparency
text-shadow: 0 0 40px #fff; // Blurry white shadow
font: bolder 320pt/320pt monospace;
mix-blend-mode: multiply;
}

细化颜色和对比度

我希望背景上的 background-image 更亮一点,所以我还添加了 filter: brightness(1.6). 另一种实现方法是 background-blend-mode,将一个元素的所有不同背景混合在一起,而不是将表情符号添加为单独的元素,我们将它们添加为背景图像。
请注意,在最后一个示例中,我使用了不同的表情符号,以及 floralwhite 一些比纯白色的光线强度更低的颜色。这是展开的表情符号背景图像之一:

1
2
3
4
5
6
7
8
9
10
11
12
<svg xmlns='http://www.w3.org/2000/svg'>
<foreignObject width='400px' height='240px'>
<div xmlns='http://www.w3.org/1999/xhtml' style=
'font: bolder 720pt/220pt monospace;
color: transparent;
text-shadow: 0 0 40px floralwhite;
background: rgba(0, 0, 0, 0.3);'
>
🌾
</div>
</foreignObject>
</svg>

如果想将自己的图像用于形状,要确保边界模糊以创造柔和的光线。CSS blur()过滤器可以很方便地处理同样的事情。我还使用 CSS@supports 来调整某些浏览器的阴影模糊值作为备用。
现在让我们回到第一个示例并添加一些内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div class="backdrop">
<p class="shapes">🍃</p>
<p class="shapes">🍂</p>
<p class="shapes">\</p>
</div>

<p class="content">
<img
width="70px"
style="float: left; margin-right: 10px;"
src="image.jpeg"
alt=""
/>
Top ten tourists spots for the summer vacation <br /><br /><i
style="font-weight: normal;"
>Here are the most popular places...</i
>
</p>

动画光源

我还决定添加一个简单的 CSS 动画,并将@keyframes 其应用于.backdrop :hover:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.backdrop:hover > .shapes:nth-of-type(1) {
animation: 2s ease-in-out infinite alternate move;
}
.backdrop:hover > .shapes:nth-of-type(2):hover {
animation: 4s ease-in-out infinite alternate move-1;
}

@keyframes move {
from {
text-indent: -20px;
}
to {
text-indent: 20px;
}
}
@keyframes move-1 {
from {
text-indent: -60px;
}
to {
text-indent: 40px;
}
}

为 emoji 上的 text-indent 属性设置动画会产生一种非常微妙的运动,就像移动的云层改变光线的方向。

总结

好了!我们从自然和艺术中汲取了一些灵感,模仿了太阳穿过树木和灌木丛,将斑驳的光和阴影点投射到物体的表面。我们用 CSS 和几个表情符号完成了所有这些。

这个方法的关键在于我们如何在表情符号上应用颜色,在浅色中使用额外的模糊 text-shadow 来设置光线,半透明的 background-color 定义阴影斑点。我们所要做的就是确保光影的背景使用具有足够对比度的逼真的纹理,这样就能看到斑驳的光线了。

前言

在 Wikipedia 的Common.css有一段 CSS

1
2
3
4
5
6
.mw-collapsible-leftside-toggle .mw-collapsible-toggle {
/* @noflip */
float: left;
/* @noflip */
text-align: left;
}

这里的@noflip 有什么用呢?这就是一些人所说的“CSS 装饰”,我觉得这很形象。实际上,它们只是 CSS 注释而已,但显然这里还有更多内容,因为它们看起来像具有功能的语句。

如果没有某种 CSS 处理过程,这些注释将无济于事。我不是很确定这里使用的是什么 CSS 处理器,但我认为假设它运行时会产生一个“从右到左”的样式表是合理的,它会变成浮动:左 进入浮动:右和文本对齐:左进入文本对齐:右。

替代方案?

我认为值得注意的是,现在使用大多数浏览器支持的 text-align: start 效果可能更好,这样就不必依赖 CSS 处理和备用样式表来修改 CSS。但是我觉得 float 是没有“逻辑”等价物,但可能有一种方法可以重构布局(使用grid?),这样“翻转”就是不必要的。将元素包裹在一个元素周围对于浮动来说是非常独特的,所以这里可能没有简单的替代方案。

稍微搜索了一下,似乎是 /* @noflip */ 的来源is CSSJanus

网页截图

这个仓库显示它是由维基媒体制作的,所以我认为这是一个已解决的案例。看起来这项技术已经运用到其他,比如样式组件的插件,Sublime Text 的插件,Salesforce 甚至在他们的设计系统中使用了它。

还有另一个名为 css-flip 的处理器(现在已归档,出自 Twitter)看起来它做了完全相同的事情,自述文件显示了有多少属性可能需要这个:

1
background-position, background-position-x, border-bottom-left-radius, border-bottom-right-radius, border-color, border-left, border-left-color, border-left-style, border-left-width, border-radius, border-right, border-right-color, border-right-style, border-right-width, border-style, border-top-left-radius, border-top-right-radius, border-width, box-shadow, clear, direction, float, left, margin, margin-left, margin-right, padding, padding-left, padding-right, right, text-align transition transition-property

总结

It would have hugely surprised me if there wasn’t a PostCSS plugin for this, and a little searching turned up postcss-rtl, but alas, it’s also been deprecated by the owner.

This all started with talking about “CSS decorators” though, which I guess we’re defining as “CSS comments that have processor directives in them.” The one I personally use the most is this:

我想一定会一个实现 flip 的PostCSS 插件,然后我就搜索到了 postcss-rtl,但是它也被所有者弃用了 ☹️。

不过,这一切都始于谈论“CSS 装饰”,我想我们应该将其定义为“其中包含处理器指令的 CSS 注释”。 我个人用得最多的是这个:

1
2
3
4
5
6
7
8
9
10
/* prettier-ignore */
.cool {
linear-gradient(
to left,
pink
pink 20%
red 20%
red
)
}

我很喜欢 Prettier,但如果我花时间自己格式化一些 CSS 以提高可读性,我会在前一行中添加一个 /* prettier-ignore */ 以格式化的时候弄乱它。

Pull Request 拉取请求——这是一项对小型和大型开发团队都有帮助的强大功能。拉取请求不仅可以改进审查和反馈过程,而且还有助于跟踪和讨论代码更改。最后但并非最不重要的一点是,它是为你没有写入权限的其他存储库做出贡献的理想方式。

什么是拉取请求?

首先,要明白拉取请求并不是 Git 的核心功能。相反,它们是由你使用的 Git 托管平台提供的: GitHub、GitLab、Bit bucket、AzureDevops 和其他一些平台都内置了这样的功能。

为什么要创建拉取请求?

在我们详细了解如何创建完美的拉取请求之前,让我们先谈谈你为什么会想要使用此功能。

想象一下,你刚刚完成了软件的一项新功能。也许你一直在一个功能分支中工作,所以你的下一步是将它合并到主线分支(master或main)。这在某些情况下没有任何问题,例如,你是项目中唯一的开发人员,或者你有足够的经验并且知道你的团队成员肯定会对此感到高兴。
但是,如果你的更改有点复杂并且你希望其他人查看你的工作怎么办?这就是拉取请求的目的,通过拉取请求,你可以邀请其他人审查你的工作并向你提供反馈。
拉取请求打开后,你可以与其他开发人员讨论你的代码。大多数 Git 托管平台允许其他用户在此过程中添加评论并提出更改建议。在你的审阅者批准你的工作后,它可能会合并到另一个分支中。

但是,拥有审查工作流程并不是拉取请求的唯一原因。如果你想为你没有写入权限的其他存储库做出贡献,它们会派上用场。想想那里的所有开源项目,如果你有一个新功能的想法,或者如果你想提交补丁,拉取请求是一种很好的方式来表达你的想法,而无需加入项目并成为主要贡献者。
这将我们带到了一个与拉取请求紧密相关的主题:forks。

使用forks工作

forks是现有Git仓库的个人副本。回到我们的开源示例:你的第一步是创建原始存储库的分支。之后,你可以在自己的个人副本中更改代码。
完成后,你打开一个拉取请求,要求原始存储库的所有者包含你的更改。所有者或其他主要贡献者之一可以查看你的代码,然后决定包含(或不包含)它。
让审阅者的生活更轻松:如何创建出色的拉取请求
如前所述,拉取请求不是 Git 的核心功能。相反,每个 Git 平台都有自己的设计和关于拉取请求应该如何工作的想法。它们在 GitLab、GitHub、Bitbucket 等上看起来不同。每个平台都有略微不同的跟踪、讨论和审查更改的工作流程。

例如,像Tower Git 客户端这样的桌面GUI可以使这变得更容易:它们提供一致的用户界面,无论你使用什么代码托管服务。

话虽如此,一般工作流程始终相同,包括以下步骤:

  • 如果你没有相关存储库的写入权限,第一步是创建一个分支,即你的存储库的个人版本。
  • 在你的分叉存储库中创建一个新的本地分支。(提醒:拉取请求基于分支,而不是提交!)
  • 在你的本地分支中进行一些更改并提交。
  • 将更改推送到你自己的远程存储库。
  • 使用你的更改创建拉取请求并开始与其他人讨论。

让我们看看拉取请求本身以及如何创建一个让其他开发人员的生活更轻松的请求。首先,它应该很短,以便可以快速查看。当查看 3,000 行而不是 30 行时,更难理解代码。
此外,请确保添加一个良好且不言自明的标题和有意义的描述。尝试描述什么,你变了,为什么你开拉入请求,以及如何更改影响的项目。大多数平台都允许你添加有助于演示更改的屏幕截图。

批准、合并还是拒绝?

一旦你的更改获得批准,你(或具有写入权限的人)就可以将分叉分支合并到主分支中。但是如果审阅者不想合并当前状态的拉取请求怎么办?好吧,你总是可以添加新的提交,在推送那个分支之后,现有的拉取请求就会更新。或者,所有者或其他具有写入权限的人可以在他们不想合并更改时拒绝拉取请求。

开发商的安全网

如你所见,拉取请求是与开发人员同事交流和协作的好方法。通过请其他人审查你的工作,你可以确保只有高质量的代码才能进入你的代码库。

在JavaScript的学习中,我们经常会遇到JavaScript的事件机制,例如,事件绑定、事件监听、事件委托(事件代理)等。这些名词是什么意思呢,有什么作用呢?

事件绑定

要想让 JavaScript 对用户的操作作出响应,首先要对 DOM 元素绑定事件处理函数。所谓事件处理函数,就是处理用户操作的函数,不同的操作对应不同的名称。

在JavaScript中,有三种常用的绑定事件的方法:

在DOM元素中直接绑定;

在JavaScript代码中绑定;
绑定事件监听函数。

我们可以在DOM元素上绑定onclick、onmouseover、onmouseout、onmousedown、onmouseup、ondblclick、onkeydown、onkeypress、onkeyup等。好多不一一列出了。如果想知道更多事件类型请查看,DOM事件。

在JavaScript代码中绑定事件

在JavaScript代码中(即script标签内)绑定事件可以使JavaScript代码与HTML标签分离,文档结构清晰,便于管理和开发。

使用事件监听绑定事件

绑定事件的另一种方法是用 addEventListener() 或 attachEvent() 来绑定事件监听函数。下面详细介绍,事件监听。

事件监听

关于事件监听,W3C规范中定义了3个事件阶段,依次是捕获阶段、目标阶段、冒泡阶段。

起初Netscape制定了JavaScript的一套事件驱动机制(即事件捕获)。随即IE也推出了自己的一套事件驱动机制(即事件冒泡)。最后W3C规范了两种事件机制,分为捕获阶段、目标阶段、冒泡阶段。IE8以前IE一直坚持自己的事件机制(前端人员一直头痛的兼容性问题),IE9以后IE也支持了W3C规范。

W3C规范
语法:

1
element.addEventListener(event, function, useCapture)
  • event : (必需)事件名,支持所有DOM事件。
  • function:(必需)指定要事件触发时执行的函数。
  • useCapture:(可选)指定事件是否在捕获或冒泡阶段执行。true,捕获。false,冒泡。默认false。

事件监听的优点

  • 1、可以绑定多个事件。常规的事件绑定只执行最后绑定的事件。两个事件都执行了。
  • 2、可以解除相应的绑定

封装事件监听

1
2
3
4
5
6
7
8
//绑定监听事件
function addEventHandler(target,type,fn){
if(target.addEventListener){
target.addEventListener(type,fn);
}else{
target.attachEvent("on"+type,fn);
}
}
1
2
3
4
5
6
7
8
//移除监听事件
function removeEventHandler(target,type,fn){
if(target.removeEventListener){
target.removeEventListener(type,fn);
}else{
target.detachEvent("on"+type,fn);
}
}
1
2
3
4
5
//测试
var btn5 = document.getElementById("btn5");
addEventHandler(btn5,"click",hello1);//添加事件hello1
addEventHandler(btn5,"click",hello2);//添加事件hello2
removeEventHandler(btn5,"click",hello1);//移除事件hello1

事件委托

事件委托就是利用冒泡的原理,把事件加到父元素或祖先元素上,触发执行效果。

1
2
3
4
5
6
7
8
var btn6 = document.getElementById("btn6");
document.onclick = function(event){
event = event || window.event;
var target = event.target || event.srcElement;
if(target == btn6){
alert(btn5.value);
}
}

事件委托可以提高JavaScript性能。事件委托可以显著的提高事件的处理速度,减少内存的占用。

在HTML里,我们会使用input标签去处理密码。
就像这样:

1
<input type="password">

如果你使用它,你会在输入时字符会变成这样的小圆点 •••••••

那是因为浏览器试图帮助提高安全性。如果它没有这样做,那么有人可能会从你的身边偷看你正在输入的内容。这应该比查看手指在键盘上按下的键更容易。

但是现在 UX 已经发生了一些变化,并且更常见的选项是:

秘密

我觉得显示/隐藏密码是个很通用的场景。这样我们就可以确保正确输入,并且不会遭受打错字的痛苦。

所以! 该怎么办?

1: 使用 type=”password”, 然后使用JavaScript切换到 type=”text”

这就是现在大家通常会做的事情,因为它现在实际上适用于所有浏览器。

1
2
3
4
5
6
const input = document.querySelector(".password-input");
if (input.getAttribute("type") === "password") {
input.setAttribute("type", "text");
} else {
input.setAttribute("type", "password");
}

这里的问题是除了你必须为此更改输入类型有点奇怪之外,还有是对密码管理器工具失效。

2: 在CSS使用 -webkit-text-security

这不是一个特别通用的方案,因有些浏览器不支持这个属性。

1
2
3
4
5
6
input[type="password"] {
-webkit-text-security: square;
}
form.show-passwords input[type="password"] {
-webkit-text-security: none;
}

3: 在CSS使用 input-security

现在有个关于input security提案,我没可以切换input-security的值。我觉得这是一个比较好的提案,但是现在大多数浏览器还不支持,所以严格意义上说,我还只能用方案1。

1
2
3
form.show-passwords input[type="password"] {
input-security: none;
}

新版Node.js

模块是导出一个或多个值的 JavaScript 文件。导出的值可以是变量、对象或函数。

ES6 导入语法允许导入从不同 JavaScript 文件导出的模块。在 React 和 React Native 应用程序中使用模块是一种常见的模式。语法由以下 ES 模块标准组成:

1
import XXX from 'xxx';

ES 模块是使用模块的 ECMAScript 标准。Node.js 使用 CommonJS 标准来导入模块。这种标准的语法可以这样写:

1
const XXX = require('xxx');

Node js 不直接支持 ES6 导入。尝试import在 JS 文件中编写语法:

1
import { ApolloServer, gql } from 'apollo-server';

使用npm start或运行Node.js服务器npm run dev

Node Error

此错误的解决方案位于上述错误代码段的第一行,现在是 Node.js 推荐的方法。设置 “type”: “module”package.json文件。

1
2
3
{
"type": "module"
}

但是这个方案只适用于最新的 Node.js 和14.x.x+。

低于 14 的 Node.js

这个问题的另一个解决方案是使用Babel。它是一个 JavaScript 编译器,允许使用最新的语法编写 JS。Babel 不是一个框架或平台,所以它可以用在任何用 JavaScript 编写的项目中,因此也可以用在 Node.js 项目中。

首先从终端窗口安装以下开发依赖项:

1
npm i -D @babel/core @babel/preset-env @babel/node

然后在名为 Node.js 项目的根目录创建一个文件babel.config.json并添加以下内容:

1
2
3
{
"presets": ["@babel/preset-env"]
}

该包@babel/node是一个 CLI 程序,它在运行之前使用 Babel 预设和插件编译 Node.js 项目中的 JS 代码。这意味着它会babel.config.json在执行 Node 项目之前读取并应用任何提及的配置。

更换node用babel-node在执行服务器startdev脚本。

使用npm run dev脚本运行 Node 服务器的示例:

1
2
3
4
5
{
"scripts": {
"dev": "nodemon --exec babel-node server.js"
}
}