分类目录归档:技术

6ee6df690137fd06bc6166adb63caca1

使用小程序的 Canvas 2D 提取特定点的颜色

在小程序当中,我们可以通过在 Canvas 画布上绑定 Tap 事件,来获取到用户点击行为,当我们获取到点击行为对应的坐标时,就可以读取到对应位置的颜色。并根据我们的需求,将颜色转换成我们想要的 RBG 色值。

这就是我们常见的各种取色软件的最常见的实现方式。当然,落实到实际开发过程中,大家或多或少会有所不同(涉及到调色。我们拍照的颜色和我们所看到的颜色并不完全一样。不同的相机调色会有所不同。类似的,我们需要加入相应的逆向算法排除对应的相机自身调教的影响)。

在小程序的场景中具体实现方式可参考如下代码:

页面布局

<view>
  <view><button bindtap="chooseImage">1. 选择图片</button></view>
  <view><canvas id="myCanvas" bindtap="onCanvasTap" type="2d" style="background-color:gray;width: 100%;margin-top: 100rpx;"></canvas></view>
</view>
Code language: HTML, XML (xml)

对应的 JS

和在 在小程序中使用的 Canvas 2D API 绘制本地图片 一样,你需要提取到 Canvas 的 Ctx ,用于执行操作。当你通过 bindTap 拿到你的点击点相对于 Canvas 的 左上角的坐标后,就可以使用 <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/getImageData">getImageData</a> 来提取具体范围的数据。因为我的目的是提取某个点的颜色,因此我的第三、第四参数都是 1 (取一个像素点的宽度和高度)。

提取出图片数据后,你可以在 data 当中提取一个 4 个元素的数组,按照顺序,分别是 RGBA 的四个值,你可以根据需要使用这个数据(比如放大展示在界面上)。

Page({
  data: {
    color: ''
  },
  onCanvasTap(e) {
    const query = wx.createSelectorQuery()
    query.select('#myCanvas')
      .fields({
        node: true,
        size: true
      })
      .exec((res) => {
        const canvas = res[0].node
        const ctx = canvas.getContext('2d')
        const data = ctx.getImageData(e.detail.x, e.detail.y, 1, 1).data;
        const [red,gree,blue,alpha] = data;
      })
  },
});
Code language: JavaScript (javascript)
6ee6df690137fd06bc6166adb63caca1

在小程序中使用的 Canvas 2D API 绘制本地图片

小程序自 2.9.0 起,不再推荐使用其自己封装的 Canvas Context,而是更加推荐大家使用标准的 Canvas 2D API 来完成相关操作。因此,对于开发者来说,需要将过去的 Canvas API 调整为新的标准的 API 。

刚好我最近也实现了类似的功能,将这部分逻辑分享给大家。

页面布局

<view>
  <view><button bindtap="chooseImage">选择图片</button></view>
  <view><canvas id="myCanvas"  type="2d" style="background-color:gray;width: 100%;margin-top: 100rpx;"></canvas></view>
</view>
Code language: HTML, XML (xml)

页面逻辑

Page({
   chooseImage(){
    // 创建一个 Query
    const query = wx.createSelectorQuery()
    // 选中 Canvas 对象
    query.select('#myCanvas')
      .fields({
        node: true,
        size: true // 提取 Node 信息
      })
      .exec((res) => {

        // 获取到 Canvas Node
        const canvas = res[0].node

        // 获取到 Context
        const ctx = canvas.getContext('2d')
        wx.chooseMedia({
          count: 1,
          success: function (res) {
            // 提取图片的基本信息
            wx.getImageInfo({
              src: res.tempFiles[0].tempFilePath,
              success: imgInfo => {
                // 使用 canvas.createImage 来创建一个图片
                const img = canvas.createImage()
                img.src = imgInfo.path
                img.onload = () => {
                  // 将图片画在画布上
                  ctx.drawImage(img, 0, 0, imgInfo.width, imgInfo.height)
                }
              }
            })
          }
        })
      })
   }
})
Code language: JavaScript (javascript)

