Rust 和 Wasm 的融合,使用 yew 构建 web 前端(3)- 资源文件及小重构
前两篇文章《起步及 crate 选择》和《组件和路由》中,我们介绍了选型原因,搭建了 yew 的基本开发环境,并进行了最基础的组件和路由编码。并且和 yew 中文文档的翻译者 sansx 老师及一些感兴趣的朋友进行了友好而热烈的交流。
关于交流心得,笔者感觉有必要提及一下,作为一个即要走路也要看路的技术认知:
- 关于
html!
宏中的<>……</>
,这是因为html!
宏仅能有一个根标签元素。<>……</>
充当了一个根标签,输出实际上是空的。另外,html!
宏中的标签必须闭合,即使 html5 标准中不需要/>
的自闭合标签,也不能省略/>
。如<img src="path" />
。 - yew 生产环境的应用。笔者仅是 yew 的初学者,理解不很恰当。根据对官方 API 文档的理解,个人认为当前版本(yew 0.18)用于生产环境,是一个不小的挑战(包括开发和维护)。但从项目源码、issues 讨论,以及路线规划来看,个人认为下个版本(yew 0.19)差强人意,待发布后,yew 0.19 用于生产环境是可以接受的。笔者也有此计划。
- ssr 或者 seo 方面,yew 官方有计划,但未有实质进度。但笔者认为影响不大,网上几年前就有文章给出了结论:新时代的搜索引擎(Google、Yahoo、Bing、DuckDuckGo 等),能够像现代浏览器一样访问网站,能很好的抓取动态渲染后的内容,不用担心使用 yew 之类的框架而导致 seo 出现问题。几年过去了,搜索引擎的技术进步应该很大。再者,笔者认为现在信息传播的方式已经有所改变,国内尤为明显。最后,当国外搜索引擎已经收录大量中文站点的内容时,某些国内搜索引擎,却仅是首页甚至是未有收录;这样的情形,即使技术方面对 seo 很适配,估计也是不能解决收录问题的。
- Rust 官方周报 393 期中有一篇技术,是关于 Rust + WebAssembly 为 deno 开发插件系统的,看起来前景很不错。基于 WebAssembly 的性能和特性,如果插件足够通用,说不定可发展为一个独立的职业。
前两篇文章中,我们实现的界面是非常简陋的,没有引入任何样式、图像等 web 应用必不可少的资源文件。本篇文章中,我们将实践如何对 yew 组件使用样式,组件包含图片等。严格来说,这部分是属于构建工具 trunk
的知识。trunk
工具在首篇文章《起步及 crate 选择》中已经提及,是完全的 Rust 技术栈开发,不同于 wasm-pack 那样需要 node 环境。其在样式方面,支持 css/sass/scss(scss 实质是 sass3 及之后的升级版,目前使用更广一些),我们都将进行实践。图像方面,笔者分别引入 icon 和在组件中放置 <img>
标签以作示例。其它 js 和数据等资源文件,未有设计,但使用和图像是类同的。
引入样式表
笔者在 frontend-yew
目录中,创建如下目录和结构,放置资源文件:
mkdir -p assets/{css, imgs, js, data}
cd assets/css
touch style.css style.sass style.scss
css 代码
我们分别有 css、sass,以及 scss,仅是为验证 trunk
对其都可以编译。
style.css
.home {
background-color: red;
}
style.sass
$users-color: blue
.users
background-color: $users-color;
style.scss
.logo-title {
line-height: 40px;
display:flex;
align-items: center;
}
.nav {
line-height: 30px;
display:flex;
align-items: center;
margin-bottom: 20px;
font-weight: bold;
}
$projects-color: green;
.projects {
background-color: $projects-color;
}
将样式表加入 trunk 构建路径
trunk 工具构建时,资源文件通过 <link>
标签引入,但需要声明 data-trunk
。我们要将上述三个样式表加入构建路径,在 index.html
文件中的 <head>
标签内,加入它们的路径:
<!doctype html>
<html lang="zh">
<head>
<title>tide-async-graphql-mongodb - frontend - yew</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="zzy, https://github.com/zzy/tide-async-graphql-mongodb">
<link data-trunk rel="css" href="assets/css/style.css">
<link data-trunk rel="sass" href="assets/css/style.sass">
<link data-trunk rel="scss" href="assets/css/style.scss">
</head>
</html>
组件中使用 css
重要:以下均为代码片段,请注意文件名,以及不同的样式表压入方法。
使用 &str
字符串字面量
如在 main.rs
中的应用入口组件上,使用 style.scss
声明的样式:
fn view(&self) -> Html {
type Anchor = RouterAnchor<Route>;
let home_cls = "nav";
html! {
<>
<div class="logo-title">
{ "tide-async-graphql-mongodb / frontend-yew" }
</div>
<div class=home_cls>
<Anchor route=Route::Users>
{ "用户列表" }
</Anchor>
{ " - " }
……
……
……
</>
}
}
如在 users.rs
中的用户列表组件上,使用 style.sass
声明的样式:
fn view(&self) -> Html {
html! {
<div class="users">
{ "用户列表 - 蓝色" }
</div>
}
}
使用 classes! 宏
yew 的近期版本中,新增了 classes!
宏,让样式表的压入更灵活,扩展性更强。
如在 home.rs
中的主界面组件上,使用 style.css
声明的样式:
fn view(&self) -> Html {
let home_cls = "home";
html! {
<div class=classes!(home_cls)>
{ "主界面 - 红色" }
</div>
}
}
如在 projects.rs
中的项目列表组件上,使用 style.scss
声明的样式:
fn view(&self) -> Html {
html! {
<div class=classes!("projects")>
{ "项目列表 - 绿色" }
</div>
}
}
引入图像
笔者向 assets
目录中放入一个 favicon.png
图像,向 assets/imgs
目录中放入一个 budshome.png
图像。
icon 和 <img>
都是通过 <link>
标签加入到构建路径,但 rel
属性则不同:icon 图像的引入,定义为 rel="icon"
,而 <img>
使用的图像资源,则要在构建时复制:可以选择复制单个文件,也可以复制文件夹。
<link data-trunk rel="icon" href="assets/favicon.png">
<link data-trunk rel="copy-dir" href="assets/imgs">
# 或者复制单个文件
<link data-trunk rel="copy-file" href="assets/imgs/budshome.png">
笔者使用的是复制文件夹。至此,index.html
文件完整内容为:
<!doctype html>
<html lang="zh">
<head>
<title>tide-async-graphql-mongodb - frontend - yew</title>
<meta charset="utf-8">
<link data-trunk rel="icon" href="assets/favicon.png">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="zzy, https://github.com/zzy/tide-async-graphql-mongodb">
<link data-trunk rel="css" href="assets/css/style.css">
<link data-trunk rel="sass" href="assets/css/style.sass">
<link data-trunk rel="scss" href="assets/css/style.scss">
<link data-trunk rel="copy-dir" href="assets/imgs">
</head>
</html>
在 yew 组件代码中,我们直接嵌入图像元素,注意此时图像路径从的根目录为 imgs
。
注意:
html!
宏中的标签必须闭合,即使 html5 标准中不需要/>
的自闭合标签,也不能省略/>
。
fn view(&self) -> Html {
type Anchor = RouterAnchor<Route>;
let home_cls = "nav";
html! {
<>
<div class="logo-title">
<img src="imgs/budshome.png" />
{ "tide-async-graphql-mongodb / frontend-yew" }
</div>
<div class=home_cls>
<Anchor route=Route::Users>
{ "用户列表" }
……
……
……
</>
}
}
运行和测试
执行 trunk serve
命令,浏览器会自动打开一个页面,或者手动在浏览器中访问 http://127.0.0.1:3001。如果你未按照上篇 trunk.toml
所介绍的配置,请访问你自定义的端口(默认为 8080)。
点击导航菜单,可以看到页面内容有了一些基础的样式,也显示了图像元素,当然还是很简陋。但本文是示例说明资源文件的引入和构建,目标已经达成。
代码重构:精简 html! 宏中代码,提取为函数
有朋友联系,讨论 main.rs
文件中的 <main>
标签内代码是否为好的实践?是否应当提取为一个函数之类的?以保持 html!
宏中代码尽量精简。
笔者深以为然,函数相对来说是较好的实践。同时引申一下:yew 的新版本,增加了 yew-functional
函数组件包,目前还未发布为独立的 crate。
我们简单对其重构,增加一个 switch
函数,返回值为 yew 中的 Html
类型,实质上是 VNode
枚举。
fn switch(switch: Route) -> Html {
match switch {
Route::Users => {
html! { <Users/> }
}
Route::Projects => {
html! { <Projects/> }
}
Route::Home => {
html! { <Home /> }
}
}
}
此时,main.rs
文件中的 <main>
标签内代码可精简为:
<main>
<Router<Route> render=Router::render(switch) />
</main>
yew 示例项目:sansx/yew-graphql-demo。此项目是 sansx 老师开发的 yew 示例。本系列文章中,笔者将对其深入参考 ;-)
谢谢您的阅读,欢迎交流。
相关文章
- Python: 复制文件和文件夹
- 【说站】安卓BD文件管理器v1.5.6.4专业版
- 文件路径问题
- 从 PE 文件资源表中提取文件的版本信息
- 【Android 内存优化】Android 工程中使用 libjpeg-turbo 压缩图片 ( 初始化压缩对象 | 打开文件 | 设置压缩参数 | 写入压缩图像数据 | 完成压缩 | 释放资源 )
- 【Android 热修复】热修复原理 ( Dex 文件拷贝后续操作 | 外部存储空间权限申请 | 执行效果验证 | 源码资源 )
- 【Android 安装包优化】Android 应用中 7zr 可执行程序准备 ( Android Studio 导入可执行 7zr 程序 | 从 Assets 资源文件拷贝 7zr 到内置存储 )
- 【Android Gradle】安卓应用构建流程 ( 资源文件编译 )
- 【Unity3D】资源文件 ① ( Unity 中常用的文件类型 | Unity 文件操作 | 文件系统中查看文件 | 添加文件 | 删除文件 | 导入文件 | 复制文件 | 缩略图显示 )
- 【Unity3D】资源文件 ② ( Unity 中场景文件简介 | 查看场景文件内容 | 场景文件相关操作 | 创建场景 | 打开场景 )
- drawable-v21 drawable-v24资源适配文件详解手机开发
- Maven让资源文件处理插件能够解析资源文件中的Maven属性详解程序员
- java获取资源文件详解编程语言
- 探寻Oracle dbf文件之秘密(oracledbf查看)
- 文件Linux解压实战:文件ZIP的解压技巧(linux的解压zip)
- Linux文件的取差集处理(linux文件差集)
- 夹Linux 进入文件夹的技巧(linux怎么进入文件)
- Linux环境下的文件压缩处理(linux下的压缩文件)
- 如何访问Linux系统文件(如何访问linux文件)
- BTSync:让Linux更加智能的文件同步神器(btsynclinux)
- 轻松实现:本地文件传输至 Linux 操作系统(本地文件传到linux)
- Linux下如何制作CHM文件(linux制作chm)
- 系统Linux LA文件系统:深入探索安全性与性能(linuxla文件)
- 轻松学习!25个常用Linux解压命令,打包、压缩war文件不再难!(linux解压命令war)
- 为构建文件服务器 使用 Redis 管理资源(文件带服务器redis)
- MySQL数据库文件不可读,导致数据无法访问,举例说明可能的原因和解决方法
- MySQL 安装故障下载后找不到安装文件(mysql下载后没有文件)
- 掌握oracle中的ora文件门槛(oracle中ora文件)
- 递归列出所有文件和目录
- c#递归访问文件夹(删掉歌词文件)
- Android中主要资源文件及文件夹介绍