Эх сурвалжийг харах

Переход на Vue 3, в процессе

Book Pauk 3 жил өмнө
parent
commit
687f89729b

+ 1 - 0
.eslintrc

@@ -29,6 +29,7 @@
     }],
     "vue/max-attributes-per-line": "off",
     "vue/html-self-closing": "off",
+    "vue/no-v-html": "off",
 
     "strict": 0,
     "indent": [0, 4, {

+ 1 - 0
build/webpack.base.config.js

@@ -99,6 +99,7 @@ module.exports = {
         new DefinePlugin({
             __VUE_OPTIONS_API__: true,
             __VUE_PROD_DEVTOOLS__: false,
+            __QUASAR_SSR__: false,
             __QUASAR_SSR_SERVER__: false,
             __QUASAR_SSR_CLIENT__: false,
             __QUASAR_VERSION__: false,

+ 19 - 22
client/components/App.vue

@@ -2,16 +2,18 @@
     <div class="fit row">
         <Notify ref="notify" />
         <StdDialog ref="stdDialog" />
-        <keep-alive v-if="showPage">
-            <router-view class="col"></router-view>
-        </keep-alive>
+
+        <router-view v-slot="{ Component }">
+            <keep-alive v-if="showPage">
+                <component :is="Component" class="col" />
+            </keep-alive>
+        </router-view>
     </div>
 </template>
 
 <script>
 //-----------------------------------------------------------------------------
-import Vue from 'vue';
-import Component from 'vue-class-component';
+import vueComponent from './vueComponent.js';
 
 import Notify from './share/Notify.vue';
 import StdDialog from './share/StdDialog.vue';
@@ -19,7 +21,7 @@ import StdDialog from './share/StdDialog.vue';
 import miscApi from '../api/misc';
 import * as utils from '../share/utils';
 
-export default @Component({
+const componentOptions = {
     components: {
         Notify,
         StdDialog,
@@ -31,8 +33,9 @@ export default @Component({
         }
     },
 
-})
-class App extends Vue {
+};
+class App {
+    _options = componentOptions;
     showPage = false;
 
     itemRuText = {
@@ -54,7 +57,7 @@ class App extends Vue {
         //root route
         let cachedRoute = '';
         let cachedPath = '';
-        this.$root.rootRoute = () => {
+        this.$root.getRootRoute = () => {
             if (this.$route.path != cachedPath) {
                 cachedPath = this.$route.path;
                 const m = cachedPath.match(/^(\/[^/]*).*$/i);
@@ -73,8 +76,8 @@ class App extends Vue {
             }
         });
 
-        // set-app-title
-        this.$root.$on('set-app-title', this.setAppTitle);
+        // setAppTitle
+        this.$root.setAppTitle = this.setAppTitle;
 
         //global keyHooks
         this.keyHooks = [];
@@ -108,14 +111,6 @@ class App extends Vue {
         });
     }
 
-    routerReady() {
-        return new Promise ((resolve) => {
-            this.$router.onReady(() => {
-                resolve();
-            });
-        });
-    }
-
     mounted() {
         this.$root.notify = this.$refs.notify;
         this.$root.stdDialog = this.$refs.stdDialog;
@@ -142,7 +137,7 @@ class App extends Vue {
             if (navigator.storage && navigator.storage.persist) {
                 navigator.storage.persist();
             }
-            await this.routerReady();
+            await this.$router.isReady();
             this.redirectIfNeeded();
         })();
     }
@@ -184,7 +179,7 @@ class App extends Vue {
     }
 
     get rootRoute() {
-        return this.$root.rootRoute();
+        return this.$root.getRootRoute();
     }
 
     setAppTitle(title) {
@@ -194,7 +189,7 @@ class App extends Vue {
             } else if (this.mode == 'omnireader') {
                 document.title = `Omni Reader - всегда с вами`;
             } else if (this.config && this.mode !== null) {
-                document.title = `${this.config.name} - ${this.itemRuText[this.$root.rootRoute]}`;
+                document.title = `${this.config.name} - ${this.itemRuText[this.rootRoute]}`;
             }
         } else {
             document.title = title;
@@ -239,6 +234,8 @@ class App extends Vue {
         }
     }
 }
+
+export default vueComponent(App);
 //-----------------------------------------------------------------------------
 </script>
 

+ 16 - 11
client/components/CardIndex/CardIndex.vue

@@ -1,15 +1,17 @@
 <template>
     <div>
-        <keep-alive>
-            <router-view></router-view>
-        </keep-alive>
+
+        <router-view v-slot="{ Component }">
+            <keep-alive>
+                <component :is="Component" />
+            </keep-alive>
+        </router-view>        
     </div>
 </template>
 
 <script>
 //-----------------------------------------------------------------------------
-import Vue from 'vue';
-import Component from 'vue-class-component';
+import vueComponent from '../vueComponent.js';
 import _ from 'lodash';
 
 const selfRoute = '/cardindex';
@@ -21,18 +23,19 @@ const tab2Route = [
 ];
 let lastActiveTab = null;
 
-export default @Component({
+const componentOptions = {
     watch: {
-        selectedTab: function(newValue, oldValue) {
+        selectedTab: function(newValue) {
             lastActiveTab = newValue;
             this.setRouteByTab(newValue);
         },
-        curRoute: function(newValue, oldValue) {
+        curRoute: function(newValue) {
             this.setTabByRoute(newValue);
         },
     },
-})
-class CardIndex extends Vue {
+};
+class CardIndex {
+    _options = componentOptions;
     selectedTab = null;
 
     mounted() {
@@ -58,11 +61,13 @@ class CardIndex extends Vue {
     }
 
     get curRoute() {
-        const m = this.$route.path.match(/^(\/[^\/]*\/[^\/]*).*$/i);
+        const m = this.$route.path.match(/^(\/[^/]*\/[^/]*).*$/i);
         return (m ? m[1] : this.$route.path);
     }
 
 }
+
+export default vueComponent(CardIndex);
 //-----------------------------------------------------------------------------
 </script>
 

+ 2 - 2
client/components/ExternalLibs/ExternalLibs.vue

@@ -412,7 +412,7 @@ class ExternalLibs extends Vue {
         if (this.ready && this.selectedLink) {
             result += ` | ${(this.libs.comment ? this.libs.comment + ' ': '') + lu.removeProtocol(this.libs.startLink)}`;
         }
-        this.$root.$emit('set-app-title', result);
+        this.$root.setAppTitle(result);
         return result;
     }
 
@@ -810,7 +810,7 @@ class ExternalLibs extends Vue {
     }
 
     keyHook(event) {
-        if (this.$root.rootRoute() == '/external-libs') {
+        if (this.$root.getRootRoute() == '/external-libs') {
             if (this.$root.stdDialog.active)
                 return false;
 

+ 4 - 4
client/components/Reader/Reader.vue

@@ -311,7 +311,7 @@ class Reader extends Vue {
             await bookManager.init(this.settings);
             bookManager.addEventListener(this.bookManagerEvent);
 
-            if (this.$root.rootRoute() == '/reader') {
+            if (this.$root.getRootRoute() == '/reader') {
                 if (this.routeParamUrl) {
                     await this.loadBook({url: this.routeParamUrl, bookPos: this.routeParamPos, force: this.routeParamRefresh});
                 } else {
@@ -921,7 +921,7 @@ class Reader extends Vue {
         }
 
         if (result != 'TextPage') {
-            this.$root.$emit('set-app-title');
+            this.$root.setAppTitle();
         }
 
         // на LoaderPage всегда показываем toolBar
@@ -936,7 +936,7 @@ class Reader extends Vue {
                 const isParsed = await bookManager.hasBookParsed(last);
 
                 if (!isParsed) {
-                    this.$root.$emit('set-app-title');
+                    this.$root.setAppTitle();
                     return;
                 }
 
@@ -1262,7 +1262,7 @@ class Reader extends Vue {
 
     keyHook(event) {
         let result = false;
-        if (this.$root.rootRoute() == '/reader') {
+        if (this.$root.getRootRoute() == '/reader') {
             if (this.$root.stdDialog.active)
                 return result;
 

+ 1 - 1
client/components/Reader/TextPage/TextPage.vue

@@ -436,7 +436,7 @@ class TextPage extends Vue {
 
                     this.title = bt.fullTitle;
 
-                    this.$root.$emit('set-app-title', this.title);
+                    this.$root.setAppTitle(this.title);
 
                     this.parsed = this.book.parsed;
 

+ 4 - 5
client/components/share/Notify.vue

@@ -4,12 +4,9 @@
 
 <script>
 //-----------------------------------------------------------------------------
-import Vue from 'vue';
-import Component from 'vue-class-component';
+import vueComponent from '../vueComponent.js';
 
-export default @Component({
-})
-class Notify extends Vue {
+class Notify {
     notify(opts) {
         let {
             caption = null,
@@ -55,5 +52,7 @@ class Notify extends Vue {
         this.notify(Object.assign({color: 'info', icon: 'la la-bell', message, caption}, options));
     }
 }
+
+export default vueComponent(Notify);
 //-----------------------------------------------------------------------------
 </script>

+ 40 - 21
client/components/share/StdDialog.vue

@@ -1,5 +1,5 @@
 <template>
-    <q-dialog ref="dialog" v-model="active" @show="onShow" @hide="onHide" no-route-dismiss>
+    <q-dialog ref="dialog" v-model="active" no-route-dismiss @show="onShow" @hide="onHide">
         <slot></slot>
 
         <!--------------------------------------------------->
@@ -10,7 +10,7 @@
                     <div v-html="caption"></div>
                 </div>
                 <div class="close-icon column justify-center items-center">
-                    <q-btn flat round dense v-close-popup>
+                    <q-btn v-close-popup flat round dense>
                         <q-icon name="la la-times" size="18px"></q-icon>
                     </q-btn>
                 </div>
@@ -21,7 +21,9 @@
             </div>
 
             <div class="buttons row justify-end q-pa-md">
-                <q-btn class="q-px-md" dense no-caps @click="okClick">OK</q-btn>
+                <q-btn class="q-px-md" dense no-caps @click="okClick">
+                    OK
+                </q-btn>
             </div>
         </div>
 
@@ -33,7 +35,7 @@
                     <div v-html="caption"></div>
                 </div>
                 <div class="close-icon column justify-center items-center">
-                    <q-btn flat round dense v-close-popup>
+                    <q-btn v-close-popup flat round dense>
                         <q-icon name="la la-times" size="18px"></q-icon>
                     </q-btn>
                 </div>
@@ -44,8 +46,12 @@
             </div>
 
             <div class="buttons row justify-end q-pa-md">
-                <q-btn class="q-px-md q-ml-sm" dense no-caps v-close-popup>Отмена</q-btn>
-                <q-btn class="q-px-md q-ml-sm" color="primary" dense no-caps @click="okClick">OK</q-btn>
+                <q-btn v-close-popup class="q-px-md q-ml-sm" dense no-caps>
+                    Отмена
+                </q-btn>
+                <q-btn class="q-px-md q-ml-sm" color="primary" dense no-caps @click="okClick">
+                    OK
+                </q-btn>
             </div>
         </div>
 
@@ -57,7 +63,7 @@
                     <div v-html="caption"></div>
                 </div>
                 <div class="close-icon column justify-center items-center">
-                    <q-btn flat round dense v-close-popup>
+                    <q-btn v-close-popup flat round dense>
                         <q-icon name="la la-times" size="18px"></q-icon>
                     </q-btn>
                 </div>
@@ -65,13 +71,19 @@
 
             <div class="q-mx-md">
                 <div v-html="message"></div>
-                <q-input ref="input" class="q-mt-xs" outlined dense v-model="inputValue"/>
-                <div class="error"><span v-show="error != ''">{{ error }}</span></div>
+                <q-input ref="input" v-model="inputValue" class="q-mt-xs" outlined dense />
+                <div class="error">
+                    <span v-show="error != ''">{{ error }}</span>
+                </div>
             </div>
 
             <div class="buttons row justify-end q-pa-md">
-                <q-btn class="q-px-md q-ml-sm" dense no-caps v-close-popup>Отмена</q-btn>
-                <q-btn class="q-px-md q-ml-sm" color="primary" dense no-caps @click="okClick">OK</q-btn>
+                <q-btn v-close-popup class="q-px-md q-ml-sm" dense no-caps>
+                    Отмена
+                </q-btn>
+                <q-btn class="q-px-md q-ml-sm" color="primary" dense no-caps @click="okClick">
+                    OK
+                </q-btn>
             </div>
         </div>
 
@@ -83,7 +95,7 @@
                     <div v-html="caption"></div>
                 </div>
                 <div class="close-icon column justify-center items-center">
-                    <q-btn flat round dense v-close-popup>
+                    <q-btn v-close-popup flat round dense>
                         <q-icon name="la la-times" size="18px"></q-icon>
                     </q-btn>
                 </div>
@@ -92,14 +104,20 @@
             <div class="q-mx-md">
                 <div v-html="message"></div>
                 <div class="q-my-md text-center">
-                    <div v-show="hotKeyCode == ''" class="text-grey-5">Нет</div>
+                    <div v-show="hotKeyCode == ''" class="text-grey-5">
+                        Нет
+                    </div>
                     <div>{{ hotKeyCode }}</div>
                 </div>
             </div>
 
             <div class="buttons row justify-end q-pa-md">
-                <q-btn class="q-px-md q-ml-sm" dense no-caps v-close-popup>Отмена</q-btn>
-                <q-btn class="q-px-md q-ml-sm" color="primary" dense no-caps @click="okClick" :disabled="hotKeyCode == ''">OK</q-btn>
+                <q-btn v-close-popup class="q-px-md q-ml-sm" dense no-caps>
+                    Отмена
+                </q-btn>
+                <q-btn class="q-px-md q-ml-sm" color="primary" dense no-caps :disabled="hotKeyCode == ''" @click="okClick">
+                    OK
+                </q-btn>
             </div>
         </div>
     </q-dialog>
@@ -107,19 +125,18 @@
 
 <script>
 //-----------------------------------------------------------------------------
-import Vue from 'vue';
-import Component from 'vue-class-component';
-
+import vueComponent from '../vueComponent.js';
 import * as utils from '../../share/utils';
 
-export default @Component({
+const componentOptions = {
     watch: {
         inputValue: function(newValue) {
             this.validate(newValue);
         },
     }
-})
-class StdDialog extends Vue {
+};
+class StdDialog {
+    _options = componentOptions;
     caption = '';
     message = '';
     active = false;
@@ -313,6 +330,8 @@ class StdDialog extends Vue {
         }
     }
 }
+
+export default vueComponent(StdDialog);
 //-----------------------------------------------------------------------------
 </script>
 

+ 5 - 2
client/components/vueComponent.js

@@ -35,13 +35,16 @@ export default function(componentClass) {
             computed[method] = {get: desc.get};
             if (desc.set)
                 computed[method].set = desc.set;
-        } else if (!['constructor', 'vueOptions'].includes(method)) {//usual
+        } else if (['beforeCreate', 'created', 'beforeMount', 'mounted', 'beforeUpdate', 'updated', 'activated',
+                    'deactivated', 'beforeUnmount', 'unmounted', 'errorCaptured', 'renderTracked', 'renderTriggered'].includes(method)) {//life cycle hooks
+            comp[method] = obj[method];
+        } else if (method !== 'constructor') {//usual
             methods[method] = obj[method];
         }
     }
     comp.methods = methods;
     comp.computed = computed;
 
-    console.log(comp);
+    //console.log(comp);
     return defineComponent(comp);
 }

+ 3 - 3
client/main.js

@@ -1,16 +1,16 @@
 import { createApp } from 'vue';
 
-//import router from './router';
+import router from './router';
 import store from './store';
 import {Quasar, QuasarOptions} from './quasar';
 //import vueSanitize from 'vue-sanitize';
 
-import App from './components/App1.vue';
+import App from './components/App.vue';
 
 //Vue.prototype.$isMobileDevice = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
 
 const app = createApp(App);
-//app.use(router);
+app.use(router);
 app.use(store);
 app.use(Quasar, QuasarOptions);
 //app.use(vueSanitize);

+ 1 - 5
client/quasar.js

@@ -2,7 +2,6 @@ import 'quasar/dist/quasar.css';
 //import Quasar from 'quasar/dist/quasar.umd.prod.js';
 
 import Quasar from 'quasar/src/vue-plugin.js';
-/*
 //config
 const config = {};
 
@@ -91,8 +90,5 @@ import '@quasar/extras/line-awesome/line-awesome.css';
 import lineAwesome from 'quasar/icon-set/line-awesome.js'
 Quasar.iconSet.set(lineAwesome);
 
-export default {quasar: Quasar, quasarOptions: { config, components, directives, plugins }};
-*/
-
-const QuasarOptions = {};
+const QuasarOptions = { config, components, directives, plugins };
 export {Quasar, QuasarOptions};

+ 11 - 11
client/router.js

@@ -2,39 +2,39 @@ import { createRouter, createWebHashHistory } from 'vue-router';
 import _ from 'lodash';
 
 const CardIndex = () => import('./components/CardIndex/CardIndex.vue');
-const Search = () => import('./components/CardIndex/Search/Search.vue');
+/*const Search = () => import('./components/CardIndex/Search/Search.vue');
 const Card = () => import('./components/CardIndex/Card/Card.vue');
 const Book = () => import('./components/CardIndex/Book/Book.vue');
-const History = () => import('./components/CardIndex/History/History.vue');
+const History = () => import('./components/CardIndex/History/History.vue');*/
 
 //немедленная загрузка
 //import Reader from './components/Reader/Reader.vue';
-const Reader = () => import('./components/Reader/Reader.vue');
-const ExternalLibs = () => import('./components/ExternalLibs/ExternalLibs.vue');
+const Reader = () => import('./components/Reader/Reader1.vue');
+//const ExternalLibs = () => import('./components/ExternalLibs/ExternalLibs.vue');
 
-const Income = () => import('./components/Income/Income.vue');
+/*const Income = () => import('./components/Income/Income.vue');
 const Sources = () => import('./components/Sources/Sources.vue');
 const Settings = () => import('./components/Settings/Settings.vue');
 const Help = () => import('./components/Help/Help.vue');
-const NotFound404 = () => import('./components/NotFound404/NotFound404.vue');
+const NotFound404 = () => import('./components/NotFound404/NotFound404.vue');*/
 
 const myRoutes = [
     ['/', null, null, '/cardindex'],
     ['/cardindex', CardIndex],
-    ['/cardindex~search', Search],
+    /*['/cardindex~search', Search],
     ['/cardindex~card', Card],
     ['/cardindex~card/:authorId', Card],
     ['/cardindex~book', Book],
     ['/cardindex~book/:bookId', Book],
-    ['/cardindex~history', History],
+    ['/cardindex~history', History],*/
 
     ['/reader', Reader],
-    ['/external-libs', ExternalLibs],
-    ['/income', Income],
+    //['/external-libs', ExternalLibs],
+    /*['/income', Income],
     ['/sources', Sources],
     ['/settings', Settings],
     ['/help', Help],
-    ['/404', NotFound404],
+    ['/404', NotFound404],*/
     ['/(.*)', null, null, '/cardindex'],
 ];