新聞中心
前言
React-PDF 簡介
React PDF 是一個(gè)使用 React 創(chuàng)建 PDF 文件的工具,支持在瀏覽器、移動(dòng)設(shè)備和服務(wù)器上創(chuàng)建PDF文件。

成都創(chuàng)新互聯(lián)網(wǎng)站建設(shè)由有經(jīng)驗(yàn)的網(wǎng)站設(shè)計(jì)師、開發(fā)人員和項(xiàng)目經(jīng)理組成的專業(yè)建站團(tuán)隊(duì),負(fù)責(zé)網(wǎng)站視覺設(shè)計(jì)、用戶體驗(yàn)優(yōu)化、交互設(shè)計(jì)和前端開發(fā)等方面的工作,以確保網(wǎng)站外觀精美、網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)易于使用并且具有良好的響應(yīng)性。
可以用它們輕松地將內(nèi)容呈現(xiàn)到文檔中,我們可以使用 CSS 屬性進(jìn)行樣式設(shè)置,使用 flexbox 進(jìn)行布局,它支持渲染文本、圖像、 svg 等等,詳情可以參考官網(wǎng)
程序?qū)崿F(xiàn)
今天我將使用 React-pdf 和 next.js 來構(gòu)建一個(gè)在線簡歷生成器,先一起來看下效果
在線地址:https://cv.runjs.cool/
初始化項(xiàng)目
yarn create next-app --example with-ant-design next-resume
cd next-resume
yarn add @react-pdf/renderer
React-pdf 渲染需要一些額外的依賴項(xiàng)和 webpack5 配置。
yarn add process browserify-zlib stream-browserify util buffer assert
這一步驟是因?yàn)?React-pdf 構(gòu)建在 PDFKit 的基礎(chǔ)之上,在使用瀏覽器時(shí)需要使用兩個(gè) node.js API polyfill。而 webpack 5 不再包括自動(dòng)引入 nodejs polyfill ,我們必須選擇進(jìn)入所有我們想要的 polyfill。為了做到這一點(diǎn),我們必須為我們的項(xiàng)目添加一些依賴項(xiàng):
在根目錄下創(chuàng)建一個(gè) next.config.js
module.exports = {
reactStrictMode: true,
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
config.resolve.fallback = {
...config.resolve.fallback,
module: "empty",
dgram: "empty",
dns: "mock",
fs: "empty",
http2: "empty",
net: "empty",
tls: "empty",
child_process: "empty",
process: require.resolve("process/browser"),
zlib: require.resolve("browserify-zlib"),
stream: require.resolve("stream-browserify"),
util: require.resolve("util"),
buffer: require.resolve("buffer"),
asset: require.resolve("assert"),
};
config.plugins.push(
new webpack.ProvidePlugin({
Buffer: ["buffer", "Buffer"],
process: "process/browser",
})
);
return config;
},
};實(shí)現(xiàn)邏輯
新建在 App.js 將用戶輸入實(shí)時(shí)綁定到 state 中,然后時(shí)時(shí)渲染預(yù)覽頁面
import Preview from './component/Preview'
import React, { useState } from 'react'
function App() {
const [profile, setProfile] = useState({
name: "狂奔滴小馬",
about: "分享 Javascript 熱門\n框架,探索 web 極致\n優(yōu)化體驗(yàn)。",
email: "[email protected]",
avatar:"https://p6-passport.byteacctimg.com/img/user-avatar/585e1491713363bc8f67d06c485e8260~300x300.image",
})
const handleChange = (name, value) => {
setProfile({ ...profile, [name]: value })
}
return (
style={{
width: '100%',
height: '100vh',
display: 'flex',
}}
>
name='name'
defaultValue={profile.name}
onChange={(e) => {
handleChange(e.target.name, e.target.value)
}}
/>
name='avatar'
defaultValue={profile.avatar}
onChange={(e) => {
handleChange(e.target.name, e.target.value)
}}
/>
name='about'
defaultValue={profile.about}
onChange={(e) => {
handleChange(e.target.name, e.target.value)
}}
/>
name='email'
defaultValue={profile.email}
onChange={(e) => {
handleChange(e.target.name, e.target.value)
}}
/>
)
}
export default App
Preview.js 是頁面的右側(cè)部分,并嵌入我們將要?jiǎng)?chuàng)建的PDF文檔。
另外我們還有 PDFDownloadLink,它可以用來下載 pdf 文件。
import React from 'react'
import { Document, Page, PDFViewer, PDFDownloadLink } from '@react-pdf/renderer'
import LeftSection from './LeftSection'
import RightSection from './RightSection'
import styles from '../styles'
const Preview = ({ profile }) => {
return (
showToolbar={false}
style={{
width: '100%',
height: '95%',
}}
>
document={}
fileName='somename.pdf'
>
{({ loading }) => (loading ? 'Loading document...' : 'Download now!')}
)
}
// 創(chuàng)建文檔組件
const Template = ({ profile }) => {
return (
)
}
export default Preview
我們可以直接設(shè)置 PDF 為 A4 紙尺寸。
import { StyleSheet } from '@react-pdf/renderer'
export default StyleSheet.create({
page: {
display: 'flex',
flexDirection: 'row',
},
section_right: {
margin: 10,
padding: 10,
paddingTop: 20,
width: '75%',
},
section_left: {
width: '25%',
height: '100%',
backgroundColor: '#084c41',
},
profile_container: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
marginTop: '20',
marginBottom: '20px',
height: '150',
},
name_text: {
paddingTop: '10px',
paddingBottom: '5px',
fontSize: '14px',
fontWeight: '900',
color: 'white',
}
})通過 StyleSheet.create 創(chuàng)建 JavaScript 樣式表
LeftSection.js 代碼展示
import { View, Text, Image, } from '@react-pdf/renderer'
import styles from '../styles'
export const Profile = ({ profile }) => {
return (
style={{
justifyContent: 'center',
}}
>
{profile.name}
{profile.about}
)
}
const LeftSection = ({ profile }) => {
return (
)
}
export default LeftSection
也可以直接寫內(nèi)聯(lián)樣式控制 PDF 內(nèi)的樣式。但是不支持 float 浮動(dòng)屬性,具體大家可以看官網(wǎng)
遇到問題
本以為這樣就可以完成,沒想到還有一個(gè)巨坑,不支持中文,中文在 pdf 中會顯示亂碼, 通過 issue 找到了答案
import { StyleSheet, Font } from "@react-pdf/renderer";
Font.register({
family: "Alibaba-PuHuiTi-Light",
src: "/Alibaba-PuHuiTi-Light.ttf",
});
export const styles = StyleSheet.create({
page: {
fontFamily: "Alibaba-PuHuiTi-Light",
flexDirection: "row",
display: "flex",
...
},
})
然后就可以顯示中文字體了。這邊我下載了阿里巴巴普惠體。
重構(gòu)
以上是一個(gè)簡易版的實(shí)現(xiàn),通過上面的代碼示例,你應(yīng)該至少看懂了原理,為了讓整個(gè)簡歷數(shù)據(jù)豐富,我使用了antd 來實(shí)現(xiàn)豐富的表單列表。使用 react context 來管理我們的數(shù)據(jù)。下面展示下目錄結(jié)構(gòu):
├── components
│ ├── app
│ │ └── index.tsx
│ ├── editor
│ │ ├── FormCreator.tsx
│ │ ├── conifg.js
│ │ └── index.tsx
│ ├── icon
│ │ └── index.tsx
│ └── preview
│ ├── avatar.tsx
│ ├── awardList.tsx
│ ├── educationList.tsx
│ ├── index.tsx
│ ├── profile.tsx
│ ├── projectList.tsx
│ ├── skillList.tsx
│ ├── style.ts
│ └── workExpList.tsx
├── context
│ └── resumeContext.ts
├── hooks
│ └── useResume
│ └── index.ts
├── pages
│ ├── _app.tsx
│ ├── api
│ │ └── hello.js
│ └── index.tsx
└── styles
├── logo.png
└── globals.css
部署
最后我使用 vercel 部署并且綁定自定義域名
體驗(yàn)地址 https://cv.runjs.cool/
以上就是本文全部內(nèi)容,希望這篇文章對大家有所幫助,也可以參考我往期的文章或者在評論區(qū)交流你的想法和心得,歡迎一起探索前端。
參考資料
[1]官網(wǎng): https://react-pdf.org/
[2]issue: https://github.com/diegomura/react-pdf/issues/267
[3]dev.to: https://dev.to/przpiw/react-pdf-rendering-4g7b
[4]devtool: https://cv.devtool.tech/app
網(wǎng)頁名稱:使用 React-Pdf 打造在線簡歷生成器
URL鏈接:http://m.fisionsoft.com.cn/article/cddihio.html


咨詢
建站咨詢
