🔍 搜尋結果:題

🔍 搜尋結果:題

MVC是一個巨大誤會

我是web工程師,從剛開始學MVC就深感困惑: - 怎麼每個地方說的MVC都不太一樣? - 有些文章講的MVC,跟我正在用的MVC,怎麼像完全不同的東西? Model、Controller、View三者到底如何互動?真是一個定義不明、含糊不清的名詞。 這讓我研究了很久。最後,發覺它是一個嚴重的誤會。 這個誤會導致了學習和溝通上的代價,請聽我娓娓道來。 # 哪些是MVC? web領域,不論前端(client-side)、後端(server-side)、不論什麼程式語言,幾乎所有framework都自稱、或被認為是「MVC」。 有哪些呢? 前端:Backbone.js、AngularJS、Ember.js… 後端:Ruby on Rails、CodeIgniter、Laravel、Django… 真的是這樣嗎?它們全都是MVC嗎? # MVC是什麼? 該怎麼定義MVC呢? 我們先來看看維基百科怎麼說: > MVC模式(Model-View-Controller)是軟體工程中的一種軟體架構模式,把軟體系統分為三個基本部分:模型(Model)、檢視(View)和控制器(Controller)。 嗯,跟大家說的一樣。我們繼續往下看: > 模型(Model) 用於封裝與應用程式的業務邏輯相關的資料以及對資料的處理方法。「 Model 」有對資料直接存取的權力,例如對資料庫的存取。「Model」不依賴「View」和「Controller」,也就是說, Model 不關心它會被如何顯示或是如何被操作。但是 Model 中資料的變化一般會通過一種重新整理機制被公布。為了實作這種機制,那些用於監視此 Model 的 View 必須事先在此 Model 上註冊,從而,View 可以了解在資料 Model 上發生的改變。(比較:觀察者模式(軟體設計模式)) 看起來有些陌生,整段描述跟你的web開發經驗完全不同,對嗎? 最大的疑問來自這句: > 那些用於監視此 Model 的 View 必須事先在此 Model 上註冊,從而,View 可以了解在資料 Model 上發生的改變。(比較:觀察者模式(軟體設計模式)) 後面直接叫你去看觀察者模式(observer pattern)。 問題來了:你有在view跟model之間實作observer pattern嗎? 也就是說,你的Model在資料改變之後,能主動通知View嗎? 沒有的話,就根本不符合MVC的定義。 # 全都不是MVC? 我們現在發現MVC有observer pattern這個必要條件了。 事情嚴重了起來。 client-side framework或許能夠符合這個條件。 以Backbone.js官網範例來說,我們可以這樣在Model上註冊: ``` book.on({ "change:title": titleView.update, "change:author": authorPane.update, "destroy": bookView.remove }); ``` 它的確實作了observer pattern。 但server-side framework呢? 你的Model如何能在發生改變之後去「主動通知」View? 你平常開發web哪有用到server push的技術? 所有server-side framework,從Ruby的Rails;PHP的CodeIgniter、Laravel;到Python的Django,他們全都不是MVC。 它們實作的,是昇陽電腦在1998年提出的「Model 2」。 # 什麼是Model 2? Model 2名氣不大,在維基百科連中文條目都沒有。我們看看英文條目怎麼講: > Model 2 is a complex design pattern used in the design of Java Web applications which separates the display of content from the logic used to obtain and manipulate the content. > In a Model 2 application, requests from the client browser are passed to the controller. The controller performs any logic necessary to obtain the correct content for display. 它針對web而設計,讓controller進行必要的程序之後,將資料塞進view去呈現。 正是我們server-side框架在做的事情。 也就是說,server-side目前只能實作Model 2;client-side可以實作Model 2,也可以實作MVC。 # 巨大的代價 web工程師最常碰的就是client-side跟server-side框架。結果整個業界把MVC跟Model 2混為一談,都說成MVC。 這帶來了什麼後果呢? MVC變成一個從初學者到業界工程師,永遠說不清楚、下不了定義的名詞。 這件事對於學習和討論,造成了非常巨大的成本。(參考下方的Q1和Q2) # 那該怎麼辦? 下次有初學者詢問「什麼是MVC」的時候,怎麼回答才不會害他回家之後「越查資料越混亂」? [Rails is not MVC](http://andrzejonsoftware.blogspot.tw/2011/09/rails-is-not-mvc.html)的作者提出了三種解決方法: > 第一個方法是聲稱MVC已經從原始意義改變了,Model 2也可以稱為MVC。如此一來,我們可以用「傳統MVC」或「真MVC」來描述原始的MVC。這是現在普遍的作法,但我不認為改變定義是一個好主意。這幾乎是越搞越亂。 > 第二個方法是到處推廣Rails其實是Model 2,MVC就留給…MVC吧。這很困難,但至少能保持定義不變。 > 第三個是直接忽略這些混亂。管它那麼多? 我個人覺得MVC這個詞已經沒救了,不管怎麼解釋都會帶給別人混亂。 當對方同時學習client-side跟server-side時,混亂更強烈。 我選擇這樣回答: 「MVC有分很多種喔!網路上全部沒寫清楚,你一定看不懂。 沒關係,你只要知道View可以抽出來就好。 C跟M先別管,你先隨便瞎搞吧。」 --- # Q&A ## Q1: 怎麼可能各大server-side framework都搞錯? 確實有人腦袋清醒得很,它就是Python的Django。 Django的官方文件內根本沒有「Controller」這個名詞。 看看Django官網的常見問題: > Q: Django似乎是一個MVC框架,但你們把Controller命名為「View」,把View命名為「Template」。你們幹嘛不用標準命名啊? > A: (前略)…如果你真的很想要一個縮寫,你就說Django是一個MTV框架吧。Model、Template、View。這樣分比較有道理些。 Django不想變成搞亂MVC的幫凶,只好委屈地又發明了一個名詞「MTV」。 ## Q2: 那client-side框架有受影響嗎? 有。client-side框架也必須為MVC巨大誤會浪費一堆時間解釋。 看看Backbone.js官網的常見問答: > Backbone跟「傳統MVC」的關聯何在? > …我們來比較一下Backbone跟像是Rails這種server-side MVC框架的差別… Backbone實作了「傳統MVC」,卻被迫用「傳統MVC」來描述server-side的Model 2,然後花一堆篇幅解釋。 ## Q3: 知道Model 2的存在又如何?我現在依然一片混亂! 沒錯,Model 2跟MVC都用到Model、Controller、View三個名詞,所以看起來類似。 但是,我們不應該再把時間花在思考「MVC怎麼如此難懂」。 我們討論的重點,應該是「如何分辨MVC與Model 2」、「在server-side如何實作Model 2才漂亮」、「在client-side實作MVC跟Model 2的優劣分別何在」。 ## Q4: 好,那你現在回答我,「如何分辨MVC與Model 2」? OK,就讓我拋磚引玉一下。 分別談談Model、View、Controller吧: ### View - Model 2: 不具有行為,只是等別人塞資料進去的模板(template)。 - MVC: 具有監視Model的行為,並以此去改變呈現(presentation)。 兩種View有沒有很像?跟張飛、岳飛一樣像。 看看Backbone.js官網的View範例。你server-side的View哪是長這樣? ``` var DocumentRow = Backbone.View.extend({ tagName: "li", className: "document-row", events: { "click .icon": "open", "click .button.edit": "openEditDialog", "click .button.delete": "destroy" }, initialize: function() { this.listenTo(this.model, "change", this.render); }, render: function() { ... } }); ``` ### Controller - Model 2: 接收請求與參數,轉交給Model處理,再把結果(最新的資料)塞進View。 - MVC: 接收請求與參數,轉交給Model處理。沒其他事了。 兩種Controller有沒有很像?跟小狗、熱狗一樣像。 MVC的View跟Model 2的Controller可能還比較像一點。(隨便說說,千萬別這樣類比。) ### Model - Model 2: 接收Controller傳來的參數,回傳結果。 - MVC: 接收Controller傳來的參數,將結果通知View。 Model倒是有些類似。 總之,Model 2跟MVC除了三個部份的名字一樣之外,沒什麼關聯了。 ## Q5: 我決定徹底鑽研MVC跟Model 2的定義了。給我一些延伸閱讀? http://www.ithome.com.tw/node/77330 http://andrzejonsoftware.blogspot.tw/2011/09/rails-is-not-mvc.html https://docs.djangoproject.com/en/1.7/faq/general/#django-appears-to-be-a-mvc-framework-but-you-call-the-controller-the-view-and-the-view-the-template-how-come-you-don-t-use-the-standard-names http://backbonejs.org/#FAQ-mvc https://r.je/views-are-not-templates.html --- ##一些社群的看法(2015-2-28) 附上幾個社群的連結,裡面有許多很棒的討論。 https://www.facebook.com/groups/javascript.tw/permalink/600136880087654/ https://www.facebook.com/groups/199493136812961/permalink/759391387489797/ https://www.facebook.com/groups/pythontw/permalink/10153760201638438/ https://www.facebook.com/mosky.liu/posts/10203964969186383 http://www.ithome.com.tw/voice/94877

給OOP初學者的建議:先搞懂「資料跟行為在一起」就好,其它的慢慢來

初學者接觸OOP,幾乎都會有以下疑惑: 我到底為什麼要學OOP?OOP解決了什麼問題?書上這些範例就算不用OOP也寫得出來吧? 然後覺得「繼承」、「多型」、「介面」、「抽象類別」等等的名詞很難,覺得OOP很難。 其實這些名詞雖然重要,但對新手來說,本來就很難在一開始就搞懂。 建議先搞懂「資料跟行為在一起」是什麼,以及它的好處在哪,就可以了,其它的慢慢來。 # 什麼叫做「資料跟行為在一起」? 假設我們在開發一個「中英文互助學習網」,鼓勵中文人士與英語人士登入討論。 這個系統的貼文、留言功能會顯示「發文日期」。 發文日期要根據使用者的註冊身份(台灣人、英語人士)顯示不同格式(台灣格式、西方格式)。 下面就以這個日期格式的功能舉例說明「資料跟行為在一起」是什麼意思。 ## 作法一:直接硬寫(不OOP、資料跟行為混在一起) 初學者通常會用最簡單、也最直覺的作法,直接硬寫出來,像這樣: ``` <?php $postDate = '2016-06-02'; # 假設資料庫取出來的發文日期長這樣 if (/* 判斷是否顯示台灣格式 */) { # 轉換成這樣 2016.6.2 $arr = explode('-', $postDate); $year = $arr[0]; $month = $arr[1]; $day = $arr[2]; echo "$year.$month.$day"; } else { // 西方格式 # 轉換成這樣 6/2/2016 $arr = explode('-', $postDate); $year = $arr[0]; $month = $arr[1]; $day = $arr[2]; echo "$month/$day/$year"; } ``` 這種寫法的資料(日期)跟行為(轉換成各種格式)混在一起。 它的優點是寫起來很簡單,缺點則有兩個: * 日期格式的邏輯會重複出現在很多地方,整段code會到處重複出現 * 整段code大概會塞在 `div` 或是 `span` 的裡面,導致它跟HTML混在一起,很亂 ## 作法二:自訂函數(不OOP、資料跟行為沒混在一起) 為了解決作法一遇到的問題,聰明的初學者很快就想到可以用「自訂函數」!就像這樣: ``` <?php function localFormat($date) { $arr = explode('-', $date); $year = $arr[0]; $month = $arr[1]; $day = $arr[2]; return "$year.$month.$day"; } function englishFormat($date) { $arr = explode('-', $date); $year = $arr[0]; $month = $arr[1]; $day = $arr[2]; return "$month/$day/$year"; } $postDate = '2016-06-02'; # 假設資料庫取出來的發文日期長這樣 if (/* 判斷是否為台灣人身份 */) { echo localFormat($postDate); } else { // 英語人士身份 echo englishFormat($postDate); } ``` 這種寫法將行為(轉換成各種格式)用自訂函數給獨立出來,也大幅改善了作法一遇到的問題。 對小型的網頁程式來說,這招非常好用,不但開發快速、簡單,還漂亮地將資料跟行為拆開。 但是程式規模變大之後,為了將各種行為拆出來,會寫出很多自訂函數,類似這樣: ``` ?php function localFormat($param) { // blah blah ... } function englishFormat($param) { // blah blah ... } function someTask($param) { // blah blah ... } function anotherTask($param) { // blah blah ... } function otherTask($param) { // blah blah ... } //... ``` 於是又衍生出三個問題: 1. 像localFormat、englishFormat這樣的函數名稱意義模糊,看不出是處理日期、人名,還是什麼東西的格式 2. 這些自訂函數各有不同的行為,全部放在一起顯得很亂,應該要想辦法分類、整理這些函數 3. 像localFormat、englishFormat這樣的函數,只吃特定格式的參數,最好能跟某種資料的形式綁在一起,以後要改程式時,能讓相關的資料跟行為一起被看到 問題1很好解決,只要替函數名稱加前綴字變成dateLocalFormat、dateEnglishFormat就行了。 問題2也很好解決,只要多開幾個檔案,把相關的函數放進同一個檔案就行了。 問題3就很棘手,資料跟行為拆開之後,如何在概念上又找方法整理在一起? ## 作法三:使用class(OOP、資料跟行為在一起) 正是這些處理資料、整理行為的問題,導致了OOP的誕生: ``` <?php class Date { public $year; public $month; public $day; public function __construct($date) { $arr = explode('-', $date); $this->year = $arr[0]; $this->month = $arr[1]; $this->day = $arr[2]; } public function localFormat() { return $this->year . '.' .$this->month . '.' . $this->day; } public function englishFormat() { return $this->month . '/' .$this->day . '/' . $this->year; } } $postDate = '2016-06-02'; # 假設資料庫取出來的發文日期長這樣 $date = new Date($postDate); if (/* 判斷是否為台灣人身份 */) { echo $date->localFormat(); } else { // 英語人士身份 echo $date->englishFormat(); } ``` OOP的寫法,一次解決了前述三個問題: 問題1 => 現在從類別名稱就可以知道底下方法的意義了 問題2 => 現在相關的函數都整理進同一個類別底下成為方法了 問題3 => 現在資料的形式都統一在constructor處理一次,之後不管新增多少方法都不用處理資料了 這就是所謂的「資料跟行為在一起」,也正是OOP的核心概念。 利用這種方式整理程式碼、寫出一個又一個的類別,可以大幅提昇程式碼的品質。 # 結論 上述的作法一跟作法二並沒那麼糟糕,但確實會帶來一些問題。 對於小型的網頁程式來說,可能還算夠用。 但是隨著程式規模變大,如果將概念上相關的資料跟行為整理在一起,會很有幫助。 實務上也可以先從作法二開始寫起,直到發現某些資料跟行為關係密切,再拉出來整理成類別即可。 至於很多OOP教學會提到的「繼承」、「多型」、「介面」、「抽象類別」等等名詞,一時搞不懂沒有關係,你可能實務上也暫時用不到。之後找時間慢慢搞懂它們的用途就好。 光是知道「將資料跟行為放在一起」的技巧,就能夠開始寫OOP程式碼了。 (註:本篇文章的程式碼純屬教學用途。實務上PHP已經有DateTime類別可以使用,或是用更漂亮的Carbon類別。) ## Q&A Q1:我常常設計一些類別,只有資料沒有行為,聽起來OK嗎? 不OK,這很不OOP,而且沒意義。 乾脆直接用關聯式陣列去表示那些資料就好。 Q2:我常常設計一些類別,只有行為沒有資料,聽起來OK嗎? 這個要看情況,不一定。 但唯一可以確定的是,這種作法很不OOP。 因為OOP的核心是「資料跟行為在一起」。 這也是為什麼你會看到有人明明寫了類別、用了物件,別人卻說「這不夠OOP」。 然後你又會看到像JavaScript這樣連「類別」關鍵字都沒有(ES5以前),卻能夠寫出很OOP程式碼的關係。 判定的標準都是一樣的,而且也就只有這麼一個標準:資料跟行為有沒有在一起。 Q3:一個類別包含的概念是越大越好,還是越小越好? 不一定。不過我們從作法一到作法三的過程,有一個明確目的:希望讓程式碼更好懂。 如果聲稱一個類別包含的概念很大(例:設計LanguageHelpWebsite類別,用來代表「中英文互助學習網」需要的所有功能),那會把幾乎整個網站的所有行為跟資料都放進去,成為所謂的God object。它可沒有讓程式碼更好懂。 相反地,如果聲稱一個類別包含的概念很小(例:分別設計LocalDate、EnglishDate類別),雖然意義可能更精準了,但用一整個Date類別的概念去思考,程式碼會更容易理解,也就是所謂的內聚性(Cohesion)更高。 所以要替OOP就是「資料跟行為在一起」加個但書: 要以方便理解程式為前提,將資料和行為放在一起。

