0%

前言

现在有越来越多的平台支持用户分享自己创作的文章,常见的就有知乎、微信公众号、简书、CSDN 等,这些平台为你的内容带来流量的同时,也要你承担相应的限制,比如 CSDN 就会出现各种广告,微信公众号就不能添加外部链接等等。总的来说还是不自由,内容创作者只是把内容托管到了它们的平台上面而已。尽管博客在中国流行的时间还是在十几年前,这个时间点搭建一个博客甚至还有点逆时代潮流的感觉,但是也正是自己的站点,能给予自己更多的自由,更多的表达空间,尤其是程序员、摄影师等,更需要一个展示自己内容的空间。

Hexo

Hexo 博客本质上是一个 CMS(Content Management System),内容管理系统,从官网的解释里面可以看到,这是一个静态的博客,也就是说,写作的流程是这样的:

  • 用 Markdown 写作
  • 使用 Hexo 生成静态页面
  • 使用 Hexo 部署静态页面

Netlify

Netlify 是一个提供 Web 项目托管的平台,支持 Github、Gitlab、Bitbucket 等平台的项目,这里我们主要提供 Netlify 来部署我们的网站,并且自动发布最新的网站更改,其次 Netlify 还提供免费的二级域名。

创建发布博客

创建 Hexo 博客项目

1
2
npm i -g hexo-cli # 安装hexo cli
hexo init project-name # 创建项目

创建 Github 仓库 push 代码

Github 就不多提了,push 更新到 GitHub 的仓库,让 Netlify 自动部署就行。

创建 Netlify 账户

  • 使用 GitHub 账号登录
  • Add a new site 然后选择 Import an existing project ,最后选择对应的 Github 仓库
  • 填写表单如下,然后点击Deploy Site
  • 设置域名,点击Add a custom domain to your site。根据提示在 DNS 平台设置 CNAME 的 DNS,然后点击Verify,基本两分钟内搞定
  • 使用 HTTPS,可以使用自定义的证书,也可以使用 Netlify 申请免费证书

大功告成 Demo

当使用 Github 将网站项目文件夹里的所有东西上传完毕之后,那么就可以打开 Netlify 给予它访问 Github 仓库的权限。
在此之后,这一切都是自动的:包括当修改了哪篇文章之后:只要 Github 上你网站的仓库发生了变化,Netlify 就会自动重新构建网页文件并且自动发布。

前言

我们都熟悉将 CSS 样式以 link 的形式引用到 HTML 文档<head>标签的方法,这只是我们写 CSS 的几种方法之一。但在一个单页面应用程序(SPA)中,比如在 React 项目中,它是什么样子的呢?有几种方法可以对 React 应用程序增加样式。有些与传统方式重叠,有些则没有那么多规则。

引入外部样式表

就像标题所说,React 可以引入样式文件。这个过程有点像 html 用 link 引入 CSS

  • 在项目目录创建创建新的 CSS 文件
  • 写 CSS 样式
  • 在 React 的文件头部 import CSS 文件,如下:
1
2
3
4
5
6
7
import { React } from 'react';
import './Components/css/App.css';

function App() {
return <div className="main"></div>;
}
export default App;

写内联样式

您可能经常听到内联样式对于可维护性和诸如此类的东西并不是那么好,但是在某些情况下内联样式是有意义的。在 React 中,可维护性不是什么大问题,因为 CSS 通常已经放在同一个文件中了。

这是 React 中一个超级简单的内联样式示例:

1
<div className="main" style={{color:"red"}}>

更好的方式是是先创建样式对象,然后放入 style 参数中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { React } from 'react';
function App() {
const styles = {
main: {
backgroundColor: '#f1f1f1',
width: '100%',
},
inputText: {
padding: '10px',
color: 'red',
},
};
return (
<div className="main" style={styles.main}>
<input type="text" style={styles.inputText}></input>
</div>
);
}
export default App;

CSS Module

CSS 模块具有局部作用域变量的优点,可以与 React 一起使用。它到底是什么呢?

CSS 模块的工作原理是将单个 CSS 文件编译成 CSS。CSS 输出是正常的全局 CSS,可以直接注入到浏览器中,也可以连接在一起并写入文件以供生产使用。数据用于将您在文件中使用的人类可读的名称映射到全局安全的输出 CSS。

简单地说,CSS Modules 允许我们在多个文件中使用相同的类名而不会发生冲突,因为每个类名都有一个唯一的 id 名。这在较大的应用程序中特别有用。每个类名的局部作用域都限定在它被导入的特定组件上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* styles.module.css */
.font {
color: #f00;
font-size: 20px;
}

import { React } from "react";
import styles from "./styles.module.css";
function App() {
return (
<h1 className={styles.heading}>Hello World</h1>
);
}
export default App;

styled-components

Have you used styled-components? It’s quite popular and allows you to build custom components using actual CSS in your JavaScript. A styled-component is basically a React component with — get ready for it — styles. Some of the features include unique class names, dynamic styling and better management of the CSS as each component has its own separate styles.

Install the styled-components npm package in the command line:
你使用过styled-components吗? 可以使用它在 JavaScript 中使用实际的 CSS 构建自定义组件。一个styled-components基本上是一个带有样式的 React 组件。其中的一些特性包括惟一的类名、动态样式和更好的 CSS 管理,因为每个组件都有自己独立的样式。

在命令行中安装styled-components的 npm 包:

1
npm install styled-components
1
2
3
4
5
6
7
8
9
10
11
12
import { React } from 'react';
import styled from 'styled-components';
function App() {
const Wrapper = styled.div`
width: 100%;
height: 100px;
background-color: red;
display: block;
`;
return <Wrapper />;
}
export default App;

条件样式

styled-components的优点之一是组件本身是具有函数功能的,因为你可以在 CSS 中使用 props。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { React, useState } from 'react';
import styled from 'styled-components';
function App() {
// display state
const [display, setDisplay] = useState(true);
return (
<>
<Wrapper $display={display} />
<button onClick={() => setDisplay(!display)}>Toggle</button>
</>
);
}
// the wrapper styled component
const Wrapper = styled.div`
width: 100%;
height: 100px;
background-color: red;
display: ${(props) => (props.$display ? 'block' : 'none')};
`;
export default App;

总结

我们研究了几种在React应用程序中编写样式的不同方法。并不是说哪一个比其他的好,因为每种方法的好坏取决于具体的情况。希望现在你已经很好地理解了它们,并知道在React样式工具中有找到合适的。

前言

首先,如果你不知道 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性能。事件委托可以显著的提高事件的处理速度,减少内存的占用。