paint-brush
怎么样去操作 Swift 确定 Web 建设  @imike
15,815 讀數
15,815 讀數

如何使用 Swift 进行 Web 开发

通过 Mikhail Isaev33m2023/03/20
Read on Terminal Reader

太長; 讀書

SwifWeb 是一个框架,让您能够使用 SwiftUI 编写网站。它包装了整个 HTML 和 CSS 标准,以及所有的 Web API。在本文中,我将向您展示如何使用 SwifWeb 框架开始构建网站。
featured image - 如何使用 Swift 进行 Web 开发
Mikhail Isaev HackerNoon profile picture
0-item
1-item
Web 激发的世界级是茫茫的,在一天到晚一大批的源源一个劲的新型技术设备水平中很轻易有被遗忘。绝大部分数哪些新型技术设备水平还是用到 JavaScript 或 TypeScript 建立的。可,在此文中,我将就直接在打开网页器中向您推荐怎么样才能用到安卓原生系统 Swift 完成 Web 激发,我想必它会给您留给记忆犹新映像。


这怎么可能?

要让 Swift 在网页上上本市运作,它应该先被编译成 WebAssembly 字节码,但是 JavaScript 应该将该源代码加载图片到页面设置上。全编译时候有的难搞,这是由于我们都应该利用唯一性的辅助交通工具链和共建的让资料,这即是为之类有的让 CLI 辅助交通工具能够用:Carton 和 Webber。

可以使用第三方工具链吗?

社区网站做过大批做工作,利用修整初始 Swift 方式链,使将 Swift 编译成 WebAssembly 被选为很有可能。这些利用每周智能从初始方式链中领取更变并在测验未能时修理这些的树状来升级方式链。这些的目的是被选为官方版方式链的一款分,这些都希望这会在赶紧的未来十年造成。

纸箱还是韦伯?

由 SwiftWasm 居委会制成,可以于 Tokamak 大型项目,该结构使您能够用 SwiftUI 编辑站点。


专为 SwifWeb 创业项目而开发。 SwifWeb 的不一小细节是它彩盒了大部分 HTML 和 CSS 标准规定,已经各种的 Web API。


即便您可以更钟爱采用 SwiftUI 来编写出 Web 用途方试以推动源代码不一性,但我所以她是问题的做法,所以 Web 联合开发在其实质上都是同的,是不能以与 SwiftUI 雷同的方试做补救。


这也就是你们构建 SwifWeb 的的原因,它使您是可以可以直接从 Swift 中选择 HTML、CSS 和 Web API 的各种能力,选择其迷人的句型、主动做好和表格。我构建了 Webber 的工具,而是 Carton 无非以对的的习惯编译、校准和推进 SwifWeb 应用领域程度,而是它不再是为它构建的。


我是mt Mikhail Isaev,是 SwifWeb 的我们。在这篇文中,我将向您体现怎么样去施用 SwifWeb 开始了创建网站建设。

所需工具


迅速

您需要安装 Swift,最简单的方法是:

  • 在 macOS 上是安装 Xcode
  • 在 Linux 或 Windows(WSL2) 上是使用来自的脚本


某些实际情况使用)
 brew install swifweb/tap/webber
稍后的更新到多种新版本只需使用
brew upgrade webber


在 Ubuntu 或 Windows(WSL2 中的 Ubuntu)入手动克隆和编译 Webber
 sudo apt-get install binaryen curl //get.wasmer.io -sSfL | sh apt-get install npm cd /opt sudo git clone //github.com/swifweb/webber cd webber sudo swift build -c release sudo ln -s /opt/webber/.build/release/Webber /usr/local/bin/webber
稍后手机版本更新到最新头条手机版本运动
cd /opt/webber sudo git pull sudo swift build -c release

分支总是包含稳定的代码,所以可以随意从中提取更新

创建新项目

打开末端并继续执行
webber new

在交互式菜单中选择pwaspa ,然后输入项目名称。


将目录更改为新创建的项目并执行webber serve

此命令会将您的项目编译成 WebAssembly,将所有必需的文件打包到一个特殊的.webber文件夹中,并在默认情况下使用端口8888在所有接口上开始为您的项目提供服务。


