载说明:原创不易,未经授权,谢绝任何形式的转载
在这篇文章中,我们将介绍一些最受欢迎的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小时内与您取得联系。