参考文档

a computer screen with a bunch of text on it

WordPress 出现 RedisException: OOM command not allowed when used memory > maxmemory 的报错怎么处理?

早晨起来,想登录博客,记录下自己的灵感,突然发现死活登录不上 WordPress 后台。

登录到 VPS 后台,发现没有出现我之前常出的问题 — 硬盘满了。于是再次回到网页端登录,仔细研究后发现,我的登录应该是成功的,但登录完成后,又重新跳转回来,根据这个情况,我猜测可能是登录态出现了问题。

于是尝试切换到 Safari 、Chrome 的无痕模式登录,依然没有解决问题。因此可以排除掉客户端的问题导致的。

找到问题

接下来就是查看服务端问题。登录到服务器上,找到 WordPress 的日志,查看最近的几条日志,突然在众多 Notice 当中,看到了一个 Exception:

RedisException: OOM command not allowed when used memory > 'maxmemory'
Code language: JavaScript (javascript)

看到这个报错,突然明白了问题在哪了。

我的 WordPress 使用 Redis 作为缓存,而我过去一直配置的缓存空间是 128M,看报错,显然是因为 Redis 使用的内存空间大于 128M,而我过去没有配置逐出机制(默认是 noeviction),导致直接 OOM 爆掉了。

而我的登录态也使用了 Redis,没办法在缓存当中塞入新的 Key,自然登录也就失败了。

解决问题

找到问题之后,下一步便是解决问题。

解决问题并不复杂,为 Redis 调整内存空间大小,并配置逐出机制,就可以解决这个问题。

maxmemory 221000000
maxmemory-policy allkeys-lru

将 Redis 逐出机制设置为 allkeys-lru ,并将内存设置为 200M 后,重启 Redis ,果然我的 WordPress 可以正常登录了。

参考

allkeys-lru 表示对移除最近使用最少的 (least recently used)Key。

更多算法可以参考 Key Evicution

telegram

为你的 WordPress 站点配置 Telegram Instant View

Telegram 内置了一个非常好用的阅读功能 —— Instant View。Instant View 可以实现在 Telegram 内部重新对网站内容进行排版,从而为读者提供更好的阅读体验。

作为一个网站主,如果你希望对你的网站提供相应的支持,则可以自行在 Instant View 的网站添加你自己的网站进行适配。

为 WordPress 添加 Instant View 适配

访问 Instant View 官网,并使用你自己的 Telegram 账号登录

d2b5ca33bd970f64a6301fa75ae2eb22 8
Instant View 官网

登录成功后,点击右侧的 My Templates,进入到 Templates 管理页面。

d2b5ca33bd970f64a6301fa75ae2eb22 9

并在 Templates 管理页面中间的输入框中输入你网站任一文章的地址,并回车,你会自动进入到规则的适配页面。

d2b5ca33bd970f64a6301fa75ae2eb22 10
规则适配页面

随后,在页面中输入你的站点的规则,这里我们可以使用其他开发者写好的规则。将规则粘贴在页面中

# Use Instant View version 2.0
~version: "2.0"

# Use this template only blog article pages
?exists: /html/head/meta[@property="article:published_time"]

# Get article text in <article> 
body:     //article

# Get title from <h1>

title:    $body//h1[1]
subtitle: $title/next-sibling::h2
author_url: //span[has-class("author")]//@href

# Get article cover image
cover: //img[has-class("wp-post-image")]

# Convert all iframe elements to inline element
@inline: $body//iframe[starts-with(@src, "/media/")]

# Remote header and footer
@remove: //article/header
@remove: //article/footer

# Replace p to figure
@replace_tag(<figure>): $body//p[.//img]

# Youtube Embedded Fix
@replace_tag(<figure>): $body//p[.//iframe]
Code language: PHP (php)

粘贴并保存后,会自动在最右侧页面生成预览的效果。