分享最近面試心得

正想分享近期面試心得,站長就先PO文了,哈哈 由於我本身是美術科系畢業,之前也是做包裝和平面設計的工作,所以網頁設計和前端的職缺我都有投,目標是先讓自己進入業界環境。 剛開始蠻挫折的因為沒什麼前端junior職缺,且職缺要求五花八門技術又要有相關工作經驗或是相關科系,工作內容好像什麼都要會,也很多我看不懂的工具... 過一兩週後,開始有人找我,但大多都是網頁設計相關的工作,至於工作內容也很雜,且薪資也不在預期之中。 這幾天陸續面試,其實沒什麼自信且緊張,有些公司面試有筆試,拿到試題腦袋一片空白,平常用電腦打字,現在變成拿筆寫出code或回答問題,最後就把試題會的部分寫一寫,完全看不懂的就跳過,之後面試官來面試我,原本想說試題好多都不會,根本亂寫一通,可能會被洗臉,先做好心理準備XD 結果面試官一題一題有耐心的問我為什麼會這樣回答,不管我答對還是錯面試官都詳細的告訴我釐清觀念,其實考官有說題目都比較刁專有陷阱,因為知道我是初學者,所以也在他預料範圍內,很感謝他們耐心教導,對方也告訴我一些這方面的經驗或關鍵字,真感人! 總之,近期的面試都吸取很多知識和建議,也被面試官提點我的JS部分要在深入學習扎實一點,還有去看看什麼是clean code --- 分享一下面試題目(我比較有印象的) ``` if ([]) { console.log('Y') } else { console.log('N') } //結果為如何 ``` ``` console.log( (0.1 + 0.2) === 0.3 ) //結果為如何 ``` ``` console.log( NaN === NaN ) //結果為如何 ``` ``` console.log(parseInt('123ABC')) //結果為如何 ``` ``` const a = '3' const b = 1 console.log (a+b) //結果為如何 ``` ``` console.log ([...'...'].length) //結果為如何 ``` 還有一系列的`typeof`型別比較問題,但我無法**直覺信心**的直接寫出答案 因為平常都是寫code時順便用`console.log`來確認型別,這部分要再重新複習😥 還有一些`class`和`this`的試題,我完全看不懂也不會😵 先分享這樣,希望近期能收到好結果~~

JavaScript 系列九:發表作業&心得分享

