antd 实现pdf 预览_react实现移动端PDF在线预览插件

本文介绍了如何在React移动端项目中利用antd和mozilla/pdf.js库实现PDF在线预览。通过创建PDF组件、Page组件和Viewer组件,实现了PDF的加载、渲染和页面切换。同时,注意在不同阶段调整meta标签以控制缩放行为。
摘要由CSDN通过智能技术生成

前端实现DPF在线预览的插件比较多,不过大多都不够成熟,用起来可能觉得没那么好用;选了一个个人觉得相对好用,适合我们现有框架的mozilla/pdf.js

头部引入mozilla/pdf.js的库

这个库目前没有用npm安装的,直接在头部引入线上的或者下载一个就可以用了

复制代码

封装一个PDF组件,直接复制粘贴这段代码就可以

class PDF extends React.Component {

constructor (props) {

super(props)

this.state = {

pdf: null,

scale: 1.2

}

}

getChildContext () {

return {

pdf: this.state.pdf,

scale: this.state.scale

}

}

componentDidMount () {

PDFJS.getDocument(this.props.src).then((pdf) => {

console.log(pdf)

this.setState({ pdf })

})

}

render () {

return (

{this.props.children}
)

}

}

PDF.propTypes = {

src: React.PropTypes.string.isRequired

}

PDF.childContextTypes = {

pdf: React.PropTypes.object,

scale: React.PropTypes.number

}

class Page extends React.Component {

constructor (props) {

super(props)

this.state = {

status: 'N/A',

page: null,

width: 0,

height: 0

}

}

shouldComponentUpdate (nextProps, nextState, nextContext) {

return this.context.pdf != nextContext.pdf || this.state.status !== nextState.status

}

componentDidUpdate (nextProps, nextState, nextContext) {

this._update(nextContext.pdf)

}

componentDidMount () {

this._update(this.context.pdf)

}

_update (pdf) {

if (pdf) {

this._loadPage(pdf)

} else {

this.setState({ status: 'loading' })

}

}

_loadPage (pdf) {

if (this.state.status === 'rendering' || this.state.page != null) return;

pdf.getPage(this.props.index).then(this._renderPage.bind(this))

this.setState({ status: 'rendering' })

}

_renderPage (page) {

console.log(page)

let { scale } = this.context

let viewport = page.getViewport(scale)

let { width, height } = viewport

let canvas = this.refs.canvas

let context = canvas.getContext('2d')

console.log(viewport.height, viewport.width)

canvas.width = width

canvas.height = height

page.render({

canvasContext: context,

viewport

})

this.setState({ status: 'rendered', page, width, height })

}

render () {

let { width, height, status } = this.state

return (

)

}

}

Page.propTypes = {

index: React.PropTypes.number.isRequired

}

Page.contextTypes = PDF.childContextTypes

class Viewer extends React.Component {

render () {

let { pdf } = this.context

let numPages = pdf ? pdf.pdfInfo.numPages : 0

let fingerprint = pdf ? pdf.pdfInfo.fingerprint : 'none'

let pages = Array.apply(null, { length: numPages })

.map((v, i) => ())

return (

{pages}

)

}

}

Viewer.contextTypes = PDF.childContextTypes

复制代码

最后一步就是调用这个PDF组件就可以了,这里需要改一下头部的meta[name="viewport"]的属性为可自由放大缩小,退出PDF页时需要恢复meta标签为不可手动缩放的

class previewPDF extends React.Component {

constructor (props) {

super (props);

}

// 初始化PDF组件时改变meta为可手动缩放

componentDidMount(){

document.querySelector('meta[name="viewport"]').setAttribute("content", "width=device-width,user-scalable=yes,initial-scale=0.5,maximum-scale=1.2,minimum-scale=0.1");

}

// 组件卸载时恢复meta

componentWillUnmount(){

document.querySelector('meta[name="viewport"]').setAttribute("content", "width=device-width,user-scalable=no,initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5");

window.location.reload();

}

render() {

let PDF_URL = getQueryString('pdf', this.props.location.search);

return (

);

}

}

复制代码

-------------------更新内容------------------

React.PropTypes的问题

由于React v15.5起,React.PropTypes已移至另一个包中。

React.PropTypes请改用prop-types库。

prop-types的使用如下:

