图片占位符组件 Holder.js 的使用
目录
1. 引言
笔者在自学和实践全栈开发,在学到 react-bootstrap card 时看到了官方示例使用到了图片占位符组件 holder.js, 发现非常的巧妙和有趣,能够使得我们的前端开发更友好,于是跟着学做了一遍。在使用的过程中遇到了一些小坑,在解决了这些问题后觉得有必要记录下来, 以备下次快速查询使用,起到笔记备忘的作用,因为下次使用时一定会忘记而又得从头研究一遍。操作实践内容都是从生产级层面来考虑,不是玩具性代码。
此 Demo 属于 React 体系,技术栈为:
React.js + Next.js + App Router + TypeScript + Tailwind CSS + React-Bootstrap + PNPM
2. 准备条件
- 系统:笔者使用的是 macOS 系统,其它系统操作类似。
- 科学上网环境。如无可参考笔者的 科学上网之 Gost 方案 v2。
-
如果未安装则安装 Homebrew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
-
如果未安装则安装 Visual Studio Code:
brew install --cask visual-studio-code
配置 VS Code 以便之后从终端启动:
- 打开 VS Code。
- 打开命令面板 (
Cmd+Shift+P
) 并输入“shell command”以查找 Shell Command: Install ‘code’ command in PATH 命令。 - 重新启动终端以使新的
$PATH
值生效。您可以在任何文件夹中键入code .
来开始编辑该文件夹中的文件。
-
如果未安装则安装 Node.js:
brew install node
-
如果未安装则安装 PNPM:
npm install -g pnpm
-
如果未安装则安装 TypeScript:
npm install -g typescript
3. 操作步骤
- 打开 Terminal.app 终端或 iTerm2 等终端,并导航到项目想存放的目录。
-
创建项目:
可用自定义项目名替换下面的 react-bs-demo。
pn create react-bs-demo
-
导航到项目里:
cd react-bs-demo
-
安装依赖框架:
pn add react-bootstrap bootstrap sass holderjs
-
用 Visual Studio Code 打开:
code .
-
打开 layout.tsx 文件,删除
import "./globals.css";
,然后添加import "bootstrap/dist/css/bootstrap.min.css";
:// layout.tsx import type { Metadata } from "next"; import { Inter } from "next/font/google"; import "bootstrap/dist/css/bootstrap.min.css"; const inter = Inter({ subsets: ["latin"] }); export const metadata: Metadata = { title: "My Placeholder Demo of Image", description: "Generated by create next app", }; export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( <html lang="zh-CN"> <body className={inter.className}>{children}</body> </html> ); }
-
打开 page.tsx 文件,并替换为以下代码:
// page.tsx "use client"; import { useEffect } from "react"; import { Button, ButtonGroup, Card, Dropdown } from "react-bootstrap"; import { run as runHolder } from "holderjs/holder"; export default function Home() { useEffect(() => { runHolder(); }); const cardWidth = { width: "18rem" }; return ( <main className="p-5"> <Card style={cardWidth}> <Card.Img variant="top" data-src="holder.js/100px180?text=Placeholder of Image&theme=social" /> <Card.Body> <Card.Title>Card Title</Card.Title> <Card.Text> Some quick example text to build on the card title and make up the bulk of the card's content. </Card.Text> <Button variant="primary">Go somewhere</Button> </Card.Body> </Card> </main> ); }
Card.Img
的data-src
属性值就是图片占位符工具 holderjs 的配置部分,更多功能配置可见 深入了解 部分。 如果有正常正确的图片链接,便可以添加一个src
属性,把值放到里面,这样便简洁清晰互不影响,亦不会忘, 当没有图片或图片地址错误时便显示data-src
里的holderjs
生成的占位图片,当src
存在且指定的图片地址没问题时便使用真正的图片。即:<Card.Img variant="top" src="https://getbootstrap.com/docs/5.3/assets/brand/bootstrap-logo-shadow.png" data-src="holder.js/100px180?text=Placeholder of Image&theme=social" />
-
在终端中运行
pn dev --turbo
,然后在浏览器中打开 http://localhost:3000,即可得到封面图所示界面。 -
但是在代码头的导入语句处会出现红色波浪线, 鼠标移上去会出现类似警告提示(在底部的 PROBLEMS 面板中也会出现, 虽然不影响使用):
Could not find a declaration file for module 'holderjs/holder'. '/Users/myqs/Downloads/bs-react-demo/node_modules/.pnpm/holderjs@2.9.9/node_modules/holderjs/holder.js' implicitly has an 'any' type. Try `npm i --save-dev @types/holderjs` if it exists or add a new declaration (.d.ts) file containing `declare module 'holderjs/holder';`
按照提示即
npm i --save-dev @types/holderjs
尝试解决, 由于我使用的是 pnpm, 所以是pn i --save-dev @types/holderjs
。如果无效则继续后续步骤。- 在项目根目录下创建文件夹 types, 并在文件夹中创建 holderjs.d.ts 文件。
-
在 holderjs.d.ts 文件中写入如下代码:
declare module 'holderjs/holder' { export function run(options?: any): void; export default run; }
-
打开 tsconfig.json 文件, 在 compilerOptions 选项下找到 typeRoots (若没有则新增) 并添加
"./types", "./node_modules/@types"
这两项。整个文件似下:{ "compilerOptions": { "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true, "plugins": [ { "name": "next" } ], "paths": { "@/*": ["./src/*"] }, "typeRoots": ["./types", "./node_modules/@types"] }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "exclude": ["node_modules"] }
4. 深入了解
通过访问托管到 GitHub 的官方 holder.js 项目来获得更多功能使用说明。