我对tauri和它的后端rust还很陌生。我开始在visual studio上开发,到目前为止,开发进展顺利,直到我需要创建物理窗口时,用户需要被引导到应用程序的其他部分,例如设置或从应用程序的前端访问人工智能模型。
从我对tauri的这个设置的理解来看,前端由Typescript,CSS,HTMl和React处理。后端由rust处理。
根据Tauri官方文档,窗口打开有三种方式(参见Tauri文档https://tauri.app/v1/guides/features/multiwindow#accessing-a-window-at-runtime):
1.静态
窗口可以静态添加,方法是在最初创建tauri项目时,在windows-tauri-app命令提供的tauri.conf.json文件的**“windows:“**部分或块中添加条目。
tauri.conf.json:
{
"tauri": {
"windows": [
{
"label": "external",
"title": "Tauri Docs",
"url": "https://tauri.app"
},
{
"label": "local",
"title": "Tauri",
"url": "index.html"
}
]
}
}
字符串
用户接近
2.前端:JavaScript/Typescript
窗口可以通过在前端创建webview示例打开。
JavaScript:
import { WebviewWindow } from '@tauri-apps/api/window'
const webview = new WebviewWindow('theUniqueLabel', {
url: 'path/to/page.html',
})
// since the webview window is created asynchronously,
// Tauri emits the `tauri://created` and `tauri://error` to notify you of the creation response
webview.once('tauri://created', function () {
// webview window successfully created
})
webview.once('tauri://error', function (e) {
// an error occurred during webview window creation
})
型
打印文本:
import { WebviewWindow } from '@tauri-apps/api/window';
const webview = new WebviewWindow('theUniqueLabel', {
url: 'path/to/page.html',
});
// since the webview window is created asynchronously,
// Tauri emits the `tauri://created` and `tauri://error` to notify you of the creation response
webview.once('tauri://created', () => {
// webview window successfully created
console.log('Webview window successfully created');
});
webview.once('tauri://error', (e) => {
// an error occurred during webview window creation
console.error('Error creating webview window:', e);
});
型
3.后端:Rust
通过App示例、App句柄或tauri命令,使用AppBuilder::结构体创建窗口:
应用示例:
tauri::Builder::default()
.setup(|app| {
let docs_window = tauri::WindowBuilder::new(
app,
"external", /* the unique window label */
tauri::WindowUrl::External("https://tauri.app/".parse().unwrap())
).build()?;
let local_window = tauri::WindowBuilder::new(
app,
"local",
tauri::WindowUrl::App("index.html".into())
).build()?;
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running app");
型
应用句柄:
tauri::Builder::default()
.setup(|app| {
let handle = app.handle();
std::thread::spawn(move || {
let local_window = tauri::WindowBuilder::new(
&handle,
"local",
tauri::WindowUrl::App("index.html".into())
).build()?;
});
Ok(())
})
型
tauri命令:
\#\[tauri::command\]
async fn open_specific_window(handle: tauri::AppHandle) {
let specific_window = tauri::WindowBuilder::new(
&handle,
"external", /\* the unique window label \*/
tauri::WindowUrl::External("https://tauri.app/".parse().unwrap())
).build().unwrap();
}
型
- 注意:* 命令函数需要是一个candic函数,以避免windows上的死锁。(参考这个堆栈来看看这个gent是如何解决的:(I am trying to create a new window using Tauri 1.2, Rust, React, and Typescript. I am facing some issues)
我的方法
我使用了第三种方法,因为直观上,它看起来像是我最简单的方法,并且它以直接的方式优化性能。其他两种方法工作得很好,但第三种方法需要额外的步骤,我将强调这一点作为这个堆栈的答案。再次,我想使用第三种方法,因为我相信它应该具有优化的性能和易于实现。一个我会贴到这个堆栈上的?
另外,这是我的第一个堆栈上堆栈溢出。我想打开这个问题,以帮助其他人在不浪费他们的时间像我一样。任何建议,欢迎。
我尝试了第三种方法,正如我在问题的细节中所规定的那样。
Rust命令
我创建了一个rust命令来创建窗口:
#[tauri::command]
async fn open_settings_window(app: tauri::AppHandle) {
let file_path = "src-tauri/src/Views/settings.html";
let _settings_window = tauri::WindowBuilder::new(
&app,
"Settings", /* the unique window label */
tauri::WindowUrl::App(file_path.into()),
)
.title("Settings")
.build()
.unwrap();
}
型
- 注意:* 我花了很长时间才弄清楚tauri::WindowUrl::App()只加载html,请使用html文件。
前端调用rust命令
当用户点击按钮(id = settings-button)时,我调用了rust命令:
下面是App.tsx文件:
import { useState } from "react";
import reactLogo from "./assets/react.svg";
import { invoke } from "@tauri-apps/api/tauri";
import "./App.css";
function App() {
const [greetMsg, setGreetMsg] = useState("");
const [name, setName] = useState("");
async function open_settings() {
await invoke("open_settings_window") ;
console.log("Window was opened") ;
}
async function greet() {
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
setGreetMsg(await invoke("greet", { name }));
}
async function TerminateApplication() {
await invoke("terminate_application") ;
}
return (
<div className="container">
<h1>Welcome to SSLT!</h1>
<div className="eye-container align-justify-center">
<div className="eye align-justify-center">
<div className="iris align-justify-center">
<div className="pupil align-justify-center"></div>
</div>
</div>
</div>
<form
id="form"
className="row"
onSubmit={(e) => {
e.preventDefault();
greet();
}}
>
<input
id="greet-input"
onChange={(e) => setName(e.currentTarget.value)}
placeholder="Enter a name..."
/>
<button type="submit">Greet</button>
</form>
<p>{greetMsg}</p>
<div className="options-container align-justify-center">
<button type="submit" className="option">AI model</button>
<button className="option" onClick={open_settings} id="settings-button" >
Settings
</button>
<button className="option" onClick={TerminateApplication}>Exit</button>
</div>
</div>
);
}
export default App;
型
它正确地调用了rust命令,并按照rust命令中的编程创建了一个文件。唯一的问题是它实际上并没有在指定的html文件中显示连接的类型脚本的内容。
html文件内容:
<!doctype html>
<html lang="en">
<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>Tauri + React + TS</title>
</head>
<body>
<div>Hello</div>
<!-- Include the compiled TypeScript file -->
<script type="module" src="settings-main.tsx"></script>
</body>
</html>
型
如果有人有这个问题,请帮助。我最终得到了解决方案...
1条答案
按热度按时间vojdkbi01#
我终于找到了解决办法...
好吧,我找到了一个解决方案。 typescript 应该使用div和React重新呈现。
1.创建一个额外的文件,{specific window}-main.tsx
字符串
document.getElementById("settings-root")
通过其id获取容器div,并相应地将上述组件渲染到该div中。2.连接html文件中的新脚本(tauri窗口创建命令中调用的文件)。
型
注意:确保div有一个可以在React部分中关联的id,请参阅步骤1的说明。
结论
这解决了我使用rust命令创建窗口的问题,最终将实际的 typescript 加载到容器中并显示其内容。
下面是两个窗口打开的示例:
Link to the result of the solution
使用方法3的简短指南
1.为特定窗口创建tauri命令
型
2.创建包含窗口内容的window.tsx文件
型
3.创建html文件
型
4.创建window-main.tsx文件
型
注意事项:请检查组件(本例中为Window_View())是否正确导入,组件是否在过程
ReactDOM.createRoot(document.getElementById("window-root") as HTMLElement).render();
中呈现。另外,只需检查过程是否通过其id获取正确的div,它需要是我们创建的html文件中声明的div。总的来说
只要检查所有的导入,脚本,和任何带有路径的东西是否正确。请,你不想浪费你的时间...
谢谢你
感谢您的时间,我真的希望这有助于任何人有同样的问题.这是我很难甚至得到任何视频教程或官方文档,以帮助在这个问题.我希望这有助于:)