webber serve的附加参数

  • 运用款式

    -t pwa用于渐进式 Web 应用程序

    -t spa用于单个 Web 应用程序

  • Service Worker 目标的名称(在 PWA 项目中通常命名为Service

    -s Service

  • 应用目标的名称(默认为App

    -a App

  • 在调整台中打印出更好地相关信息

    -v

  • Webber 服务器的端口(默认为8888

    -p 8080

使用-p 443像真正的 SSL 一样进行测试(使用允许的自签名 SSL 设置)

  • 自动化开启的总体目标查看器明称

    --browser safari--browser chrome

  • 兼有允许的自个人签名 SSL 设立以调整工作人的浏览记录器的额外增加例子

    --browser-self-signed

  • 地处隐藏摸式的游览器器的各种实验总结

    --browser-incognito

应用

该应用程序开始于Sources/App/App.swift

 import Web @main class App: WebApp { @AppBuilder override var app: Configuration { Lifecycle.didFinishLaunching { app in app.registerServiceWorker("service") } Routes { Page { IndexPage() } Page("login") { LoginPage() } Page("article/:id") { ArticlePage() } Page("**") { NotFoundPage() } } MainStyle() } }

生命周期

它以类似 iOS 的方式工作:

didFinishLaunching应用刚启动时

willTerminate当应用程序将要结束时

willResignActive当窗口将要处于非活动状态时

didBecomeActive当窗口处于活动状态时

didEnterBackground当窗口进入后台时

willEnterForeground当窗口进入前景时


这里最有用的方法是didFinishLaunching因为它是配置应用程序的好地方。你看它感觉真的像一个 iOS 应用程序! 😀


这里的app包含有用的便利方法:

registerServiceWorker(“serviceName“)调用以注册 PWA service worker

addScript(“path/to/script.js“)调用以添加相关或外部脚本

addStylesheet(“path/to/style.css“)调用以添加相对或外部样式

addFont(“path/to/font.woff”, type:)调用添加相对或外部字体,可选择设置类型

addIcon(“path/to/icon“, type:color:)调用添加图标,可选择设置类型和颜色


凡此种种,它是运行环境其它的库的去处,如 、 、 等。

航线

要求路由以按照其某些 URL 提示 应适当的网站页面。


要理解怎么应用路由,您必须要理解 URL 是哪些样的

//website.com/hello/world - 这里/hello/world路径

如您所见所闻,开一已经,我可以在 App 类中证明函所以顶尖级路由。顶极含意着在那些路由中申明的手机网页将居于工具栏中的一部分室内空间。


好的,假如可不可以用这几种办法设定根路由
Page("/") { IndexPage() } Page("") { IndexPage() } Page { IndexPage() }
我觉得接下来一是最美的人丽的🙂


可以这类如何设置公司注册或公司注册路由
Page("login") { LoginPage() } Page("registration") { RegistrationPage() }


参数相关路由

Page("article/:id") { ArticlePage() }

上例中的:id是路由的动态部分。我们可以在ArticlePage类中检索此标识符以显示与其关联的文章。

 class ArticlePage: PageController { override func didLoad(with req: PageRequest) { if let articleId = req.parameters.get("id") { // Retrieve article here } } }
途径中能有众多主要参数。以完全相同的方式索引因此这种。

查询

路径中下一个有趣的事情是查询,它也非常易于使用。例如,让我们考虑/search路由,它期望具有搜索textage查询参数。

//website.com/search**?text=Alex&age=19** - 最后一部分是查询


只需证明函查找路径
Page("search") { SearchPage() }

并像这样在SearchPage类中检索查询数据

class SearchPage: PageController { struct Query: Decodable { let text: String? let age: Int? } override func didLoad(with req: PageRequest) { do { let query = try req.query.decode(Query.self) // use optional query.text and query.age // to query search results } catch { print("Can't decode query: \(error)") } } }

任何事物

您也可以使用*来声明接受特定路径部分中的任何内容的路由,如下所示

Page("foo", "*", "bar") { SearchPage() }
顶端的路由将提供 foo 和 bar 两者的某些的内容,譬如 /foo/aaa/bar、/foo/bbb/bar 等。

包罗万象

使用**符号,您可以设置一个特殊的包罗万象的路由,该路由将处理任何未与特定路径上的其他路由匹配的内容。


用它来做vscode 404 路由
Page("**") { NotFoundPage() }
或指定方法,举例子当找不超过顾客时
Page("user", "**") { UserNotFoundPage() }


就让们公开道歉上文证明的线路的情况报告

/user/1 - 如果有 /user/:id 的路由,那么它将返回UserPage 。否则,它将陷入……


UserNotFoundPage

/user/1/hello - 如果有 /user/:id/hello 的路由,那么它将落入UserNotFoundPage

/something - 如果没有 /something 的路线那么它将落入NotFoundPage

嵌套路由

我们可能不想为下一个路由替换页面上的全部内容,而只是替换某些块。这就是FragmentRouter派上用场的地方!


假设我们在/user页面上有选项卡。每个选项卡都是一个子路径,我们希望使用FragmentRouter对子路径中的更改做出反应。


App类中声明顶级路由

Page("user") { UserPage() }

并在UserPage类中声明FragmentRouter

 class UserPage: PageController { @DOM override var body: DOM.Content { // NavBar is from Materialize library :) Navbar() .item("Profile") { self.changePath(to: "/user/profile") } .item("Friends") { self.changePath(to: "/user/friends") } FragmentRouter(self) .routes { Page("profile") { UserProfilePage() } Page("friends") { UserFriendsPage() } } } }


在上面的示例中, FragmentRouter处理/user/profile/user/friends子路由并将其呈现在Navbar下,因此页面永远不会重新加载整个内容,而只会重新加载特定的片段。


也可声明范文二个存在一模一件或不一件子路径名的片断,她们将像魔术表演一件一个操作!


顺便说一句, FragmentRouter是一个Div ,您可以通过调用来配置它

FragmentRouter(self) .configure { div in // do anything you want with the div }

样式表

您需要动用经典的 CSS 文件目录,但您也有动用 Swift 开发的种类表的新的奇异力!

基本

要使用 Swift 声明 CSS 规则,我们有Rule对象。


它还可以用调节其的方法以严正声明形式在校园营销推广活动的环节之中所构建
Rule(...selector...) .alignContent(.baseline) .color(.red) // or rgba/hex color .margin(v: 0, h: .auto)
或便用 @resultBuilder 的这样 SwiftUI 的策略
Rule(...selector...) { AlignContent(.baseline) Color(.red) Margin(v: 0, h: .auto) }


两种方式都是一样的,但是,我更喜欢第一种方式,因为在我输入. 😀

MDN 上简述的所有 CSS 形式都能作。不但这般,它还能定时办理阅读器前缀!
因为,您能够在很多单一事情时以这般行为放置自名词解释抗性
Rule(...selector...) .custom("customKey", "customValue")

选择器

要设制制度该印象哪几种事物,咱们有必要设制某个选定器。我将选定器作为统计数据比对库的在线查看,但我将该选定器在线查看的十一些分为指示针。


在校园营销推广活动的环节之中所构建指南的最方便做法是适用默认字节串对其做初始值化
Pointer("a")


但是正确的快速方法是通过在需要的 HTML 标记处调用.pointer来构建它,就像这样

H1.pointer // h1 A.pointer // a Pointer.any // * Class("myClass").pointer // .myClass Id("myId").pointer // #myId

它是关于基本指针的,但它们也有像:hover :first :first-child等修饰符。

 H1.pointer.first // h1:first H1.pointer.firstChild // h1:first-child H1.pointer.hover // h1:hover
您可能申明丝毫原有的呈现符,其都有能用的 的。
如若短缺这些项目,请不会优柔寡断地使用括展以更改它!和最好不要忘記在 github 上运送 pull request 来为每隔人增多它。
您还能否接入指南
H1.class(.myClass) // h1.myClass H1.id(.myId) // h1#myId H1.id(.myId).disabled // h1#myId:disabled Div.pointer.inside(P.pointer) // div p Div.pointer.parent(P.pointer) // div > p Div.pointer.immediatedlyAfter(P.pointer) // Div + p P.pointer.precededBy(Ul.pointer) // p ~ ul


如何在规则中使用选择器

Rule(Pointer("a")) // or Rule(A.pointer)

如何在规则中使用多个选择器

Rule(A.pointer, H1.id(.myId), Div.pointer.parent(P.pointer))
它产生以內 CSS 编号
a, h1#myId, div > p { }

反应性

令自己为自己的软件环节声明范文暗色和浅蓝色形状,稍后,自己将就能够更好地在其中间调节。
 import Web @main class App: WebApp { enum Theme { case light, dark } @State var theme: Theme = .light @AppBuilder override var app: Configuration { // ... Lifecycle, Routes ... LightStyle().disabled($theme.map { $0 != .happy }) DarkStyle().disabled($theme.map { $0 != .sad }) } }


LightStyleDarkStyle可以在单独的文件中或例如在 App.swift 中声明


class LightStyle: Stylesheet { @Rules override var rules: Rules.Content { Rule(Body.pointer).backgroundColor(.white) Rule(H1.pointer).color(.black) } } class DarkStyle: Stylesheet { @Rules override var rules: Rules.Content { Rule(Body.pointer).backgroundColor(.black) Rule(H1.pointer).color(.white) } }


接着在其他新页面的消费者界面显示中的其他区域调节
App.current.theme = .light // to switch to light theme // or App.current.theme = .dark // to switch to dark theme
它将系统激活或禁用相关联的版式表!这不再是很酷吗? 😎


但你或许能说用 Swift 说明图样用无限流量卡比用 CSS 更难,那有怎样的的意义呢?


重大是想法性!我国行将 @State 与 CSS 特点一齐利用并gif动态更换值!


看说一下,我们的可不可以运行某个具备着一部分出错式特性的类,并在操作时随意更换它,往往显示屏幕上运行这种的所有原子还会创新!它比是很多原子更换类要高效得多!


 import Web @main class App: WebApp { @State var reactiveColor = Color.cyan @AppBuilder override var app: Configuration { // ... Lifecycle, Routes ... MainStyle() } } extension Class { static var somethingCool: Class { "somethingCool" } } class MainStyle: Stylesheet { @Rules override var rules: Rules.Content { // for all elements with `somethingCool` class Rule(Class.hello.pointer) .color(App.current.$reactiveColor) // for H1 and H2 elements with `somethingCool` class Rule(H1.class(.hello), H2.class(.hello)) .color(App.current.$reactiveColor) } }


稍后从代碼中的所以好地方取用
App.current.reactiveColor = .yellow // or any color you want
它将更新软件种类表和每个用它的营养元素中的背景色😜


还有,还还行将原创 CSS 修改到形状腕表
class MainStyle: Stylesheet { @Rules override var rules: Rules.Content { // for all elements with `somethingCool` class Rule(Class.hello.pointer) .color(App.current.$reactiveColor) // for H1 and H2 elements with `somethingCool` class Rule(H1.class(.hello), H2.class(.hello)) .color(App.current.$reactiveColor) """ /* Raw CSS goes here */ body { margin: 0; padding: 0; } """ } }
您就可以基于必须 重复混和原本 CSS 字段串

页数

路由器在每条路线上渲染页面。 Page 是从PageController继承的任何类。


PageController具有诸如willLoad didLoad willUnload didUnload之类的生命周期方法、UI 方法buildUIbody以及用于 HTML 元素的属性包装器变量。

从技术上讲, PageController只是一个 Div,您可以在buildUI方法中设置它的任何属性。


 class IndexPage: PageController { // MARK: - Lifecycle override func willLoad(with req: PageRequest) { super.willLoad(with: req) } override func didLoad(with req: PageRequest) { super.didLoad(with: req) // set page title and metaDescription self.title = "My Index Page" self.metaDescription = "..." // also parse query and hash here } override func willUnload() { super.willUnload() } override func didUnload() { super.didUnload() } // MARK: - UI override func buildUI() { super.buildUI() // access any properties of the page's div here // eg self.backgroundcolor(.lightGrey) // optionally call body method here to add child HTML elements body { P("Hello world") } // or alternatively self.appendChild(P("Hello world")) } // the best place to declare any child HTML elements @DOM override var body: DOM.Content { H1("Hello world") P("Text under title") Button("Click me") { self.alert("Click!") print("button clicked") } } }


倘若你的首页好大,你以至于可能用那么短的玩法声明怎么写它
PageController { page in H1("Hello world") P("Text under title") Button("Click me") { page.alert("Click!") print("button clicked") } } .backgroundcolor(.lightGrey) .onWillLoad { page in } .onDidLoad { page in } .onWillUnload { page in } .onDidUnload { page in }
是不会是又耐看又简练? 🥲


奖金便利方法

alert(message: String) - 直接 JS alert方法

changePath(to: String) - 切换 URL 路径

元素

最终,我将说了您如何才能(!)创造出一个和便用 HTML 要素!


大部分中有属性数据的 HTML 化学元素在 Swift 中所快速可用,完正的文件列表在这类上。


仅是一款 HTML 要素的简洁所有范例:
SwifWeb编号公司网页源代码

Div()

<div></div>

H1(“text“)

<h1>text</h1>

A(“Click me“).href(““).target(.blank)

<a href=”” target=”_blank”>Click me</a>

Button(“Click“).onClick { print(“click“) }

<button onclick=”…”>Click</button>

InputText($text).placeholder("Title")

<input type=”text” placeholder=”title”>

InputCheckbox($checked)

<input type=”checkbox”>


如您耳闻,在 Swift 中远程访问其它 HTML 标签纸都是加容易,可能不仅复制粘贴本身,因此都以一模一样的英文名称表达出来。这是可能不一的复制粘贴形式有不一的方式 ,我也想混用。


简单的Div

 Div()
人们可像这样的话访问共享它的各个抗性和图样抗性
Div().class(.myDivs) // <div class="myDivs"> .id(.myDiv) // <div id="myDiv"> .backgroundColor(.green) // <div style="background-color: green;"> .onClick { // adds `onClick` listener directly to the DOM element print("Clicked on div") } .attribute("key", "value") // <div key="value"> .attribute("boolKey", true, .trueFalse) // <div boolKey="true"> .attribute("boolKey", true, .yesNo) // <div boolKey="yes"> .attribute("checked", true, .keyAsValue) // <div checked="checked"> .attribute("muted", true, .keyWithoutValue) // <div muted> .custom("border", "2px solid red") // <div style="border: 2px solid red;">

子类化

子类化 HTML 元素为其预定义样式,或者使用大量预定义的子元素和一些外部可用的方便方法制作复合元素,或者实现生命周期事件,如didAddToDOMdidRemoveFromDOM

让我们创建一个Divider元素,它只是一个Div但具有预定义的.divider

public class Divider: Div { // it is very important to override the name // because otherwise it will be <divider> in HTML open class override var name: String { "\(Div.self)".lowercased() } required public init() { super.init() } // this method executes immediately after any init method public override func postInit() { super.postInit() // here we are adding `divider` class self.class(.divider) } }
在子类化时读取超级大技巧如此重点。不会有它,您可能会遭遇到意想不着的情况。

追加到 DOM

该元素可以立即或稍后附加到PageControllerHTML 元素的 DOM。


接着
Div { H1("Title") P("Subtitle") Div { Ul { Li("One") Li("Two") } } }


或者稍后使用lazy var

 lazy var myDiv1 = Div() lazy var myDiv2 = Div() Div { myDiv1 myDiv2 }

所以你可以提前声明一个HTML 元素,然后随时将它添加到 DOM 中!

从 DOM 中移除

lazy var myDiv = Div() Div { myDiv } // somewhere later myDiv.remove()

访问父元素

每 HTML 物质都有条个会的 superview 附属性,如果你它被“添加到 DOM 中,它会互访其父物质
Div().superview?.backgroundColor(.red)

如果/否则条件

我们经常需要只在某些条件下显示元素,所以让我们使用if/else来实现

lazy var myDiv1 = Div() lazy var myDiv2 = Div() lazy var myDiv3 = Div() var myDiv4: Div? var showDiv2 = true Div { myDiv1 if showDiv2 { myDiv2 } else { myDiv3 } if let myDiv4 = myDiv4 { myDiv4 } else { P("Div 4 was nil") } }

但它不是反应性的。如果您尝试将showDiv2设置为false则不会发生任何事情。


反响性列子
lazy var myDiv1 = Div() lazy var myDiv2 = Div() lazy var myDiv3 = Div() @State var showDiv2 = true Div { myDiv1 myDiv2.hidden($showDiv2.map { !$0 }) // shows myDiv2 if showDiv2 == true myDiv3.hidden($showDiv2.map { $0 }) // shows myDiv3 if showDiv2 == false }


我们为什么要使用$showDiv2.map {…}

筛选:因它非 SwiftUI。可以并没有。


在下面阅续关干@State更多信息。


原始 HTML

您很有可能还要有将原本 HTML 增长到网页或 HTML 因素中,这很会保证
Div { """ <a href="//google.com">Go to Google</a> """ }


对于每个

静态示例

let names = ["Bob", "John", "Annie"] Div { ForEach(names) { name in Div(name) } // or ForEach(names) { index, name in Div("\(index). \(name)") } // or with range ForEach(1...20) { index in Div() } // and even like this 20.times { Div().class(.shootingStar) } }

动态示例

@State var names = ["Bob", "John", "Annie"] Div { ForEach($names) { name in Div(name) } // or with index ForEach($names) { index, name in Div("\(index). \(name)") } } Button("Change 1").onClick { // this will append new Div with name automatically self.names.append("George") } Button("Change 2").onClick { // this will replace and update Divs with names automatically self.names = ["Bob", "Peppa", "George"] }

CSS

与上面的示例相同,但也可以使用BuilderFunction

 Stylesheet { ForEach(1...20) { index in CSSRule(Div.pointer.nthChild("\(index)")) // set rule properties depending on index } 20.times { index in CSSRule(Div.pointer.nthChild("\(index)")) // set rule properties depending on index } }


您可以在ForEach循环中使用BuilderFunction仅计算一次某个值,例如以下示例中的delay

ForEach(1...20) { index in BuilderFunction(9999.asRandomMax()) { delay in CSSRule(Pointer(".shooting_star").nthChild("\(index)")) .custom("top", "calc(50% - (\(400.asRandomMax() - 200)px))") .custom("left", "calc(50% - (\(300.asRandomMax() + 300)px))") .animationDelay(delay.ms) CSSRule(Pointer(".shooting_star").nthChild("\(index)").before) .animationDelay(delay.ms) CSSRule(Pointer(".shooting_star").nthChild("\(index)").after) .animationDelay(delay.ms) } }


它也是可以将指数函数用作技术参数
BuilderFunction(calculate) { calculatedValue in // CSS rule or DOM element } func calculate() -> Int { return 1 + 1 }

BuilderFunction也可用于 HTML 元素 :)

与@State 的反应性

@State是当今声明式编程最需要的东西。


如我表面告诉你您的:它并非是 SwiftUI,故此没了追踪定位和重绘整个內容的静态状况机。 HTML 原素并非是二次空间结构,往往是类,故此它是是真的因素,您都可以简单登陆它是。它更多更智能化,您有了整个的决策权。

引擎盖下是什么?

它就是一个标签礼品盒器,通知函其它订阅关注者它的发生变化。

如何订阅更改?

 enum Countries { case usa, australia, mexico } @State var selectedCounty: Countries = .usa $selectedCounty.listen { print("country changed") } $selectedCounty.listen { newValue in print("country changed to \(newValue)") } $selectedCounty.listen { oldValue, newValue in print("country changed from \(oldValue) to \(newValue)") }

HTML 元素如何对变化做出反应?

简单化的txt文档范例
@State var text = "Hello world!" H1($text) // whenever text changes it updates inner-text in H1 InputText($text) // while user is typing text it updates $text which updates H1
简单的数子样例
@State var height = 20.px Div().height($height) // whenever height var changes it updates height of the Div
比较简单的布尔实例
@State var hidden = false Div().hidden($hidden) // whenever hidden changes it updates visibility of the Div
遍历实例
@State var isItCold = true H1($isItCold.map { $0 ? "It is cold 🥶" : "It is not cold 😌" })
地址转换俩个睡眠状态
@State var one = true @State var two = true Div().display($one.and($two).map { one, two in // returns .block if both one and two are true one && two ? .block : .none })
地址映射两上面的的方式
@State var one = true @State var two = true @State var three = 15 Div().display($one.and($two).map { one, two in // returns true if both one and two are true one && two }.and($three).map { oneTwo, three in // here oneTwo is a result of the previous mapping // returns .block if oneTwo is true and three is 15 oneTwo && three == 15 ? .block : .none })

所有 HTML 和 CSS 属性都可以处理@State

扩展

扩展 HTML 元素

您能向 Div 等大概金属元素“添加些许非常方便的技巧
extension Div { func makeItBeautiful() {} }

或元素组,如果您知道它们的父class


父类很少。

BaseActiveStringElement - 适用于可以用字符串初始化的元素,如ah1等。

BaseContentElement - 适用于其中可以包含内容的所有元素,如divul等。

BaseElement - 适用于所有元素


那么几乎所有事物的扩容是可以以只要写
extension BaseElement { func doSomething() {} }

声明颜色

颜色类负责颜色。它有预定义的 HTML 颜色,但你可以有自己的

extension Color { var myColor1: Color { .hex(0xf1f1f1) } // which is 0xF1F1F1 var myColor2: Color { .hsl(60, 60, 60) } // which is hsl(60, 60, 60) var myColor3: Color { .hsla(60, 60, 60, 0.8) } // which is hsla(60, 60, 60, 0.8) var myColor4: Color { .rgb(60, 60, 60) } // which is rgb(60, 60, 60) var myColor5: Color { .rgba(60, 60, 60, 0.8) } // which is rgba(60, 60, 60, 0.8) }

然后像H1(“Text“).color(.myColor1)一样使用它

声明类

extension Class { var my: Class { "my" } }

然后像Div().class(.my)一样使用它

声明id

 extension Id { var myId: Id { "my" } }

然后像Div().id(.my)一样使用它

网络 API

窗户

window对象被完全包装并可通过App.current.window变量访问。

上带来了了全版参考使用。


我不想们在下面做一种简练的论述

前景标志

您可以在App.swiftLifecycle中收听它,也可以直接通过这种方式收听

App.current.window.$isInForeground.listen { isInForeground in // foreground flag changed }
或是立即随地读
if App.current.window.isInForeground { // do somethign }
或 用 HTML 稀土元素对其制作出想法
Div().backgroundColor(App.current.window.$isInForeground.map { $0 ? .grey : .white })

活动标志

它与前景标志相同,但可通过App.current.window.isActive访问

它检则我们能不能仍在窗户内采取沟通互动。

在线状态

与前景标志相同,但可通过App.current.window.isOnline访问

它检则顾客是不是一样就能够浏览互连机络网。

暗模式状态

与前景标志相同,但可通过App.current.window.isDark访问

它加测业主的网页电脑浏览器或作业软件系统是否能够居于暗模式英文。

内部尺寸

窗口期的内容地方(视口)的各个,有滑动条

App.current.window.innerSizeSize对象里面的width height值。

也可用作@State变量。

外部尺寸

看器窗口期的粗细,具有APP栏/会滚动条。

App.current.window.outerSizeSize对象里面的widthheight值。

也可用作@State变量。

屏幕

用于检查呈现当前窗口的屏幕属性的特殊对象。通过App.current.window.screen可用。

最有趣的属性通常是pixelRatio

历史

包含了朋友采访的 URL(在浏览网页器界面内)。

通过App.current.window.historyHistory.shared可用。

它可以作为@State变量访问,因此您可以在需要时监听它的变化。

 App.current.window.$history.listen { history in // read history properties }
它也同时算作简单函数仿问
History.shared.length // size of the history stack History.shared.back() // to go back in history stack History.shared.forward() // to go forward in history stack History.shared.go(offset:) // going to specific index in history stack
上具备了更加基本短信。

地点

带有密切相关现在 URL 的讯息。

通过App.current.window.locationLocation.shared可用。

它可以作为@State变量访问,因此您可以在需要时监听它的变化。

如,这正是路由器的事情措施。
 App.current.window.$location.listen { location in // read location properties }


它也就能够最为简单因变量网络访问
Location.shared.href // also $href Location.shared.host // also $host Location.shared.port // also $port Location.shared.pathname // also $pathname Location.shared.search // also $search Location.shared.hash // also $hash
上具备了更加简要的信息。

航海家

主要包括有关的信息查询阅读器的信息查询。

通过App.current.window.navigatorNavigator.shared可用

最有趣的属性通常是userAgent platform language cookieEnabled

本地存储

同意在网络参数手机电脑浏览器中保持键/值对。储存没能收回年份的参数。

可作为App.current.window.localStorage或只是LocalStorage.shared

 // You can save any value that can be represented in JavaScript LocalStorage.shared.set("key", "value") // saves String LocalStorage.shared.set("key", 123) // saves Int LocalStorage.shared.set("key", 0.8) // saves Double LocalStorage.shared.set("key", ["key":"value"]) // saves Dictionary LocalStorage.shared.set("key", ["v1", "v2"]) // saves Array // Getting values back LocalStorage.shared.string(forKey: "key") // returns String? LocalStorage.shared.integer(forKey: "key") // returns Int? LocalStorage.shared.string(forKey: "key") // returns String? LocalStorage.shared.value(forKey: "key") // returns JSValue? // Removing item LocalStorage.shared.removeItem(forKey: "key") // Removing all items LocalStorage.shared.clear()
侦测更变
LocalStorage.onChange { key, oldValue, newValue in print("LocalStorage: key \(key) has been updated") }
跟踪定位大部分货品的移除
LocalStorage.onClear { print("LocalStorage: all items has been removed") }

会话存储

准许在网络上预览器中上传键/值对。为数不多储一两个对话的数值。

可作为App.current.window.sessionStorage或只是SessionStorage.shared

API 与上述LocalStorage完全相同。

文档

表示法浏览记录器里添加载的一点百度网页图片,逐项为百度网页图片的内容的闸道点。

通过App.current.window.document可用。

 App.current.window.document.title // also $title App.current.window.document.metaDescription // also $metaDescription App.current.window.document.head // <head> element App.current.window.document.body // <body> element App.current.window.documentquerySelector("#my") // returns BaseElement? App.current.window.document.querySelectorAll(".my") // returns [BaseElement]

本土化

静态定位

原素本地服务化是自动式的,决定于顾客系統表达

如何使用

H1(String( .en("Hello"), .fr("Bonjour"), .ru("Привет"), .es("Hola"), .zh_Hans("你好"), .ja("こんにちは")))

动态定位

这样您想立即重设显示屏幕上的当地化空格符串(不能自己重初始化网站)您可用读取调整现阶段编程语言
Localization.current = .es
如若您将用户组的程序代码语言存为在 cookie 或 localstorage 中的某处,那麼您须得在应用软件程序代码开机时去软件设置
Lifecycle.didFinishLaunching { Localization.current = .es }

如何使用

H1(LString( .en("Hello"), .fr("Bonjour"), .ru("Привет"), .es("Hola"), .zh_Hans("你好"), .ja("こんにちは")))

进阶范例

H1(Localization.currentState.map { "Curent language: \($0.rawValue)" }) H2(LString(.en("English string"), .es("Hilo Español"))) Button("change lang").onClick { Localization.current = Localization.current.rawValue.contains("en") ? .es : .en }

拿来

import FetchAPI Fetch("//jsonplaceholder.typicode.com/todos/1") { switch $0 { case .failure: break case .success(let response): print("response.code: \(response.status)") print("response.statusText: \(response.statusText)") print("response.ok: \(response.ok)") print("response.redirected: \(response.redirected)") print("response.headers: \(response.headers.dictionary)") struct Todo: Decodable { let id, userId: Int let title: String let completed: Bool } response.json(as: Todo.self) { switch $0 { case .failure(let error): break case .success(let todo): print("decoded todo: \(todo)") } } } }

XMLHttpRequest

 import XMLHttpRequest XMLHttpRequest() .open(method: "GET", url: "//jsonplaceholder.typicode.com/todos/1") .onAbort { print("XHR onAbort") }.onLoad { print("XHR onLoad") }.onError { print("XHR onError") }.onTimeout { print("XHR onTimeout") }.onProgress{ progress in print("XHR onProgress") }.onLoadEnd { print("XHR onLoadEnd") }.onLoadStart { print("XHR onLoadStart") }.onReadyStateChange { readyState in print("XHR onReadyStateChange") } .send()

WebSocket

 import WebSocket let webSocket = WebSocket("wss://echo.websocket.org").onOpen { print("ws connected") }.onClose { (closeEvent: CloseEvent) in print("ws disconnected code: \(closeEvent.code) reason: \(closeEvent.reason)") }.onError { print("ws error") }.onMessage { message in print("ws message: \(message)") switch message.data { case .arrayBuffer(let arrayBuffer): break case .blob(let blob): break case .text(let text): break case .unknown(let jsValue): break } } Dispatch.asyncAfter(2) { // send as simple string webSocket.send("Hello from SwifWeb") // send as Blob webSocket.send(Blob("Hello from SwifWeb")) }

安慰

简单的print(“Hello world“)等同于 JavaScript 中的console.log('Hello world')


控制台方法也被爱包裹❤️

 Console.dir(...) Console.error(...) Console.warning(...) Console.clear()

实时预览

要使用实时监控图片预览,请在您都想的所有程序中申明 WebPreview 类。
 class IndexPage: PageController {} class Welcome_Preview: WebPreview { @Preview override class var content: Preview.Content { Language.en Title("Initial page") Size(640, 480) // add here as many elements as needed IndexPage() } }


Xcode

请阅读训练上的就说明。这个是1个难搞但截然有效果的处理预案😎


VS代码

转到VSCode中的扩展并搜索Webber

安装后按Cmd+Shift+P (或 Linux/Windows 上的Ctrl+Shift+P

查找并启动Webber Live Preview

在右侧,您将看到实时预览窗口,只要您保存包含WebPreview类的文件,它就会刷新。

访问 JavaScript

它可以通过作为SwifWeb基础的JavaScriptKit获得。

在中阅读赏析你的最简单的方法。

资源

您可以在项目中添加cssjspngjpg和任何其他静态资源。

但是要在调试期间或最终发布文件中使用它们,您必须像这样在Package.swift中声明它们

.executableTarget(name: "App", dependencies: [ .product(name: "Web", package: "web") ], resources: [ .copy("css/*.css"), .copy("css"), .copy("images/*.jpg"), .copy("images/*.png"), .copy("images/*.svg"), .copy("images"), .copy("fonts/*.woff2"), .copy("fonts") ]),

稍后您将能够访问它们,例如像这样Img().src(“/images/logo.png“)

调试

通过以下方式启动Webber

webber serve只是为了快速启动它

webber serve -t pwa -s Service以 PWA 模式启动它

附加参数

-v--verbose在控制台中显示更多信息以进行调试

-p 443--port 443在 443 端口而不是默认的 8888 端口上启动 webber 服务器

--browser chrome/safari自动打开浏览器,默认不打开

--browser-self-signed需要在本地调试服务工作者,否则它们不起作用

--browser-incognito以隐身模式打开其他浏览器实例,仅适用于 chrome


因为,要在过程调试玩法下实现您的应该用过程,请在 Chrome 中智能式使用 它并在您修该一点文件名称时智能式载入浏览访问器以一些形式启动的它使用在spa水疗

webber serve --browser chrome

中用真正意义的 PWA 測試

webber serve -t pwa -s Service -p 443 --browser chrome --browser-self-signed --browser-incognito


初始应用程序加载

您能够想改进什么起始刷新过程中 。

为此,只需打开项目内的.webber/entrypoint/dev文件夹并编辑index.html文件。

它包含带有非常有用的侦听器的初始 HTML 代码: WASMLoadingStarted WASMLoadingStartedWithoutProgress WASMLoadingProgress WASMLoadingError

您能够 私自编辑器该代碼以实现了您的自确定材质 🔥

当你完成新的实现时,不要忘记将它保存到.webber/entrypoint/release文件夹中

建筑发布

只需执行webber releasewebber release -t pwa -s Service for PWA。

然后从.webber/release文件夹中获取编译后的文件并将它们上传到您的服务器。

如何部署

您能能将文件格式上传文件到任何静止冷水机。

托管应该为wasm文件提供正确的内容类型!

是的,为wasm文件设置正确的标头Content-Type: application/wasm非常重要,否则不幸的是浏览器将无法加载您的 WebAssembly 应用程序。

例如,GithubPages没有为wasm文件提供正确的 Content-Type,因此很遗憾,无法在其上托管 WebAssembly 站点。

Nginx

如果你用的是自己的nginx服务器,那么打开/etc/nginx/mime.types查看是否包含application/wasm wasm;记录。如果是,那么您就可以开始了!

结论

我愿意我下面给您引来以及惊喜并您最好不要会试 SwifWeb 并数量最多会逐渐将它用到您的下某个中大型 Web 大型项目!


请随时为任何做出贡献,并为 ⭐️ 全部加注星标!


我您都可以在中仅寻到比较大的不支持,课外阅读这些方法,并在丝毫即將光临的更新换代时最时拒收通知短信!很高兴英文看到我和她我们公司在相拥!


这仅是一款开始了,为感看好越来越多关干 SwifWeb 的稿件!


讲讲你的好朋友!
바카라사이트 바카라사이트 온라인바카라