d2b5ca33bd970f64a6301fa75ae2eb22 11
加入规则适配后的效果

当你的规则适配效果无误后,接下来只需要点击右上叫的 Mark as Checked ,来标记该页面已经检查完车。

d2b5ca33bd970f64a6301fa75ae2eb22 12
标记为检查成功

测试完成第一个后, 接下来你只需要在你的博客当中挑选出 10 篇文章,进行文章的验证即可。

d2b5ca33bd970f64a6301fa75ae2eb22 4
验证至少 10 个页面才行

根据 Telegram Instant View 的规则,你需要验证满 10 篇文章,才能提交你的模板给官方人员审核。

d2b5ca33bd970f64a6301fa75ae2eb22 5

提交后,你会见到这样的提示,接下来只需要等待你的模板通过测试即可。

d2b5ca33bd970f64a6301fa75ae2eb22 6
提交成功

预览效果

在审核期间,你可以在编辑器页面右上角点击「View in Telegram」来查看预览的效果。包括你也可以复制里面的 rhash 的值,使用这个值来生成 Instant View 的链接分享给别人。不过,最方便的当然还是等官方审核通过以后再用。

d2b5ca33bd970f64a6301fa75ae2eb22 13
预览效果。

总结

Telegram Instant View 的开发不困难,掌握了一定的 HTML 、XPath 的基础,就可以开发完成,简单的几步,就可以让你的网站在 Telegram 当中拥有一个不错的预览效果,这个时间值得去花。

text

为你的服务器配上自定义的登录界面

我自己在服务器上使用的是 Ubuntu 20.04,每次在登录时,Ubuntu 都会展示一系列的信息,冗余且在多个服务器上看不出差异,并不能非常友好的提醒我这个是哪个服务器。

d2b5ca33bd970f64a6301fa75ae2eb22 25

于是,我决定对其进行自定义,改成我自己喜欢的样子。

d2b5ca33bd970f64a6301fa75ae2eb22 29

1. 分析现有的 Message 格式

想要修改,就一下先分析一下组成结构。我截图所示的输出可以分为三个部分:header、motd 和 last login message

而我主要不满的是 header 和 motd 的部分,对于 last login message,我虽然觉得有些多余,但在很多场景下,确实可以用于提醒。所以我就不隐藏了。不过,如果你希望隐藏 last login 的话,可以在当前用户的根目录下创建一个 .hushlogin 文件来关闭 last login message

touch ~/.hushlogin

2. 修改 motd 和 header

修改 motd

motd 的全称是 Message of Today,他的内容被存放在 /etc/motd 当中,想要修改 Motd 的文字,只需要直接修改 /etc/motd 文件的内容即可。不过需要注意的是,motd 文件不支持做格式化,只支持展示默认的文本。因此,你可以通过在其中加入空行来引起注意。

l9p67

修改 header

Header 部分存放在 /etc/update-motd.d/ 目录中,你可以通过修改这个文件夹下的文件来实现不同样式的 motd 风格。其中文件名格式为 优先级-文件名的方式进行组织,你可以根据自己的需要,创建适当优先级的文件。

2czq5

比如,00-header 文件的源码如下

#!/bin/sh
#
#    00-header - create the header of the MOTD
#    Copyright (C) 2009-2010 Canonical Ltd.
#
#    Authors: Dustin Kirkland <kirkland@canonical.com>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with this program; if not, write to the Free Software Foundation, Inc.,
#    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

[ -r /etc/lsb-release ] && . /etc/lsb-release

if [ -z "$DISTRIB_DESCRIPTION" ] && [ -x /usr/bin/lsb_release ]; then
	# Fall back to using the very slow lsb_release utility
	DISTRIB_DESCRIPTION=$(lsb_release -s -d)
fi

printf "Welcome to %s (%s %s %s)\n" "$DISTRIB_DESCRIPTION" "$(uname -o)" "$(uname -r)" "$(uname -m)"
Code language: PHP (php)