第1課 ── 學習 Vue 元件基本觀念 [作業](https://tinyurl.com/yst8ytys) 第2課 ── 學習 Vue 的 props 觀念 [作業](https://play.vuejs.org/#eNrtF11vFFX0r1w3MW0JM7MYiWRZQCE+YBSJPLo+zO7c7oydvTPeuftRm000lQCWpESMoCFRowIJKU2MMVWqv6azLE/+Bc/9mrl3dtvSiPHFPmznnu9z7vm6a7U30tQd9HGtUWtmHRql7GyLRL00oQy9s3reD7r4MsWDCA/RMk16qFVzPRvOuVu101WuGfKCrkXwSFAGeNnvxwyttQhCnQTYCSYsa6C1iurjhdDxcU4b+MxfXJJ8CFHM+pToE0JpkjGQoY9cdJzQBtgyDCMGNggZ8o/hEbug0e3Y76xY6Nhv45ijLChN+iTAQQUuTeN/bW7qmyO/l8YYvHn/A4UZg/OarodZmATcV4lL+0xxlI6BeWGUuZY4N+1n4eIacl1XILmzaLwkJEtfSZbE2I2T7uIst6aTNsjfoc86YWmHHbwA47SBGO3jwrvQJ0GMqWkmBCrp+PEVllAfLjrD7CLDvcVWrSevjV4GqRAq9NaVdy+5GaMR6UbLq9JArnGpdECHUf+vBPMFWVagEb93U4V102iuxXZIS+r9nFA3DlnDcFBaV97fGakm9WmGFy2Du/uEcmkJnTtXSlCKZ61DZ7RJh2uohMFQYWGKJObp3PSKpgEHkJPGPsNwQqgZRAPUif0sOwOyk2C1VRPwCiYikPoXEsL8iGBa0ACVKL7iiND00cazT3cmt69N129Ovt5+9v3m9MbPJbopJCG2mmIQK2q+VSvUiPNFTgHAgdNLAhwDmAfP1bReqduzle9vy+Sra/nWnRdnS9GQDrZHyDc6nJIsqJRko8lJM7hoE1zRLHhNPFxlB4dJHGAKNODxdHcnv/qTSIb86gPwvKQ2TK2GanJ3O791f3LvRn7v9vTBFzNB0rarrqrjomMX4s5KOxnNRkrRmzbMhKndZywh6PVOHHVWOGPRZSHR8q27k+u3nm5/tvfnRtOTpDpDPUjRedmayoE0N1/DE2fVvGp68F3AK2O0UZyTVIgUBW1GEJh1sdmSTEuUlLJejZBrlXJ+AfElPHxbXq8chjzcPHR6lBnaD+Yu0vNoEgy9XYoxOYTPbMADZ1nwmT0IJcv2XDDTFqGGVmvSzOY3EJruWMRGGVoM2guLWNW3Rajcq5LOJK1VOmbWFd/6q+kZ7RWOGVuN+ecxOU96Pu1GpIHqoj+nfhDAyJLHcYu4vAFrwpEzjAIGM/9U/WVB3YuIE+KoG8LoP1XPBqGABlEG6lYbaDnGI1PMWaR0coTT9rMIBvOJuhDGieyWLkmrwhRzEFHcYVEChkMU+z0iUB/2MwbT1oFlhsFGCDj4xVTg/DjqEgf2uB4oNeBdH9aBExT3lBHVSv2PzKiU6YFWDCln5r/zRMGoVTdeO66rX2/uLzkOH0n5k9+fPtrQyzJHovzq+t6TX//avbm3c3/y5fZk85e9nY38+p3882+n63+0iMhdBJ/5j99NH27lj7+xpysvBAhAlcgee6K05uBhSuSPf2sRXeuThz/ku5stkm+uTz9Zb4SMpVnD8z7q+5lP3QAPPDAZtOmXgCdqx0OOo1Je7xrzHhAp76fFgqh2/itic1PbmLHsW3C15VuwYsc/n8A67ZNikXuOrUdZoFcf4/513TfEVQKyWFTb8PToCqUiBRNabKHKk8L48pmRUBjN7/lB1Ae/dYzPoYWT9XS0gBpoob6g91CpWPWWtTXpMhpDWh3eYKz1T8Y3hooqOkbdVUkKaQyV4mTRx5hDT2loke4REYxtWEBXBEa6AFmejhA8W6IAiTdYKWuodLxWr/Y191Ut3juGBpiyCJZaR5QlBCtJT6Nj3r51Yzxd/y8fu3zKp7c8j/9B1qswP1/Wm3rlSK2WgEVxWD1YxHOLA/7vVx4W89FrRa96s7Uyr1Je+Xfr5OTR62T8N2L3XWg=) 一開始方向錯誤,沒有懂老師出題的用意,就照先前的想法做了控制面板,後來才想清楚不是單純用vue做東西,而是做出quasar這種開發模板用的componen 第3課 ── 學習 Vue 的 events 觀念 [作業](https://play.vuejs.org/#eNrNV1tvG0UU/iuTVVHsNL7kIUJaArQplwgRhIjEC4vU8e7YXrI3ZmedGMtPIaJtIvJAaWkkbiK0qaqmCCGakhT+C/I6zlP+Amdmdta7rhPaChCWsto555uzc8755ptJR7sYBOVWRDRdmwtNagfsFcOz3cCnDC225yPGfA/Vqe8iQytXlIXPMLSXDM/wyKrAWqSOI4ehjuEhZPoQwCMeC3XUGYbpTnOnhRkuFCUQIUpYRD01QijE7QX7bTtkOvpA2dDQzX8BphD69RY8dMSadlgWk0Rw9XNwjTg6rHnRdw0t5zJ9x6fcRYk14mJklV1S7gYlxBsBhPYnREfV8mzOSv3Is3RUx05I8vCPI1grLJJGWYesw1NltmyH4Xw7HzXN7TU8mkCam2M3mqzm8C6dnmEQ0cAZRagUXxyX4kgiwwxHc3+GFHmdme01xuf4FjaXT0vSwnQZZrfPzNH2RufLDGeeKb9/qYOLtIwuehahoT9KtXwr28Rx/JWzEh3T7P8XW8+flmDNebLHudRWmjYbn9vYJj5XZv9EhqX/KsPn2IYfJm9dEG1ldwlr+hbXaOkTMlrwUm1GCDuEsoKhLdiwSHQeefBnaBMThlYUcYZfSAozdjbY89P//HrnZH/rySBKCsZGeTNxnr0S+VzBzGxCXnLEj6OIEShcYnChjDDmpxA38JrMVdLTDwaMuIGDGYERQnOW3UKmg8PwZWilb4HeCDt41NGm1toq1X0KKAcOMOTXh6eZoSnIBUmqEuGsSqDlDNGGSF0QS0HEIOMU5FJOMcg4OblKOURKtwyKM0z5+XvGJYimfGKAXhW0QwnJsmEE+dJAYnQKuiILWoGKwttcJVNnGIas7fDXKdl8F9OG7YGAiQYH2LKg+7AjKHHB0jW8Mm+GxK7YFoOGz1SrLwh0k3DVFIaw1RQmyw7hW21YkUNWhaWBAyGPMiASjtIK5Vb+FDYM8uuVYHe6sE9ChimT3wa+JKvVprXstYhfpCZKJTS4t9F7/MfR9d1476v+jUdH25/G62u9g18Hd28ffX43fvhjvP7w5HD7fSjS0huX0LuwtIYoNC9Fk7Eg1CuVsG7ymB+FZZ82KtzDqwih44Pfju5tpFcrDkIy/snhZm//dv/6g/7WL739jfjKzfjat4O1x3Kq4ASCYbzz3WD3fry3PVjb7N96cPz91uDqzxIzJE8O2L/xWXz/ZhYoKDkGE6/fifceJZoCvMpDNq8eX/ky3rkT/7SVXAEFvfq7P8SHiSXhUNZ0wXRsczkX6fjgm/4X1+LfN6G2vYODeOMWKpU4rdKdPO5uGlAfSqvkJZHoJUaHN5CMMufsic7nbFKk34ncGqGJKdHoed93CPYULhHorPVppKeWkRclQa4SnWRTydKA4xxxbVaYzIjJ5LRcdVFhdcFawKbyWoOjSRJPl9VIj4ykNmk5UkfNp3BleQ9bdgSVXMSsWca1sFBQOjFbhX1fLaISKqRqMCtMRVDtyWB1Mg3l2B5ZSPbqZRM7ZuFch9e0i6aSnVm8nILrvseWRMFz0CkhCRlcKhV/G1FmMg5YFUgU+o5tIXF+q1ldWUt5BHQ6yS7ogiZwZZMNO0Pcyqp9koLZ8nvwP5MQnWRZ6diM4IJI9cC34diiifipOHrTbxEKwQwWQhpEnynP8HUKiuWEqvsXUnaEYQ==) 嘗試從quasar的原始碼反向工程做出一樣的效果 第4課 ── 學習 Vue 的 v-model 觀念 [作業](https://play.vuejs.org/#eNrNVltv3EQU/iuDVdQN2mtuTc0m4iIh8YAEqtQXzIPXnt012B4zHm8SrRa1TSuVhrA8tAmKkKDqRakCSSsQDckGfgzr3eQpf4EzF3udTSraPvXB9pwz5z7nfOO29n4QFFsR1nStGlrUCdiC4TteQChDnyx/7AcRQ3VKPGRoxZJicHlDe9fw8ZKQs3HdjFyG2oaPkEVA2cc+C3XUTk108nzPNpmZm5ByCFHMIuonFEIOl7xquhHWkR+5rlBBqAOO4C0oD7MmsbllSS+azGqmFHcdMWynDI9EPtDcJWdwS9VSmiUQDHuBazIMFEJV22khyzXDcN7QasReNjTBhx2VRhKp7hEbuyJUEB3FbWiJxHtRAMni04I5Hy+K9QSaX0C5kR6aR+nWyIZr1rALanXHdbE94itaUKU3IkISMdfxszGmnEyU1RIUGFbVUqbsQIZs2eXLd2QreCZtOL6OyuLcA9O2Hb8hyY7hF/nBSMFFx2Zw+JVy+W0h2sROo8kEI2w1Bct2QnC0rKO6i5cEhy8KtkOxxRwCXiziRp4vtmqm9VWDQsvYBeASqiPaqOWm5vJo6hJ/JmQE0EEqYC2vZSaCT9BbhQI62l7tH/4zvLsV7/w4WP9ruHkzvrXSP/jz6Mnj4fdP4ueP4lvPT3qbV6GoVz76EH0K8UmvvBhNxoJQL5XCusVtfhkWCW2U+A6vI5iOD/aH26vJXHEZJM2f9L7r7z0e3N0ddP/o763GtzfiOz8frRxKzVZBnDMCRvzwl6Ot3+Kdzfha799r1+Puevz3BqyloDjSU2KDX2/2D9fiH9aGW89Oerfj7m7/4FF/b41nuNJFn0VmaFIUr94b3ts+vvFgsPXgqLt7vL8BAcVPnw2f3o/Xd47v7w4f7sc/bQ02rh/fuBOv/Q5mTnrfSp+yoRFoxr2uZCX9o5ioUFC9kgzvedATUALFSwBFZKKjK4xC/ygskZ509AEhLjZ9xU2cjfNHo8GhjC0H8FXmEscZuFIQJd/YczgAfm5oZ8bM0L54RSyyiM9MCJCOAElMZgqcdjLjowHUE+V2mrT85jPpplXujBR5mqDG8FLWWksBRDaNFEmEa9i8wLPOXTyT8cU8uoBbcCUUGcw2hq4dwxGKv45gJMcxTfZindBRegvttmrRTqdaEquXwpZiWkPVKiR0JABQDNJOCwsISLBnphxwuIBpN3zpbkzLrIUAHExqubguYEfoQAVJkKWo6ada0CWT5bIXIl52kwqBDNZU5qbyqHLpsngpuIHbWNygWcgDG8p6Co+TwHlppyOzep1YUYi+kUWFvpRcOCDHTrjStcgqsZ+JeW4mjyYrk/CameEhIxRapgszUS5eTlwV1YSrH4QX55sFYSkyC9A7O8sftU+ojUHdh3+MDKNQI4wRD+oAZYCjgejP01YNn6rzC0WNR5O0MIUCJLQsjIj4hS4Wm45qAVBiPKwa5XeQj8MwVymKesgCpJP2GiWYhhtoGpKYHitB5VSq5xg6L9t0+NN8U86ZjMddnD3q1MP/CZ5bn8rZG7XzH5rEyeY=) 同上 第5課 ── 學習 Vue 的 slots 觀念 [作業](https://play.vuejs.org/#eNqdVd1uG0UUfpWDEeJH3o0TCqkWUylBofiiroQbIaS9Ge+O7VHXM6uZsR0TWSoqkVADBFAFFarUIgpEKj8XVCjQwtNk3fQKHoEzM7trO2mo2ht7zpnv/M45325X1tLUHw5oJajUVSRZqs+FnPVTITVcGK8TzqmEjhR9CCv+UqExFmHljZDTLYuMaYcMEg3bIQeIBJpzyrUKYHvmZFI1lzHR5KWXHRBAUj2QHLYn6ApyRJ/qnoiNrZNHREe9UjLOB5rGpaIvBhxl49MojKf6UlkJCpr204RoihJAPWZDiBKi1JthpS3icVixerwpE5XoMaZxrgd4j0JE+IsaOozHMBYDCYoMaYzZRyylCjABlpgLUKzLgXHfBHbGZXgYeioROiCRZoKXzhHRHmiNmrcuNi81mpsbsNaCNTi/udG6VF/K7wpMq3G+CY1mqS+jLC1UaRRFObYJ/19go+OSJyPQPaagbWFVFGh+xkdANWW8C4pSDu2xsXimMt/faJ0oq3nxhOrfWzduPGWZRsTnxdMCDkWlx4k5vuLmrk9kl/EAanbqUhLHWJgTJyH3zVg44IjFGkdvuVZ7wUJ7lHV72irUsGdVMVMYaBxAV7LYarokRYSkfSuRBEfCiwTOKEdLpYnULk7IXXUuVFvImMoAOG6ONWyT6HLXvlSAE9Wjkhk7swCJQBz6jWg7GThwB/17in1AsQr/bBE7GkhlsKlgGF4eq9Z/rcClQjHzWgFONDaNDY1TzNDlFwSkg9bFbueFhBW7//PGpK1Egrtp1YwrijDX4lkt2Amb/qjHcqBIScQ0NtBBtSS8cJhfYaorChLGKTE1zLUu6IkhNm0+wZk7f8WBkQ3y569UK/MEZijvOc+DkB/d3c3u//nw7m7JVuYesp2rh/d//+fBJ4cHP0yv/zrdu3d4sJt9/HV27dbR1b9C/uj250f7Pz/85iMwIw+oy+7cnl7/O9v5Ptv5KfviWrbzY/bLHyF3yzCPym7uo6/DgyvTz76c3ryS7f2WfXjPmT769tPszleFab6rMN3/LnuwB55nxrukt8fRbypFapk3Nw1gXYiEEm759Wn40Tw2wbbLGUma66C4nwuRH6o5XwT4jtjACRrWTdXnMKT7cwta+ipcuQ4VcOCkTxe0x82ftOl+mXvelFNG3M/5LeeFLW+28mo4esxurZZbY/WjnBHO1Nz4min1SprwV0p0QjXOqKfMeLr1qy2vnn193leH9FmCk/uuaAstquCRNE2op8YKa6zC2pByhqy8jjEuXyBRy+rfRssqtGhXUNhs2C8iwDs0GVLNIoJWkpGkitzOlaeQRDqnLOTzq+3lDjErcwrFlMRhqC1nD3jVlWcamc/4sW4vcIIWyIy5CX77XZNKuWTSTkK3XFfw4I2k4VPze4JdLRP4xYbM0agnScwGuARnUuNpkQQm/wFjNTqv) 嘗試模仿quasar拼裝不同呃component 第6課 ── 學習用外部狀態管理 vue 元件 [作業](https://play.vuejs.org/#eNrtVktvFEcQ/ivFhshrsi+bWEo2hgBOohwgQiBx2gO9M727HWamx909axtrTwQFsBUOIRA45KEQHkJAFEUBYkj+jGdtn/gLqX7M7KyxwcohyiF7mO2u/rq6q+qrql4uHY3jWj+hpWZpVnqCxepwK2JhzIWCE0vHEqV4BB3BQ2iVavVMone0Sh8UkB8xEvBuEWklObIV0UWD9WmHJIGC5VYE4HFUENFIySYsw/wxFTXzYyswb3VokdM/qOhdPlGkPGk1AAiqEhHhdhJQoZrQIYGkFVQddZgI3RwGeAdw+0OqetzXR1oNZuPU9MGRTicro3DSbMy22u8CUV4Pt9uZNiJR1M8FIU8inGt1WqCPnq3n3sWJomEcEEVxBjA7X20rlOpDAtKmwaFW6ag+vVWyQo8HXKCwHRDvXCZUdFFVs5WFHlPoZrvSlOw8ReFUJhB4Hd8Oj8REoLertI9fxBgr4RDsMwO74fBs3dwou5xvXd+vhtw3l3NYs44In/XdEOA4FzQEFsskBF9fDiRTQNDhOh6SekoHC4jPYiaZx6Iu0ICpGpyiArcIGtMgoJGfyEyj3t/nQRIr9Fc2kqANYKgVKSV4th0dFPlMMSYhpqJD0VQfx4orEprA6B8lQBTwMMKVPg0gSsL5hIRAF6nwGJ7CkJAhkERVICIqkRAy5Dmp2LN0iNDImjO+PrK+GMdRJOeOc5mHZpdYvi6aO8RzLKJ7i6n+dQJO9Lpg3V4uHg82jm20dyXmnM2qf4GaLn+1IW64R3rm6P8J+t8k6G6R/Qckna0XSilOpVoK9PCALeQhEV2GLaVhanhMfB8DaqeDVtTm/pLFLTBfYT2fajTeNsge1ccbgez3jKiN7ugas6wbmvDWND3oHaRWF9Z3d3SpUio2v7HGulMLjAWPTfcz/D1DgoQ24RjnASWRaTdvah8YYPACIqV1rSIsoqJVwoxgHRSN1I5lRL5F9ojPF3BtjCpFxAKLECE1RAZcIdD9ZfhstFs0avm1nMkckwZZ3ATSlpgwSjsRgGH+odNtsDAvUNNSE7qC+TZ8yEiKzsfWGiHMwy8V1vujA5pt2kH2Z68Lh0Ui6TfI3k5+NdKi2y5PvT9dgemp9/Az494EPCaYj3jFRm3GCDoswCs1oW3YG1Epy7hkweer6EW6mJOv5rzqPJJRcwrL025863Q6Zikki1XH2JlGI160eC58KqoCK1eCdHrXifNjp7Ydexi250htxp79KptHjz7N5n3VKmw+WFl/8dfGtXvpo2+H159t3PoivXhhfe33zft3Nr66nz75Ob345OXzW2cSCqc/mYOTGElrjOZFTylkfL0uO57W+bmscdGt6xVNPVSdrv2x8WAlfwhqEFj9L5+vrj+9M7z2eHj1t/WnK+mlG+mV7zcvvCh0I8BpevuHzXsP00e3Ni+sDm8+3vrx6ublX7c3pzHg8PqX6cMbRaCpjztg0ot300fPLEYXvnHI6uWtS9+kt++mv1wtdDgY3vspfe4kEqs5MrQoOuIFzDs3pmlr7bvh11fSP1fRt+tra+nKTahWdY7tqZgU/NGE00ogt1x/0fbP7SA35m6TafOa8FkStqlwIlOft8GMiXnNyvYaK7dL+3MBdpuTMY+TeHxtL5WubejgbHPFKXQkyXqFdSUu7KchU+UJ23s+1q1nomKtnBw9RzTLEZu/+kdZhwVGeynvys6XufvyBZt4p1zenSCqV8PaUi7bwH+IKQqYXJNQhbKLPMqMaBLegYl4cSJXFWAF+9S1nrMeCbzy/mUdgwHmqk3PybM5uIPF7bQJ0Bj0gCkhBVxeWt6o0VqyE7BhkIAVk/n6EeOdK9zDMsL8OeHAvdTsbHnZ5dIAK4tuFjaMr+sXWVAtkYtBifDtU6h3BYGXCKkjFHPmGgOSXZAoK/gSraIw3WiE+Dgj0vXt/Khmj/ez/mSgWDJrrmgWyuHgb/u4VhA=) 稍微翻了quasar的原始碼,還是搞不懂為何上一個v-close-popup的attribute就可以讓按鈕有關掉modal的功能 很神奇 第7課 ── 學習開發狀態複雜的 vue 元件 [作業](https://play.vuejs.org/#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) 研究了前輩的作業才發向若要讓input的值可以被檢查就不能限定number,要不然輸入非number會直接show出來,卡這個很久... 因為想學quasar的樣式(range條的顏色變化等)做了些研究,後來嘗試把所有想法塞進去,結果做出來是蠻炫的但不是很好看... 心得:覺得老師的出題方向就是幫助學生從業界的需求去學習,然後一點一點從小地方開始做,並且能夠自行研究,而且不強調怎麼寫,而是確實做出來,很務實的取向,覺得獲益良多,上完9堂課默默繳了不貴的學費,有新的課堂會再回來做。 目前正嘗試自行開發一個網頁應用,寫cdoe真的要很有耐心,其實想想現在有很多輔助/查詢工具真的很方便,越寫越佩服那些做框架的人...

新手適用:重構程式碼的幾個簡單方向

## 介紹 程式碼重構,在不改變外部功能的情況下改進現有程式碼。它是寫程式的核心部分之一,不容忽視,否則您將無法獲得更好的程式碼。程式碼重構可以增強程式碼的可讀性、可維護性和可擴展性。它還能提高性能並提高開發人員的工作效率。 今天,我們將研究一些可以幫助您重構程式碼的技術。 原文出處:https://dev.to/documatic/5-code-refactoring-techniques-to-improve-your-code-2lia ## 如何整合Refactoring 在尋找改進重構的技術之前,讓我們看看如何將程式碼重構整合到您的工作流程中。您可以使用以下建議: - 你應該專門分配時間來重構程式碼。 - 將較大的重構問題分解為較小的重構問題進行管理。 - 嘗試讓整個團隊參與重構過程。 - 使用可以幫助您查找常見重構錯誤的自動化工具。 現在,讓我們從用於重構的技術開始。 --- ## 提取方法 此方法將程式碼轉換為單獨的方法/函數。這樣做是為了改善程式碼的結構和可讀性。它將長而復雜的程式碼提取為更小且更易於管理的方法。 要使用這種技術,我們首先需要找到一個執行有點複雜的特定任務的程式碼區塊。找到後,我們提取程式碼並放入新方法中。另外,請確保為該方法提供一個有意義的名稱。 **例子:** 重構前 ``` function calculateInvoiceTotal(items) { let total = 0; for (let i = 0; i < items.length; i++) { const item = items[i]; if (!item.quantity || !item.price) { console.error('Invalid item', item); continue; } const itemTotal = item.quantity * item.price; total += itemTotal; } return total; } ``` 重構後: ``` function calculateInvoiceTotal(items) { let total = 0; for (let i = 0; i < items.length; i++) { const item = items[i]; const itemTotal = calculateItemTotal(item); total += itemTotal; } return total; } function calculateItemTotal(item) { if (!item.quantity || !item.price) { console.error('Invalid item', item); return 0; } return item.quantity * item.price; } ``` 您可以看到我們如何將在 `for` 迴圈內執行的複雜程式碼轉換為另一種方法,以實現簡單性和可讀性。 --- ## 使用常數 此程式碼重構是為了編寫更清晰、更易讀的程式碼。直接寫數字可能會導致其他人感到困惑,因為他們的目的沒有定義。將硬編碼值轉換為具有有意義名稱的變數可以幫助其他人理解它。此外,您可以為其加入註解以進一步說名。它還可以幫助除錯並降低未來出錯的風險。 **例子:** 前 ``` if (temperature > 32) { // Do something if temperature is above freezing } ``` 後 ``` const int FREEZING_POINT = 32; if (temperature > FREEZING_POINT) { // Do something if temperature is above freezing } ``` ## 合併重複程式碼 重複或相同的程式碼可能出現在來自不同地方的程式碼中。此程式碼不需要完全相同,但它可以執行類似的任務或從原始程式碼擴展一點。重複的程式碼會導致幾個問題,包括增加維護成本、難以更改程式碼庫以及引入錯誤的更高風險。 在重構程式碼時,您必須注意重複程式碼。找到此類程式碼時,一種處理方法是將此類程式碼轉換為單個可重用的函數/方法。 例子: 前 ``` function calculateTotal(numbers) { let total = 0; for (let i = 0; i < numbers.length; i++) { total += numbers[i]; } return total; } function calculateAverage(numbers) { let total = 0; for (let i = 0; i < numbers.length; i++) { total += numbers[i]; } const average = total / numbers.length; return average; } ``` 後 ``` function calculateSum(numbers) { let total = 0; for (let i = 0; i < numbers.length; i++) { total += numbers[i]; } return total; } function calculateTotal(numbers) { return calculateSum(numbers); } function calculateAverage(numbers) { const total = calculateSum(numbers); const average = total / numbers.length; return average; } ``` 在之前的程式碼範例中,我們進行了求和並再次求和以求平均值。之後,我們將其替換為為兩者提供總和的函數。 --- ## 簡化方法 這與您正在尋找要優化的方法/功能時進行辨識非常相似。此技術可以幫助您減少程式碼行數。 此方法可以分解為更小的程式碼塊,您可以在要優化的函數中找到這些程式碼塊: - 刪除不必要的變數和表達式:可能有一些變數或表達式是您為了除錯而遺漏但忘記刪除的,例如 JavaScript 中的 console.log。 - 使用內建函數:有時使用庫或語言的內建函數會更好。因為可以用更少的程式碼實現相同的功能。 - 簡化條件語句:如果一個方法有複雜的條件語句,可以考慮通過組合條件或使用三元運算符來簡化它們。 ## 使用延遲載入 這是一種僅在需要時才載入物件的技術。這可以通過減少使用的內存量來提高應用程式的性能。這導致更快地載入應用程式。 這種技術在 Web 開發中非常流行。特別是對於像 React 這樣的 JavaScript 框架,您可以通過延遲載入來導入不同的元件。這也可以用於根據需要載入圖像。 **例子:** 前 ``` import React from 'react'; import MyComponent from './MyComponent'; const App = () => { return ( <div> <h1>My App</h1> <MyComponent /> </div> ); } export default App; ``` 後: ``` import React, { lazy, Suspense } from 'react'; const MyComponent = lazy(() => import('./MyComponent')); const App = () => { return ( <div> <h1>My App</h1> <Suspense fallback={<div>Loading...</div>}> <MyComponent /> </Suspense> </div> ); } export default App; ``` 在更新版本中,我們使用 `lazy` 函數異步導入 `MyComponent` 元件。這意味著該元件僅在實際需要時才載入,從而提高了我們應用程式的整體性能。我們還使用“Suspense”元件在載入元件時顯示後備 UI。 ## 結論 重構是任何想要提高程式碼質量、性能和可維護性的開發人員的基本實踐。通過花時間分析和優化您的程式碼,您可以消除冗餘、降低複雜性並建立更高效和可擴展的應用程式。 通過不斷審查和改進您的程式碼,您可以建立更健壯和更有彈性的應用程式。

10 個可以改善開發體驗的 VSCode 外掛

- 原文出處:https://dev.to/j471n/vs-code-extensions-to-take-your-coding-to-the-next-level-50od ## Documatic 此外掛將 [Documatic](https://www.documatic.com/) 引入 VSCode:使用簡單查詢快速搜尋大型程式碼庫。 Documatic 使用 AI 連結您的查詢和程式碼片段之間的關係,因此您不必知道要查找的確切關鍵字! **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=Tyriar.sort-lines) ![](https://i.imgur.com/KYutr9T.gif) ## Sort lines 此外掛允許您按字母或數字快速對程式碼進行排序,從而在處理大文件時節省時間。當您有要排序的資料時,這會非常方便。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=Tyriar.sort-lines) ![使用動畫](https://github.com/Tyriar/vscode-sort-lines/raw/HEAD/images/usage-animation.gif) ## TabNine 此外掛使用 AI 提供程式碼自動完成建議,可以幫助您節省時間並提高程式碼品質。它支援很多語言和框架。但是要小心使用它,因為它會佔用你系統的很多資源。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=TabNine.tabnine-vscode) ![Tabnine 主要完成](https://raw.githubusercontent.com/codota/tabnine-vscode/master/assets/completions-main.gif) ## **Template String Converter** 可以在程式碼編輯器中鍵入“${”時將普通字串轉換為模板字串。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=meganrogge.template-string-converter) ![鍵入一個美元符號然後在字串中打開大括號將引號轉換為反引號](https://raw.githubusercontent.com/meganrogge/template-string-converter/master/images/demo.gif) ## **Error Lens** ErrorLens 增強了語言診斷功能,突出顯示語言生成診斷的整行,並連結相關訊息。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=usernamehw.errorlens) ![演示圖片](https://raw.githubusercontent.com/usernamehw/vscode-error-lens/master/img/demo.png) ## **WakaTime** [WakaTime](https://wakatime.com/vs-code) 是一個開源 VS Code 外掛,用於從您的寫程式工時中,自動生成指標、分析和時間追蹤。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=WakaTime.vscode-wakatime) ![專案概覽](https://wakatime.com/static/img/ScreenShots/Screen-Shot-2016-03-21.png) ## **Chat** 通過使用此外掛,您可以在 VS Code 中與您的 Slack 和 Discord 團隊聊天。 * **安靜的通知**:聊天應用程式可能會讓人分心。此外掛使聊天變得有用、上下文相關且不會分散注意力。 * **豐富的格式**:分享 Markdown 程式碼片段,並在您的聊天訊息中加入表情符號。 * **本地外觀**:在您喜歡的主題和網格編輯器佈局中使用聊天。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=karigari.chat) ![截圖](https://raw.githubusercontent.com/karigari/vscode-chat/master/readme/Live%20Share%20Chat.gif) ## **SVG Preview** 允許您直接在 VS 程式碼中查看 SVG 文件。如果您在 vs 程式碼中打開 SVG 文件,那麼預設情況下它會顯示 SVG 程式碼。使用它後,您可以看到 SVG 的預覽。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=SimonSiefke.svg-preview) ![演示](https://github.com/SimonSiefke/vscode-svg-preview/raw/master/demo_images/demo.gif) ## **Headwind** Headwind 是用於 Visual Studio Code 的 Tailwind CSS 類排序器。它通過解析您的程式碼並重新打印類別標籤來強制執行一致的類別排序。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=heybourn.headwind) ![解釋器](https://github.com/heybourn/headwind/blob/master/img/explainer.gif?raw=true) ## **Material Design Palette Generator** [Material Design Palette Generator](https://marketplace.visualstudio.com/items?itemName=piyush-bhatt.vscode-mat-palette) 是一個 VSCode 外掛,用於生成 [material 調色板](https://material.io/design/color/the-color-system.html#tools-for-picking-colors)。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=piyush-bhatt.vscode-mat-palette) ![獲取從給定的十六進制顏色生成的完整調色板](https://raw.githubusercontent.com/piyush-bhatt/vscode-mat-palette/master/assets/readme/Primary.gif) --- 以上,簡單分享,希望對您有幫助!

# JS油猴系列-遮蔽廣告(D卡未登入)腳本、自定義新增名單

## 前情提要 逛論壇或網站常常有惱人的蓋板廣告,要馬就是要你登入、註冊, 要馬就是搞一堆課程的販售廣告, 對重視使用者體驗的人來說,真的是一場噩夢! 為了解決這個問題,我模擬了AdBlock的其中一個功能,刪除頁面上的元素! 乾乾淨淨才是王道阿。 ## 效果 按下ctrl+Q啟動刪除元素模式: ![](https://i.imgur.com/411nh3Q.png) 被選取的會加上邊框色彩,讓人確認是否要刪除: ![](https://i.imgur.com/zPEKMhC.png) 點選確認後: ![](https://i.imgur.com/nnOY4Ji.png) 煩人的元素就此消失在這個永恆的宇宙裡。 ## 觀念筆記 ### 套件一:toastr ```javascript= //toast.js cdn匯入 const toastJS = ` <link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.css" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.js"></script>` $('body').append(toastJS); ``` ![](https://i.imgur.com/lNDch3V.png) [測試效果反應網站](https://codeseven.github.io/toastr/demo.html) ![](https://i.imgur.com/v95GUfO.png) [[十分鐘學習] toastr - 簡易提示訊息](https://ithelp.ithome.com.tw/articles/10197861) ### 套件二:SweetAlert2 ```javascript= //設定cdn使用Sweetalert套件 let Sweetalert2=`<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>` $('html').append(Sweetalert2) ``` ![](https://i.imgur.com/qUeTUlj.png) ![](https://i.imgur.com/FJH8EMX.png) 有提供很多API範例,還可以自己定義可愛的小動物XD [官方網站](https://sweetalert2.github.io/) ### 監聽鍵盤組合鍵 ``` document.addEventListener('keydown', function(e){ if(e.which==81 && e.ctrlKey==true){ //..... } ``` ### Object.assign 動態修改樣式 ![](https://i.imgur.com/AzZMRCc.png) [用JS動態修改CSS的三種寫法,花式JS玩弄樣式,嚇死你的同事!](https://codelove.tw/@JsLover0018/post/Ja64Kx) ## 油猴程式碼 ```javascript= // ==UserScript== // @name 刪除廣告元素 // @namespace http://tampermonkey.net/ // @version 0.1 // @description try to take over the world! // @author You // @match *://*/* // @require https://code.jquery.com/jquery-3.6.3.min.js // @icon https://www.hexschool.com/ // @grant none // ==/UserScript== (function() { //--------------------------------------- // 宣告變數 let set let Check = true; let List=[] //設定選取的border色彩效果 let styleNeon = `@keyframes neon-color { from { filter: hue-rotate(0deg); } to { filter: hue-rotate(360deg); } }` $('style:last').append(styleNeon) //設定cdn使用Sweetalert套件 let Sweetalert2=`<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>` $('html').append(Sweetalert2) //使用者點選某個元素 執行刪除元素function function SetDeleteEl(e){ e.preventDefault(); set=e.target.class console.log(set) const border={ border:"4px dotted red" } const Neon={ animation: "neon-color 2.5s linear infinite" } const NoBorder={ border:"none" } const StopNeon={ animation: "" } Object.assign(e.target.style,border) Object.assign(e.target.style,Neon) //e.target.remove() if (Check==true){ Swal.fire({ title: '確定要刪除這個元素?', showDenyButton: true, showCancelButton: false, confirmButtonText: '確認', denyButtonText: `取消`, }).then((result) => { /* Read more about isConfirmed, isDenied below */ if (result.isConfirmed) { e.target.remove() List.push(e.target.className) localStorage.setItem('List',List); Check=false; Swal.fire('成功刪除此元素!', '', 'success') } else if (result.isDenied) { Check=false; Swal.fire('動作已取消', '', 'info') Object.assign(e.target.style,NoBorder) Object.assign(e.target.style,StopNeon) }; }); } //選取流程結束後 解開選取流程的事件綁定 $('body').unbind('click',SetDeleteEl) } //toast.js cdn匯入 const toastJS = ` <link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.css" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.js"></script>` $('body').append(toastJS); // 當使用者按下Ctrl+Q 就執行主程序 document.addEventListener('keydown', function(e){ if(e.which==81 && e.ctrlKey==true){ RemoveListItem(); toastr.options = { // 參數設定[註1] "closeButton": false, // 顯示關閉按鈕 "debug": false, // 除錯 "newestOnTop": false, // 最新一筆顯示在最上面 "progressBar": false, // 顯示隱藏時間進度條 "positionClass": "toast-bottom-right", "preventDuplicates": false, // 隱藏重覆訊息 "onclick": null, // 當點選提示訊息時,則執行此函式 "showDuration": "300", // 顯示時間(單位: 毫秒) "hideDuration": "1000", // 隱藏時間(單位: 毫秒) "timeOut": "2000", // 當超過此設定時間時,則隱藏提示訊息(單位: 毫秒) "extendedTimeOut": "1000", // 當使用者觸碰到提示訊息時,離開後超過此設定時間則隱藏提示訊息(單位: 毫秒) "showEasing": "swing", // 顯示動畫時間曲線 "hideEasing": "linear", // 隱藏動畫時間曲線 "showMethod": "fadeIn", // 顯示動畫效果 "hideMethod": "fadeOut" // 隱藏動畫效果 } toastr.success( "已開啟刪除元素模式!" ); $('body').on('click',SetDeleteEl) Check=true }}) function RemoveListItem(){ if (localStorage.getItem('List')!=null){ item=localStorage.getItem('List').split(',') for (i=0;i<item.length;i++){ item[i]='.'+item[i] item[i]=item[i].replaceAll(' ','.') try{ document.querySelector(item[i]).remove()} catch{} } // item='.'+item // item=item.replaceAll(' ','.') // document.querySelector(item).remove() } } //-------------------------------------------------------- })(); ``` ## 心得 短短150行左右的程式碼,就寫得好辛苦!(汗 過去寫過很多次類似的東西,所以基本上沒有卡關的地方, 只是設計邏輯、嘗試的過程還是比想像的還要耗精神( ´•̥̥̥ω•̥̥̥ ) 但寫出來比過去快很多,也比過去好看超級多的。 給自己一個讚讚! 重新把localstorge複習一遍,Object.assign、套件使用等。 算是一個確確實實的實力鞏固過程。 ## 延伸 未來可以新增控制黑名單元素的UI。 可以新增、刪除,看有哪些元素被列入要刪除的黑名單。

自學網頁の嬰兒教材:JavaScript(八)作業分享

第1課 ── 碼表應用程式 https://replit.com/@superyngo1/vue3timer 第一次獨立開發,css苦手,看前輩做的這麼漂亮就練習了一個文字背景漸變 第2課 ── 筆記應用程式 https://replit.com/@superyngo1/vue3notebook 看到學長的範例就練習建置vue的sfc和typescript 花了一些心思設定筆記的選取順序和刪除變換 css苦手 第3課 ── 分帳應用程式 https://replit.com/@superyngo1/vue3billsplitter?v=1 被typescrtpt的型別檢查搞得很苦 看了一些youtube教學css比較會排版面了 規格要求外新增了待付的選項 第4課 ── 行事曆應用程式 https://replit.com/@superyngo1/vue3calendar 漸漸掌握vue的資料框架 看前輩用很多vue標籤覺得厲害 仍對typescrtpt頭痛 第5課 ── 體重追蹤應用程式 https://replit.com/@superyngo1/Weight-Tracker-Chart 放棄建置(以及typescript)回到用cdn導入vue 寫的愉快 感謝學長拆雷 第6課 ── 天氣查詢應用程式 https://replit.com/@superyngo1/vue3weathercheck 第一次導入api 還算輕鬆 看到學長寫法用v-show去控制顯示資料原來還可以這樣 第7課 ── 國家資訊與地圖應用程式 https://replit.com/@superyngo1/vue3-World-Map-with-Country-info 原本以為只要資料串好 格式設定好應該很簡單 結果卡在一堆低級錯誤(for loop格式寫錯等) 還糾結為何flag顯示不出來圖案(看學長的可以) 最後才發現原來是瀏覽器的問題 心累

在 React 裡面,關於 Strict Mode 的簡單說明

`React.StrictMode` 是一個好用的元件,用於突出顯示應用程式中的潛在問題。就像 `<Fragment>` 一樣,`<StrictMode>` 不會渲染任何額外的 DOM 元素。在這篇文章中,我們將深入探討什麼是嚴格模式、它是如何運作的,以及為什麼你應該考慮使用看看。 原文出處:https://dev.to/codeofrelevancy/what-is-strict-mode-in-react-3p5b --- ## 什麼是 React 中的嚴格模式? 嚴格模式是一組開發工具,可幫助您在程式碼中找到潛在問題。當您在 React 應用程式中啟用嚴格模式時,您實際上是在告訴 React 打開一堆額外的檢查👀 和警告,以便幫助您寫出更好的程式碼。這些檢查和警告可以捕獲以下內容: 1. 有副作用的元件 2. 已棄用或不安全的生命週期方法 3. 某些內置函數的不安全用法 4. 列表中的重複鍵 ![嚴格模式](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/10tfwojwoyip5ld20yec.gif) --- ## 啟用嚴格模式 在 React 應用程式中啟用嚴格模式非常簡單。您可以通過在主 `index.js` 文件中加入一行程式碼來實現: ``` import React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') ); ``` ## 為應用程式的一部分啟用嚴格模式 您還可以為應用程式的任何部分啟用嚴格模式: ``` import { StrictMode } from 'react'; function App() { return ( <> <Header /> <StrictMode> <main> <Sidebar /> <Content /> </main> </StrictMode> <Footer /> </> ); } ``` 在這種情況下,嚴格模式檢查不會針對“頁首”和“頁腳”元件執行。但是,它們將在 `Sidebar` 和 `Content` 以及它們內部的所有元件上執行,無論它有多深層。 --- ## 嚴格模式只影響開發環境 請務必注意,嚴格模式對 React 應用程式的正式環境建置沒有影響。嚴格模式啟用的任何檢查或警告都不會出現在用戶看到的應用程式最終版本中。除此之外,嚴格模式會打開額外的檢查和警告,它可能會減慢您的開發環境速度。 ![嚴格模式只影響開發環境](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nu5kpm4ixxfesjdhv1cv.gif) --- ## 嚴格模式可以幫助你捕捉細微的錯誤 有時 React 應用程式中的錯誤可能很難追踪,特別是諸如 race conditions 或對元件狀態的不正確假設等細微問題。啟用嚴格模式的額外檢查和警告,您可以在這些錯誤導致嚴重問題之前發現它們。 --- ## 嚴格模式可以幫助您了解最新的最佳實踐 React 是一個快速發展的框架,最佳實踐會隨著時間而改變。啟用嚴格模式並留意它提供的警告和建議,您可以確保您的 React 程式碼遵循當前的最佳實踐。例如在渲染列表時使用 key 屬性,或者在 render() 中避免副作用。 --- ## 儘早發現潛在問題 嚴格模式可以在您的程式碼中發現可能在未來引起的問題,以免它們成為嚴重問題。比方說,它可以檢測並警告已棄用的生命週期方法以及對不再推薦的 [findDOMNode()](https://react.dev/reference/react-dom/findDOMNode) 的存取。 ![findDOMNode](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/awx9dnh9eexg4eb73wt2.png) ![findDOMNode](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i5hjs6oae3lj38mbhjwk.png) --- ## 防止常見錯誤 啟用嚴格模式,您可以避免一些隱晦的常見錯誤,例如:直接修改狀態而不是使用 setState()、使用未宣告變數。 --- ## 辨識不安全的生命週期 React Strict Mode 可以幫助辨識元件中不安全生命週期方法的使用。例如,它可以警告您使用 `componentWillUpdate` 和 `componentWillReceiveProps` 方法,這兩種方法都被認為是不安全的,將在 React 的未來版本中被刪除。 ![不安全生命週期](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s6d9qh4xjz16u9xlsle5.png) 假設您有一個元件,它使用 `componentWillReceiveProps()` 來根據傳入的 props 更新其狀態: ``` class BlackMamba extends React.Component { constructor(props) { super(props); this.state = { venom: props.venom }; } componentWillReceiveProps(nextProps) { this.setState({ venom: nextProps.venom }); } render() { return <div>{this.state.venom}</div>; } } ``` 在常規模式下,該元件會按預期工作,但在“React.StrictMode”下,您會在控制台中看到一條警告: > 警告:BlackMamba 使用 `componentWillReceiveProps`,這被認為是一種不安全的生命週期方法。請使用靜態的 getDerivedStateFromProps 。 --- ## 過時的字串引用 API 用法 嚴格模式還可以警告您過時的字串 `ref` API 的使用。該 API 已被官方棄用。您應該使用更安全、更易於使用的 `createRef` API。 ![過時的字串引用 API 用法](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gv8lf8ubk7vv4yg8m4qo.png) 比方說,您有一個元件使用這樣的字串引用: ``` import { Component } from "react"; import { createRoot } from "react-dom/client"; class BlackMamba extends Component { componentDidMount() { this.refs.venom.focus(); } render() { return ( <> <h1>Black Mamba</h1> <input ref="venom" /> </> ); } } const root = createRoot(document.getElementById("root")); root.render(<BlackMamba />); ``` 您不會在控制台中看到任何錯誤。 ![輸出](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/trxw9auusgunit73rvzp.png) 當您像這樣在您的應用中啟用“React.StrictMode”時: ``` import { StrictMode, Component } from "react"; import { createRoot } from "react-dom/client"; class BlackMamba extends Component { componentDidMount() { this.refs.venom.focus(); } render() { return ( <> <h1>Black Mamba</h1> <input ref="venom" /> </> ); } } const root = createRoot(document.getElementById("root")); root.render( <StrictMode> <BlackMamba /> </StrictMode> ); ``` 您會在控制台中看到如下所示的警告: > Warning: A string ref, "venom", has been found within a strict mode tree. String refs are a source of potential bugs and should be avoided. We recommend using useRef() or createRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref ![輸出](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tnf0qdctk8q7q9d1mzf0.png) 讓我們用 `createRef` API 修復它: ``` import { StrictMode, Component, createRef } from "react"; import { createRoot } from "react-dom/client"; class BlackMamba extends Component { constructor(props) { super(props); this.venom = createRef(); } componentDidMount() { this.venom.current.focus(); } render() { return ( <> <h1>Black Mamba</h1> <input ref={this.venom} /> </> ); } } const root = createRoot(document.getElementById("root")); root.render( <StrictMode> <BlackMamba /> </StrictMode> ); ``` 修理完成! ![輸出](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0pq7w11m292b3sh9e3aj.png) --- ## 過時的 Context API [舊版 Context API](https://legacy.reactjs.org/docs/legacy-context.html) 在 React 中已棄用,已被新的 Context API 取代。 React Strict Mode 可以幫助您檢測過時的 Context API 的任何使用情況,並鼓勵您切換到 [新 API](https://react.dev/reference/react/useContext) ![檢測遺留上下文 API](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iowjhzc795mngti4ayo0.png) --- 如果您還沒有使用嚴格模式,那絕對值得使用看看! 以上簡單分享,希望對您有幫助!

給新手參考:前端專案的檔案架構範例

在開發 Web 應用程式時建立可維護的檔案結構很重要,良好的架構有助於組織程式碼,並使其他開發人員了解您的 Web 應用程式結構。 原文出處:https://dev.to/noruwa/folder-structure-for-modern-web-applications-4d11 ### 設計檔案結構的一些技巧 - 了解您的 Web 專案的目的:為了弄清楚如何組織您的 Web 專案,您需要很好地了解專案需求 - 為您的文件夾和文件使用正確的命名慣例,它們應該描述您的 Web 應用程式的用途 ### 結構及說明 **Assets** assets 包含將在您的 Web 應用程式中使用的所有圖像、圖示、css 文件、字體文件等。自定義圖像、圖示、付費字體都放在這個文件夾中。 ![資產](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bosdpni04f4rhoscokrl.PNG) **Contexts** 當使用 React Js 作為您的前端 ui 庫時,context 文件夾存放所有跨元件和多個頁面使用的 react context 檔案。 ![上下文](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/34ah8q7qbthfe5pbkcbf.PNG) **Components** components 文件夾包含應用程式的 UI。包含我們所有的 UI 元件,如導航列、頁腳、按鈕、視窗、卡片等等。 ![元件](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0fsm5cd609kxc1ydcv4b.PNG) ** Composables** 在 Vue 應用程式中,“Composables”是一種利用 Vue 的組合 API 來封裝和重用有狀態邏輯的功能。 **Data** 用來放會在不同部分和頁面中作為 JSON 文件使用的文本資料。這樣做將使資訊更新更容易。 ![資料 JSON](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/74ey2c253fveerw4ox3y.PNG) ![資料](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mybd8n92pxns26feb6qt.PNG) **Features** 包含每個頁面(身份驗證、主題、視窗)會用到的功能。例如,每個頁面可能都會用到視窗功能。 ![功能](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gljjlh0jgarivzabdamm.PNG) **Hooks** 讓 React 元件有狀態和生命週期特性的函數。我們還可以建立名稱以“use”開頭的自定義掛鉤,並可用於呼叫其他掛鉤。 ![掛鉤](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a84dq8pahtjgff63ru7e.PNG) **Layouts** 在定義網頁的總體外觀時,Layouts 文件夾會派上用場。它用於放置佈局的元件,例如側邊欄、導航欄和頁腳。如果您的 Web 應用程式有很多佈局,這個文件夾是保存它們的好地方。 ![佈局](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6h73gy0uruci8qlq5sjl.PNG) **Modules** Modules 文件夾處理應用程式中的特定任務。 ![模塊](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/boeni6zfudcg14201s87.PNG) **Pages** pages 目錄包含您的 Web 應用程式畫面。 Next Js 和 Nuxt Js 等前端框架中的頁面目錄,會讀取目錄中的所有文件並自動為您建立路由設定。 ** Public** 直接在伺服器根目錄提供服務,包含不會更改的公共文件,例如 favicon.ico。 **Routes** routes 文件夾只是你的 web 應用程式中的一個地方,用於存放到不同頁面的路由路徑。 ** Utility/Utils** 該文件夾用於存放所有實用函數,例如 auth、theme、handleApiError 等。 ** Views** Views 文件夾類似於 pages 文件夾,用來放頁面的重複部分。 ### 結論 良好的檔案結構可以讓您和其他開發人員更快地找到文件並更輕鬆地管理它們。希望這篇文章對您有幫助!

[資源分享] 超好用的擴充套件你還不裝?裝了人生直接逆襲,日子過得好舒服!!

## Midnight Lizard ![](https://i.imgur.com/PKrYQfh.png) ``` 這個擴展改變了頁面的顏色,亮度和對比度以提高可讀性,並且為所有網站開啟夜間模式。 將幫助您定制整個互聯網的外觀,以便於使用。您可以為每個喜愛的網站設置不同的配色方案,並為所有其他網站設置一個默認主題。從預定義的方案中選擇或創建自己的方案。用戶配色方案的數量是無限的。 ━━━━━ 的優點 ━━━━━ ✔智能黑暗的主題 ✔增加對比度 ✔反轉的亮度,而不是倒置的顏色 ✔選擇灰度 ✔在類似的背景顏色之間增加差異 ✔將圖像恢復到鼠標懸停時的原始狀態 ✔顯著提高可讀性 ✔增強的語法突出顯示(對於程序員) ✔有藍色濾鏡可以用紅光代替藍色光 ``` ## Stylebot ![](https://i.imgur.com/MQN95R6.png) ``` 壹個方便改變網頁外觀的擴展 選擇壹個元素,然後從編輯器中選擇要進行的任何更改。您可以更改字體,顏色,邊距,可見性等。您也可以自定義 CSS。 ★易於使用:使用 UI 操作挑選元素並設置樣式 ★簡單快捷:更改立即保存 ★代碼編輯器-在這裏編寫自己的 CSS ★可讀性模式-通過隱藏非必要的頁面元素(如側邊欄,頁腳和廣告),提升網頁閱讀體驗。 ★灰度模式-啟用灰度以減少來自網頁的刺激 ``` ## 後記 未來可能還會新增更多唷!

新框架 Svelte 的優點以及與眾不同的特色介紹

*先說清楚一件事:* *這不是要抨擊其他框架,如 React、Vue 或 Angular。我使用了所有這些工具,而 React(使用 NextJS)仍然是我的首選。* 原文出處:https://dev.to/jannikwempe/why-svelte-is-different-and-awesome-4381 # 什麼是 Svelte? > Svelte 是一種全新的用戶界面建置方法。 React 和 Vue 等傳統框架在瀏覽器中完成大部分工作,而 Svelte 將這些工作轉移到建置應用程式時發生的**編譯步驟**。 TLDR; 它類似於 React 或 Vue,但主要區別在於它是 [編譯器](https://svelte.dev/blog/frameworks-without-the-framework)。 上面連結的博客文章中引用了一句話: >等等,這個新框架有 runtime 嗎?啊。謝謝,我先不用了。 > – 2018 年的前端開發人員 儘管這在 2018 年沒有發生,但我認為我們會在某個時候達到這種心態。 ## “Svelte 是一個編譯器”是什麼意思? 它本質上意味著特定於 Svelte 的程式碼被編譯(考慮轉換)為 JavaScript,可由瀏覽器執行。 您可能知道的另一個編譯器是 TypeScript 編譯器 (`tsc`),它將 TypeScript 編譯為 JavaScript。這是同一個概念。 那麼這是怎麼回事呢?您還可以將 React 程式碼編寫為 `.js` 並發布。的確如此,但是如果沒有發布 React 執行時系統,JavaScript 程式碼將無法在瀏覽器中執行。 > 執行時系統是指使軟體程序能夠在計算機系統上執行的軟體和硬件資源的集合。 *注意:儘管我很多人都在談論“(無)runtime 時”,但更準確地說應該是“(無)runtime **系統**”。* 閱讀來自 [Dan Abramov](https://mobile.twitter.com/dan_abramov) 的精彩 [React as a UI Runtime](https://overreacted.io/react-as-a-ui-runtime/) 博文.它深入解釋了 React 是一個 runtime(系統)。 除了不需要 runtime 之外,還有另一個好處。 Svelte 可以擴展和更改 JavaScript 語法,因為編譯器最終將其編譯為 JavaScript。因此 Svelte 可以擺脫 JavaScript 語法提供的一些限制。 這也可能是一個缺點,因為如果 Svelte 嚴重偏離 JavaScript 語法,它實際上將成為另一種需要學習的語言。不用擔心,Svelte 試圖堅持 JavaScript 語法。 # Svelte 作為編譯器的好處 由於 Svelte 是一個編譯器,因此不需要將執行時系統加載到客戶端中,因此有幾個優點。這些都是 Svelte 的特別之處。我想到的最重要的優勢將在下一節中展示。 ## 效能 這應該是顯而易見的:沒有為客戶端加載的執行時會導致更快的加載時間。 下圖顯示了 JS 框架基準測試的摘錄(請參閱 [this GitHub repo](https://github.com/krausest/js-framework-benchmark))。它基於一個帶有隨機條目的大表,並測量各種操作的時間,包括渲染持續時間。 ![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1619355158508/Olvdi5zOk.png) 使用 Svelte 的應用程式提供了最少的程式碼。 *(不知何故,Svelte 似乎需要比普通 JS 更少的程式碼,我不知道這是怎麼發生的 😀)* 但它不僅向客戶端發送更少的程式碼,而且執行速度更快: ![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1619355565050/accrTZHyr.png) 原因之一是 Svelte 不使用虛擬 DOM (vDOM)。 Svelte 不依賴於 vDOM 和 DOM 之間的差異來更新 DOM。其他提到的框架,如 React、Vue ~~和 Angular~~ *(編輯:Angular 使用增量 DOM)* 確實使用 vDOM。您可以在 Sveltes 博客文章 [Virtual DOM is pure overhead](https://svelte.dev/blog/virtual-dom-is-pure-overhead) 中了解有關此內容的詳細訊息。 該帖子的快速引用: > Svelte 是一個編譯器,它知道**在建置時**你的應用程式會發生什麼變化,而不是等到執行時才開始工作。 ## 微前端架構中的 Svelte 微前端 (MFE) 本身就是一個主題(在 [本文](https://martinfowler.com/articles/micro-frontends.html) 中閱讀它)由 [Martin Fowler](https://twitter.com/martinfowler))。但這個概念基本上是不同的團隊可以分別開發前端的不同部分。團隊還可以選擇他們想要使用的技術堆棧。因此,客戶端最終可能會加載不同版本的 Angular、Vue、React 等: > 一些微前端的實現會導致重複依賴,*增加我們的用戶必須下載的字節數*。 *(來自上面連結的 Martin Fowler 文章)* 但是 Svelte 呢? Svelte(也使用它的不同版本)並沒有增加客戶端必須加載的 kbs 的缺點。 Svelte 是 MFE 架構的絕佳選擇。 # 其他福利 這些好處並不是因為 Svelte 是一個編譯器,而是它們讓 Svelte 脫穎而出。 ## REPL Svelte 有一個很棒的 REPL。您可以毫不費力地開始玩耍和嘗試。這太棒了! [試用](https://svelte.dev/repl/hello-world?version=3.37.0)。 也可以分別點擊“JS Output”或“CSS Output”查看編譯後的JS和輸出的CSS(可以寫在同一個`.svelte`文件中)。 這足以證明 Svelte 是一個編譯器嗎? 😉 REPL 也用在他們很棒的教程中。您可以動手學習 Svelte:[Svelte 教程](https://svelte.dev/tutorial/basics)。 ## 內置功能 Svelte 內置了一些幾乎所有應用程式(至少是大型應用程式)都需要的功能,例如過渡、動畫和 store。首先不需要額外的依賴或在各種選擇之間做出決定。 > store 只是一個具有訂閱方法的物件,只要 store 值發生變化,就可以通知感興趣的各方。 ``` import { writable } from 'svelte/store'; export const count = writable(0); export const increment = () => { count.update(n => n + 1); } ``` 就是這樣。您可以在您的應用中導入 `count` 和 `increment`。簡單的! [試用 Svelte store 教程](https://svelte.dev/tutorial/writable-stores) Svelte 中的動畫和過渡很容易使用。你能猜出下面的程式碼在做什麼嗎? ``` {#if visible} <p in:fly="{{ y: 200, duration: 2000 }}" out:fade> Flies in, fades out </p> {/if} ``` [試用 Svelte 轉換教程](https://svelte.dev/tutorial/in-and-out) 但它們也可以用於更複雜的事情,如下所示: ![動畫.gif](https://cdn.hashnode.com/res/hashnode/image/upload/v1619357232242/hS_6eOg5V.gif) 享受在 React 中建置它的樂趣🤪 [試用 Svelte 動畫教程](https://svelte.dev/tutorial/animate) #SvelteKit [SvelteKit](https://kit.svelte.dev/) 是它自己的主題。但這是我如此興奮的主要原因之一。想想 SvelteKit 之於 Svelte,就像 NextJS 之於 React。 但為什麼它很棒? >SvelteKit **完全接受無伺服器範式**,並將在支持所有主要無伺服器提供商的情況下推出,並帶有一個“適配器”API,用於針對我們未正式迎合的任何平台。 閱讀 [SvelteKit 有何關係?](https://svelte.dev/blog/whats-the-deal-with-sveltekit) 在我撰寫本文時,SvelteKit 目前處於測試階段。等不及發布了! # 結論 我可以繼續下去(我有沒有提到 Svelte 是用 TypeScript 編寫的?)。但這結束了。你可以看到我很興奮,對吧?我會賭 Svelte。學習 Svelte 以及與基於執行時系統的框架的區別絕對不是浪費時間。 我期待 Sveltes 未來的發展。我希望它能很快得到更廣泛的使用,我可以使用 Svelte 開始客戶專案😉 *閱讀更多關於 [我的博客上的前端和無伺服器](https://blog.jannikwempe.com/)。*

我推薦 Svelte 給所有工程師的 10 個理由

原文出處:https://dev.to/mhatvan/10-reasons-why-i-recommend-svelte-to-every-new-web-developer-nh3 儘管 [Svelte](https://svelte.dev/) 的初始版本早在 2016 年 11 月就發布了,但它在 JavaScript 前端框架中仍然處於劣勢,並且最近才開始受到社區應有的關注。 在使用了多年的各種 JavaScript 框架(包括 Angular、React 和 Vue.js)之後,我認為我對編寫程式碼如何愉快以及如何令人沮喪有了良好的總體印象。 幾年前,使用 [jQuery](https://jquery.com/) 編寫程式碼感覺就像來自純 JavaScript 的啟示。然後在我的第一份工作中,我開始使用 Angular 2,突然間 jQuery 感覺像是一個拖累。現在,React 是最酷的孩子,相比之下,Angular 感覺太複雜了。您可能會看到這是怎麼回事! 對我來說,Svelte 是快速變化的 JavaScript 框架生態系統中的下一個進化步驟。用 Svelte 的方式編寫感覺很容易,你可以看出它的建立者 [Rich Harris](https://twitter.com/Rich_Harris)厭倦了現有框架要求您學習的所有煩人的抽象和必要的樣板程式碼。 現在你可能會問自己這個問題: ## 是什麼讓 Svelte 與眾不同? 您可能聽說過 Svelte 出現在諸如 [前端框架的真實世界比較](https://medium.com/dailyjs/a-realworld-comparison-of-front-end-frameworks-2020-4e50655fe4c1) 和 [State of JS Survey](https://2019.stateofjs.com/front-end-frameworks/) 等開發人員調查將其列為在捆綁包大小、性能、程式碼行數方面排名最好的框架之一以及最重要的開發者滿意度。 與流行的 [React](https://reactjs.org/) 和 [Vue.js](https://vuejs.org/) 庫相比,它們在執行時執行大量工作並使用一種稱為“虛擬”的技術DOM diffing”用於檢測變化,Svelte 作為建置步驟被編譯成無框架的 vanilla JavaScript,因此可以從大量程式碼優化中受益。 出於本能的猶豫,我起初將 Svelte 視為“只是另一個 JavaScript 框架”而不予考慮,也沒有費心去研究它。第二次聽說後,我想知道:Svelte 是炒作還是真的那麼好?我決定對它進行實戰測試並將其用於我的個人專案。 現在幾個月後,我可以給你一個明確的答案: ## Svelte 簡單、強大且優雅,您會愛上它! 事不宜遲,以下是我向每位開始學習編程的新 Web 開發人員推薦 Svelte 的十大理由: ## 1. Svelte 元件易於理解 如果您以前從未見過 Svelte 語法,這就是一個簡單示例的樣子: https://gist.github.com/mhatvan/3630989d364e4020f26ebb96d2d7c332 與其他引入大量抽象概念、需要花時間學習和理解的前端框架相比,看到 Svelte 只是並排使用普通的舊 HTML、CSS 和 JavaScript,真是令人耳目一新。您可以通過其對初學者友好的語法查看並輕鬆辨識此處發生的情況。 ## 2.簡單寫簡潔的程式碼 正如您在上面的程式碼示例中看到的,您編寫的業務邏輯既簡單又易於閱讀。畢竟,您編寫的程式碼越少,錯誤就越少,對吧? Svelte 的天才創造者 Rich Harris 在他的文章 [少寫程式碼](https://svelte.dev/blog/write-less-code) 中對 React 和 Vue.js 進行了一些很好的比較。根據他對編寫簡單的兩個數字相加邏輯所需的字符的檢查,React 元件通常比其 Svelte 元件大 40% 左右! ## 3. 與標記語句的反應性 每當您希望根據其他變數更新和重新計算變數值時,您可以使用反應式聲明。只需在您想要響應的變數前面放一個美元符號,您就可以開始了! https://gist.github.com/mhatvan/7e2f0fea362c79d64a34cb7e0c088453 每次單擊按鈕時,`count` 將增加 1,而 `doubled` 將知道 `count` 的值發生變化並相應地更新。從反應性的角度思考真的很有趣,而且寫起來感覺很好。 ## 4.開箱即用的簡單全局狀態管理 無需任何復雜的第三方狀態管理工具,如 [Redux](https://redux.js.org/) 或 [Vuex](https://vuex.vuejs.org/)。 您只需將一個變數定義為可寫/可讀存儲,並在任何以 `$` 符號為前綴的 `.svelte` 文件中使用它。 https://gist.github.com/mhatvan/710b6bb6df4ece7e9a5f53886eb2dd0d 在此示例中,我們檢查當前環境,它作為值存在於我們的商店中,並使用它來決定是否應顯示 cookie 通知。很簡單,不是嗎? 使用 Svelte 存儲,您也永遠不必擔心內存洩漏,因為以 `$` 符號為前綴的存儲變數充當自動訂閱和自動取消訂閱。 ## 5. 內置可存取性和未使用的 CSS 檢查 Svelte 希望讓網路變得更美好,並通過程式碼中的有用提示幫助您。 每當您忘記將 alt 屬性放在 `<img>` 標籤上時,Svelte 都會為您顯示 `A11y: <img> 元素應該有一個 alt 屬性` 提醒。在 Svelte 中實現了一長串可存取性檢查,它們會提示您而不會成為麻煩。 為了使程式碼盡可能簡潔並避免遺留程式碼片段,只要在元件中找不到相應的標記,Svelte 還會為您標記未使用的 CSS 選擇器。 ## 6.元件自動導出 每當你想在元件 B 中使用元件 A 時,你通常需要先編寫程式碼導出元件 A,這樣它才能被元件 B 導入。使用 Svelte,你永遠不必擔心忘記導出, `.svelte` 元件始終默認自動為您導出,並準備好由任何其他元件導入。 ## 7. 默認情況下樣式是有範圍的 類似於 [CSS-in-JS](https://webdesign.tutsplus.com/articles/an-introduction-to-css-in-js-examples-pros-and-cons--cms-33574) 庫,Svelte默認情況下,樣式是有範圍的,這意味著 `svelte-<unique-hash>` 類名將附加到您的樣式,因此它們不會洩漏和影響任何其他元件樣式。當然,您可以選擇全局應用樣式,只需在它們前面加上 `:global()` 修飾符,或者如果您願意,也可以只使用 `.css` 文件。 ## 8. #await 塊 對於大多數 Web 應用程式,您將需要處理異步資料以向用戶顯示有用的統計訊息。 https://gist.github.com/mhatvan/2e44dc1ec402f477830f90bd77614f34 `{#await}` 塊的優點是您不必為已解決/拒絕的承諾定義額外的狀態,您只需在模板中定義內聯變數即可。 ## 9.傳遞道具的速記屬性 如果存在與變數名稱相同的 prop 名稱,我們可以將其作為簡寫屬性傳遞給元件,如下面的“{message}”。與使用 `message="{message}"` 相比沒有任何優勢,但更簡潔。 https://gist.github.com/mhatvan/9085f5330eeccdc2238e4f4e609b4f88 在上方,您可以看到根據 round 是真還是假將 class:round 屬性應用於按鈕。這很容易成為一個可重用的元件,您可以從外部傳遞 `round` 的值來有條件地決定元件的樣式。 ## 10.內置效果和動畫 Svelte 預裝了強大的效果模塊: - `svelte/motion` 效果,如補間和彈簧 - `svelte/transition` 效果,如淡入淡出、模糊、飛行、滑動、縮放、繪製 - `svelte/animate` 效果如翻轉 - `svelte/easing` 效果,如彈跳、立方體、彈性等等 Svelte 官方教程中有幾個示例,但我最喜歡[這個進度條示例](https://svelte.dev/tutorial/tweened),因為它很簡單。 動畫是 web 開發的一個領域,您通常會在其中尋找外部依賴項來為您處理它,因此您可以開箱即用地使用它們真是太好了。 ## 不採用 Svelte 的合理理由 為了避免讓這篇文章聽起來像一篇冗長的狂熱帖子,以下是我迄今為止使用 Svelte 時遇到的缺點: ### `.svelte` 文件不能導出多個元件 一方面,我們受益於默認自動導出的 .svelte 文件,但這也意味著我們無法從單個文件導出多個元件。我不認為這有什麼大不了的,因為它會迫使您遵循最佳實踐來使用許多小的獨立元件編寫您的應用程式,這使它們易於理解和單元測試。 ### 一般模板語法 為了顯示條件邏輯,Svelte 使用類似於眾所周知的 [Handlebars](https://handlebarsjs.com/guide/builtin-helpers.html#if) 模板語法的語法。 https://gist.github.com/mhatvan/95cc1837441a272cb8422fcae24d91e0 這種編寫邏輯的方式我沒有遇到任何問題,但我更喜歡更簡潔的語法。 ### 使用 export let 在子元件中接收 props 當您想要將值從父元件傳遞到子元件時,您需要將一個值作為屬性傳遞,並使用帶有匹配變數名稱的 export let 來接收它。 https://gist.github.com/mhatvan/b67ceafb05d21c15b5782c068690d632 在現代 JavaScript 中,`export` 通常用作導出模塊的關鍵字和 `let` 聲明塊範圍變數,所以我覺得語法濫用現有關鍵字,但我習慣了它並且效果很好. ###開發速度 這與 Svelte 的開發體驗沒有直接關係,但您絕對應該知道,在財務支持方面,Svelte 無法(目前)與更大的和讚助的開源專案競爭,如 React、Angular、Vue.js 和其他專案,截至目前的貢獻者數量和受歡迎程度。 儘管如此,社區正在迅速發展,社區為 Svelte 建置的第三方專案列表也在不斷增加,這些專案可在 [Made with Svelte](https://madewithsvelte.com/) 上找到。開發 Svelte 相關工具的開發人員都是天才,您可以隨時在 [Discord](https://discord.com/invite/qa4pnmw) 頻道、[Twitter](https://twitter.com/sveltejs) 上尋求幫助) 或 [Reddit](https://reddit.com/r/sveltejs)。 Svelte 最近還加入了 TypeScript 支持,而且效果很好! 我喜歡 Svelte 的易用性、較小的包大小和開發人員體驗等因素,因此我可以接受較慢的開發速度作為權衡。如果您總是需要盡可能快地合併最新功能,那麼您可能需要查看其他可用的 JavaScript 框架。 ### 缺少可用的工作 大多數公司仍在尋找對三大前端框架有經驗的開發人員,但也有各種知名的 Svelte 早期採用者,如 IBM、Apple、Philips、GoDaddy、1Password 或紐約時報,僅舉幾例.您可以在 [Svelte 網站](https://svelte.dev/) 底部找到大量使用 Svelte 的公司。通常,採用新框架需要一段時間才能出現在公司的工作機會中。儘管如此,Svelte 學習起來很有趣,許多開發人員喜歡使用 Svelte,尤其是在他們自己的個人專案或小規模應用程式中。 ## 結論 如果對初學者友好的語法、較小的包大小輸出和 Svelte 的瘋狂性能對您來說是一個不錯的選擇,我建議您開始使用 [Svelte 教程](https://svelte.dev/tutorial/basics)。該教程非常詳細,您可以快速了解該框架的強大功能。 在 JavaScript 框架的世界裡,事情肯定會快速變化,我希望你和我一樣相信 Svelte 擁有所有的優勢和潛力,可以讓它成為新的 #1 JavaScript 前端框架! 您之前使用過 Svelte 嗎?你的經驗是什麼? 在評論中告訴我,我很想知道。 感謝閱讀,希望您喜歡! ## 有用的資源 - [Svelte 教程](https://svelte.dev/tutorial/basics) - [Svelte REPL](https://svelte.dev/repl) - [Rich Harris - 重新思考反應性](https://www.youtube.com/watch?v=AdNJ3fydeao) - [為什麼要苗條](https://github.com/feltcoop/why-svelte) - [為什麼 SvelteJS 可能是新 Web 開發人員的最佳框架](https://dev.to/bholmesdev/why-sveltejs-may-be-the-best-framework-for-new-web-devs-205i) - [為什麼我們從 React 轉向 Svelte](https://medium.com/better-programming/why-we-moved-from-react-to-svelte-f20afb1dc5d5) - [我喜歡 Svelte 的寫作風格](https://css-tricks.com/what-i-like-about-writing-styles-with-svelte/) - [我在 React 和 Svelte 中建立了完全相同的應用程式。這是差異。](https://medium.com/javascript-in-plain-english/i-created-the-exact-same-app-in-react-and-svelte-here-are-the-differences-c0bd2cc9b3f8) ## 正在尋找 Svelte 支持的伺服器端渲染解決方案? 在使用 [Sapper](https://sapper.svelte.dev/) 接觸框架後,我是一個忠實的粉絲,一有機會就嘗試推廣 Svelte 之道。 如果您要建立一個網站並正在尋找合適的工具,我發表了一篇關於我迄今為止使用 Sapper 的經驗的文章,供您在此處閱讀:[“為什麼我為我的網站選擇 SapperJS,以及我做了什麼”到目前為止,我已經了解了該框架”](https://markushatvan.com/blog/why-i-chose-sapperjs-for-my-website-and-what-ive-learned-about-the-framework-so-遠的)。

寫了多年 React 之後,改寫 Svelte 的心得與感想

原文出處:https://dev.to/mikenikles/why-i-moved-from-react-to-svelte-and-others-will-follow-210l # React 多年來一直是我的首選 2015 年 10 月 14 日,我主持了 [首屆 React 溫哥華聚會](https://www.meetup.com/ReactJS-Vancouver-Meetup/events/225362860/)。當時我在一年中的大部分時間裡都在使用 React,並希望將志同道合的開發人員聚集在一起。 那時的 React,我敢說,是 web 前端世界的革命性的。與 jQuery、Backbone.js 或 Angular 1.x 等替代方案相比,使用 React 進行開發感覺直觀、清新且富有成效。就個人而言,隔離建置塊(又名元件)的想法真的很吸引我,因為它自然會導致結構化、組織良好且更易於維護的程式碼庫。 在接下來的幾年裡,我一直密切關注 Angular 2.x+、Vue 等,但沒有一個是值得跳槽的選擇。 # 然後我了解了 Svelte 我第一次了解 Svelte 是在 2018 年年中,也就是 3.0 版發布前將近一年(見下文)。 “[計算機,為我建置一個應用程式。](https://www.youtube.com/watch?v=qqt6YxAZoOc)”[Rich Harris](https://twitter.com/Rich_Harris) 讓我著迷Svelte。 > 如果您不熟悉 Svelte ([https://svelte.dev/](https://svelte.dev/)),請存取網站並花 5 分鐘閱讀介紹。 閱讀了嗎?真的?優秀👍 看完影片後,我心中的主要問題是是否值得學習 Svelte 並開始將其用於新專案甚至現有專案。平心而論,Svelte 給我留下了深刻的印象,但仍然不足以讓我完全接受它。 # Svelte 3.x 2019 年 4 月 22 日 - [Svelte 3:重新思考反應性](https://svelte.dev/blog/svelte-3-rethinking-reactivity) 是我一直在等待的博文。 > 請花一些時間閱讀博文並[觀看影片](https://www.youtube.com/watch?v=AdNJ3fydeao) - 這是關於電子表格的,但我保證它很有趣😉 為什麼這是一件大事?首先,Svelte 團隊一直在談論版本 3,我想看看它的實際應用。另一方面,Svelte 及其承諾比我第一次聽說 React 時更讓我興奮。 那時我指導 Web 開發人員,並花了很多時間讓他們加快 React 的速度。為了開發 React 應用程式,需要學習、理解並在一定程度上掌握 JSX、CSS-in-JS、Redux、create-react-app、SSR 和其他概念。 > 對於 Svelte,這些都不是必需的。 ``` <script> let name = 'world'; </script> <style> h1 { color: blue; } </style> <h1>Hello {name}!</h1> ``` 夠簡單嗎?我同意。事實上,它非常簡單,我將它推薦給我的 Web 開發新手。 ## 很快,那段程式碼發生了什麼? `script` 標籤是元件邏輯所在的位置。 `style` 標籤定義了這個元件的 CSS - 這些都不會洩漏到元件之外,所以我們可以安全地使用 h1 並且它只適用於這個元件。它是真正的 CSS,而不是偽裝成 CSS 的 Javascript 對像或偽裝成 CSS 的字串文字。 底部是元件的 HTML。使用帶有 `{myVariable}` 的變數。與 React 的 JSX 相比,Svelte 允許您使用正確的 HTML 標籤,例如 `for`、`class` 而不是 `forHtml` 和 `className`。請參閱 React 文件中的“[屬性差異](https://reactjs.org/docs/dom-elements.html#differences-in-attributes)”以獲取所有非標準 HTML 屬性的列表。 # 讓我們重建 React 示例 為了讓您了解 Svelte 與 React 的對比,讓我們重新建置 [https://reactjs.org/](https://reactjs.org/) 上列出的內容。 ## 一個簡單的元件 請參閱上面的程式碼片段。 ## 一個有狀態的元件 [互動演示](https://svelte.dev/repl/6e9ef214ae774287b21f902d7e6f0e68?version=3.16.6) ``` <script> let seconds = 0; setInterval(() => seconds += 1, 1000); </script> Seconds: {seconds} ``` React:33行 Svelte:6 行 ## 一個應用程式 [互動演示](https://svelte.dev/repl/817d413fd6c344bf859f0dbf8063de2f?version=3.16.6) ``` <script> /* App.svelte */ import TodoList from './TodoList.svelte'; let items = []; let text = ''; const handleSubmit = () => { if (!text.length) { return } const newItem = { text, id: Date.now(), }; items = items.concat(newItem); } </script> <div> <h3>TODO</h3> <TodoList {items} /> <form on:submit|preventDefault={handleSubmit}> <label for="new-todo"> What needs to be done? </label> <input id="new-todo" bind:value={text} /> <button> Add #{items.length + 1} </button> </form> </div> ``` ``` <script> /* TodoList.svelte */ export let items = []; </script> <ul> {#each items as item} <li key={item.id}>{item.text}</li> {/each} </ul> ``` React:66行 Svelte:43 行 ## 使用外部插件的元件 [互動演示](https://svelte.dev/repl/28f4b2e36e4244b8b23cae3d584c4c88?version=3.16.6) ``` <script> const md = new window.remarkable.Remarkable(); let value = 'Hello, **world**!'; </script> <svelte:head> <script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/2.0.0/remarkable.min.js"></script> </svelte:head> <div className="MarkdownEditor"> <h3>Input</h3> <label htmlFor="markdown-content"> Enter some markdown </label> <textarea id="markdown-content" bind:value={value} /> <h3>Output</h3> <div className="content"> {@html md.render(value)} </div> </div> ``` React:42行 Svelte:24 行 > 更少的程式碼 = 更少的錯誤 > 更少的程式碼 = 更好的性能 = 更好的用戶體驗 > 更少的程式碼 = 更少的維護 = 更多的時間來開發功能 # 我還喜歡 Svelte 什麼? ## 反應性 另一個強大的功能是 [反應式聲明](https://svelte.dev/tutorial/reactive-declarations)。讓我們從一個例子開始: ``` <script> let count = 0; $: doubled = count * 2; function handleClick() { count += 1; } </script> <button on:click={handleClick}> Clicked {count} {count === 1 ? 'time' : 'times'} </button> <p>{count} doubled is {doubled}</p> ``` 每當你有依賴於其他變數的變數時,用 `$: myVariable = [引用其他變數的程式碼]` 聲明它們。以上,每當 count 發生變化時,doubled 都會自動重新計算,並且 UI 會更新以反映新值。 ## Stores 在需要跨元件共享狀態的情況下,Svelte 提供了存儲的概念。 [教程很好地解釋了 store](https://svelte.dev/tutorial/auto-subscriptions)。無需閱讀冗長的教程 - store 就這麼簡單。 ### Derived stores 通常,一家 store 依賴於其他 store。這就是 Svelte 提供 derived() 來組合 store 的地方。 [有關詳細訊息,請參閱教程](https://svelte.dev/tutorial/derived-stores)。 ## 作為邏輯塊等待 好吧,這是一個非常優雅的。讓我們從程式碼開始([交互式演示](https://svelte.dev/repl/b9fc662a253443dc901ff189ce1cdd4b?version=3.16.7)): ``` <script> let githubRepoInfoPromise; let repoName = 'mikenikles/ghost-v3-google-cloud-storage'; const loadRepoInfo = async () => { const response = await fetch(`https://api.github.com/repos/${repoName}`); if (response.status === 200) { return await response.json(); } else { throw new Error(response.statusText); } } const handleClick = () => { githubRepoInfoPromise = loadRepoInfo(); } </script> <input type="text" placeholder="user/repo" bind:value={repoName} /> <button on:click={handleClick}> load Github repo info </button> {#await githubRepoInfoPromise} <p>...loading</p> {:then apiResponse} <p>{apiResponse ? `${apiResponse.full_name} is written in ${apiResponse.language}` : ''}</p> {:catch error} <p style="color: red">{error.message}</p> {/await} ``` 看到 HTML 中的“#await”塊了嗎?在真實世界的應用程式中,您將有一個加載元件、一個錯誤元件和在這種情況下呈現 API 響應的實際元件。嘗試在文本框中輸入無效的 repo 名稱以觸發錯誤案例。 # “等等,那……呢?” ## 開源元件? 當我向某人介紹 Svelte 時,我得到的主要回應是“但是生態系統、元件、教程、工具等呢?” 是的,開源 Svelte 元件遠不及 React 元件多。話雖如此,您多久使用一個開源 React 元件並在沒有任何問題或不必要的開銷的情況下集成它?我認為我們 Javascript 社區中的許多人已經變得過於依賴 `npm install ...` 來拼湊一個 web 應用程式。通常建置自己的元件,尤其是在 Svelte 中,可以減少整體花費的時間。我沒有資料可以證明,這是基於我個人的經驗。 不過,與此相關的是,對於任何願意重用開源元件的人來說,Svelte 元件的列表越來越多。 ## 正在找工作? 機會很多,請參閱 [https://sveltejobs.dev/](https://sveltejobs.dev/)。 Apple 的欺詐工程團隊正在[尋找 Svelte 開發人員](https://sveltejobs.dev/jobs/apple-senior-front-end-developer)(截至 2019 年 12 月)。 還要記住,與申請需要 React、Vue、Angular 等的工作相比,競爭要小得多。 # 然後,有 Sapper 來部署 Svelte 應用程式 開發應用程式只是整個蛋糕的一小部分——應用程式還需要部署。為此,Svelte 團隊提供了 [Sapper](https://sapper.svelte.dev/)。這本身就是一篇完整的帖子,所以現在請查看網站了解詳細訊息。 # 結論 每天,新的 Web 開發人員開始他們的旅程,許多人遇到的第一件事就是不確定首先要學什麼。我說未來就是簡單、快速的開發時間,我想不出比這更簡單、更快的事情了: ``` <script> let name = 'world'; </script> <style> h1 { color: blue; } </style> <h1>Hello {name}!</h1> ``` 以上分享,希望對您有幫助

Svelte 程式範例:動手寫一個「蕃茄鐘工作法」小專案

原文出處:https://dev.to/vintharas/discovering-svelte-getting-started-with-svelte-writing-a-pomodoro-technique-app-2lph ## 開始使用 Svelte [開始使用 Svelte 的最簡單方法](https://svelte.dev/blog/the-easiest-way-to-get-started) 是: 1. 瀏覽 [svelte.dev 中的 Svelte 教程](https://svelte.dev/tutorial) 2. 在 [svelte.dev 中的 Svelte REPL](https://svelte.dev/repl) 中進行試玩 3. 使用 svelte 模板從頭開始建立應用程式 儘管我認為通讀教程對於學習 Svelte 的語法和可用的東西確實很有幫助,但我認為**學習某些東西的最佳方法是在盡可能接近它的環境中實際操作**會在現實世界中開發一個 Svelte 應用程式。 **[你需要自己努力解決問題才能真正學到東西](https://amzn.to/2soWN5m)**。 ## 建立一個新專案 我們使用 [degit](https://github.com/Rich-Harris/degit)(也是由 Svelte 的建立者 Rich Harris 編寫的專案腳手架工具)生成一個新專案。類型: ``` $ npx degit sveltejs/template il-pomodoro ``` 這將在 `il-pomodoro` 目錄中建立一個全新的 Svelte 專案。我們跳進去,安裝依賴項並執行開發伺服器: ``` # Jump in $ cd il-pomodoro # Install the dependencies $ npm install # Run the development server $ npm run dev ``` 現在我們在 localhost:5000 上打開瀏覽器,讓我們看看我們得到了什麼…… **塔達!測試成功!** ![](https://thepracticaldev.s3.amazonaws.com/i/zyr2vgqeub11k253xsdx.png) ## 設置你的編輯器 Svelte 是一個編譯器優先的框架,它編譯代表 Svelte 元件的 .svelte 文件來建置 Web 應用程式。我在教程中看到的那個特殊的 .svelte 擴展和非 Web 標準語法告訴我,我需要在我的編輯器中提供一些額外的支持來處理 Svelte。 Svelte 博客有一篇關於[如何設置編輯器以使用 Svelte](https://svelte.dev/blog/setting-up-your-editor) 的好文章。我通常使用 Vim 或 VSCode,所以讓我們設置這兩個編輯器以使用 Svelte。 ### 設置 VSCode 以使用 Svelte 對於 VSCode,有 [svelte-code](https://marketplace.visualstudio.com/items?itemName=JamesBirtles.svelte-vscode) 插件,它支持 `.svelte` 語法突出顯示、診斷、自動完成和 [更多](https://marketplace.visualstudio.com/items?itemName=JamesBirtles.svelte-vscode)。 ### 設置 Vim 以使用 Svelte 對於 Vim,[設置你的編輯器文章](https://svelte.dev/blog/setting-up-your-editor) 沒有提供很多支持。它基本上告訴您將 .svelte 文件的文件類型更改為 HTML。經過一番挖掘,我發現了一些插件,它們可以讓你在 Vim 中獲得更好的 Svelte 體驗,並達到 VSCode 的標準: * [vim-svelte](https://github.com/evanleck/vim-svelte) 為 .svelte 文件提供語法高亮和縮進 * [coc-svelte](https://github.com/coc-extensions/coc-svelte) 通過連接到 Svelte LSP [^2] 為 Svelte 開發提供類似 IDE 的高級支持。這是 [coc.nvim](https://github.com/neoclide/coc.nvim) 自動補全插件(恰好是我最喜歡的 vim 補全插件)的擴展。 好的,現在我們已經設置好了編輯器,讓我們仔細看看我們的新 Svelte 專案。 ## 檔案結構 我們在編輯器中打開 il-pomodoro 文件夾,我們會看到一堆文件和文件夾: * 一個 `src` 文件夾,其中包含 Svelte hello world 應用程式的源程式碼 * 一個 `public` 文件夾,在 Svelte 編譯器編譯和處理後將包含我們的 Web 應用程式 * `rollup.config.js`,其中包含我們的捆綁器 ([rollup](https://rollupjs.org/)) 的配置。 Rollup 負責使用 Svelte 處理我們的源程式碼文件,以生成可以在瀏覽器中執行的開發和生產包。 對於初學者來說非常有趣的部分發生在 `src` 文件夾中,所以我們接下來要看的地方。該文件夾僅包含兩個文件: * `App.svelte` 這是我們應用程式的根元件 * `main.js`,其中包含用於初始化我們的應用程式的引導程式碼 作為我們應用程式入口點的文件是“main.js”: ``` import App from './App.svelte'; const app = new App({ target: document.body, props: { name: 'world' } }); export default app; ``` 這會建立一個新的 Svelte `App` 元件,並將其附加到 `document.body`,並使用一個名為 `title` 的屬性,其值為 `world`。 讓我們看看 `App` 到底是什麼: ``` <script> export let name; </script> <main> <h1>Hello {name}!</h1> <p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p> </main> <style> main { text-align: center; padding: 1em; max-width: 240px; margin: 0 auto; } h1 { color: #ff3e00; text-transform: uppercase; font-size: 4em; font-weight: 100; } @media (min-width: 640px) { main { max-width: none; } } </style> ``` 我懂了!所以 Svelte 元件是一些可重用的 UI,它封裝了元件的標記 (HTML)、它的行為(`<script>` 標籤內的 JavaScript)及其外觀和感覺(`<style>` 標籤內的 CSS) .涼爽的!這就說得通了。 如果我們回到標記中,我們可以理解當我們將它指向 localhost:5000 時我們在瀏覽器中看到的內容: ``` <main> <h1>Hello {name}!</h1> <p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p> </main> ``` prop `name` 在實例化時傳遞給元件,並保存在該 `name` 變數中: ``` <script> export let name; </script> ``` 然後傳播到元件的標記,並呈現在我們在瀏覽器中看到的“h1”標籤內。涼爽的!有點奇怪但熟悉的“export let name”語法必須是**Svelte 元件將其 API 定義為 props 的方式**。 ## 加入標題 讓我們開始修補一些簡單的東西,比如為應用程式的第一個視圖加入標題並將其綁定到一些資料。初始模板給了我如何做到這一點的提示。我只需要向我的元件加入一個新變數以包含該標題。因為我在原始模板中沒有用到 `name` 變數,所以我將替換它: ``` <script> export let title </script> ``` 並更新 `main.js` 以注入我的應用程式的標題: ``` import App from './App.svelte'; const app = new App({ target: document.body, props: { title: 'il Pomodoro' } }); export default app; ``` 再想一想,我真的不需要將該變數公開為道具。我們不希望此元件的用戶更改此標題,因此我們將其保留為元件內部的一部分。 讓我們重寫我們的 App 元件來執行此操作: ``` <script> let title = "il Pomodoro"; </script> ``` 最後,我將更新 HTML 模板以使用“title”而不是“name”: ``` <main> <h1>{title}</h1> </main> ``` **搞定了!** ![](https://www.barbarianmeetscoding.com/images/svelte-il-pomodoro.jpg) ## 任務列表 驚人的!讓我們繼續建立一個非常簡單的任務列表。由於這感覺像是一個完全獨立的責任,我們將把它放在它自己的元件中。 我建立了一個新文件“TaskList.svelte”來表示該新元件並加入了一些標記,以便在我從“App.svelte”中使用它時盡可能少地出錯: ``` <p>I'm a list of tasks</p> ``` 我將它加入到 `App.svelte`: ``` <script> let title = "il Pomodoro"; </script> <main> <h1>{title}</h1> <TaskList /> </main> <style> /* styles omitted for sake of clarity. They'd be here. */ </style> ``` 而且……沒用。嗯……我做錯了什麼…… VSCode 和瀏覽器都會警告我以下內容: ``` 'TaskList' is not defined. svelte(missing-declaration) ``` 這告訴我兩件事: 1. 我的 vim 設置沒有按預期工作,因為我在編輯器中沒有收到錯誤(稍後要解決的問題),並且 2.我好像忘記導入元件了! 當然!所以我將它加入到“App.svelte”元件中: ``` <script> let title = "il Pomodoro"; import TaskList from './TaskList.svelte'; </script> <main> <h1>{title}</h1> <TaskList /> </main> ``` 是的!** ![](https://www.barbarianmeetscoding.com/images/svelte-tasks-list-text.jpg) 現在讓我們加入一些任務。我今天的前 3 項任務是: ``` <script> const tasks = [ "plan some fun trip with Teo", "buy some flowers to my wife", "write an article about Svelte" ]; </script> ``` 現在我需要在列表中的螢幕上顯示這些內容。 Svelte 有一種特殊的方法來迭代模板內的列表:[{#each} 塊](https://svelte.dev/docs#each)。 它是這樣工作的: ``` <ul> {#each tasks as task} <li>{task}</li> {/each} </ul> ``` 因此,我們遍歷 tasks 列表中的每個 task 並將其放入列表項 li 元素中。我們還從列表中刪除了點,因為它們看起來很糟糕: ``` <style> ul { list-style: none; } </style> ``` 這就是我們得到的: ![](https://www.barbarianmeetscoding.com/images/svelte-tasks-list.jpg) **叮叮叮!** 番茄鐘結束了。得走了!我們將很快繼續使用更多 Svelte、交互式任務列表和番茄鐘。 > ### 尋找番茄鐘應用程式的源程式碼? > https://github.com/Vintharas/il-pomodoro-in-svelte > https://svelte.dev/repl/27164871e86d4ce1a9815489dc323500?version=3.16.7 ## 到目前為止的一些思考 驚人的!這是開始使用 Svelte 的快速方法。到目前為止,這是我的印象: * [svelte.dev](https://svelte.dev/docs) 真的很棒。 * [交互式教程](https://svelte.dev/tutorial) 有一個循序漸進的介紹,帶您了解 Svelte 的所有功能和重要概念。 * [Svelte playground](https://svelte.dev/repl) 真的很酷,它可以讓你修改 Svelte 建立多文件應用程式,保存它們並與你的朋友和同事分享。 * [開發文件非常好](https://svelte.dev/docs) 也非常全面並且有很多示例。將它們加入書籤並根據需要用作參考。 * **以上所有內容都提供了與 Svelte 的美妙初次接觸**,當您第一次進入一個新的生態系統時,您會非常感激。 * 開始新專案的方式有點奇怪。我已經習慣了所有具有 CLI 的流行框架,使用 `npx degit etc...` 來建立一個新專案有點令人困惑。但在前 5 秒的混亂之後,我只是執行命令並繼續我的生活。 * **我對文本編輯器支持的第一印象並不好**,例如,VSCode 沒有在 Svelte 模板內為我提供語句完成功能,而我希望它能工作(例如,允許我過濾“任務” `)。在我試用 Svelte 的短暫時間內,我沒有讓 Vim 設置正常工作。 * **使用 Svelte 本身就是一種非常好的體驗**。 * 初次接觸時,感覺 Web 標準非常友好,並且一切如您所願。最小驚奇原則非常適用於 Svelte。 * 我喜歡 Svelte 元件的平面結構,以及它在 HTML 標記、Javascript (`<script>`) 和 CSS (`<style>`) 中劃分元件的方式,這很有意義。樣板文件的數量幾乎可以忽略不計。 * 在標記中註入資料很簡單 * 使用 `export` 暴露 props 雖然不是標準的但很有意義並且很容易理解。 * 我想知道為什麼 Svelte 使用 `{#each tasks as task}` 而它可以使用 `{#for task of tasks}` 並減少學習 Svelte 的人的認知負荷。 (也就是需要學習更多的自定義語法) 這就是今天的全部內容!希望你喜歡這篇文章。保重並期待更多 Svelte 即將推出。 > 您是一位經驗豐富的 Svelte 用戶嗎?如果是這樣,請不要猶豫,告訴我我做事有多麼錯誤 :D 我很樂意聽取您的意見,我們都會因此變得更好。 ## 在 Vim 中修復 Svelte 經過一些故障排除後,我意識到按照 Svelte 博客中的建議,我之前使用自動命令設置 Svelte 以將 .svelte 文件的文件類型更新為 html: ``` augroup svelte au! BufNewFile,BufRead *.svelte set ft=html augroup END ``` 這意味著沒有應用 coc-vim 和 svelte 語法文件,因為它們需要 svelte 的文件類型。刪除自動命令後,一切都像在 Visual Studio Code 中一樣好用。哇哇! [^1]:查看 [這個超級古老的番茄工作法應用程式](https://www.barbarianmeetscoding.com/projects/ilpomodoro/) 我在開始進行 Web 開發的那一天使用 Knockout.js 編寫的。 [^2]: LSP 代表語言伺服器協議。 (來自維基百科)它是一個開放的、基於 JSON-RPC 的協議,用於文本編輯器或 IDE 和提供編程語言特定功能的伺服器之間。該協議的目標是允許獨立於任何給定的編輯器或 IDE 實現和分發編程語言支持。