noname icon indicating copy to clipboard operation
noname copied to clipboard

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

Open nonameShijian opened this issue 11 months ago • 2 comments

以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);

nonameShijian avatar Mar 12 '24 08:03 nonameShijian

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

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

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

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

itsnoteasytonameaccount avatar Mar 23 '24 19:03 itsnoteasytonameaccount

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

nonameShijian avatar Mar 24 '24 05:03 nonameShijian