import PropTypes from 'prop-types';

class Greeting extends React.Component {

render() {

return (

Hello, {this.props.name}

);

}

}

Greeting.propTypes = {

name: PropTypes.string

};

复制代码

更新后的PDF组件

import React, { Component } from 'react';

import PropTypes from 'prop-types';

export class PDF extends Component {

constructor (props) {

super(props)

this.state = {

pdf: null,

scale: 1.2

}

}

getChildContext () {

return {

pdf: this.state.pdf,

scale: this.state.scale

}

}

componentDidMount () {

PDFJS.getDocument(this.props.src).then((pdf) => {

console.log(pdf)

this.setState({ pdf })

})

}

render () {

return (

{this.props.children}
)

}

}

// PDF.propTypes = {

// src: PropTypes.string.isRequired

// }

PDF.childContextTypes = {

pdf: PropTypes.object,

scale: PropTypes.number

}

export class Page extends Component {

constructor (props) {

super(props)

this.state = {

status: 'N/A',

page: null,

width: 0,

height: 0

}

}

// shouldComponentUpdate (nextProps, nextState, nextContext) {

// return this.context.pdf != nextContext.pdf || this.state.status !== nextState.status

// }

// componentDidUpdate (nextProps, nextState, nextContext) {

// debugger

// this._update(nextContext.pdf)

// }

componentDidMount () {

this._update(this.context.pdf)

}

_update (pdf) {

if (pdf) {

this._loadPage(pdf)

} else {

this.setState({ status: 'loading' })

}

}

_loadPage (pdf) {

if (this.state.status === 'rendering' || this.state.page != null) return;

pdf.getPage(this.props.index).then(this._renderPage.bind(this))

this.setState({ status: 'rendering' })

}

_renderPage (page) {

let { scale } = this.context

let viewport = page.getViewport(scale)

let { width, height } = viewport

let canvas = this.refs.canvas

let context = canvas.getContext('2d')

canvas.width = width

canvas.height = height

page.render({

canvasContext: context,

viewport

})

this.setState({ status: 'rendered', page, width, height })

}

render () {

let { width, height, status } = this.state

return (

)

}

}

// Page.propTypes = {

// index: PropTypes.number.isRequired

// }

Page.contextTypes = PDF.childContextTypes

export class Viewer extends Component {

render () {

let { pdf } = this.context

let numPages = pdf ? pdf.pdfInfo.numPages : 0

let fingerprint = pdf ? pdf.pdfInfo.fingerprint : 'none'

let pages = Array.apply(null, { length: numPages })

.map((v, i) => ())

return (

{pages}

)

}

}

Viewer.contextTypes = PDF.childContextTypes

复制代码

实现动态生成Table组件的columns,可以使用React的状态管理来实现。具体步骤如下: 1. 定义一个state来保存columns数组。初始值可以为一个空数组。 ```javascript const [columns, setColumns] = useState([]); ``` 2. 在组件加载时,从数据源获取表头数据,并根据数据动态生成columns数组,然后将其保存到state中。 ```javascript useEffect(() => { // 获取表头数据 const headers = fetchDataFromAPI(); // 根据表头数据动态生成columns数组 const newColumns = headers.map((header) => ({ title: header.name, dataIndex: header.field, })); // 保存columns数组到state中 setColumns(newColumns); }, []); ``` 3. 在Table组件中使用动态生成的columns数组。 ```javascript <Table dataSource={data} columns={columns} /> ``` 完整代码如下: ```javascript import React, { useState, useEffect } from 'react'; import { Table } from 'antd'; function DynamicTable() { const [columns, setColumns] = useState([]); useEffect(() => { // 获取表头数据 const headers = fetchDataFromAPI(); // 根据表头数据动态生成columns数组 const newColumns = headers.map((header) => ({ title: header.name, dataIndex: header.field, })); // 保存columns数组到state中 setColumns(newColumns); }, []); const data = [ { key: '1', name: 'John Brown', age: 32, address: 'New York No. 1 Lake Park', }, { key: '2', name: 'Jim Green', age: 42, address: 'London No. 1 Lake Park', }, { key: '3', name: 'Joe Black', age: 32, address: 'Sidney No. 1 Lake Park', }, ]; return <Table dataSource={data} columns={columns} />; } export default DynamicTable; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值