## 前言
print作為瀏覽已經比較成熟的技術可以經常被用來打印頁面的部分內容,我們可以在mdn上查看到mdn相關的簡單介紹。
- [window.print api介紹](https://developer.mozilla.org/en-US/docs/Web/API/Window/print)
- [caniuse print:包括print的事件,分頁,媒體查詢等兼容性部分](https://caniuse.com/#search=print)
- [https://github.com/DoersGuild/jQuery.print](https://github.com/DoersGuild/jQuery.print)
備注:juqery的print除了基本的打印之外,還可以控制一些基本的樣式,標題,頁眉頁腳的設置等。
## 需求
本文主要介紹的不是以上的基本點,而是table在打印的時候,會因為一頁無法承載而導致分頁,然而我們并不知道分頁之后的效果,當我們點擊預覽的時候才發現,原來一個整體的表格被分為了兩個部分,而且還是同一行的被分割壞了。
那么產品無疑是希望體驗升級的:
- 在頁面查看時直接顯示打印之后的效果,對于打印預覽是有心里預期的,可以直接展示出什么位置會分頁。所以我在代碼設計上,直接為每個分頁的部分直接變為新分割一個表格,然后通過頁面的margin間距,在展示時就有分頁的預期效果。
```
.m-print-table{
&:not(:first-child){
margin-top:10px
}
}
```
- 將print對于表格的分頁進行代碼設計,通過代碼計算出當前頁的空間是否還能放下當前行,如果可以那么顯示并循環;如果不可以,計算本行內容的大小,進行計算分割出還可以放下幾行內容,剩下的內容放到下一頁。
## 常識
### 展示高度
頁面的展示高度一般設置為950
### ui頁面 && 打印預覽
ui頁面的顯示與打印預覽的部分有較大的差別,并不是完全打印ui頁面的效果。
- 一般情況下,每行所承載的數據量和ui頁面是不同的。
- 一般情況下打印很多情況下需要分頁,而ui上其實數據多頁面也是連在一起的。
## 代碼的設計原則
### 原本的頁面模板
準備好進行按照預覽規則拆分首先需要一個原來的表格模板,以及以后打印之后的容器模板。
為了簡化模型,我這里只考慮兩列,左邊為數據項,右邊為內容的表格。
```
// 要處理的原表格模板的所有tr
let trs = $('#demoTable').find('tr')
// 打印之后顯示的table存放的容器
// 內容進行轉換
let $container = $('#printContainer')
```
### 準備好分頁的間隔模板
```
const tableHeader = '<table class="m-print-table-process"><tbody>'
const tableFooter = '</tbody></table><div class="pager"></div>'
```
### 分頁符的樣式
因為我的ui體驗是設計頁面展示時也進行相應的分頁,所以沒有加媒體查詢,你可以去根據自己的需要決定是否需要加。
```
.pager{
page-break-after:always;
}
@media print{
//媒體查詢樣式
}
```
### 判斷條件
```
// 是否是初始頁 初始頁可能會有一些抬頭信息,比如下賣弄的81高度
let pageInit = true
// 默認的頁面高度
let pageHeight = 950
// 初始化頁面高度參數為0 不斷累加
let initHeight = 0
// 計算當前頁面的可用展示高度,每次進入新頁面重新計算
let currentPageHeight = pageInit ? pageHeight - 81 : pageHeight;
// 獲取當前行的高度
let height = idStr && (idStr === 'processList' || idStr === 'billList') ? this.getHeight(strArr) : 35
// 如果高度大于當前可展示高度
if(initHeight >= currentPageHeight || (initHeight + height >= currentPageHeight){
}
```
### 區分的根據不同類型進行展示
- 展示數據為數組的
```
// 特殊業務類型的
// 目前只考慮兩頁之內可以放下
// 獲取分割后的數組 以及新的頁面高度(傳入當前行字符串,當前頁面剩余可展示高度)
let {countArr, newPageHeight} = this.getSplitArr(strArr, currentPageHeight - initHeight)
countArr.map((item, index) => {
// 當前的繼續追加到表格中 下一個重開表格
if (index === 0) {
let tdStr = item.map(it => `${it}<br/>`).join('')
tempHtml += `<tr><td>${typeStr}</td><td>${tdStr}</td></tr>`
} else if (index === 1) {
if (item.length > 0) {
tempHtml = tempHtml + tableFooter + tableHeader
let tdStr = item.map(it => `${it}<br/>`).join('')
tempHtml += `<tr><td>${typeStr}</td><td>${tdStr}</td></tr>`
}
initHeight = newPageHeight
}
})
```
- 展示數據為基本數據字符串類型的
```
tempHtml = tempHtml + tableFooter + tableHeader
tempHtml += `<tr>${trs[i].innerHTML}</tr>`
initHeight = initHeight - currentPageHeight + height
pageInit = false
```
- 當前頁還可以放下數據的,正常拼接
```
tempHtml += `<tr>${trs[i].innerHTML}</tr>`
initHeight += height
```
### 分割字符串數組的方法
其中計算高度的部分,40為經過試驗后每行剩余可展示的科學可用的40個中文字符,而25位默認一行數據所需要的高度。
備注:這里我業務展示的數據是一個數組結構,如果你的是字符串結構要比我的判斷簡單很多。
經過這個方法將數據進行分割到兩個數據后(countArr),前面的部分放到上一頁,剩下的數據放到下一頁,并計算出下一頁還剩余的空間(newPageHeight),暫時沒考慮第二頁也放不下的情況。
```
/**
* @description 根據數組以及頁面剩余高度,拆分數據數組
* @param {Array} dataArr
* @param {Number} remainHeight
*/
getSplitArr(dataArr, remainHeight) {
if (!dataArr || dataArr.length === 0) console.warn('數據為空')
let getHeight = (data) => Math.ceil(data.length / 40) * 25
let countArr = [[], []]
let partIndex = 0
let totalHeight = remainHeight + 20
let newPageHeight = dataArr.reduce((countHeight, item) => {
countHeight += getHeight(item)
if (countHeight < totalHeight) {
countArr[partIndex].push(item)
} else {
totalHeight = 930
countHeight = 0
partIndex++
countArr[partIndex].push(item)
}
return countHeight
}, 0)
return {countArr, newPageHeight}
},
```
### 計算高度的方法
備注:僅供參考建議。+20為保留的每個tr行的上下padding.
```
getHeight(dataArr) {
let getHeight = (data) => Math.ceil(data.length / 40) * 25
return dataArr.reduce((countHeight, item) => {
countHeight += getHeight(item)
// console.log(countHeight)
return countHeight
}, 0) + 20
}
```
## 小結
以上是這次表格分頁小小的實踐,雖然瀏覽器打印整頁已經技術非常成熟,但是根據產品需求進行指定的分頁和一些數據的分割控制和顯示還是需要一些代碼設計的。
希望能幫助到你實現這部分需求的實現。
- 前端入門
- 前端入職須知
- 入職準備
- 前端ide
- vsc快速上手指南
- 上手指南一
- 常用插件推薦
- 微信開發者
- sublime的使用
- hbuilder入門
- ws
- 前端面試
- 概要
- bat面試題庫
- 題庫一
- 面試大綱
- 題庫二
- 面試大綱
- 前端基礎面試題
- js基礎面試題
- vue&&react面試題
- 數據結構&&算法面試題
- 題庫三
- 001
- 題庫四
- 中小公司leader
- 常規題庫
- 前端規范
- 001
- css
- 001
- 002
- es6(js)
- 001
- 002
- 003
- 004
- node
- 001
- vue
- 001
- react
- 001
- 預處理器
- 001
- gulp
- 001
- webpack
- 001
- 設計模式
- 001
- web常識
- 001
- koa
- 001
- 小程序
- 001
- 數據結構與算法
- 001
- 推薦文章
- 面試指南
- web性能
- 面試分享
- 001
- ps
- ps入門階段
- 圖片類型以及區別
- 基本概念以及常用工具
- ps操作技巧
- 幾個問題
- ps互動教程軟件(app)
- 資源導航
- ps站點資源導航
- ui站點導航
- html
- h5專題
- audio/video
- Geolocation
- Websockets
- Web storage
- Communication
- Web Workers
- requestAnimationFrame
- async&&defer
- fileApi
- h5調用底層能力
- input新解
- canvas實戰篇
- 教程
- js
- javascript入門
- js代碼審查工具
- js性能優化
- 瀏覽器dom對象
- js優質資源
- indexDB入門
- jquery
- jq基本語法
- jq插件與原生插件
- Jq使用建議
- ajax后退解決方案
- jq常見問題
- js常用技術
- js控制運動-move.js
- 常用正則歸納
- js實用技術
- 鼠標行為分析
- document.referrer
- 你可能不知道的調試技巧
- 表格文件的讀取與下載
- 異步編程那些事
- 數據結構
- 編程環境和模型
- 列表
- 棧
- 隊列
- 鏈表
- 字典
- 散列
- 集合
- 二叉樹和二叉查找樹
- 參考
- js編程
- js模塊機制
- 算法
- 基本算法
- 遞歸
- 圖和圖算法
- 圖定義
- 系統建模
- 圖類
- 搜索圖
- 查找最短路徑
- 拓撲排序
- 圖實踐
- 排序算法
- 測試平臺
- 冒泡排序
- 選擇排序
- 插入排序
- 基本排序的比較
- 希爾排序
- 歸并排序
- 快速排序
- 實踐
- 二分排序
- 檢索算法
- 順序查找
- 二分查找
- 查找文本數據
- 檢索實踐
- 高級算法
- 動態規劃
- 貪心算法
- 高級算法實踐
- 代碼重構
- 簡化函數參數
- 001
- 002
- 基礎鞏固
- 001
- es2015實戰
- 初識es-module
- 異步編程
- es6工廠函數
- filter|map|reduce
- js實戰篇
- 前端圖像處理
- touch事件知多少
- 手勢與實踐
- print表格分頁
- 精彩文章推薦
- 001
- 插件庫
- 插件大全
- 功能性插件
- pdfjs
- wdatepicker
- qrcoder
- barcode插件
- photoviewer
- hammer.js
- echarts
- 視頻控件
- 發送瀏覽器通知
- 觸屏簽名插件
- 圖片相關插件推薦
- 待分類插件(pc)
- 待分類插件(手機端)
- 交互組件
- layerjs
- web
- web兼容
- pc端兼容bug匯總
- ie兼容bug匯總
- ie8測試專題
- web常用技術點
- web兼容匯總001
- ie6專題
- css兼容
- web安全
- web安全初級
- app/h5組件
- app教程
- 前端教程
- rubikx的教程
- 與app交互邏輯
- h5喚起app通識
- webview專題
- webview總綱
- js與oc交互協議
- js與安卓交互協議
- 兼容問題匯總
- jsBridge專題
- errorBook.js
- 常用工具
- chrome-devtool使用
- chraels
- 開發注意事項
- web常識
- markdown教程
- 自定義風格思路
- 經驗與問題總結
- 總結1
- 前端應該注意哪些seo
- 懶加載和預加載
- https
- 前端重構
- web優化
- 移動端web優化
- http緩存
- web端優化
- 圖片專題
- svg專題
- 深入淺出svg
- 地圖使用
- 注意事項
- 需求提交
- 常規交互需求提交
- 緩存
- 干貨文章
- 瀏覽器緩存
- 內存
- web性能指南
- 讀書筆記
- ui框架
- 概論
- easyui
- bootstrap
- 入門推薦
- modal插件使用
- 按鈕組件
- 正確使用柵格布局
- 下拉框插件使用
- 表單使用與驗證
- tab切換項插件
- 分頁控件
- 進度條控件
- 文件上傳控件
- 面板控件
- 常見特效與插件
- weui
- sui-pc
- sui-mobile
- layerUI
- frozen-UI
- rubik-u那些事
- 基本內容
- 小程序
- 小程序入門
- 入門
- 實踐踩坑
- 001
- 基本語法
- 開發大綱
- 注意事項
- 微信專題
- 基本入門
- 準備工作
- 定制菜單
- 圖文消息與圖文推送
- h5支付
- 公眾號支付
- node完成微信支付
- 進階使用
- 微信分享
- weui使用
- 基本使用
- 支付寶專題
- 支付寶h5支付
- app支付接入
- 服務窗支付
- java
- java入門
- eclipse基本使用
- 語言特點
- java代碼規范
- 編譯調試
- java基本語句
- springMVC
- javaweb
- vm模板引擎
- freemarker
- 常用常識
- 常用常識2
- 部署項目
- web --xml文件解析
- java生成pdf文件
- java讀取、寫文件案例
- 圖片加水印
- 圖片加水印2
- java-cookie
- 驗證碼文件
- sql-mapper語法
- maven教程
- mySql教程
- jeecms
- flash
- flash入門
- flash準備工作
- 運行與編譯
- 瀏覽器中flash設置教程
- flash檢測