如何在PyScript中更优地初始化并调用JavaScript类?
优化PyScript调用JavaScript类实例的方案
问题描述
希望完全通过PyScript初始化JavaScript类并调用其方法,当前实现用单例工厂类MyClassFactory跟踪MyClass实例,再通过useMyClass函数封装供PyScript调用,但觉得流程繁琐,寻求更简洁的实现方式。
现有实现代码
<head> <meta charset="UTF-8"> <script defer src="https://pyscript.net/latest/pyscript.js"></script> </head> <body> <script> class MyClass { constructor() { this.hi_count = 0; } sayHi() { if (this.hi_count === 0) { document.write('Hi<br>') } else { document.write('Hi Again<br>') } this.hi_count++ } } class MyClassFactory { constructor() { if (MyClassFactory.instance) { return MyClassFactory.instance; } this.myClasses = new Map(); MyClassFactory.instance = this; } createMyClass(id) { if(this.myClasses.has(id)) { return this.myClasses.get(id); } else { const myClass = new MyClass(); this.myClasses.set(id, myClass); return myClass; } } } function useMyClass(id, method) { const myClassFactory = new MyClassFactory(); const myClass = myClassFactory.createMyClass(id); myClass[method](); } </script> <py-script> import js js.useMyClass(1,"sayHi") # Creates new instance and calls sayHi method js.useMyClass(2,"sayHi") # Creates new instance and calls sayHi method js.useMyClass(1,"sayHi") # Uses existing instance with id 1 and calls sayHi method </py-script> </body> </html>
优化方案
方案1:简化JS侧实例管理,直接返回实例给PyScript
去掉冗余的工厂类,用全局Map直接管理MyClass实例,提供一个获取实例的函数,让PyScript能直接拿到实例引用,灵活调用方法或访问属性:
<head> <meta charset="UTF-8"> <script defer src="https://pyscript.net/latest/pyscript.js"></script> </head> <body> <script> class MyClass { constructor() { this.hi_count = 0; } sayHi() { document.write(this.hi_count === 0 ? 'Hi<br>' : 'Hi Again<br>'); this.hi_count++; } // 新增方法示例,PyScript可直接调用 getHiCount() { return this.hi_count; } } // 全局Map存储实例,替代工厂类逻辑 const myClassInstances = new Map(); // 暴露获取实例的函数给全局 window.getMyClassInstance = function(id) { if (!myClassInstances.has(id)) { myClassInstances.set(id, new MyClass()); } return myClassInstances.get(id); }; </script> <py-script> import js // 获取实例后直接调用方法,逻辑更直观 instance1 = js.getMyClassInstance(1) instance1.sayHi() instance2 = js.getMyClassInstance(2) instance2.sayHi() // 复用实例并调用其他方法 instance1.sayHi() print(f"Instance 1 hi count: {instance1.getHiCount()}") </py-script> </body> </html>
方案2:PyScript侧完全管理实例,JS仅暴露类
把MyClass暴露给全局,让PyScript直接初始化实例,并用Python字典管理实例,彻底简化JS侧代码,完全实现PyScript掌控初始化流程:
<head> <meta charset="UTF-8"> <script defer src="https://pyscript.net/latest/pyscript.js"></script> </head> <body> <script> class MyClass { constructor() { this.hi_count = 0; } sayHi() { document.write(this.hi_count === 0 ? 'Hi<br>' : 'Hi Again<br>'); this.hi_count++; } } // 将类暴露给全局,供PyScript访问 window.MyClass = MyClass; </script> <py-script> import js // Python侧用字典管理实例,完全掌控初始化逻辑 my_instances = {} def get_my_class(instance_id): if instance_id not in my_instances: // 通过js.MyClass.new()创建JS类实例 my_instances[instance_id] = js.MyClass.new() return my_instances[instance_id] // 使用示例 inst1 = get_my_class(1) inst1.sayHi() inst2 = get_my_class(2) inst2.sayHi() inst1.sayHi() </py-script> </body> </html>
两种方案的优势:
- 方案1保留JS侧实例管理,但去掉了冗余的工厂类结构,PyScript能直接操作实例,扩展性更强;
- 方案2将实例管理完全交给PyScript,JS仅负责定义类,完全符合“通过PyScript初始化”的需求。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

