🔍 搜尋結果:?

🔍 搜尋結果:?

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

[好文分享] 太屌了吧!?用Class(類)製作Jquery的效果!

## 目錄 ##### [【前端動手玩創意】等待的轉圈圈效果 (1)](https://ithelp.ithome.com.tw/articles/10311621) ##### [【前端動手玩創意】google五星評分的星星(2)](https://ithelp.ithome.com.tw/articles/10311643) ##### [【前端動手玩創意】CSS-3D卡片翻轉效果(3) (今天難度頗高,想挑戰再進來!)](https://ithelp.ithome.com.tw/articles/10311672) ##### [【前端動手玩創意】一句CSS做出好看的hero section!(4)](https://ithelp.ithome.com.tw/articles/10311691) ##### [【前端動手玩創意】創造一個Skill bar(5)](https://ithelp.ithome.com.tw/articles/10311756) ##### [【前端動手玩創意】遮蔽廣告(D卡未登入)腳本、自定義新增名單(6)](https://ithelp.ithome.com.tw/articles/10311999) ##### [【前端動手玩創意】前端canvas截圖的招式!竟然有三招,可存成SVG或PNG (7)](https://ithelp.ithome.com.tw/articles/10312001) ##### [【前端動手玩創意】讓你的PDF檔案更難被抓取(8)](https://ithelp.ithome.com.tw/articles/10312046) ##### [【前端動手玩創意】哇操!你敢信?花式寫todo-list,body裡面一行都沒有也能搞?(9)](https://ithelp.ithome.com.tw/articles/10312056) ##### [【前端動手玩創意】卡片製作,才不是!是卡片製作器!(10)](https://ithelp.ithome.com.tw/articles/10312066) ## 前情提要 各位知道jquery,這個JS的函式庫提供我們非常多實用的方法,包裝好給我們用。 其中底層邏輯都還是跑不出js原生的概念, 今天就讓我們用原生JS的類來創造一些Jquery幫我們打包好的方法吧! 來掀開它的奧秘底牌。 ## 程式碼內容 假設我們要創造一個叫做Dquery的東西,該怎麼做呢: ``` class Dquery { constructor(selector) { this.elements = document.querySelectorAll(selector); //噴出DOM來 } css(property, value) { for (let i = 0; i < this.elements.length; i++) { this.elements[i].style[property] = value; } return this; //修改style } addClass(className) { for (let i = 0; i < this.elements.length; i++) { this.elements[i].classList.add(className); } return this; //增加class } removeClass(className) { for (let i = 0; i < this.elements.length; i++) { this.elements[i].classList.remove(className); } return this; } on(eventType, callback) { for (let i = 0; i < this.elements.length; i++) { this.elements[i].addEventListener(eventType, callback); } return this; //監聽事件的運作 } html(htmlString) { if (typeof htmlString === 'undefined') { return this.elements[0].innerHTML; } else { for (let i = 0; i < this.elements.length; i++) { this.elements[i].innerHTML = htmlString; } return this; } } } function $(selector) { return new Dquery(selector); } ``` ## 觀念筆記 其實概念就是先把底層邏輯刷過一遍 最後return this 就達成jquery的效果了唷。 ## 心得 Jquery曾經非常流行,儘管後來式微了,卻還是有一批死忠的粉絲鍾愛著它的簡便, 事實上它就是JS,所以討人喜歡也是正常的, 這次學會了用ES6類的概念,會讓我們在前端的功力大幅提升唷!!

HTML新標籤dialog簡化modal實作

