From 7936bd38fc7d1a9af61c86d102933287297e2e91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=81=E9=94=90?= Date: Mon, 6 Dec 2021 16:44:34 +0800 Subject: [PATCH] feat: vue3 compatible --- demo/main.js | 14 +- package.json | 6 +- src/PDFViewer.vue | 26 +- src/components/IFrame/IFrameV3.js | 68 + src/components/IFrame/index.js | 7 + src/components/IconButton.vue | 3 + .../RotateWrapper/RotateWrapper.vue | 25 +- src/components/Viewer/Viewer.vue | 46 +- yarn.lock | 2282 ++++++++++++++++- 9 files changed, 2316 insertions(+), 161 deletions(-) create mode 100644 src/components/IFrame/IFrameV3.js create mode 100644 src/components/IFrame/index.js diff --git a/demo/main.js b/demo/main.js index f66a9a6..acb0486 100644 --- a/demo/main.js +++ b/demo/main.js @@ -1,8 +1,12 @@ -import Vue from 'vue' +import Vue, { createApp } from 'vue' import App from './App.vue' -new Vue({ - el: '#app', - render: (h) => h(App), -}) +if (typeof createApp === 'function') { + createApp(App).mount('#app') +} else { + new Vue({ + el: '#app', + render: h => h(App), + }) +} diff --git a/package.json b/package.json index 977c09d..36bd2c4 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "devDependencies": { "@babel/core": "^7.14.2", "@babel/preset-env": "^7.14.2", + "@vue/cli-plugin-babel": "~4.5.0", "@vue/compiler-sfc": "^3.0.11", "babel-loader": "^8.2.3", "css-loader": "^5.2.6", @@ -45,11 +46,10 @@ "style-loader": "^3.3.1", "uglifyjs-webpack-plugin": "^2.2.0", "url-loader": "^4.1.1", - "vue": "^2.6.12", - "vue-loader": "^15.9.7", + "vue": "^3.2.23", + "vue-loader": "16", "vue-loader-next": "npm:vue-loader@^16.2.0", "vue-style-loader": "^4.1.3", - "vue-template-compiler": "^2.6.12", "webpack": "5", "webpack-cli": "^4.7.0", "webpack-dev-server": "^3.11.2", diff --git a/src/PDFViewer.vue b/src/PDFViewer.vue index 978fdba..b19dc7b 100644 --- a/src/PDFViewer.vue +++ b/src/PDFViewer.vue @@ -3,14 +3,16 @@
{ + const cssEl = document.createElement('STYLE') + cssEl.textContent = style + + iframeHead.value.appendChild(cssEl) + + return cssEl + } + + const getContentWindow = () => { + return iframeRef.value.contentWindow + } + + expose({ + appendStyle, + getContentWindow, + }) + + onMounted(() => { + iframeBody.value = iframeRef.value.contentDocument.body + iframeHead.value = iframeRef.value.contentDocument.head + const el = document.createElement('div') + iframeBody.value.appendChild(el) + appendStyle(style) + if (props.css) { + iframeStyle.value = appendStyle(props.css) + } + + iframeApp = createApp({ + name: 'iApp', + setup() { + return () => slots.default() + }, + }).mount(el) + }) + onBeforeUpdate(() => { + if (!iframeApp || !iframeRef.value) { + return + } + if (props.css) { + iframeStyle.value.innerHTML = props.css + } + }) + return () => + createVNode('iframe', { + ref: iframeRef, + style: { width: '100%', height: '100%', border: 'none' }, + }) + }, +} diff --git a/src/components/IFrame/index.js b/src/components/IFrame/index.js new file mode 100644 index 0000000..cdb744c --- /dev/null +++ b/src/components/IFrame/index.js @@ -0,0 +1,7 @@ +import IFrameV3 from './IFrameV3' +import IFrame from './IFrame' + +export default { + IFrameV3, + IFrame, +} diff --git a/src/components/IconButton.vue b/src/components/IconButton.vue index fe28e23..b20f430 100644 --- a/src/components/IconButton.vue +++ b/src/components/IconButton.vue @@ -9,6 +9,9 @@ import Iconfont from './Iconfont.vue' export default { name: 'IconButton', + // vue3 triggers click event twice + // https://github.com/vuejs/vue-next/commit/e1660f4338fbf4d2a434e13193a58e00f844379b + inheritAttrs: false, components: { Iconfont, }, diff --git a/src/components/RotateWrapper/RotateWrapper.vue b/src/components/RotateWrapper/RotateWrapper.vue index 59dc67a..5a4fec4 100644 --- a/src/components/RotateWrapper/RotateWrapper.vue +++ b/src/components/RotateWrapper/RotateWrapper.vue @@ -2,13 +2,13 @@
+
@@ -16,7 +16,9 @@ export default { name: 'RotateWrapper', props: { - src: String, + src: { + type: String, + }, rotateDeg: Number, duration: { type: Number, @@ -48,6 +50,23 @@ export default { }, }, watch: { + src: { + immediate: true, + handler(n) { + this.loaded = false + if (n) { + const image = document.createElement('img') + image.src = n + + const tmp = image.cloneNode() + // blob src does not fire onload + tmp.onload = async () => { + await this.$nextTick() + this.handleLoaded() + } + } + }, + }, async rotateDeg() { await this.$nextTick() this._timer = setInterval(() => { diff --git a/src/components/Viewer/Viewer.vue b/src/components/Viewer/Viewer.vue index 17d82d7..cb311c0 100644 --- a/src/components/Viewer/Viewer.vue +++ b/src/components/Viewer/Viewer.vue @@ -1,5 +1,5 @@