libccy / noname

http://noname.pub
GNU General Public License v3.0
2.79k stars 603 forks source link

关于将现有的类封装为vue组件的尝试 #1068

Open nonameShijian opened 8 months ago

nonameShijian commented 8 months ago

以Dialog为例: 创建testDialog.vue: 内容就是初始dom模板和其Dialog的构造函数,其的其他方法由原先的类js中获取

<template>
    <div ref="dialog" class="dialog">
        <div ref="contentContainer" class="content-container">
            <div ref="content" class="content"></div>
        </div>
        <div ref="bar1" class="bar top"></div>
        <div ref="bar2" class="bar bottom"></div>
    </div>
</template>

<script setup>
import { Dialog } from "/noname/library/element/dialog.js";
import { ref, onMounted } from "/game/vue.esm-browser.js";
import { AI as ai } from '/noname/ai/index.js';
import { Get as get } from '/noname/get/index.js';
import { Game as game } from '/noname/game/index.js';
import { Library as lib } from "/noname/library/index.js";
import { status as _status } from '/noname/status/index.js';
import { UI as ui } from '/noname/ui/index.js';

const props = defineProps({
    static: {
        type: Boolean,
        required: false
    },
    hidden: {
        type: Boolean,
        required: false
    },
    notouchscroll: {
        type: Boolean,
        required: false
    },
    forcebutton: {
        type: Boolean,
        required: false
    },
    noforcebutton: {
        type: Boolean,
        required: false
    }
});

const dialog = ref();
defineExpose({ dialog })
const contentContainer = ref();
const content = ref();
const bar1 = ref();
const bar2 = ref();

onMounted(() => {
    let hidden = false;
    let noTouchScroll = false;
    let forceButton = false;
    let noForceButton = false;

    Object.setPrototypeOf(dialog.value, (lib.element.Dialog || Dialog).prototype);
    dialog.value.contentContainer = contentContainer.value;
    dialog.value.content = content.value;
    dialog.value.bar1 = bar1.value;
    dialog.value.bar2 = bar2.value;
    dialog.value.buttons = [];

    for (const [key, value] of Object.entries(props)) {
        switch (key) {
            case 'static': dialog.value.static = value; break;
            case 'hidden': hidden = true; break;
            case 'notouchscroll': noTouchScroll = true; break;
            case 'forcebutton': forceButton = true; break;
            case 'noforcebutton': noForceButton = true; break;
        }
    }

    if (!lib.config.touchscreen) dialog.value.contentContainer.onscroll = ui.update;
    if (!noTouchScroll) {
        dialog.value.contentContainer.ontouchstart = ui.click.dialogtouchStart;
        dialog.value.contentContainer.ontouchmove = ui.click.touchScroll;
        // @ts-ignore
        dialog.value.contentContainer.style.webkitOverflowScrolling = 'touch';
        dialog.value.ontouchstart = ui.click.dragtouchdialog;
    }
    if (noForceButton) dialog.value.noforcebutton = true;
    else if (forceButton) {
        dialog.value.forcebutton = true;
        dialog.value.classList.add('forcebutton');
    }
});
</script>

<style>
</style>

然后创建index.vue应用这个dialog组件:

<template>
    <noname-dialog ref="dialogRef" static hidden notouchscroll></noname-dialog>
</template>
<script setup>
import { onMounted, ref } from "/game/vue.esm-browser.js";
import NonameDialog from './testDialog.vue';

const dialogRef = ref(null);
onMounted(() => {
    window.dialog = dialogRef.value.dialog;
    dialogRef.value.dialog.add("测试");
});
</script>

最后在浏览器控制台中调用:

const { createApp } = await import("/game/vue.esm-browser.js");
const App = (await import('./index.vue')).default;
const app = createApp(App)
app.mount(document.body);
itsnoteasytonameaccount commented 7 months ago

不建议这样做吧。 使用某项技术是为了解决特定问题,而不应该为了使用技术而使用技术。 当前工程结构虽然看似原始了点,但我觉得蛮好的,启动也方便,没必要使用vue吧。

我认为引入vue是有如下缺点的:

  1. 引入vue runtime无端增加运行的代码体积,工程复杂化,视情况需要引入打包器
  2. 可能引起性能的劣化,这类框架实际上相对原生代码实现界面性能是更差的,相当于是用一部分性能换取更清晰的工程组织方式、以及一些编写更简洁的语法糖
  3. 大量的重构工作量

如果使用vue编写部分组件带来的好处能超过上述缺点那我也支持使用,但如果没有好处的话,我建议不要这样做,另建一个分支或者自己试试可以,还是不要合入主干吧

nonameShijian commented 7 months ago

不建议这样做吧。 使用某项技术是为了解决特定问题,而不应该为了使用技术而使用技术。 当前工程结构虽然看似原始了点,但我觉得蛮好的,启动也方便,没必要使用vue吧。

我认为引入vue是有如下缺点的:

  1. 引入vue runtime无端增加运行的代码体积,工程复杂化,视情况需要引入打包器
  2. 可能引起性能的劣化,这类框架实际上相对原生代码实现界面性能是更差的,相当于是用一部分性能换取更清晰的工程组织方式、以及一些编写更简洁的语法糖
  3. 大量的重构工作量

如果使用vue编写部分组件带来的好处能超过上述缺点那我也支持使用,但如果没有好处的话,我建议不要这样做,另建一个分支或者自己试试可以,还是不要合入主干吧

主分支代码中直接使用vue文件确实会这样导致性能问题和重构问题。但是就目前来说,vue的引入我是更想让其应用于扩展文件(extension)。

目前如果你使用的是我提供的客户端或者使用noname-server.exe(一些特性还在测试中。不久后会更新官方的客户端来让所有人使用新特性),你可以直接import一个css,ts,json,vue文件,就像是在一个vue工程中那样。

但由于项目的更新方式(离线更新),这些新特性并不是主分支将来所急着去用的,反而是可以让扩展(extension)能更标准,便捷的编写。

以ui扩展为例子,目前的ui扩展,十周年ui等,其写法和主分支的某个特定版本过分藕合绑定。我打算写一套逻辑特定但ui可以自由切换为其他样式(目前的ui扩展大多都不互相兼容)的扩展用作此类美化扩展的标杆。

至于性能方面: 主分支加入了vue的runtime文件但是目前没有加载,所以在没有扩展主动加载的情况是不会有大的性能问题的。 目前确实加入了编译vue(sfc)和typeScript的代码,但是其运行在service worker,也不需要过于担心性能问题,虽然旧的客户端无法加载service worker