看youtube看到的 新的<dialog></dialog>標籤內建開關api 範例: ``` const dialog = document.querySelector("dialog") dialog.show() // 打開dialog(原先位置) dialog.showModal() // 打開dialog(置中且屏蔽背景) dialog.close() // 關閉dialog ``` 幾個重點: 1.不用再用CSS display開關 2.用showModal()自動置中且屏蔽背景 3.modal設定css背景方式: ``` dialog::backdrop { background-color: hsl(250, 100%, 50%, 0.25); } ``` 4.可結合form使用,form提供新的method="dialog",或是form裡面的button設定formmethod="dialog"來關閉 ``` <dialog> <form method="dialog"> <input type="text" /> <button type="submit">Submit</button><!-- 不會submit--> <button formmethod="dialog" type="submit">Cancel</button><!-- 不會submit--> </form> </dialog> ``` 5.如果想要點擊dialog以外的地方自動關閉可用下列程式碼: ``` dialog.addEventListener("click", e => { const dialogDimensions = dialog.getBoundingClientRect() if ( e.clientX < dialogDimensions.left || e.clientX > dialogDimensions.right || e.clientY < dialogDimensions.top || e.clientY > dialogDimensions.bottom ) { dialog.close() } }) ``` 6.dialog.close()方法可以傳值到Dialog.returnValue ``` Dialog.close(valueToPass) const getValue=Dialog.returnValue ``` 參考資料: [Modals Will Never Be The Same - HTML dialog Element](https://blog.webdevsimplified.com/2023-04/html-dialog/) [影片 The New dialog HTML Element Changes Modals Forever ](https://www.youtube.com/watch?v=ywtkJkxJsdg&t=620s)

[心態分享] 新手學前端應該具備的心態:絕對不是謙虛,假謙虛的心態:做作又噁心!

## 前情提要 最近在網上想找一些學習前端的夥伴,發現要組個討論會非常的難。 是因為沒有人學前端嗎?不是,與事實相反,非常多人學。那麼是因為大家程度太差嗎? 也不是,其實自學的人吸收能力都不錯。 那到底是因為什麼,其實是源自於一個魯蛇心態:「貶低自己、迂迴溝通」 ## 觀念解說 什麼意思?貶低自己?沒錯,很多前端新手當要進行自我介紹或是參加討論, 都因為自尊心太高,要幫自己打上一堆預防針:「我還是菜鳥,我什麼都不會。」 當人家問你說寫過什麼,就說:「都只是一些人家的作業,我沒有做什麼耶」 你以為謙虛是一種美德,事實上這種噁心的做作,只是降低大家討論進步的溝通效率, 要人家稱讚你老半天說:「不會啦!很棒,有東西就拿出來」 你才願意把你自己的作品連結丟出來。 事實上你明明就有自己嘗試做過一些東西,一定要迂迴老半天才願意拿出來,真的太假掰。 ## 健康的心態 那麼前端的新手應該具備什麼心態呢?我們要培養的不是假裝謙虛:「我什麼都不會啦,只是照著做」 「就看網路課程而已,我只是剛摸過js」 「對框架沒概念耶,只是看過VUE的課程。」 就省去這些假掰的噁心詞彙,你學過什麼就說出來,把自己會的東西講出來, 明明學過,又不願意老實講,真的很糟糕。 這不僅是對自己的尊重也是尊重別人。 別人沒有義務必須要每一次的對話都要先稱讚你,才有辦法跟你討論正事。 格局多大,完全建立在你自己的心態健康不健康之上。 做過什麼作品,就算是抄課程上的那就拿出來講,表達出來才有辦法討論。 不是明明你也想要找學習夥伴討論、交流,真的要互相討論的時候才拿出來當作藉口。 那你到底是想要進步,還是你只是想要人家安慰? ## 總結心得 我不知道這是源自於人格上的自卑,又或是東方文化容易被打擊所培養的自我防禦意識。 但在前端程式的交流,真的要練習培養大方的態度, 實事求是,不需要你把自己包裝的多厲害,只要不要你裝模作樣說自己什麼都不會、 什麼都沒寫過, 問了老半天才要把你明明偷偷嘗試過的五種作品拿出來,才發現你bs5也碰過、VUE也學了, 那講了老半天的預防針到底有什麼意義? 請培養健康正確的心態,不要看不起自己,也請尊重別人跟你溝通的對談成本。 真的沒有人有義務一路上安慰你,想要討論交流,你必須擁有正確大方地表達、人格態度。

給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就是「資料跟行為在一起」加個但書: 要以方便理解程式為前提,將資料和行為放在一起。

[好文轉載]哇操!你敢信?花式寫todo-list,body裡面一行都沒有也能搞?

[【前端動手玩創意】哇操!你敢信?花式寫todo-list,body裡面一行都沒有也能搞?](https://ithelp.ithome.com.tw/articles/10312056) ## 前情提要 如果說蟑螂怕拖鞋,老鼠愛大米,任何事物都有相生相剋的道理,那麼前端最害怕什麼呢? 恐怕就是todo-list。 這應該是前端的四大惡夢之一,並不是因為太難了,而是因為太簡單而且太無聊了, 不只無聊,還是每次教學都必須寫的一個磨難,簡直是瞬間殺死靈魂中隊前端的愛。 今天要來用不同風格寫出todo-list,把代辦事項寫出新滋味。 body裡面一行都沒有也能搞? 就是可以搞,讓我們馬上來欣賞這段有特別滋味的玩法!ε(*´・∀・`)з゙ ## 程式碼 ``` <!DOCTYPE html> <html> <head> <title>Todo List</title> </head> <body></body> <script> //渲染DOM AddHtml(); //資料內容 function AddHtml() { const Data = { h1: "Todo List", button: "Add", }; //主體的DOM const html = `<h1>${Data.h1}</h1> <input type="text" id="input" /> <button onclick="CheckNull()">${Data.button}</button> <ul id="list"></ul>`; //渲染至畫面上 document.body.innerHTML += html; } //邏輯確認:是否有輸入值 function CheckNull() { if (!input.value.trim("")) { return; } else { AddItem(); } } //新增代辦事項 function AddItem() { const li = `<li>${document.getElementById("input").value}</li>`; document.getElementById("list").innerHTML += li; input.value = ""; } </script> </html> ``` [可以貼到try it的地方執行看看效果](https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_form_submit) ## 觀念筆記 所謂MVC架構就是模型、視圖、控制,背後其實有一個元素貫串任何程式,那就是:「邏輯」 每當你要下手寫一個程式卻不知道怎麼開始動手, 那就是邏輯沒有通順。 網頁不外乎就是畫面,以及資料,還有使用者的操作。 對於todo-list來說就是一個簡單的input畫面,使用者輸入的資料,點下按鈕送出的操作。 這段程式特地不寫任何一行body裡面的東西, 玩弄了一般人對於程式區分的概念。 用模板符的特性讓所有一切交給變數與函式處理,最後三個function: AddHtml、CheckNull、AddItem完美演繹了代辦清單這個網頁所需要構成的底層邏輯。 必須先加入畫面,然後確認使用者操作的條件,最後新增資料。 這樣子的流程對於新手或許不習慣,但是以邏輯面來看比一般人的寫法清晰許多。 這也是未來框架導入後,對資料流更敏感的培養練習。 ## 心得 無聊的todo-list竟然可以搞成這樣!? 真的是太有趣了(๑╹◡╹๑)! 原來前端的惡夢也可以變成寫不同風格的天堂,沒錯,寫程式就是這麼千變萬化! 重點是背後的邏輯抓到了,那麼想要怎麼寫,真的就是藝術的發揮。 請繼續關注, 跟著我們這個系列繼續動手玩創意!!未來還有更多更新鮮的花招呢(。◕∀◕。)

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) --- 以上,簡單分享,希望對您有幫助!

使用 Tailwind 開發時,適合搭配的 4 款 VSCode 外掛

這些外掛都在這個 VSCode 外掛包裡面 [TailwindCSS Kit](https://marketplace.visualstudio.com/items?itemName=KalimahApps.tailwindcss-kit) 原文出處:https://dev.to/kalimahapps/4-vscode-extensions-i-use-for-tailwind-2him ## 1. [Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) ![tailwind css 智能圖像](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4w36g7owmtrmljbesu24.png) Tailwind CSS IntelliSense 是一個強大的工具,可以幫助開發人員更快、更高效地編寫程式碼。它為 Tailwind CSS 類別提供即時建議,減少錯誤並提高程式碼品質。使用 IntelliSense,開發人員可以提高工作效率、縮短學習曲線並改進應用程式的可存取性。如果您是使用 Tailwind CSS 的開發人員,一定要試試這個強大的外掛。 ## 2. [Tailwind Fold](https://marketplace.visualstudio.com/items?itemName=stivo.tailwind-fold) ![tailwind 折疊擴展圖像](https://github.com/stivoat/tailwind-fold/raw/HEAD/images/docs/demo.gif) 在使用 Tailwind 時,此外掛非常有用。長長的類列表會使 html 有點混亂,此外掛提供了一種隱藏它們並僅在需要時顯示的好方法。除了預設功能外,這些選項經過細心設計,幾乎可以滿足任何偏好。例如,我喜歡在點擊線條而不是類別本身時展開類別。 ## 3. [Tailwind Documentation](https://marketplace.visualstudio.com/items?itemName=alfredbirk.tailwind-documentation) ![Tailwind 文件圖片](https://user-images.githubusercontent.com/11172530/163716626-8d74a1bb-f05b-4b45-aa12-70f66e0efad8.gif) Tailwind Documentation 提供對官方 Tailwind CSS 文件的快速存取。此外掛使開發人員能夠直接從 VSCode 編輯器中存取 Tailwind CSS 文件,而無需打開瀏覽器或離開編輯器。 ## 4. [Tailwind Config Viewer](https://marketplace.visualstudio.com/items?itemName=KalimahApps.tailwind-config-viewer) ![Tailwind 配置查看器圖像](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zxwuaxi8v4o9olb4g06d.png) Tailwind 配置可能會令人困惑。它們可能呈指數級增長,並使用戶更難了解已解析的設定。這外掛使用戶能夠查看 **resolved** Tailwind 配置,它還會顯示任何與顏色相關的類別(text-\*、bg-\*、accent-\* ... 等)的顏色 --- 以上,簡單分享,希望對您有幫助!

# 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。 可以新增、刪除,看有哪些元素被列入要刪除的黑名單。

[前端學習] 用JS動態修改CSS的三種寫法,花式JS玩弄樣式,嚇死你的同事!

## 前情提要 還在寫行內樣式醜醜的嗎?教你不用寫css檔案,使用javascript來動態修改樣式的招數! 這樣子處理的層次又更不一樣, 前端之路有你有我,馬上來看看這是怎麼完成的。 ## 要修改CSS怎麼做呢?物件儲存 首先樣式寫成物件 ```css= const die={ display:"none" } ``` 為什麼要寫成物件呢?修改一種,可能看不出來,修改很多樣式就能感受到, 物件這個儲存方式是有它特別的美感與好處的。 下面我來舉例: ```css= const wrapperStyle = { position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%,-50%)', width: '350px', backgroundColor: '#261d4a', borderRadius: '5px', transition: 'box-shadow .5s ease', overflow: 'hidden' }; ``` ## 語法介紹 Object.assign 使用範例 `Object.assign(element.style,Style)` element是你要修改的元素,Style是樣式寫的object 這是修改一個的情況,當像是上面很多屬性要改的話,我們物件與JS的好處就產生了! 直接使用迴圈來全部套入: ```javascript= const wrapper = document.getElementsByClassName('wrapper'); for (let i = 0; i < wrapper.length; i++) { Object.assign(wrapper[i].style, wrapperStyle); } ``` [MDN官網說明](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) [JS 原力覺醒 Day27 - JS 常用 API - Object.assign && Object.defineProperty](https://ithelp.ithome.com.tw/notifications) ## 還有沒有別的寫法? 有。 ``` document.getElementById("myElement").style.cssText = ` display: block; position: absolute; `; ``` 這樣寫也跟原生css寫起來差不多,比較舒服。 用這種比較分離畫面與程式的寫法, 體感上爽度更高。 就不會是找到元素後還要.style.display="none" 一直.屬性.進去點點點這樣。 ## 說好的三種呢? ``` function setStyle( objId, propertyObject ) { var elem = document.getElementById(objId); for (var property in propertyObject) elem.style[property] = propertyObject[property]; } setStyle('myElement', {'fontsize':'12px', 'left':'200px'}); ``` 這種寫成function的風格我也很愛,感覺很舒服,跟第一個的有點類似卻不太一樣。 這個是把迴圈弄再函式了,所以呼叫一次就會全部修改。 第一個則是把物件內的東西丟給迴圈,一次一次去做改動變化, 邏輯上一模一樣,手段跟風格差異而已唷。 [stackoverflow](https://stackoverflow.com/questions/3968593/how-can-i-set-multiple-css-styles-in-javascript) ## 心得 使用這個小技巧很有趣,之後我們會應用到「JS油猴系列-遮蔽廣告腳本,自定義新增名單」文章裡面。 當要寫腳本,很需要JS動態修改CSS的時候,這種小技巧就佔了很大的角色呢٩(๑•̀ω•́๑)۶! 是不是沒有想到居然可以用JS修改呀! 加上我認為比較差的寫法,就不只三種了呢。 趕快選一種喜歡的, 練習成自己的寶藏知識吧!

發文點子

分類: node類 腳本類 ajax類 頁面製作類 研究類 --------------------------------------------------------------------------- 1. 用JS動態修改CSS 的三種寫法 (完成) 2. 用node.js來寫聊天室--->進階篇章:對戰小遊戲 3. 串API練習-寫出qrcode製作器 4.串API練習-使用post完成"reurl.cc縮網址"功能 5. 串API練習-查詢股價用ajax,再用d3.js視覺化整理 6.寫出chrome離線小恐龍遊戲 7.JS油猴系列-遮蔽廣告腳本,自定義新增名單 (完成) 8.網頁製作入門-寫一個sitcom官網示範教學 9.瀑布流呈現-結合前端爬蟲抓PTT表特版圖片 10. hackmd視覺化-讓自己的筆記變成部落格 (X) :整理自己所學 11.把元素轉成圖片的三種方法:介紹html2canvas--->各種套件都介紹 12. jQuery CDN 掛點解決方案?簡單的 JavaScript 讓您有本地替代方案! https://mnya.tw/cc/word/1428.html --------------------------------------------------------------- 前端小試身手 1.至頂按鈕 自動隱藏且可直接使用的網頁回頂部按鈕 https://mnya.tw/cc/word/1735.html 2.捲動軸 3.用 JavaScript 做一個 Tooltips 功能 https://www.letswrite.tw/js-tooltips/ 4. Javascript,XML 轉 JSON https://www.letswrite.tw/xml-to-json/ -------------------------------------------------------------------------- CSS Tooltip Generator https://www.cssportal.com/css-tooltip-generator/ ![](https://i.imgur.com/lBtfanS.png)

[資源分享] 裝爆的VScode擴充套件,人生沒有擴充套件就是黑白的!

## code spell checker ![](https://i.imgur.com/dEaysXp.png) 不管是自己的英文程度太差,還是粗心大意,把英文字拼錯是家常便飯, 這款擴充套件就是來幫助你的救星! 使用code spell checker馬上會幫你標出奇奇怪怪的單字, 讓你確定沒有不小心把1跟l搞錯,就debug一整天的那種尷尬事件! ## live server ![](https://i.imgur.com/BdyRNga.png) 寫前端最需要的就是看到畫面٩(。・ω・。),و 每次如果都要自己在網址列找到檔案的位置才打開html, 那實在是太沒有工程師的效率了,簡直荒唐!! 當然要使用這款live server來架,馬上就可以看到自己的前端畫面, 而且儲存之後自動更新,根本神器。 ## material icon theme ![](https://i.imgur.com/cLgrQLt.png) 沒有什麼其他的,純粹就是好看! 裝了這款之後可以讓icon變得比較不一樣,整天都跟程式為伍, 當然就是要追求好看的圖圖。 ## prettier - code formatter ![](https://i.imgur.com/DDkFzb4.png) 超級讚的排版好物,懶得自己縮排了啦!就靠這款prettier, 讓你的程式從原本醜醜的排版, 最後,變成人類也能看懂的正常程式,必裝神器之一! ## 補充有人整理的 ### github ![](https://i.imgur.com/7X9O5Dz.png) [專案點這邊](https://github.com/Lin-jun-xiang/vscode-extensions-best/blob/main/README_%E4%B8%AD%E6%96%87.md) ### 影片分享 https://www.youtube.com/watch?v=xGE_M3R69YA [ Alex 宅抬槓 ] Visual Studio Code 外掛生存戰|從 2019 到 2020 前端開發必備安裝推薦 ## 心得 以上都是寫程式過程中會發現的需求,自然會想要找擴充來安裝,提升效率、美觀, 利用這些擴充功能,寫程式的體驗真的變得很舒服呢(๑•́ ₃ •̀๑)。 未來如果有什麼新的,也會持續補充,也歡迎大家分享討論唷~~

自學網頁の嬰兒教材: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) --- 如果您還沒有使用嚴格模式,那絕對值得使用看看! 以上簡單分享,希望對您有幫助!

新手推薦:最基本的 10 個 Git 指令與原理

Git 是軟體工程師最重要的工具之一,今天來學一點 Git 吧! 原文出處:https://dev.to/swordheath/git-the-basic-commands-every-developer-should-know-2m1e **什麼是 Git?** Git 是一個追蹤文件變更的版本控制系統。使用 Git 可以讓您保留所有更改的記錄並根據需要返回到特定版本。它使用方法簡單,佔用空間小,而且非常高效。它的分支模型使它有別於幾乎所有其他可用的 SCM。您可以使用 GitHub 或其他線上主機來儲存文件的備份及其修訂歷史。 **Git 的主要元件** 對我來說,Git 是在團隊專案中使用的絕佳工具,因為它有助於避免程式碼混淆,並帶來一個簡單而有效的工作流程。 ** Repository** Git 存儲庫(或簡稱 repo)包含所有專案文件以及整個修訂歷史記錄。您使用一個普通的資料夾(例如網站的根目錄夾)並告訴 Git 將它變成一個存儲庫。這將建立一個 .git 子文件夾,其中儲存了所有用於追蹤修改的 Git 元資料。簡而言之,存儲庫是您保存程式碼的地方。 **Commit** 要向存儲庫加入新程式碼,您需要進行提交,這是存儲庫在特定時間點的快照、將特定更改或一系列更改提交到存儲庫中的文件。 Git 的歷史紀錄由連續的提交組成。 **Branch** 分支用於儲存您的更改,直到它們準備就緒。在主分支(master)保持穩定的情況下,您可以在分支上工作。完成後,您可以將其與母版合併。最大的好處是您可以在一個存儲庫中擁有多個分支,並在需要時合併它們。 **Pull requests** 這是 Git 中用於在將更改合併到您的程式碼庫之前討論更改的技術。PR 不僅僅是一個通知;它是針對所提議功能的專門討論串。這在多人處理同一份程式碼時特別方便,允許開發人員檢查彼此的工作。 現在我們已經簡要討論了 Git 的主要元件,我想列出每個開發人員在開始使用 Git 之前必須知道的**10 個基本 Git 命令**。 **1。開始一個新的存儲庫** ``` git init ``` **2。分別設定作者姓名和電子郵件地址以用於您的提交** ``` git config - - global user.name “[name]” git config - - global user.email “[email address]” ``` **3。從遠程存儲庫下載現有程式碼** ``` git clone <https://name-of-the-repository-link> ``` **4。建立一個新分支** ``` git branch <branch-name> ``` **5。在 master 中合併分支** ``` git merge <branch-name> ``` **6。從遠程存儲庫取得更新** ``` git pull <remote> ``` **7。將文件加入到 Git 的暫存區** ``` git add <file or directory name> ``` **8。存儲庫的當前狀態** ``` git status ``` **9。將在 master 分支上所做的更改發送到您的遠程存儲庫** ``` git push [variable name] master   ``` **10。更改 head(在版本歷史記錄中加入一筆更新)** ``` git commit -m " Commit Message" ``` --- 這些是每個使用 Git 的人都必須知道的主要指令。Git 非常好用,指令數量也相當多。但是記住這些指令並不是一項艱鉅的任務——您只需要開始使用 Git,大多數指令都會憑直覺記住。

發問-教學經驗的累積?或是說教學風格的培養?

## 前情提要 自學程式對某部分人來說,是一個不太難的事情, 學習能力好,悟性高、執行力強就有辦法可以做到,這屬於自學型人才。 像我自己就有能力可以自學到一定的程度。 但當這樣子的人要轉變成教學模式,當一個家教或老師,似乎是另一回事, 並非技術研究的越深,越會教,而是要針對教學下功夫....(? ## 舉例說明 像是我有觀察教學前端的課程設計,有的是從CSS開始, 一堂教reset跟html,一堂教margin,做出各種練習。 再來可能是padding,以此類推,這樣。 通常都是這種零件式的學習,分散大架構,東西拆開來解說。 這樣子可能可以教一個禮拜之類的, 但其實對熟練的人來說用個簡單的模板網頁,十分鐘內一定能做完。 這之間有點矛盾或說,有差別。 ## 疑惑內容 想請教前輩或是站長在這方面有沒有心得, 教學上追求循序漸進似乎是必要的,講白一點就是進度比較慢啦! 不知道這種狀況前輩們是否有遇過? 目前有在規劃假設要教人的話,是否就是慢慢來,給人家操作看看練習, 但感覺又很像在拖時間XD (因為我自己跟人家線上試上過也會覺得,有點慢,資訊量很難跟自學比) 雖然我個人不傾向於這種學習模式, 但我知道要把十分鐘弄完的東西,轉化成:解說成那麼多堂課,是另一個領域的一種功力.... 我想這應該是有些人走過的路,心態上有點不確定,因此想請益一下這塊的經驗跟心得~ 任何關於家教的想法,歡迎站長或是前輩們稍微分享看看 教育這條準備的道路心得~~

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

## 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/)。*