Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
很早之前就有寫(xiě)過(guò)一個(gè)wcPop.js彈窗插件,并且在h5酒店預(yù)訂、h5聊天室項(xiàng)目中都有使用過(guò),效果還不錯(cuò)。當(dāng)初想著有時(shí)間整合一個(gè)Vue版本,剛好趁著國(guó)慶節(jié)空閑時(shí)間搗鼓了個(gè)vue.js版自定義模態(tài)彈出框組件VPopup。
v-popup 一款聚合Msg、Dialog、Popup、ActionSheet、Toast等功能的輕量級(jí)移動(dòng)端Vue彈窗組件。
整合了有贊Vant及NutUI等熱門(mén)Vue組件庫(kù)中Popup彈出層、Toast輕提示、Notify消息提示、Dialog對(duì)話框及ActionSheet動(dòng)作面板等功能。
// 在main.js中全局引入
import Vue from 'vue'
import Popup from './components/popup'
Vue.use(Popup)
支持如下兩種方式調(diào)用組件。
<v-popup
v-model="showPopup"
title="標(biāo)題內(nèi)容"
content="彈窗內(nèi)容,告知當(dāng)前狀態(tài)、信息和解決方法,描述文字盡量控制在三行內(nèi)"
type="android"
shadeClose="false"
xclose
z-index="2000"
:btns="[
{...},
{...},
]"
/>
this.$vpopup({...}),傳入?yún)?shù)即可使用,該函數(shù)會(huì)返回彈窗組件實(shí)例。
let $el = this.$vpopup({
title: '標(biāo)題內(nèi)容',
content: '彈窗內(nèi)容,描述文字盡量控制在三行內(nèi)',
type: 'android',
shadeClose: false,
xclose: true,
zIndex: 2000,
btns: [
{text: '取消'},
{
text: '確認(rèn)',
style: 'color:#f60;',
click: () => {
$el.close()
}
},
]
});
你可根據(jù)喜好或項(xiàng)目需要任意選擇一種調(diào)用方式即可。下面就開(kāi)始講解下組件的實(shí)現(xiàn)。
在components目錄下新建popup.vue頁(yè)面。
組件參數(shù)配置
<!-- Popup 彈出層模板 -->
<template>
<div v-show="opened" class="nuxt__popup" :class="{'nuxt__popup-closed': closeCls}" :id="id">
<div v-if="JSON.parse(shade)" class="nuxt__overlay" @click="shadeClicked" :style="{opacity}"></div>
<div class="nuxt__wrap">
<div class="nuxt__wrap-section">
<div class="nuxt__wrap-child" :class="['anim-'+anim, type&&'popui__'+type, round&&'round', position]" :style="popupStyle">
<div v-if="title" class="nuxt__wrap-tit" v-html="title"></div>
<div v-if="type=='toast'&&icon" class="nuxt__toast-icon" :class="['nuxt__toast-'+icon]" v-html="toastIcon[icon]"></div>
<template v-if="$slots.content">
<div class="nuxt__wrap-cnt"><slot name="content" /></div>
</template>
<template v-else>
<div v-if="content" class="nuxt__wrap-cnt" v-html="content"></div>
</template>
<slot />
<div v-if="btns" class="nuxt__wrap-btns">
<span v-for="(btn,index) in btns" :key="index" class="btn" :class="{'btn-disabled': btn.disabled}" :style="btn.style" @click="btnClicked($event,index)" v-html="btn.text"></span>
</div>
<span v-if="xclose" class="nuxt__xclose" :class="xposition" :style="{'color': xcolor}" @click="close"></span>
</div>
</div>
</div>
</div>
</template>
<script>
// 彈窗索引,遮罩次數(shù),定時(shí)器
let $index = 0, $lockCount = 0, $timer = {};
export default {
props: {
...
},
data() {
return {
opened: false,
closeCls: '',
toastIcon: {
loading: '<svg viewBox="25 25 50 50"><circle fill="none" cx="50" cy="50" r="20"></circle></svg>',
success: '<svg viewBox="0 0 1024 1024"><path fill="none" d="M75.712 445.712l240.176 185.52s13.248 6.624 29.808 0l591.36-493.872s84.272-17.968 68.64 71.488c-57.04 57.968-638.464 617.856-638.464 617.856s-38.096 21.536-74.544 0C256.272 790.256 12.816 523.568 12.816 523.568s-6.672-64.592 62.896-77.856z"/></svg>',
fail: '<svg viewBox="0 0 1024 1024"><path fill="none" d="M450.602 665.598a62.464 62.464 0 0 0 122.88 0l40.96-563.198A102.615 102.615 0 0 0 512.042 0a105.256 105.256 0 0 0-102.4 112.64l40.96 552.958zm61.44 153.6a102.4 102.4 0 1 0 102.4 102.4 96.74 96.74 0 0 0-102.4-102.4z"/></svg>',
}
}
},
watch: {
value(val) {
const type = val ? 'open' : 'close';
this[type]();
},
},
methods: {
// 打開(kāi)彈窗
open() {
if(this.opened) return;
this.opened = true;
this.$emit('open');
typeof this.onOpen === 'function' && this.onOpen();
this.$el.style.zIndex = this.getZIndex() + 1;
if(JSON.parse(this.shade)) {
if(!$lockCount) {
document.body.classList.add('nt-overflow-hidden');
}
$lockCount++;
}
// 倒計(jì)時(shí)關(guān)閉
if(this.time) {
$index++;
// 防止重復(fù)點(diǎn)擊
if($timer[$index] !== null) clearTimeout($timer[$index])
$timer[$index] = setTimeout(() => {
this.close();
}, parseInt(this.time) * 1000);
}
// 長(zhǎng)按/右鍵彈窗
if(this.follow) {
// 避免獲取不到彈窗寬高
this.$nextTick(() => {
let obj = this.$el.querySelector('.nuxt__wrap-child');
let oW, oH, winW, winH, pos;
oW = obj.clientWidth;
oH = obj.clientHeight;
winW = window.innerWidth;
winH = window.innerHeight;
pos = this.getPos(this.follow[0], this.follow[1], oW, oH, winW, winH);
obj.style.left = pos[0] + 'px';
obj.style.top = pos[1] + 'px';
});
}
},
// 關(guān)閉彈窗
close() {
if(!this.opened) return;
this.closeCls = true;
setTimeout(() => {
this.opened = false;
this.closeCls = false;
if(JSON.parse(this.shade)) {
$lockCount--;
if(!$lockCount) {
document.body.classList.remove('nt-overflow-hidden');
}
}
if(this.time) {
$index--;
}
this.$emit('input', false);
this.$emit('close');
typeof this.onClose === 'function' && this.onClose();
}, 200);
},
// 點(diǎn)擊遮罩層
shadeClicked() {
if(JSON.parse(this.shadeClose)) {
this.close();
}
},
// 按鈕事件
btnClicked(e, index) {
let btn = this.btns[index];
if(!btn.disabled) {
typeof btn.click === 'function' && btn.click(e)
}
},
// 獲取彈窗層級(jí)
getZIndex() {
for(var $idx = parseInt(this.zIndex), $el = document.getElementsByTagName('*'), i = 0, len = $el.length; i < len; i++)
$idx = Math.max($idx, $el[i].style.zIndex)
return $idx;
},
// 獲取彈窗坐標(biāo)點(diǎn)
getPos(x, y, ow, oh, winW, winH) {
let l = (x + ow) > winW ? x - ow : x;
let t = (y + oh) > winH ? y - oh : y;
return [l, t];
}
},
}
</script>
通過(guò)監(jiān)聽(tīng)v-model值調(diào)用open和close方法。
watch: {
value(val) {
const type = val ? 'open' : 'close';
this[type]();
},
},
如果想要實(shí)現(xiàn)函數(shù)式調(diào)用this.$vpopup({...}),則需要使用到Vue.extend擴(kuò)展實(shí)例構(gòu)造器。
import Vue from 'vue';
import VuePopup from './popup.vue';
let PopupConstructor = Vue.extend(VuePopup);
let $instance;
let VPopup = function(options = {}) {
// 同一個(gè)頁(yè)面中,id相同的Popup的DOM只會(huì)存在一個(gè)
options.id = options.id || 'nuxt-popup-id';
$instance = new PopupConstructor({
propsData: options
});
$instance.vm = $instance.$mount();
let popupDom = document.querySelector('#' + options.id);
if(options.id && popupDom) {
popupDom.parentNode.replaceChild($instance.$el, popupDom);
} else {
document.body.appendChild($instance.$el);
}
Vue.nextTick(() => {
$instance.value = true;
})
return $instance;
}
VPopup.install = () => {
Vue.prototype['$vpopup'] = VPopup;
Vue.component('v-popup', VuePopup);
}
export default VPopup;
這樣就實(shí)現(xiàn)了引入 Popup 組件后,會(huì)自動(dòng)在 Vue 的 prototype 上掛載 $vpopup 方法和注冊(cè) v-popup 組件。
下面就可以愉快的使用標(biāo)簽式及函數(shù)式調(diào)用組件了。
<v-popup v-model="showActionPicker" anim="footer" type="actionsheetPicker" round title="標(biāo)題內(nèi)容"
:btns="[
{text: '取消', click: () => showActionPicker=false},
{text: '確定', style: 'color:#00e0a1;', click: () => null},
]"
>
<ul class="goods-list" style="padding:50px;text-align:center;">
<li>雙肩包</li>
<li>鞋子</li>
<li>運(yùn)動(dòng)褲</li>
</ul>
</v-popup>
<v-popup v-model="showBottom" position="bottom" round xclose title="標(biāo)題內(nèi)容">
<ul class="goods-list" style="padding:50px;text-align:center;">
<li>雙肩包</li>
<li>鞋子</li>
<li>運(yùn)動(dòng)褲</li>
</ul>
</v-popup>
按鈕設(shè)置disabled: true即可禁用按鈕事件。
<v-popup v-model="showActionSheet" anim="footer" type="actionsheet" :z-index="2020"
content="彈窗內(nèi)容,描述文字盡量控制在三行內(nèi)"
:btns="[
{text: '拍照', style: 'color:#09f;', disabled: true, click: handleInfo},
{text: '從手機(jī)相冊(cè)選擇', style: 'color:#00e0a1;', click: handleInfo},
{text: '保存圖片', style: 'color:#e63d23;', click: () => null},
{text: '取消', click: () => showActionSheet=false},
]"
/>
另外還支持自定義slot插槽內(nèi)容,當(dāng) content 和 自定義插槽 內(nèi)容同時(shí)存在,只顯示插槽內(nèi)容。
<v-popup v-model="showComponent" xclose xposition="bottom" content="這里是內(nèi)容信息"
:btns="[
{text: '確認(rèn)', style: 'color:#f60;', click: () => showComponent=false},
]"
@open="handleOpen" @close="handleClose"
>
<template #content>當(dāng) content 和 自定義插槽 內(nèi)容同時(shí)存在,只顯示插槽內(nèi)容!</template>
<div style="padding:30px 15px;">
<img src="assets/apple3.jpg" style="width:100%;" @click="handleContextPopup" />
</div>
</v-popup>
好了,就分享到這里。希望對(duì)大家有所幫助。目前該組件正在項(xiàng)目中實(shí)戰(zhàn)測(cè)試,后續(xù)會(huì)分享相關(guān)使用情況。
嗨,各位極客;在你的瀏覽器中裝上了多少插件呢?讓我猜猜:tampermonkey 油猴腳本,Chrono下載管理器,bilibilihelper,喔當(dāng)然還有必不可少的 Adblock。有了解過(guò)這些插件是怎么運(yùn)作的么?想要完成一個(gè)自己的插件么?快和我一起動(dòng)手吧!
本文參考 Chrome Extensions V3版本 開(kāi)發(fā)指南,接下來(lái)我們簡(jiǎn)單地介紹一下一個(gè)插件的組成,
Chrome 插件通常由以下幾部分組成:
{
"manifest_version": 3,
"name": "Chrome 插件開(kāi)發(fā) 示例",
"description": "這是一個(gè) Chrome 開(kāi)發(fā)示例工程",
"version": "1.0",
"permissions": [ // 插件需要的權(quán)限信息 依次為:數(shù)據(jù)存儲(chǔ)、訪問(wèn)活躍的標(biāo)簽頁(yè)、執(zhí)行插入腳本
"storage", "activeTab", "scripting"
],
// 時(shí)間
"action": {
// 設(shè)置插件在插件區(qū)域的icon
"default_icon": {
"16": "readIcon.png",
"32": "readIcon.png",
"64": "readIcon.png",
"128": "readIcon.png"
},
// 插件在插件區(qū)域被點(diǎn)擊時(shí)的彈出頁(yè)面
"default_popup": "popup.html"
},
// 后臺(tái)運(yùn)行腳本
"background": {
"service_worker": "background.js"
},
// 全局icon 會(huì)出現(xiàn)在配置頁(yè)面的icon中
"icons": {
"16": "bookIcon.png",
"32": "bookIcon.png",
"64": "bookIcon.png",
"128": "bookIcon.png"
},
// 配置頁(yè)面
"options_page": "options.html"
}
在插件區(qū)域點(diǎn)擊咱們插件后將觸發(fā)popup 事件,喚起 popup.html 頁(yè)面
點(diǎn)擊右鍵插件中的選項(xiàng)按鈕,將觸發(fā)option 事件,喚起 options.html 頁(yè)面
當(dāng)插件被載入后,將后臺(tái)執(zhí)行 background.js 腳本
我們將按照官方示例完成一個(gè)示例工程,在這個(gè)工程中,我們將提供一個(gè)可以設(shè)置網(wǎng)頁(yè)背景顏色的小工具,并且在配置頁(yè)面提供多個(gè)顏色供用戶選擇。
那我們就開(kāi)始吧!先創(chuàng)建一個(gè)文件夾,命名為 start,然后用編輯器打開(kāi)文件夾,開(kāi)始編碼啦,我使用的是vscode,當(dāng)然任何編輯器都可以完成這項(xiàng)編碼。
創(chuàng)建一個(gè) manifest.json 文件
{
"manifest_version": 3,
"name": "Chrome 插件開(kāi)發(fā) 示例",
"description": "這是一個(gè) Chrome 開(kāi)發(fā)示例工程",
"version": "1.0",
"permissions": [
"storage", "activeTab", "scripting"
],
"background": {
"service_worker": "background.js"
},
"icons": {
"16": "icon.png",
"32": "icon.png",
"64": "icon.png",
"128": "icon.png"
},
}
找一張你喜歡的照片,命名為icon并添加到文件夾中,這里先沒(méi)有配置popup頁(yè)面和option頁(yè)面,不著急,一步步來(lái)。
創(chuàng)建一個(gè) background.js 文件
// 初始化一個(gè)顏色值
let color = '#3aa757';
// 在chrome瀏覽器創(chuàng)建的時(shí)候,設(shè)置顏色初始值
chrome.runtime.onInstalled.addListener(() => {
// 需要注意的是,此時(shí)設(shè)置的持久對(duì)象的鍵名為 color 其值為 #3aa757
chrome.storage.sync.set({ color });
console.log('設(shè)置一個(gè)默認(rèn)的顏色,默認(rèn)顏色值為綠色 %cgreen', `color: ${color}`);
});
然后就可以嘗試一下插件的運(yùn)行啦,進(jìn)入插件頁(yè)面,先在右上角開(kāi)啟開(kāi)發(fā)者模式,然后點(diǎn)擊加載已解壓的擴(kuò)展程序,找到你的 start 文件夾加載進(jìn)來(lái)。
此時(shí)頁(yè)面上就會(huì)出現(xiàn)你的插件了,你會(huì)發(fā)現(xiàn)在有一個(gè)Service Worker視圖可以點(diǎn)擊,點(diǎn)擊查看一下
你就可以看到 background.js 成功運(yùn)行并打印了日志
接下來(lái)我們配置一個(gè)彈出頁(yè)面,創(chuàng)建 popup.html
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>插件彈出頁(yè)面</title>
<link rel="stylesheet" href="button.css">
</head>
<body>
<button id="changeColor"></button>
<img url="icon.png"/>
<!-- 引入js -->
<script src="popup.js"></script>
</body>
</html>
創(chuàng)建 popup.js
// 獲得 改變顏色的按鈕
let changeColor = document.getElementById("changeColor");
// 獲取當(dāng)前已設(shè)置顏色
chrome.storage.sync.get("color", ({ color }) => {
changeColor.style.backgroundColor = color;
});
// 創(chuàng)建按鈕點(diǎn)擊事件 觸發(fā)對(duì)當(dāng)前激活的瀏覽器窗口中的當(dāng)前激活的選項(xiàng)卡設(shè)置背景顏色
changeColor.addEventListener("click", async () => {
let [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
// 注入執(zhí)行js代碼
chrome.scripting.executeScript({
target: { tabId: tab.id },
function: setPageBackgroundColor,
});
});
// 注入執(zhí)行的方法塊
// 設(shè)置body的背景顏色為目標(biāo)顏色
function setPageBackgroundColor() {
chrome.storage.sync.get("color", ({ color }) => {
document.body.style.backgroundColor = color;
});
}
創(chuàng)建 button.css
body {
min-width: 357px;
overflow-x: hidden;
}
img {
margin: 5px;
border: 2px solid black;
vertical-align: middle;
width: 75px;
height: 75px;
}
button {
height: 30px;
width: 30px;
outline: none;
margin: 10px;
border: none;
border-radius: 2px;
}
button.current {
box-shadow: 0 0 0 2px white,
0 0 0 4px black;
}
喔當(dāng)然,還要修改 manifest.json,添加上 popup.html的配置,還需要準(zhǔn)備一張?jiān)诓寮^(qū)域展示的 popupIcon 照片。
{
"manifest_version": 3,
"name": "Chrome 插件開(kāi)發(fā) 示例",
... 省略 ...
"128": "icon.png"
},
"action": {
"default_icon": {
"16": "popupIcon.png",
"32": "popupIcon.png",
"64": "popupIcon.png",
"128": "popupIcon.png"
},
"default_popup": "popup.html"
}
}
然后在插件頁(yè)面刷新重新加載
這時(shí)候我們就可以點(diǎn)擊插件啦,按照1點(diǎn)擊插件,然后點(diǎn)擊2,觸發(fā)按鈕事件
bingo! 當(dāng)前頁(yè)面的背景顏色變成綠色了。
似乎只有一個(gè)綠色不太合適,我們得為用戶提供更多的選擇,那就再做一個(gè)選項(xiàng)頁(yè)面,提供配置功能吧。
創(chuàng)建 options.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>插件選項(xiàng)配置頁(yè)面</title>
<link rel="stylesheet" href="button.css">
</head>
<body>
<div id="buttonDiv">
</div>
<div>
<p>選擇一個(gè)新的背景顏色</p>
</div>
<script src="options.js"></script>
</body>
</html>
創(chuàng)建 options.js
// 獲取按鈕區(qū)域 div
let page = document.getElementById("buttonDiv");
// button.css 有一個(gè) button current css 樣式,為選中的顏色添加出黑色邊框
let selectedClassName = "current";
// 設(shè)置待選顏色按鈕
const presetButtonColors = ["#3aa757", "#e8453c", "#f9bb2d", "#4688f1"];
// 創(chuàng)建按鈕事件 通過(guò)標(biāo)記所選按鈕 保存顏色
function handleButtonClick(event) {
// 從事件的父級(jí)中找到之前被選中的按鈕
let current = event.target.parentElement.querySelector(
`.${selectedClassName}`
);
// 從他的class列表中去掉選中狀態(tài)
if (current && current !== event.target) {
current.classList.remove(selectedClassName);
}
// 獲取按鈕攜帶的數(shù)據(jù)信息 也就是我們想要的顏色
let color = event.target.dataset.color;
// 添加選中狀態(tài)
event.target.classList.add(selectedClassName);
// 設(shè)置當(dāng)前選中顏色
chrome.storage.sync.set({ color });
}
// 按顏色列表依次添加按鈕到頁(yè)面
function constructOptions(buttonColors) {
// 獲取當(dāng)前已設(shè)置的顏色
chrome.storage.sync.get("color", (data) => {
let currentColor = data.color;
// 循環(huán)顏色列表
for (let buttonColor of buttonColors) {
// 創(chuàng)建按鈕 賦予按鈕顏色
let button = document.createElement("button");
button.dataset.color = buttonColor;
button.style.backgroundColor = buttonColor;
// 如果是當(dāng)前已選中的按鈕,則設(shè)置
if (buttonColor === currentColor) {
button.classList.add(selectedClassName);
}
// 創(chuàng)建點(diǎn)擊事件
button.addEventListener("click", handleButtonClick);
// 添加回頁(yè)面上
page.appendChild(button);
}
});
}
// js 被加載后 自執(zhí)行初始化方法 創(chuàng)建按鈕
constructOptions(presetButtonColors);
然后再修改一次 manifest.json
{
"manifest_version": 3,
"name": "Chrome 插件開(kāi)發(fā) 示例",
... 省略 ...
"default_popup": "popup.html"
},
"options_page": "options.html"
}
然后再重載一次插件,bingo!右鍵我們的插件就多出選項(xiàng)頁(yè)面啦
點(diǎn)擊進(jìn)入選項(xiàng)頁(yè)面,出現(xiàn)了我們?cè)诖a中配置的四個(gè)顏色了,隨便點(diǎn)選其他三種顏色。
我們就可以驚喜的發(fā)現(xiàn)在popup頁(yè)面的按鈕顏色也發(fā)生了變化了。
至此,我們的起步示例工程的開(kāi)發(fā)就完成了。
在這次工程中,我們完成了配置基本信息、開(kāi)發(fā)了popup 彈出頁(yè)面、option 配置頁(yè)面,并實(shí)現(xiàn)了多頁(yè)面間的數(shù)據(jù)共享功能,并了解到各個(gè)頁(yè)面間的通信都需要通過(guò)第三者進(jìn)行處理,因?yàn)楸举|(zhì)上每個(gè)頁(yè)面都是獨(dú)立的進(jìn)程。
那我想提個(gè)小問(wèn)題,如果我想在選項(xiàng)配置頁(yè)面選擇了顏色之后,然后再點(diǎn)擊到一個(gè)具體的選項(xiàng)卡中自動(dòng)幫我修改背景顏色,應(yīng)該怎么實(shí)現(xiàn)呢?
谷歌插件示例工程
https://github.com/GoogleChrome/chrome-extensions-samples
谷歌插件官方文檔
https://developer.chrome.com/docs/extensions/
Vue中實(shí)現(xiàn)打印預(yù)覽和打印功能,你可以使用原生的JavaScript方法,或者使用第三方庫(kù),如vue-html2pdf 或 print.js。
以下是使用原生JavaScript方法實(shí)現(xiàn)打印功能的基本步驟:
以下是一個(gè)簡(jiǎn)單的Vue組件示例,它包含一個(gè)打印按鈕,點(diǎn)擊該按鈕會(huì)觸發(fā)打印功能:
<template>
<div>
<div ref="printSection">
<h1>{{ title }}</h1>
<p>{{ description }}</p>
</div>
<button @click="print">打印</button>
</div>
</template>
<script>
export default {
data() {
return {
title: 'Vue 打印示例',
description: '這是一個(gè)Vue打印功能的簡(jiǎn)單示例。'
}
},
methods: {
print() {
let printContents = this.$refs.printSection.innerHTML;
let originalContents = document.body.innerHTML;
document.body.innerHTML = printContents;
window.print();
document.body.innerHTML = originalContents;
}
}
}
</script>
但是這種方法有個(gè)問(wèn)題,就是會(huì)改變當(dāng)前頁(yè)面的內(nèi)容。為了避免這個(gè)問(wèn)題,我們可以使用一個(gè)新的窗口或者iframe來(lái)進(jìn)行打印。
這是一個(gè)使用新窗口進(jìn)行打印的示例:
<template>
<div>
<div ref="printSection">
<h1>{{ title }}</h1>
<p>{{ description }}</p>
</div>
<button @click="print">打印</button>
</div>
</template>
<script>
export default {
data() {
return {
title: 'Vue 打印示例',
description: '這是一個(gè)Vue打印功能的簡(jiǎn)單示例。'
}
},
methods: {
print() {
let printContents = this.$refs.printSection.innerHTML;
let popup = window.open('', '_blank');
popup.document.write(printContents);
popup.document.close();
popup.print();
}
}
}
</script>
以上代碼實(shí)現(xiàn)了基本的打印功能,但并未實(shí)現(xiàn)打印預(yù)覽功能。實(shí)現(xiàn)打印預(yù)覽功能通常需要使用到第三方庫(kù),或者利用瀏覽器的打印對(duì)話框進(jìn)行預(yù)覽。
如果你想要實(shí)現(xiàn)更復(fù)雜的打印和預(yù)覽功能,我建議查看vue-html2pdf或print.js這樣的庫(kù)。它們提供了更多的配置選項(xiàng),并且可以更好地控制打印和預(yù)覽的行為。
例如,使用vue-html2pdf庫(kù),你可以很容易地將HTML轉(zhuǎn)換為PDF,并提供下載或預(yù)覽功能。而print.js庫(kù)則提供了更多的打印選項(xiàng),包括打印到PDF,打印到紙張,以及自定義打印布局等。
注意:以上代碼在真實(shí)環(huán)境中可能需要進(jìn)行一些調(diào)整,以適應(yīng)你的具體需求。例如,你可能需要處理跨域問(wèn)題,或者調(diào)整樣式以適應(yīng)打印布局。
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。