其中有价值的代码主要就是最后几行的输出。

类似的, 10-help-text 的代码则输出了文字。

#!/bin/sh
#
#    10-help-text - print the help text associated with the distro
#    Copyright (C) 2009-2010 Canonical Ltd.
#
#    Authors: Dustin Kirkland <kirkland@canonical.com>,
#             Brian Murray <brian@canonical.com>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with this program; if not, write to the Free Software Foundation, Inc.,
#    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

printf "\n"
printf " * Documentation:  https://help.ubuntu.com\n"
printf " * Management:     https://landscape.canonical.com\n"
printf " * Support:        https://ubuntu.com/advantage\n"
Code language: PHP (php)

而我们自己如果想要控制,可以自己写一个文件,比如叫 01-custom ,在其中加入如下代码(这段代码可以生成一段黑底红字的输出,用于提醒我自己这是生产环境服务器),并执行 chmod +x /etc/update-motd.d/01-custom 来设置可执行权限。

#!/bin/bash
printf "\u1b[31mwelcome to ixiqin.com production server\n"
Code language: JavaScript (javascript)

这里需要注意的是,/etc/update-motd.d 目录下的文件本质上是一个可执行文件,你可以使用 bash / dash 等任何 Shell 来实现,也可以考虑使用 Node.js、Python 之类的脚本来实现。这样就不用像我一样,使用 Termial Color Code 来实现颜色的变化。

执行完成后的结果如下

6wek6

根据需要自定义

当你找到了具体的文件的位置和配置的方式,就可以根据自己的需要来调整 /etc/motd/etc/update-motd.d 当中文件的内容,来达到你想要的效果了。

d2b5ca33bd970f64a6301fa75ae2eb22 28

这样,就完成了对于 Shell 的登录界面的改造工作了。

computer screen displaying website home page

在 Next.js 中直接引入 SVG

随着 SVG 的兴起,过去使用雪碧图、IconFont 作为界面中图标用法已经过时。大家会更倾向于加载更加简单、空间占用更小、编写更容易的 SVG 作为图标的解决方案。

而 Next.js 同样对于 SVG 提供了支持。

最简单的加载方式 —— URL 加载

如果不希望对应用程序做任何的改进,一个最简单的方式是直接使用路径进行加载。只需要使用一个 img 标签,并设定 src 为 svg 文件的路径就可以了。

<img src="/logo.svg" alt="Logo SVG" />
Code language: HTML, XML (xml)

不过,使用 URL 来加载的问题是,当你的文件夹路径和结构比较复杂的时候,你需要使用一个较长的路径来加载 SVG,比较麻烦。

当然, 你也可以简单的优化这个方案 —— 比如自行封装一个 svg component,支持传入文件名 & alt 文字和其他参数。这样在调用的时候只需要输入文件名即可。

最舒服的加载方式 —— 编程加载

在 Next.js 当中,如果你希望更加舒服的引入 SVG,那比较好的方案是使用 import 标签来进行引入。不过,由于 SVG 本身并不是一个标准的 React 组件,你需要在 Next.js 上安装插件来支持对 SVG 的解析。

加入对 SVG 的解析需要安装 @svgr/webpack 插件。执行如下命令安装插件。

# yarn
yarn add @svgr/webpack
# npm
npm install --save @svgr/webpack
Code language: PHP (php)

安装完成后,修改 next.config.js添加相关的解析规则。

module.exports = {
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/,
      use: ["@svgr/webpack"]
    }); // 针对 SVG 的处理规则

    return config;
  }
};
Code language: JavaScript (javascript)

修改后保存,便可以直接使用 import 语法来处理

import Logo from "../assets/logo.svg";


// usage
<Logo />
Code language: JavaScript (javascript)

这样,你就可以直接将 SVG 作为一个 Component 引入,并使用你熟悉的 React Componet Props 来修改这个 Component 的各项属性。

总结

