python EEL + vue3.js 简单示例

把index.html 中引入eel.js 后,eel这个对象就是全局对象了,无论在index.htm中还是组件中,都能使用这个全局对象。

我们组件HelloWorld.vue挂载到组件App.vue上,然后把App.vue挂载到index.html 这样最常见的结构为例:

HelloWorld.vue

//HelloWorld.vue


<script setup>
import { ref } from 'vue'

const count = ref(0)
const message = ref("Hello World!")
 
const sayHelloByEEL = (x) => {
  eel.say_hello_py(x + Math.floor(Math.random() * 101).toString() + 'ee')
}

const sayHelloJS = (x) => {
    message.value = 'Say Hello From ' + Math.floor(Math.random() * 101).toString() +x;
}

//暴露sayHelloJS给Python (以say_hello_js为别名)
eel.expose(sayHelloJS, 'say_hello_js')


</script>

<template>

    <p><button type="button" @click="count++">count is: {{ count }}</button></p>
    <p><button @click="sayHelloByEEL('Javascript Button! ')">调用Python函数</button></p>
    <p>{{ message }}</p>
    <p><button @click="sayHelloJS(' JS Button!')">调用JS函数</button></p>

</template>

<style scoped>

</style>

App.vue

//App.vue

<template>
  <img alt="Vue logo" src="./assets/vue.svg"> python eel + Vue3
  <HelloWorld />
</template>

<script setup>

import HelloWorld from './components/HelloWorld.vue';

</script>

<style>
#app {
  text-align: center;
  margin-top: 60px;
}
</style>

index.html

<!doctype html>
<html>
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Apple</title>

<!-- 开发环境python端用9000端口,生产环境请换回相对路径 "/eel.js",及去掉window.eel.set_host("ws://localhost:9000"); 这句 -->
    <script type=text/javascript src="http://localhost:9000/eel.js"></script>
    <script>
          window.eel.set_host("ws://localhost:9000");
    </script>
    

  </head>
  <body style="margin: 0;">
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

main.js

//main.js

import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App);
app.mount('#app');

main.py

# main.py

import eel

eel.init('web', allowed_extensions=['.js', '.html'])

@eel.expose 
def say_hello_py(x):
    print('Hello from %s' % x)


say_hello_py('Python World!')
eel.say_hello_js('Python World!')  
eel.start({'port': 5173},port= 9000) 

如果要更灵活的测试,可用通过tkinter触发js_function。代码如下:

# tkinter_test_main.py

import eel

eel.init('web', allowed_extensions=['.js', '.html'])

@eel.expose 
def say_hello_py(x):
    print('Hello from %s' % x)




def on_button_click():
    """Generate a random number and call the JavaScript function via Eel"""
    random_number = random.randint(0, 100)
    eel.say_hello_js(f"python {random_number}")

def create_tkinter_window():
    """Create a simple Tkinter window with a button"""
    root = tk.Tk()
    root.title("Tkinter with Eel")
    Button(root, text="Send Random Number to JS", command=on_button_click).pack(pady=20)
    root.mainloop()

def run_tkinter():
    threading.Thread(target=create_tkinter_window, daemon=True).start()

if __name__ == "__main__":
    import tkinter as tk
    from tkinter import Button
    import random
    import threading

    run_tkinter()  # Create and run the Tkinter window in a separate thread

    say_hello_py('Python World!')
    eel.say_hello_js('Python World!')  
    eel.start({'port': 5173},port= 9000) 

======================

但VUE并不建议在组件中直接使用全局变量,推荐把全局变量绑定到vue的全局属性中。这样变量的更改是响应性的,会触发组件更新,确保组件反映最新状态。即:vue2使用 Vue.prototype.$eel = window.eel;  vue3使用 app.config.globalProperties.$eel = window['eel']

vue2 的例子:https://gitee.com/sunflower.git.isc/python-eel-vue  (Vue.prototype)

vue3的例子: https://github.com/youfak/python-eel-vite-vue-ts  (app.config.globalProperties)

我把以上vue3的例子化简了一下,把 hooksuseCurrentInstance 合并到组件中,并把ts改为js。

main.js

//main.js


import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App);

// 在 Vue 3 中添加全局属性(例如 `$eel`)
app.config.globalProperties.$eel = window.eel;


app.mount('#app');

 App.vue

<template>
  <img alt="Vue logo" src="./assets/vue.svg"> python eel + Vue3
  <HelloWorld />
</template>

<script>

import HelloWorld from './components/HelloWorld.vue';

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}


</script>

<style>
#app {
  text-align: center;
  margin-top: 60px;
}
</style>

HelloWorld.vue 

// HelloWorld.vue

<script setup>

//定义getCurrentInstance().appContext.config.globalProperties
import { ref, onMounted,getCurrentInstance } from 'vue'
const instance = getCurrentInstance();
const globalProperties = instance.appContext.config.globalProperties;

// create a reactive count using ref
const count = ref(0)
const message = ref("Hello World!")
 
const sayHelloByEEL = (x) => {
  globalProperties.$eel.say_hello_py(x + Math.floor(Math.random() * 101).toString())
}

const sayHelloJS = (x) => {
    message.value = 'Say Hello From ' + Math.floor(Math.random() * 101).toString() +x;
}

//使用 globalProperties 暴露sayHelloJS给Python (以say_hello_js为别名)
globalProperties.$eel.expose(sayHelloJS, 'say_hello_js')


onMounted(() => {
  console.log(globalProperties)
})


</script>

<template>

    <p><button type="button" @click="count++">count is: {{ count }}</button></p>

    <p><button @click="sayHelloByEEL('Javascript Button! ')">调用Python函数</button></p>
    <p>{{ message }}</p>
    <p><button @click="sayHelloJS(' JS Button!')">调用JS函数</button></p>

</template>

<style scoped>

</style>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值