आपको स्विफ्ट स्थापित करने की आवश्यकता है, इसे प्राप्त करने का सबसे आसान तरीका:
brew install swifweb/tap/webber
बाद में नवीनतम संस्करण में अपडेट करने के लिए बस चलाएं brew upgrade 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
इंटरैक्टिव मेनू में pwa
या spa
चुनें और प्रोजेक्ट का नाम डालें।
निर्देशिका को नव निर्मित प्रोजेक्ट में बदलें और webber serve
निष्पादित करें।
यह आदेश आपके प्रोजेक्ट को WebAssembly में संकलित करेगा, एक विशेष .webber
फ़ोल्डर के अंदर सभी आवश्यक फाइलों को पैकेज करेगा, और डिफ़ॉल्ट रूप से पोर्ट 8888
का उपयोग करके सभी इंटरफेस पर आपकी परियोजना की सेवा शुरू करेगा।
webber serve
के लिए अतिरिक्त तर्क
-t pwa
प्रोग्रेसिव वेब ऐप के लिए
सिंगल वेब ऐप के लिए -t spa
सर्विस वर्कर टारगेट का नाम (आमतौर पर PWA प्रोजेक्ट में Service
नाम दिया जाता है)
-s Service
ऐप लक्ष्य का नाम (डिफ़ॉल्ट रूप से App
)
-a App
-v
वेबर सर्वर के लिए पोर्ट (डिफ़ॉल्ट 8888
है)
-p 8080
वास्तविक एसएसएल की तरह परीक्षण करने के लिए -p 443
का उपयोग करें (अनुमत स्व-हस्ताक्षरित एसएसएल सेटिंग के साथ)
--browser safari
या --browser chrome
--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 सेवा कार्यकर्ता पंजीकृत करने के लिए
addScript(“path/to/script.js“)
सापेक्ष या बाहरी स्क्रिप्ट जोड़ने के लिए कॉल करें
addStylesheet(“path/to/style.css“)
सापेक्ष या बाहरी शैली जोड़ने के लिए कॉल करें
addFont(“path/to/font.woff”, type:)
रिश्तेदार या बाहरी फ़ॉन्ट जोड़ने के लिए कॉल करें, वैकल्पिक रूप से सेट प्रकार
addIcon(“path/to/icon“, type:color:)
आइकन जोड़ने के लिए कॉल करें, वैकल्पिक रूप से प्रकार और रंग सेट करें
//website.com/hello/world - यहाँ /hello/world रास्ता है
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 } } }
पथ में अगली दिलचस्प चीज़ क्वेरी है, जिसका उपयोग करना भी बहुत आसान है। उदाहरण के लिए, आइए /खोज मार्ग पर विचार करें, जिसमें खोज text
और age
क्वेरी पैरामीटर होने की उम्मीद है।
//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/aaa/bar, /foo/bbb/bar, आदि। **
साइन के साथ आप एक विशेष कैच-ऑल रूट सेट कर सकते हैं जो किसी भी ऐसी चीज़ को हैंडल करेगा जो किसी विशिष्ट पथ पर अन्य रूटों से मेल नहीं खाता है।
Page("**") { NotFoundPage() }
या विशिष्ट पथ के लिए उदाहरण के लिए जब उपयोगकर्ता नहीं मिला Page("user", "**") { UserNotFoundPage() }
/उपयोगकर्ता/1 - यदि /उपयोगकर्ता/:आईडी के लिए कोई मार्ग है तो यह UserPage लौटाएगा। नहीं तो गिर जाएगा...
UserNotFoundPage
/ उपयोगकर्ता / 1 / हैलो - अगर / उपयोगकर्ता /: आईडी / हैलो के लिए मार्ग हैं तो यह UserNotFoundPage में गिर जाएगा
/कुछ - अगर /कुछ के लिए कोई मार्ग नहीं है तो यह NotFoundPage में गिर जाएगा
हो सकता है कि हम अगले मार्ग के लिए पृष्ठ पर संपूर्ण सामग्री को बदलना न चाहें, लेकिन केवल कुछ ब्लॉकों के लिए। यहीं पर FragmentRouter काम आता है!
आइए मान लें कि हमारे पास /उपयोगकर्ता पृष्ठ पर टैब हैं। प्रत्येक टैब एक उपमार्ग है, और हम FragmentRouter का उपयोग करके उपमार्ग में परिवर्तनों पर प्रतिक्रिया करना चाहते हैं।
ऐप क्लास में शीर्ष-स्तरीय मार्ग घोषित करें
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 सबरूट्स को संभालता है और इसे नेवबार के तहत प्रस्तुत करता है, इसलिए पृष्ठ कभी भी पूरी सामग्री को फिर से लोड नहीं करता है बल्कि केवल विशिष्ट अंशों को ही लोड करता है।
बीटीडब्ल्यू फ्रैगमेंट राउटर एक डिव है और आप इसे कॉल करके कॉन्फ़िगर कर सकते हैं
FragmentRouter(self) .configure { div in // do anything you want with the div }
स्विफ्ट का उपयोग करके सीएसएस नियम घोषित करने के लिए हमारे पास नियम वस्तु है।
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) }
दोनों तरीके समान हैं, हालांकि, मैं टाइप करने के ठीक बाद स्वत: पूर्णता के कारण पहले वाले को पसंद करता हूं .
😀
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
आप किसी मौजूदा संशोधक की घोषणा कर सकते हैं, वे सभी उपलब्ध हैं। 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))
यह निम्नलिखित सीएसएस कोड का उत्पादन करता है 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 }) } }
LightStyle और DarkStyle को अलग-अलग फाइलों में या उदाहरण के लिए 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
और यह संबंधित स्टाइलशीट को सक्रिय या निष्क्रिय कर देगा! क्या यह अच्छा नहीं है? 😎
लेकिन आप कह सकते हैं कि CSS के बजाय स्विफ्ट में शैलियों का वर्णन करना कठिन है, तो क्या बात है?
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
और यह स्टाइलशीट और इसका उपयोग करने वाले सभी तत्वों में रंग को अपडेट करेगा 😜
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; } """ } }
आप कच्चे सीएसएस स्ट्रिंग्स को जितनी बार जरूरत हो मिक्स-इन कर सकते हैंराउटर प्रत्येक रूट पर पेज रेंडर कर रहा है। पृष्ठ पृष्ठ नियंत्रक से प्राप्त कोई भी वर्ग है।
पेजकंट्रोलर के पास जीवनचक्र विधियाँ हैं जैसे willLoad
didLoad
willUnload
didUnload
, UI विधियाँ buildUI
और body
, और HTML तत्वों के लिए संपत्ति आवरण चर।
तकनीकी रूप से पेजकंट्रोलर सिर्फ एक डिव है और आप इसके किसी भी गुण को 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)
- डायरेक्ट जेएस alert
विधि
changePath(to: String)
- यूआरएल पथ स्विच करना
स्विफवेब कोड | 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 तत्व इसके लिए शैली को पूर्वनिर्धारित करने के लिए, या बहुत सारे पूर्वनिर्धारित बाल तत्वों और बाहर उपलब्ध कुछ सुविधाजनक तरीकों के साथ एक समग्र तत्व बनाने के लिए, या जीवनचक्र की घटनाओं जैसे didAddToDOM
और didRemoveFromDOM
प्राप्त करने के लिए।
चलिए एक 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) } }
तत्व को तुरंत या बाद में पेजकंट्रोलर या HTML तत्व के 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 में जोड़ सकते हैं!
lazy var myDiv = Div() Div { myDiv } // somewhere later myDiv.remove()
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 {…}
उपयोग क्यों करना चाहिए ?
नीचे @State
के बारे में और पढ़ें ।
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"] }
उपरोक्त उदाहरणों के समान, लेकिन 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 }
बिल्डरफंक्शन एचटीएमएल तत्वों के लिए भी उपलब्ध है :)
घोषणात्मक प्रोग्रामिंग के लिए आजकल @State
सबसे वांछनीय चीज है।
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)") }
@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
मानों को संभाल सकते हैं
extension Div { func makeItBeautiful() {} }
या तत्वों के समूह यदि आप उनके मूल class
जानते हैं।
कुछ अभिभावक वर्ग हैं।
BaseActiveStringElement
- उन तत्वों के लिए है जिन्हें स्ट्रिंग के साथ प्रारंभ किया जा सकता है, जैसे a
, h1
, आदि।
BaseContentElement
- उन सभी तत्वों के लिए है जिनके अंदर सामग्री हो सकती है, जैसे div
, ul
, आदि।
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)
की तरह उपयोग करें
extension Id { var myId: Id { "my" } }
फिर इसे Div().id(.my)
की तरह उपयोग करें
window
ऑब्जेक्ट पूरी तरह से लपेटा हुआ है और App.current.window
चर के माध्यम से पहुँचा जा सकता है।
आप इसे Lifecycle
में App.swift
में या सीधे इस तरह से सुन सकते हैं
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.innerSize
अंदर width
और height
मूल्यों के भीतर आकार वस्तु है।
@State
चर के रूप में भी उपलब्ध है।
App.current.window.outerSize
अंदर width
और height
मूल्यों के भीतर आकार वस्तु है।
@State
चर के रूप में भी उपलब्ध है।
स्क्रीन के गुणों का निरीक्षण करने के लिए विशेष वस्तु जिस पर वर्तमान विंडो प्रस्तुत की जा रही है। App.current.window.screen
के माध्यम से उपलब्ध है।
सबसे दिलचस्प गुण आमतौर पर pixelRatio
है।
App.current.window.history
या केवल History.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
अधिक विवरण पर उपलब्ध हैं। App.current.window.location
या केवल Location.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.navigator
या सिर्फ Navigator.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
के रूप में उपलब्ध है।
एपीआई बिल्कुल वैसा ही है जैसा ऊपर वर्णित लोकलस्टोरेज में है।
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
अगर आपने यूजर की भाषा को कुकीज या लोकलस्टोरेज में कहीं सेव किया है तो आपको इसे ऐप लॉन्च पर सेट करना होगा 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)") } } } }
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()
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“)
जावास्क्रिप्ट में console.log('Hello world')
के बराबर है
कंसोल विधियाँ भी प्रेम ❤️ से लिपटी हुई हैं
Console.dir(...) Console.error(...) Console.warning(...) Console.clear()
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() } }
VSCode के अंदर एक्सटेंशन पर जाएं और वेबर खोजें।
एक बार इंस्टॉल हो जाने के बाद Cmd+Shift+P
(या Linux/Windows पर Ctrl+Shift+P
) दबाएं
Webber Live Preview
ढूंढें और लॉन्च करें।
दाईं ओर, आपको लाइव पूर्वावलोकन विंडो दिखाई देगी और जब भी आप उस फ़ाइल को सहेजते हैं जिसमें WebPreview क्लास होती है तो यह ताज़ा हो जाती है।
यह JavaScriptKit के माध्यम से उपलब्ध है जो कि SwifWeb की नींव है।
में पढ़ें कि आप कैसे हैं। आप प्रोजेक्ट के अंदर css
, js
, png
, jpg
, और अन्य स्थिर संसाधन जोड़ सकते हैं।
लेकिन डिबग के दौरान या अंतिम रिलीज फाइलों में उन्हें उपलब्ध कराने के लिए आपको उन सभी को पैकेज.स्विफ्ट में इस तरह घोषित करना होगा
.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 serve
इसे जल्दी से लॉन्च करने के लिए
webber serve -t pwa -s Service
PWA मोड में लॉन्च करने के लिए
-v
या --verbose
डिबगिंग उद्देश्यों के लिए कंसोल में अधिक जानकारी दिखाने के लिए
-p 443
या --port 443
डिफ़ॉल्ट 8888 के बजाय 443 पोर्ट पर वेबर सर्वर शुरू करने के लिए
--browser chrome/safari
स्वचालित रूप से वांछित ब्राउज़र खोलने के लिए, डिफ़ॉल्ट रूप से यह कोई भी नहीं खोलता है
--browser-self-signed
सेवा कर्मियों को स्थानीय रूप से डीबग करने की आवश्यकता है, अन्यथा वे काम नहीं करते हैं
--browser-incognito
ब्राउज़र के अतिरिक्त इंस्टेंस को गुप्त मोड में खोलने के लिए, केवल क्रोम के साथ काम करता है
webber serve --browser chrome
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
फ़ोल्डर में सहेजना न भूलें
PWA के लिए बस webber release
या webber release -t pwa -s Service
निष्पादित करें।
फिर .webber/release
फ़ोल्डर से संकलित फ़ाइलें लें और उन्हें अपने सर्वर पर अपलोड करें।
होस्टिंग को wasm फ़ाइलों के लिए सही सामग्री-प्रकार प्रदान करना चाहिए!
हां, सही हेडर होना बहुत जरूरी है Content-Type: application/wasm
wasm files के लिए, अन्यथा दुर्भाग्य से ब्राउज़र आपके WebAssembly एप्लिकेशन को लोड करने में सक्षम नहीं होगा।
उदाहरण के लिए GithubPages wasm फ़ाइलों के लिए सही सामग्री-प्रकार प्रदान नहीं करता है, इसलिए दुर्भाग्य से उस पर WebAssembly साइटों को होस्ट करना असंभव है।
यदि आप nginx के साथ अपने स्वयं के सर्वर का उपयोग करते हैं, तो /etc/nginx/mime.types
खोलें और जांचें कि इसमें application/wasm wasm;
अभिलेख। यदि हाँ तो आप जाने के लिए अच्छे हैं!
कृपया किसी भी में बेझिझक योगदान दें और ⭐️उन सभी को तारांकित करें!