在这篇文章中,分享了两种在 Next.js 的方法,你可以根据自己的实际情况来决定选择具体使用什么样的方式来引入 SVG。

black smartphone

使用 Proxy.py 自建 HTTP Proxy

如果你需要对一个集群进行开发,且开发过程中需要访问内网,一个比较常见的方式是建立虚拟专有网。但倘如你不愿建立虚拟专有网,那么一个比较简单的方式是建立一层 HTTP Proxy 来访问内网当中的数据,你只需要在某一个节点上设定 HTTP Proxy,并在你自己的电脑上配置 HTTP Proxy ,就可以完成使用对应的节点来访问具体的网页,解决 HTTP 访问的问题。

原理

HTTP Proxy Servr 的原理并不复杂,就是一个标准的正向代理。你只要能搭建这样的一个服务即可。

e6c9d24ely1h341f4087mj21t90g2755

实际操作逻辑

以下文章以 Debian GNU/Linux 10 为例

1. 在你的节点上安装 Python3 & pip 3

Python3 是运行 Proxy.py 的运行环境,而 pip3 则是安装 Proxy.py 的工具。执行如下命令来安装。

apt install python3 python3-pip

2. 安装 Proxy.py

这里我们不使用 Virtual Env 来安装,主要是方便后续加入 Systemd 来进行控制。如果你习惯使用 Supervisord 来控制的话,就可以使用 Virtual Env 来安装 Proxy.py。执行如下命令

pip3 install proxy.py
Code language: CSS (css)

3. 启动 Proxy 进行测试

在你的节点上执行如下命令来启动一个测试服务器。

proxy --hostname 0.0.0.0 
Code language: CSS (css)

如果你需要监听某一个特定的 IP, 则将 0.0.0.0 修改为你具体的 IP。

配置后,你可以看到如下的输出,则说明已经成功启动了 Proxy 服务器。

启动完成后,你就可以在本地测试访问如下命令来进行测试。

curl -x [服务器IP]:8899  http://httpbin.org/get
Code language: JavaScript (javascript)

当你看到如下输出时,确认返回值当中的 origin 是否是你的节点 IP,如果是你的节点 IP 则说明你的 HTTP Proxy 已经配置成功了。后续你就可以通过这个 HTTP Proxy 来进行访问了。

e6c9d24ely1h341n60ii2j21b40cuta8

测试完成后,你可以执行 Ctrl + C 来关闭当前的 Proxy Server。

4. 配置 Basic Auth Authentication

上面配置好了 HTTP Proxy Server,但一个问题是这个 Server 没有安全验证,随时会被别人所利用。所以我们需要配置一些基本的安全配置,来解决这个问题。

在你的 Proxy.py 当中加入 –basic-auth 选项,则可以实现加入基本的鉴权。其中,用户密码用英文冒号隔开。比如我需要创建一个用户名是 admin ,密码也是 admin 的proxy ,就可以执行如下命令。

proxy --hostname 0.0.0.0 --basic-auth admin:admin
Code language: CSS (css)

5. 配置开机自启动

现在 Auth 也有了,但是我们不能总是开着 Terminal 来运行我们的服务,所以一个好的办法是为其加入 Systemd ,这样我们就可以使用系统自带的能力来完成 Proxy 的自启动了。

执行 systemctl edit --force --full proxy.service 来创建一个新的 Systemd 服务,并在其中加入如下代码并保存。

[Unit]
Description=Proxy Service
Wants=network.target
After=network.target

[Service]
ExecStartPre=/bin/sleep 10
ExecStart=proxy --hostname 0.0.0.0 --basic-auth admin:admin
Restart=always

[Install]
WantedBy=multi-user.target
Code language: JavaScript (javascript)

保存完成后,执行 systemctl enable proxy.service 配置该服务器的开机自启动 & systemctl start proxy.service ,即可实现 Proxy 服务的开机自启动,并在当前启动该服务。

总结

