載說明:原創不易,未經授權,謝絕任何形式的轉載
在這篇文章中,我們將介紹一些最受歡迎的HTML、React、NextJS和Tailwind CSS模板。使用模板來進行項目開發的一個很大的優勢是,你可以避免從頭開始創建項目,而是使用模板并進行一些微小的調整以適應你的需求。這樣可以節省時間,你可以利用這些時間來增強項目的功能。
此外,借助這些模板,你還可以更快地完成工作。讓我們現在開始,不再拖延!
HTML5 UP
https://html5up.net/
提供了一系列免費的響應式HTML模板。這些模板都具有現代化的設計風格和優雅的布局,適用于各種類型的網站和項目。每個模板都提供了豐富的功能和定制選項,使你能夠輕松地創建出令人印象深刻的網站。
你可以在網站上瀏覽不同的模板,每個模板都有預覽圖和詳細的描述,展示了它的特色和用途。你可以選擇一個你喜歡的模板,并下載相應的文件。下載后,你可以根據自己的需求進行修改和定制,以適應你的項目。
無論你是初學者還是有經驗的開發者,這些模板都是一個很好的起點。它們提供了一個快速且可靠的方法,讓你在項目中使用現成的設計和布局,并根據需要進行個性化調整。
Free HTML web themes
https://www.graphberry.com/category/free-html-web-templates
這個網站提供了一系列免費的HTML網頁模板。這些模板經過精心設計,涵蓋了各種不同類型的網頁需求,包括企業網站、個人簡歷、博客、電子商務等。
在該網站上,你可以瀏覽不同的模板分類,并點擊查看每個模板的詳細信息和預覽圖。每個模板都提供了下載鏈接,你可以免費下載所需的文件。這些模板通常包括HTML、CSS和JavaScript等文件,你可以根據自己的需求進行修改和定制。
這些模板的設計風格各不相同,但都注重美觀和用戶體驗。它們提供了一個快速啟動網頁項目的方式,讓你節省時間和精力,無需從頭開始構建網頁。你可以根據模板進行一些微調和定制,以滿足你的具體需求。
對于那些剛剛開始學習前端開發或者需要快速建立網頁項目的人來說,這些免費HTML網頁模板是一個很好的資源。它們為你提供了一個基礎結構,使你能夠快速創建出具有吸引力和功能性的網頁。
每個需求都有免費的現代化React和Tailwind模板
https://treact.owaiskhan.me/
這個合集真是令人驚嘆。在這里,你可以找到用TailwindCSS構建的現代化React UI模板和組件,它們不僅輕量、安裝迅速,而且易于適應。所有組件都完全響應式,品牌顏色也可以完全自定義。無論是商業用途還是個人使用,都可以免費使用。
React落地頁
這是一個簡單的落地頁,使用Reactjs構建,包含了產品、特點、價格、關于等幾個部分。
https://react-landing-page-template-2021.vercel.app/
4+ 免費的 Nextjs 模板
https://www.creative-tim.com/templates/nextjs
36個免費的 Nextjs 模板
這也是一個不錯的Next主題、起始模板和模板合集。
https://jamstackthemes.dev/ssg/next/
10個免費的Nextjs模板
https://www.wrappixel.com/templates/category/nextjs-templates/?product_orderby=freebies
Nextjs 模板集合
https://vercel.com/templates
在這些可用選項中搜索你的模板,以加快應用程序的開發速度。這是來自Vercel的一份精彩的Next.js模板合集。在這里,你可以從各種各樣的分類中進行選擇。
https://www.creative-tim.com/templates/tailwind-free
這個Tailwind CSS模板合集非常棒。它們提供了免費的Tailwind CSS UI套件和管理儀表板。你應該去看看。
https://themewagon.com/theme-framework/tailwind-css/
這是一個令人驚嘆的資源,你可以在這里找到免費的響應式Tailwind CSS組件。通過查看下載這些模板的人數統計,你可以發現它們擁有頂級的管理儀表板和落地頁模板。如果你愿意付費,它們也提供付費選項。
https://tailwindtemplates.co/templates
發現并下載2023年最佳的免費和付費Tailwind CSS模板!無論你需要一個落地頁、管理儀表板還是一個完整的網頁模板,我們都為你提供了高質量且易于使用的設計。Tailwind CSS是一個廣受歡迎的基于實用主義的CSS框架,以其模塊化和可伸縮的架構脫穎而出。通過遵循樣式的自然順序,它能夠避免傳統CSS中的混亂代碼。使用Tailwind,你不再需要擔心瀏覽器兼容性或錯誤,它為你簡化了編碼和設計過程。通過我們的Tailwind CSS模板,將你的網站提升到新的水平!
在你的項目或落地頁中使用這些內置的開源Tailwind UI模板和組件,可以節省時間。現有超過600個免費的模板和組件可供使用。
https://tailwindcomponents.com/
https://www.tailwindawesome.com/?price=free&type=template
這個網站真是令人難以置信。我相信如果你在那里搜索,你肯定會找到你所需的模板。無論你需要電子商務、個人作品集、創業落地頁還是管理儀表板,他們都有大量可用的模板。
每周,你都會獲得一個使用React、Next JS和Gatsby JS開發的免費落地頁模板。他們的落地頁非常出色。如果你正在尋找落地頁,不妨去看一看。
https://startuplanding.redq.io/
由于文章內容篇幅有限,今天的內容就分享到這里,文章結尾,我想提醒您,文章的創作不易,如果您喜歡我的分享,請別忘了點贊和轉發,讓更多有需要的人看到。同時,如果您想獲取更多前端技術的知識,歡迎關注我,您的支持將是我分享最大的動力。我會持續輸出更多內容,敬請期待。
eduza是簡約時尚和現代的博客HTML模板,帶商店電商元素的博客頁面。考慮所有的作品集網站需求頁可以設計一個旅游網站。原生響應設計HTML5和CSS3(臺式機、平板電腦、手機…)簡單,干凈的和專業的網站模板。
> 搜索模式
> 菜單漢堡
> 滑塊
> html 5和CSS 3
> 干凈、創意、現代和美麗的設計
> 充分響應,兼容所有的屏幕大小
> 組織良好的文件
> 良好的注釋代碼
> 容易定制
> 主流瀏覽器兼容性
> 良好的文檔記錄
> W3C有效標記
紹
cJinja 是一個使用cpp編寫的輕量html模版解析庫,依賴 ejson 來實現模版的數據替換(在jinja中稱為context,上下文)。模版的語法基本與django jinja一致,功能還算豐富。源碼僅有700行,適合學習,覺得不錯的點個star吧。
(該程序為 https://github.com/HuangHongkai/tinyserver 中的一個模塊)
編譯
使用cmake來編譯,windows和linux下均可編譯。推薦使用clion作為IDE。
編譯成功后在build目錄下會有libcjinja.a和cjinja_test.exe這2個文件。libcjinja.a是靜態庫,cjinja_test.exe是一個簡單的測試程序。
運行測試程序后會出現output.html(該文件是tmp.html解析后的結果。)
已經完成的功能
需要注意,表達式之間不能含有空格,例如{{ 1 + 1 }}是非法的,而{{ 1+1 }}是合法的。
使用方法
1. 變量和變量索引
簡單的例子如下,
HtmlTemplate html("username:{{ username }}\n" "parm.list[1][2]: {{parm.list[1][2] }} \n" "parm.key: {{ parm.key }}", 1); // 參數1表示傳入的是模版字符串,0表示傳入的是文件名,默認為0 JSONObject obj = { {"username", 1234}, {"parm", { {"key", "cde"}, {"list", {1, {1,2.3, "abcd"}, "hahaha"}}, }} }; html.setValue(obj); cout << html.render() << endl << endl; /* 運行后打印如下 username:1234 parm.list[1]: abcd parm.key: cde */
HtmlTemplate是一個庫的主要類,構造函數為
explicit HtmlTemplate(const string& str, int flag = 0); // flag=0是str表示文件路徑,不為0是表示傳入的模版字符串
其中str參數為字符串,可以表示html模板原始串,也可也表示為文件的路徑,flag默認為0。
setValue 方法表示傳入數據給模版對象。
render() 方法表示將模版解析成字符串。
JSONObject來源于 ejson 庫,用來模擬python的dict,構造函數也比較容易看懂。
2. 列表迭代
HtmlTemplate html("{% for x in list %}{{ x }}\n{%endfor%}" "此時x已經是臨時變量了,不可以在打印了 {{x}}\n" , 1); JSONObject obj = OBJECT( KEYVALUE("list", LIST(1,2,3,4,5)) ); cout << html.setValue(obj).render() << endl << endl; /*運行后輸出如下 1 2 3 4 5 此時x已經是臨時變量了,不可以在打印了 */
注意到在迭代過程中x是作為臨時變量,在外部的話是無法打印出來的。
3. 字典迭代
HtmlTemplate html("{% for key in dict %}迭代1: 字典的key值為 {{ key }}\n{% endfor %}" "{% for key,value in dict %}迭代2: 字典的key值為 {{ key }}, value值為 {{ value}}\n{% endfor %}" "{% for ,value in dict %}迭代3: 字典的value值為 {{ value }}\n{% endfor %}", 1); JSONObject obj = OBJECT( KEYVALUE("dict", OBJECT( KEYVALUE("key1", "value1"), KEYVALUE("key2", 1234), KEYVALUE("key3", nullptr), )) ); cout << html.setValue(obj).render() << endl << endl; /*運行后輸出 迭代1: 字典的key值為 key1 迭代1: 字典的key值為 key2 迭代1: 字典的key值為 key3 迭代2: 字典的key值為 key1, value值為 value1 迭代2: 字典的key值為 key2, value值為 1234 迭代2: 字典的key值為 key3, value值為 null 迭代3: 字典的value值為 value1 迭代3: 字典的value值為 1234 迭代3: 字典的value值為 null */
4. 字符串拼接與表達式計算
HtmlTemplate html("{{ a+b+c+\"444\" }}\n" "{{x}} * {{y}} + 2 * 3 - 4 / {{x}} = {{ x*y+2*3-4/x }}\n", 1); JSONObject obj = OBJECT( KEYVALUE("a", "111"), KEYVALUE("b", "222"), KEYVALUE("c", "333"), KEYVALUE("x", 12), KEYVALUE("y", 34) ); cout << html.setValue(obj).render() << endl << endl; /*運行后輸出 111222333444 12 * 34 + 2 * 3 - 4 / 12 = 413.667 */
5. if-else-endif語句
HtmlTemplate html("{% if 1==1 %} 1==1 成立 {% else %} 1==1不成立 {%endif %}\n" "{% if !x %} x為空 {% else %} x不為空 {%endif %}\n" "{% if x==2 %} x==2 成立 {% endif %}\n" "{% if x+1!=2 %} x+1!=2 成立 {% endif %}\n" "{% if x<3 %} x<3 成立 {% endif %}\n" "{% if x>1 %} x>1 成立 {% endif %}\n" "{% if str==\"abcd\" %} str為abcd {% endif %}\n" "{% if 1 %} 常量表達式1 {% endif %}\n" "{% if 0 %} 常量表達式0,此處不會輸出 {%endif%}", 1); JSONObject obj = { {"x", 2}, {"str", "abcd"} }; cout << html.setValue(obj).render() << endl; /*運行后輸出 1==1 成立 x不為空 x==2 成立 x+1!=2 成立 x<3 成立 x>1 成立 str為abcd 常量表達式1 */
6.for與if嵌套使用
HtmlTemplate html("{%for x in list%}" "{%if x %}" "{% for y in list2%}" "{{x}} * {{y}} = {{ x*y }}\n" "{% endfor %}" "{% else %}" "x的值為空\n" "{%endif%}" "{% endfor%}", 1); JSONObject obj = OBJECT( KEYVALUE("list", LIST(1,2,3,4,5)), KEYVALUE("list2", LIST(1,2,3)), ); cout << html.setValue(obj).render() << endl << endl; /*運行后輸出 1 * 1 = 1 1 * 2 = 2 1 * 3 = 3 2 * 1 = 2 2 * 2 = 4 2 * 3 = 6 3 * 1 = 3 3 * 2 = 6 3 * 3 = 9 4 * 1 = 4 4 * 2 = 8 4 * 3 = 12 5 * 1 = 5 5 * 2 = 10 5 * 3 = 15 */
7.模版文件作為輸出
HtmlTemplate html("tmpl.html"); JSONObject context = OBJECT( ... ); FILE* f = fopen("output.html", "w"); // 寫入到文件中 string&& str = html.setValue(context).render(); fwrite(str.c_str(), 1, str.size(), f); fclose(f); /*運行后,代開當前目錄的tmpl.html文件作為輸入,輸出文件為output.html*/ /*如果tmpl.html不存在則拋出異常*/
8. 異常處理
HtmlTemplate html("{% if 1 %} xxx ", 1); // 不傳入context try { cout << html.render() << endl; } catch(exception& e) { cerr << e.what() << endl; } cout << endl;
運行后終端上打印如下,
會提示異常的類名,異常文件所在位置,代碼行數,以及一些錯誤的信息。
討論
1. 實現一個簡單的表達式計算器用什么方法比較好?(例如 {{ 2.3*3+4/5*x }} 這類表達式)
我分享一下我自己的方法,有什么更好的方法一起討論一下。
double cJinja::HtmlTemplate::calculator(vector<any>& number, vector<char>& op) { // 例如下表達式會成為 // 1 - 2 - 3 + 2 *3 * 4 - 4*5 // vector<char> op = { '-', '-', '+', '*', '*', '-', '*' }; // vector<any> number = { 1, 2, 3, 2, 3, 4, 4, 5 }; if (number.size() != op.size() + 1) throwException(TemplateParseException, "運算符號數和操作數不匹配"); /* 定義計算器的內部函數 */ auto calc = [](any& var1, double var2, char op) -> double{ // var2 + var1 // var2 * var1 // var2 - var1 // var2 / var1 // 注意順序 #define CALC(op2) \ if(#op2[0] == op) { \ if (var1.type() == typeid(int)) \ return var2 op2 static_cast<double>(any_cast<int>(var1)); \ else if (var1.type() == typeid(float)) \ return var2 op2 static_cast<double>(any_cast<float>(var1)) ; \ else if (var1.type() == typeid(double)) \ return var2 op2 static_cast<double>(any_cast<double>(var1)) ; \ } CALC(+); CALC(-); CALC(*); CALC(/); throwException(TemplateParseException, "不允許對空指針進行運算"); #undef CALC }; vector<double> num_stack; // 計算中間結果存儲棧 num_stack.push_back(calc(number[0], 0, '+')); // 獲取值 number[i+1] + 0 (加法運算零元為0,乘法運算零元為1) /* 計算 * / 法*/ for (size_t i = 0; i < op.size(); i++) { if (op[i] == '+' || op[i] == '-') { num_stack.push_back(calc(number[i + 1], 0, '+')); // number[i+1] + 0 } else if (op[i] == '*' || op[i] == '/') { double var1 = num_stack.back(); num_stack.pop_back(); num_stack.push_back(calc(number[i + 1], var1, op[i])); // var1/number[i+1] 或者是 var1/number[i+1] } else throwException(TemplateParseException, str_format("非法操作符 %d", op[i])); } /* 計算 + - 法*/ double result = num_stack[0]; size_t i = 1; for (auto& ch : op) { if (ch == '+') { result += num_stack[i++]; } else if(ch == '-') { result -= num_stack[i++]; } } return result; }
2. 拋出異常包含更多的信息
我定義了一個throwException宏,如下
#define throwException(Exception, ...) { \ std::cerr << "[" << #Exception << "] : FILE: " << string(__FILE__).substr(string(__FILE__).find_last_of('/') + 1) << " LINE: " << __LINE__ << " FUNCTION: " <<__FUNCTION__ << std::endl; \ throw Exception(__VA_ARGS__); \ }
其中__FILE__ 為文件名,__LINE__ 為當前代碼行數,這些都是C中的內置宏,__VA_ARGS__是可變參數,對應于宏函數參數中的....
*請認真填寫需求信息,我們會在24小時內與您取得聯系。