有了 HTTP Proxy ,你能以一个更加简单的方式来访问内网当中的服务器。你只需要控制 Proxy 节点的可访问权限,就能很好的处理内网数据的安全问题。

silver mercedes benz emblem on blue surface

从企业视角,为什么要选择 WordPress?

WordPress 在国内日渐式微,从过去的全民博客用 WordPress, 到后来的很少人会使用 WordPress 做博客,再到现在只有一小撮人还在使用 WordPress,伴随着 PHP 的衰落和 Golang 等新语言的兴起,WordPress 不再是国人的选择。过去曾经有一段时间,大家很喜欢用 WordPress 做电子商城,不过随着时间的流逝和国内外电商贸易环境差异的变化,使用 WordPress 开发电子商城也不再是一个选择。如今的企业,不再愿意选择 WordPress 来完成自己的业务。

不过,从我自己的视角来看,我们看待任何一个工具的时候,不能看他是否还流行,而是要看他是否还能解决我们所面临的问题。

WordPress 的优势是什么?

WordPress 最大的优势主要是三点:

  1. 插件市场足够丰富带来的更少的开发工作量:但凡提到 WordPress ,你就不能不提 WordPress 的插件市场。WordPress 海量的插件市场可以帮助你更好的完成你的工作。对于一些传统模式下需要自己开发的功能,你可以选择直接安装 WordPress 来完成工作。
  2. 服务端渲染带来的 SEO 友好:现代 SPA 也有服务端渲染的能力,不过对于开发者来说,则需要单独假设一套服务端渲染的服务来完成这部分工作。或者提前预生成所有的页面。对于页面较小的站点,预生成比较靠谱。但对于数据量极大的站点,预生成也是一个较为痛苦的过程。WordPress 因为更加的传统,所以一直采用的是服务端渲染的模式。服务端渲染在针对 SEO 进行优化时,可以获得更好的优化能力(毕竟有些时候 Spider 不一定会等你的页面在前端渲染完成)。
  3. 极强的编辑性带来的人力释放:WordPress 不仅仅是我们看到的给用户的这一套 UI,还包含了一个强大的用户后台。强大体现在 Editor (Gutenberg)、全站编辑(WordPress 5.9 开始提供的新能力)。这些能力可以让 WordPress 从一个只能用固定模板的网站,变成了提供了一定的自由度,可以通过拖拽来生成一个页面的能力。对于一些比较极致追求拖拽的人,还会使用 Elementor (不过不太好做性能优化,如非必要,不上 Elementor)。这个能力带来的时候可以释放开发团队的人力,在构建好最基础的 Block 之后,交由运营人员来完成后续的管理和维护。

WordPress 的劣势是什么?

但同样的,没有什么东西是只有好处没有坏处的, WordPress 的坏处同样明显。

  1. 使用 PHP 编写,国内维护人员难招:WordPress 所依赖的 PHP 生态式微,则相应的,从事 WordPress 开发的人也渐渐变得更少。对于企业来说,难以找到合适的人是一个很大的问题。
  2. 目标太大,容易被安全攻击:WordPress 作为全球使用量排行第一的 CMS(内容管理系统),盯着它的黑客也多。虽然对于 WordPress 本体的安全攻击很快就会被修复。但针对普通插件的攻击则不那么容易防范。如果选择不当,很有可能把自己变成黑客的肉鸡。

总结

技术领域没有银弹。WordPress 同样也不是那个银弹。在合适的场景下, WordPress 便能放大自己的价值。而如果不合适,同样也无法放大 WordPress 的存在价值。

programming language

记录一个令人血压飙升的前端项目

最近在看一个前端项目,里面出现了一些令人血压暴涨的骚操作。虽然可以用,但对我来说,确实是让我看到血压飙升。

1. 尽可能使用常规的指标

项目的诉求是实现页面的自适应化,在不同尺寸的屏幕上尽可能保持一致的显示。

为了实现这个诉求,我给他们的建议是使用 Bootstrap 之类的框架,在不同的屏幕上尽可能保持一致。使用 Bootstrap 之类的框架来完成。

最后研发团队选择采用了一个有用,但我看起来非常头疼的方法 —— 根据屏幕宽度计算 rem。通过这样的方式,实现了在不同的屏幕宽度下,都可以和设计稿的尺寸一比一。

但这样带来的问题是,rem 计算出的结果也是一个非常的大的值(当然也可以非常小),但依然不是一个常规的结果,需要你常常使用诸如 0.03 这样的数值来指定宽度和高度。

d2b5ca33bd970f64a6301fa75ae2eb22 38

我觉得,这样的写法并不是说不行,只是这样的写法其实会降低整个项目的可维护性。

2. 文件放置符合规范

其次,这个项目中还出现了一个问题是 —— 文件到处乱丢。在一些项目中,大家往往会有一些明确的文件路径的规范,比如样式文件应该放在哪里。在这个项目中,就出现了样式乱丢的情况。

d2b5ca33bd970f64a6301fa75ae2eb22 39
和 Component 放在一起
d2b5ca33bd970f64a6301fa75ae2eb22 40
符合规范统一放在 scss 文件中

这样的混乱的写法则会导致在实际开发的时候,如果想要调整样式,可能会出现调试失效,修改起来较为混乱的问题。

3. 一个项目中混用多个不同的尺寸单位

d2b5ca33bd970f64a6301fa75ae2eb22 41
另外一个文件采用 px 作为单位

刚刚有用 rem 的单位,另外就有一个文件采用的是 px 为单位,我非常担心在不同尺寸屏幕下出现的错位问题。

4. 放弃 Bootstrap 的样式类,转而改用手动撰写每一行样式

d2b5ca33bd970f64a6301fa75ae2eb22 42
其实完全可以用 position-absolute d-flex 等方法来覆盖

总结

这个项目从我目前的视角来看,依然还有很大的改进空间。且留下了不少的坑。在我看来,长期来看,这些代码将会留下不可维护的问题。希望他们后续慢慢修改和调整吧。唉。

programming language

在 WordPress 中实现同一个 CSS 类在不同页面展示不同的效果

在使用 WordPress 开发时,某些时候你会遇到在同一个类在不同页面的时候,希望有不同表现的诉求。在这种情况下,一个比较简单 or 比较 Tricky 的技巧是通过 Body 层的类选择器来实现。

在 WordPress 进行渲染时,会自动在页面的 <body> 上加入 postid-[id] 的类,对比本文就是 postid-5888

d2b5ca33bd970f64a6301fa75ae2eb22 29
比如本文的 class

类似的,如果是一个 Page,也会生成 page-id-[id] 的类。

d2b5ca33bd970f64a6301fa75ae2eb22 30
页面生成的类是 page-id-[id],和 post 规则不完全相同

因此,如果你需要某个页面的元素样式和其他页面元素样式不同,但页面结构保持一致,一个比较好的方式是通过这些页面类选择器来实现。以你要自定义 btn 样式为例。则可以这样实现:

// 标准页面的样式
.btn{
   // your styles
}

// 在文章 ID 为 5888 的文章上的样式
.postid-5888 .btn{
  // your styles
}
// 在页面 ID 为 84 的文章上的样式
.page-id-84 .btn{
  // your styles
}

Code language: JavaScript (javascript)

总结

借助上面的方式可以实现同一个类在不同的页面展示不同的样式。但我个人觉得,这样的实现方式可能对于 Debug 不太方便,尽可能少用。但如果你需要用的话,那一定要注意好组织代码,避免后续维护成本提升。

此外,除了通过修改 style.css 来实现,你可以考虑将 Page 单独的样式梳理在一个 page.css 中进行维护,从而降低维护难度和成本。
WordPress 当中也有一些插件来实现某个页面自定义的 CSS 能力,将这些样式放在插件中来实现也是一个不错的选择:Post/Page specific custom CSS

Reference