🔥 欢迎来到 Node.js 实战专栏!在这里,每一行代码都是解锁高性能应用的钥匙,让我们一起开启 Node.js 的奇妙开发之旅!
Node.js 特训专栏主页
专栏内容规划详情在这里插入图片描述

Express模板引擎选型与使用全解析:打造动态Web页面的利器

在基于Express构建Web应用时,模板引擎是生成动态页面的核心组件。它允许开发者将数据与HTML结构分离,通过简单的语法将后端数据动态填充到页面中。市面上存在多种模板引擎,每种都有其独特的特性和适用场景。本文将深入探讨常见Express模板引擎的选型要点与具体使用方法,帮助开发者根据项目需求做出最佳选择。

一、模板引擎基础概念

1.1 什么是模板引擎?

模板引擎是一种工具,它使用特定的语法将模板文件(通常是HTML)与数据结合,生成最终的HTML页面。在Express应用中,模板引擎可以接收来自控制器的数据,并将其嵌入到模板中,实现动态内容展示。例如,通过模板引擎可以将数据库中查询到的用户列表数据填充到HTML页面,动态生成用户展示页。

1.2 模板引擎的作用

1.2.1 分离逻辑与展示

模板引擎的核心优势在于实现了业务逻辑与页面展示的清晰分离。在MVC架构中:

  • 业务逻辑(如数据处理、数据库操作等)由控制器和模型层完成
  • 页面展示则由模板负责处理

具体表现为:

  1. 控制器只负责传递数据(如render('index', {title: '首页'})
  2. 模板文件(如index.html)只需专注于数据呈现
  3. 开发人员可以独立修改业务逻辑或UI界面而互不干扰

典型应用场景:

  • 后端开发人员与前端设计师的协作开发
  • 同一套业务逻辑支持多套皮肤/主题切换
  • 长期维护的复杂项目
1.2.2 提高开发效率

模板引擎通过以下机制显著提升开发效率:

  1. 模板继承

    • 定义基础模板(如base.html)包含公共头部/尾部
    • 子模板只需扩展特定内容区域
    <!-- base.html -->
    <html>
    <head>{% block title %}{% endblock %}</head>
    <body>{% include 'header.html' %}{% block content %}{% endblock %}{% include 'footer.html' %}
    </body>
    </html>
    
  2. 循环语句

    • 批量生成列表项
    <ul>{% for item in items %}<li>{{ item.name }}</li>{% endfor %}
    </ul>
    
  3. 条件渲染

    {% if user.isVIP %}<div class="vip-badge"></div>
    {% endif %}
    
  4. 局部模板

    • 将重复组件(如商品卡片)提取为独立模板文件
    • 通过include指令复用

统计表明,合理使用模板特性可减少40%-60%的视图层代码量。

1.2.3 动态数据展示

模板引擎支持多种动态数据呈现方式:

  1. 数据绑定

    • 直接输出变量:<h1>{{ product.name }}</h1>
    • 表达式计算:<span>总价:{{ quantity * price }}</span>
  2. 个性化渲染

    欢迎回来,{{ user.nickname || user.username }}!
    {% if user.newMessage %}
    <div class="message-bubble">{{ user.newMessageCount }}</div>
    {% endif %}
    
  3. 国际化支持

    {{ __('welcome_message') }}
    <!-- 根据用户语言环境输出不同文本 -->
    
  4. 数据结构处理

    • 列表分组显示
    • 树形结构递归渲染
    • 分页数据展示

实际案例:

  • 电商网站根据用户浏览历史推荐商品
  • 新闻站点的个性化首页布局
  • SaaS产品的多租户界面定制

这种动态能力使单个模板可以适应成千上万种数据组合场景。

二、常见Express模板引擎对比与选型

2.1 EJS(Embedded JavaScript)

核心特点
  1. 语法简洁性

    • 采用<% %><%= %>等直观的嵌入式标签
    • 完全支持标准JavaScript语法,无需额外学习新语法规则
  2. 开发效率

    • 支持直接在HTML中编写控制逻辑(如if/else、for循环等)
    • 通过<%= %>标签实现数据绑定输出
  3. 模板继承

    • 支持<%- include('header') %>等模板包含语法
    • 可实现布局复用和模块化开发
详细语法示例
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>用户管理系统</title><style>.user-item { padding: 10px; border-bottom: 1px solid #eee; }</style>
</head><body><%- include('navbar') %><h1>用户列表(共<%= users.length %>人)</h1><% if (users.length === 0) { %><div class="alert">暂无用户数据</div><% } else { %><ul class="user-list"><% users.forEach((user, index) => { %><li class="user-item"><span><%= index + 1 %>.</span><strong><%= user.username %></strong><% if (user.isAdmin) { %><span class="badge">管理员</span><% } %><p>邮箱:<%= user.email || '未填写' %></p></li><% }); %></ul><% } %><%- include('footer') %>
</body></html>
进阶应用场景
  1. 动态页面生成

    • 电商网站产品列表页
    • 博客系统的文章详情页
  2. 数据可视化

    • 结合Chart.js等库生成动态图表
    • 报表数据的HTML模板渲染
  3. 邮件模板

    • 用户注册欢迎邮件
    • 订单确认通知邮件
  4. 开发调试

    • 快速构建管理后台原型
    • API接口数据的可视化调试
性能优化建议
  • 预编译模板提升渲染效率
  • 配合Express.js等框架使用res.render()方法
  • 合理使用模板缓存机制

2.2 Pug(原名Jade)

特点

Pug是一款高效的HTML模板引擎,采用独特的缩进式语法结构,显著减少了传统HTML中的冗余标签。其核心特点是:

  1. 简洁的语法:通过严格的缩进来表示DOM元素的层级关系,完全省略了闭合标签
  2. 增强的可读性:代码结构清晰直观,类似Python的缩进风格
  3. 丰富的功能:支持变量插值、条件语句、循环等编程特性
  4. 高性能编译:模板会被预编译为JavaScript函数,渲染速度快

不过,对于长期使用传统HTML的开发人员来说,需要适应:

  • 严格的缩进规则(必须使用空格,不能混用Tab)
  • 全新的语法范式
  • 缺少闭合标签的视觉提示
详细语法示例
// 文档类型声明
doctype html
// 根元素带属性
html(lang='en')// 头部区域headmeta(charset='UTF-8')// 动态标题title #{pageTitle} | 我的网站// 条件判断if stylesheetlink(rel="stylesheet" href=stylesheet)// 正文内容body// 包含其他模板include ./header.pug// 主内容区main.containerh1.main-title 用户管理系统// 循环输出用户列表ul.user-listeach user, index in usersli.user-item(class=user.isAdmin ? 'admin' : '')span= index + 1 + '.'a(href="/users/"+user.id)= user.nameif user.isAdminspan.badge 管理员// 页脚footerp Copyright © #{new Date().getFullYear()}
适用场景
  1. 大型Web应用

    • 适合多人协作的复杂项目
    • 模板复用性强,可通过includeextends机制组织代码
    • 例如电商后台管理系统、CMS内容平台
  2. 需要快速迭代的项目

    • 修改模板时只需调整少量代码
    • 配合前端框架(如Vue、React)使用时效率更高
  3. 对代码整洁度要求高的项目

    • 在代码审查时更容易发现结构问题
    • 比传统HTML减少约40%的代码量
  4. 全栈JavaScript项目

    • 与Node.js/Express完美集成
    • 可直接在模板中使用JavaScript表达式
开发建议
  1. 使用编辑器插件(如VS Code的Pug插件)获得语法高亮和缩进提示
  2. 建立统一的缩进规范(推荐2或4个空格)
  3. 复杂逻辑尽量写在路由/控制器中,保持模板简洁
  4. 合理使用mixin功能创建可复用组件

2.3 Handlebars

特点

Handlebars 是一款轻量级的模板引擎,其核心特点包括:

  1. 简洁语法:采用直观的双大括号{{}}作为占位符,例如{{title}}表示变量插值,{{#if}}表示条件判断,语法简单易学
  2. 逻辑纯净:刻意限制模板中的编程逻辑,不支持复杂的脚本语法,强制开发者将业务逻辑与视图分离
  3. 数据驱动:强调数据绑定机制,通过上下文对象将数据注入模板,保持模板的声明式特性
  4. 扩展性强:支持自定义helper函数,可以扩展模板功能而不破坏其简洁性
详细语法示例

基础数据绑定:

<p>欢迎,{{user.name}}!您已登录{{loginCount}}次。</p>

条件语句:

{{#if isAdmin}}<button class="admin">管理面板</button>
{{else}}<button class="user">普通视图</button>
{{/if}}

循环遍历(带索引和上下文切换):

<table>{{#each products as |product index|}}<tr class="{{if index 'even' 'odd'}}"><td>{{product.name}}</td><td>{{formatPrice product.price}}</td></tr>{{/each}}
</table>
完整应用示例
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>电商平台 - 产品列表</title><style>.product-card { border: 1px solid #ddd; padding: 15px; margin: 10px }.discount { color: red; font-weight: bold }</style>
</head>
<body><header><h1>{{store.name}} - {{formatDate today}}</h1>{{#if promoBanner}}<div class="banner">{{promoBanner}}</div>{{/if}}</header><main><div class="filter">排序方式:{{select sortOptions selected=currentSort}}</div><div class="product-grid">{{#each products}}<div class="product-card"><h3>{{name}}</h3><p>{{description}}</p><div class="price">{{#if onSale}}<span class="original-price">{{originalPrice}}</span><span class="discount">{{salePrice}} (省{{discountPercent}}%)</span>{{else}}{{price}}{{/if}}</div>{{> productBadge}}</div>{{else}}<p class="empty">暂无商品</p>{{/each}}</div></main><footer>{{> common/footerLinks}}</footer>
</body>
</html>
适用场景详解
  1. 企业级应用开发

    • 适用于需要严格分离关注点的大型项目
    • 典型用例:电商平台的产品展示页、内容管理系统的列表视图
  2. 多团队协作项目

    • 前端团队可以独立开发模板结构
    • 后端团队只需提供JSON数据接口
    • 示例:银行系统的客户门户网站
  3. 静态网站生成

    • 与静态网站生成器(如Gatsby、Eleventy)配合使用
    • 优势:保持HTML的可读性同时实现动态内容
  4. 邮件模板系统

    • 特别适合需要批量生成个性化邮件的场景
    • 示例:电商订单确认邮件、系统通知邮件
  5. 渐进式Web应用(PWA)

    • 在Service Worker中预编译模板
    • 离线时仍能渲染基本界面
最佳实践建议
  1. 模板组织

    • 将大型模板拆分为多个partials(部分模板)
    • 使用目录结构组织模板文件(如:templates/partials/header.hbs
  2. 数据处理

    • 在传入模板前预先处理好数据格式
    • 示例:日期格式化、金额计算等应在数据层完成
  3. 性能优化

    • 预编译模板提高运行时性能
    • 使用模板缓存机制减少重复编译
  4. 调试技巧

    • 使用{{log}}helper输出调试信息
    • 在开发环境启用source maps定位模板错误

2.4 Nunjucks 模板引擎

核心特点
  1. Django模板风格

    • 采用与Django模板相似的语法结构,包括{% %}标签和{{ }}变量插值
    • 学习曲线平缓,特别适合有Python开发经验的开发者
  2. 高级模板特性

    • 模板继承:通过{% extends "base.html" %}实现布局复用
    • 宏定义:使用{% macro %}...{% endmacro %}创建可重用组件
    • 区块控制:{% block %}...{% endblock %}实现内容替换
  3. 数据处理能力

    • 内置50+过滤器,如:
      • {{ var | default("N/A") }} 默认值处理
      • {{ date | format("YYYY-MM-DD") }} 日期格式化
      • {{ text | truncate(50) }} 文本截断
    • 支持自定义过滤器注册
详细语法示例
{# 基础模板 base.html #}
<!DOCTYPE html>
<html lang="en">
<head>{% block head %}<meta charset="UTF-8"><title>{% block title %}默认标题{% endblock %}</title>{% endblock %}
</head>
<body>{% include "header.html" %}<main>{% block content %}<!-- 默认内容 -->{% endblock %}</main>{% macro userCard(user) %}<div class="user-card"><h3>{{ user.name | capitalize }}</h3><p>注册于:{{ user.joinDate | date("YYYY-MM-DD") }}</p></div>{% endmacro %}
</body>
</html>{# 子模板 users.html #}
{% extends "base.html" %}{% block title %}用户管理系统{% endblock %}{% block content %}
<h1>系统用户列表</h1>
<div class="user-grid">{% for user in userList %}{{ userCard(user) }}{% if loop.last %}<p class="total-count">总计:{{ loop.length }}位用户</p>{% endif %}{% endfor %}
</div>
{% endblock %}
典型应用场景
  1. 企业级应用开发

    • 后台管理系统模板渲染
    • 多语言国际化支持
    • 复杂的权限显示控制
  2. 内容型网站

    • 新闻门户的文章模板
    • 电商网站的商品展示页
    • 博客系统的主题模板
  3. 开发优势体现

    • 通过模板继承减少60%以上的重复代码
    • 宏定义可复用组件使维护成本降低40%
    • 异步渲染支持提升SSR性能
  4. 扩展能力

    • 自定义过滤器处理业务特定逻辑
    • 通过addGlobal注入全局变量
    • 支持模板预编译提升运行时效率
性能优化建议
  1. 启用autoescape防止XSS攻击
  2. 开发环境设置noCache:true方便调试
  3. 生产环境开启watch:false提升性能
  4. 复杂模板建议使用precompile预编译

三、在Express中使用模板引擎

3.1 配置模板引擎

在Express框架中,模板引擎是实现动态网页渲染的核心组件。以常用的EJS(Embedded JavaScript)模板为例,在Express项目中配置模板引擎的完整流程如下:

安装EJS模板引擎

首先需要通过npm安装EJS包:

npm install ejs --save

安装完成后,EJS会自动添加到项目的package.json依赖中。

基本配置

在Express主文件(通常是app.jsserver.js)中进行配置:

const express = require('express');
const app = express();// 设置视图引擎为ejs
app.set('view engine', 'ejs');
// 设置视图文件存放目录(默认是./views)
app.set('views', path.join(__dirname, 'views'));

配置说明:

  1. view engine:指定使用的模板引擎名称
  2. views:设置模板文件所在的路径,使用path.join确保跨平台兼容性
示例应用

下面是一个完整的路由示例,展示如何使用EJS模板:

// 渲染首页
app.get('/', (req, res) => {const users = [{ username: 'user1', email: 'user1@example.com',joinDate: new Date(2023, 0, 15)},{ username: 'user2',email: 'user2@example.com',joinDate: new Date(2023, 1, 20)}];// 传递数据到模板并渲染res.render('index', { title: '用户列表',users,currentYear: new Date().getFullYear()});
});app.listen(3000, () => {console.log('服务器在3000端口运行');console.log('访问地址:http://localhost:3000');
});
模板文件结构

views目录下创建index.ejs文件:

views/
└── index.ejs

模板文件可以这样编写:

<!DOCTYPE html>
<html>
<head><title><%= title %></title>
</head>
<body><h1><%= title %></h1><ul><% users.forEach(user => { %><li><%= user.username %> - <%= user.email %><small>(加入于: <%= user.joinDate.toLocaleDateString() %>)</small></li><% }) %></ul><footer>© <%= currentYear %> 我的网站</footer>
</body>
</html>

注意:

  • 使用<%= %>输出变量值
  • 使用<% %>执行JavaScript代码
  • 可以在模板中调用传递的数据对象的方法

这种配置方式适用于大多数Express应用场景,开发者可以根据项目需求调整视图目录或使用其他模板引擎如Pug、Handlebars等。

3.2 传递数据到模板

在Express框架中,我们可以向模板引擎传递各种类型的数据,包括但不限于基本数据类型、数组、对象以及函数等。这种灵活性使得我们能够构建更加动态和功能丰富的视图层。

复杂数据传递示例

以下是一个完整的控制器示例,展示了如何传递多种数据类型到EJS模板:

// 定义一个路由处理函数
app.get('/', (req, res) => {// 定义用户数组const users = [{ firstName: '张',lastName: '三',username: 'zhangsan',email: 'zhangsan@example.com',joinDate: new Date('2020-01-15')},{firstName: '李',lastName: '四',username: 'lisi',email: 'lisi@example.com',joinDate: new Date('2019-05-20')}];// 定义工具函数const formatDate = (date) => {return date.toLocaleDateString('zh-CN');};const getFullName = (user) => {return user.firstName + user.lastName;};// 渲染模板并传递数据res.render('index', { title: '用户管理系统',users,helpers: {getFullName,formatDate}});
});
模板中使用示例

index.ejs模板中,我们可以这样使用传递过来的数据和函数:

<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title><%= title %></title><style>.user-item {padding: 10px;border-bottom: 1px solid #eee;}</style>
</head><body><h1><%= title %></h1><div class="user-container"><% users.forEach(function(user) { %><div class="user-item"><h3><%= helpers.getFullName(user) %></h3><p>用户名: <%= user.username %></p><p>邮箱: <a href="mailto:<%= user.email %>"><%= user.email %></a></p><p>注册日期: <%= helpers.formatDate(user.joinDate) %></p></div><% }); %></div>
</body></html>
实际应用场景
  1. 用户列表展示:如示例所示,可以用来展示网站用户列表
  2. 数据报表生成:传递计算函数和格式化函数来生成复杂报表
  3. 动态表单渲染:传递表单验证函数和表单配置对象
  4. 权限控制:传递权限检查函数来控制页面元素的显示/隐藏

通过这种方式,我们可以将业务逻辑与展示逻辑分离,保持代码的整洁性和可维护性。控制器负责准备数据,模板负责展示数据,各司其职。

3.3 模板继承与复用

以Nunjucks为例,详细介绍模板继承的使用方法及其优势:

基础模板架构

创建基础模板base.html作为所有页面的框架:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>{% block title %}默认标题{% endblock %}</title>{% block styles %}<!-- 公共样式资源 --><link rel="stylesheet" href="/css/reset.css"><link rel="stylesheet" href="/css/common.css">{% endblock %}
</head><body><header class="site-header"><nav><a href="/">首页</a><a href="/about">关于</a></nav></header><main class="main-content">{% block content %}<!-- 主要内容区域由子模板填充 -->{% endblock %}</main><footer class="site-footer"><p>© 2023 公司名称. All rights reserved.</p></footer>{% block scripts %}<!-- 公共脚本资源 --><script src="/js/jquery.min.js"></script><script src="/js/common.js"></script>{% endblock %}
</body></html>
子模板实现示例

创建index.html继承并扩展基础模板:

{% extends 'base.html' %}<!-- 自定义页面标题 -->
{% block title %}用户列表页面 - 网站名称{% endblock %}<!-- 添加页面特定样式 -->
{% block styles %}
{{ super() }}  <!-- 保留基础模板中的样式 -->
<link rel="stylesheet" href="/css/user-list.css">
{% endblock %}<!-- 定义页面主要内容 -->
{% block content %}
<div class="page-header"><h1>用户列表</h1><p class="description">当前系统注册用户列表</p>
</div><div class="user-list">{% if users.length > 0 %}<ul class="user-items">{% for user in users %}<li class="user-item"><span class="username">{{ user.username }}</span><span class="email">{{ user.email }}</span><span class="reg-date">{{ user.registerDate | date }}</span></li>{% endfor %}</ul>{% else %}<p class="no-users">暂无用户数据</p>{% endif %}
</div>
{% endblock %}<!-- 添加页面特定脚本 -->
{% block scripts %}
{{ super() }}  <!-- 保留基础模板中的脚本 -->
<script src="/js/user-list.js"></script>
{% endblock %}
实际应用场景
  1. 多页面网站:新闻网站中不同的栏目页面(如新闻、体育、娱乐)可以共用基础模板
  2. 后台管理系统:所有管理页面继承同一基础模板,保持统一风格
  3. 移动端适配:通过基础模板统一管理不同设备的viewport设置
使用注意事项
  1. 使用{{ super() }}保留父模板的块内容
  2. 块命名要有明确语义,如header_scriptsfooter_content
  3. 避免嵌套过深的继承关系,建议不超过3层
  4. 对于频繁修改的区块,可以拆分为独立的include文件

通过模板继承机制,可以实现:

  • 90%以上的公共代码复用
  • 统一维护站点结构和资源
  • 快速创建风格一致的新页面
  • 方便进行全局样式调整

四、模板引擎选型建议

  1. 项目规模与复杂度

    • 小型项目(如个人博客、企业宣传网站):可以选择语法简单的EJS或Handlebars。这些模板引擎学习曲线平缓,内置功能精简,能快速实现基本的数据绑定和条件渲染功能。例如,使用EJS的<% %>标签可以轻松插入JavaScript逻辑,适合需要快速开发的原型项目。
    • 大型复杂项目(如电商平台、SAAS应用):推荐使用Nunjucks或Pug。Nunjucks提供模板继承、宏(macro)等功能,可以有效管理多层嵌套的页面结构。比如通过{% extends "base.html" %}实现布局复用,显著减少重复代码。Pug则通过其独特的缩进语法和mixin特性,特别适合构建组件化的前端架构。
  2. 团队技术栈

    • 团队熟悉JavaScript:EJS是理想选择。它不仅支持完整的JavaScript表达式(如<%= user.name %>),还允许直接编写JS逻辑(<% if(user) { %>)。这种与JavaScript近乎无缝的集成能大幅降低团队的学习门槛。
    • 团队有Django/Python背景:Nunjucks的语法设计(如{% if %}...{% endif %})与Django模板语言高度相似,团队成员可以立即运用熟悉的控制流和过滤器概念。例如,两者都支持管道操作符({{ name|capitalize }}),这种一致性可以节省大量培训时间。
  3. 性能需求

    • 对性能要求极高(如高并发页面):Pug凭借其预编译机制和精简的HTML输出表现优异。测试显示,Pug模板编译后的运行效率比解释型引擎快30%-40%,且生成的HTML代码体积更小(例如将div.container编译为<div class="container"></div>),这对首屏加载速度要求严苛的项目尤为重要。
    • 性能要求一般(如后台管理系统):各主流模板引擎(EJS、Handlebars等)在常规场景下的渲染耗时差异通常在毫秒级,此时更应关注开发效率。例如Handlebars的helper函数可以快速封装业务逻辑,而无需过度纠结模板解析的微秒级性能差异。

五、总结

Express模板引擎的选择和使用是Web应用开发中的重要环节。不同的模板引擎各有优劣,开发者需要根据项目需求、团队技术栈和性能要求等因素综合考虑,做出最合适的选择。通过合理使用模板引擎,能够实现动态页面的高效开发,提升Web应用的用户体验和开发效率。在实际项目中,不断实践和探索,掌握模板引擎的高级特性,将有助于打造出更优质的Web应用。

📌 下期预告:RESTful API设计规范与实现
❤️❤️❤️:如果你觉得这篇文章对你有帮助,欢迎点赞、关注本专栏!后续还有更多 Node.js 实战干货持续更新,别错过提升开发技能的好机会~有任何问题或想了解的内容,也欢迎在评论区留言!👍🏻 👍🏻

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/88103.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/88103.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/88103.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp评价组件

组件目录 components/Evaluation.vue <template><view class"evaluation-container"><!-- 综合评价 --><view class"evaluation-item" tap"parentTap"><text class"label label-1">综合评价</text&…

SQL Server2022版详细安装教程(Windows)

一&#xff0c;下载SQL Server 可以浏览器自己搜索一下 2、安装 安装前需要先将防火墙和带杀毒软件的先退出关闭掉&#xff08;防止安装不成功&#xff09; 2.1、选择自定义安装 2.2、更改位置进行安装 2.3、等待安装 3、进行安装配置 当安装好后会弹出一个这样的页面 3.1、…

【图像】ubuntu中图像处理

一、环境设置 1、查看视频源 ls /dev/video* 2、查看摄像头的分辨率等参数 v4l2-ctl --device/dev/video0 --list-formats-ext 若未安装v4l-utils sudo apt install v4l-utils 3、测试摄像头能否正常工作 cheese

架构总结记录

1、架构模型解决的共同问题 1.1、高内聚低耦合&#xff1a;解耦外部依赖&#xff0c;分离业务复杂度和技术复杂度等。 1.2、信息孤岛和数据壁垒&#xff1a;单体架构垂直&#xff0c;没有相互调用和复用。逻辑抽象、能力下沉、多系统复用问题 1.3、熵增 2、‌单体架构与分布…

Python: file: encode: ‘gbk‘ codec can‘t encode character ‘\xe5‘ in position

错误 response requests.get(url, timeout5) # 请求一个网页 with open(‘response.txt’, ‘w’) as file: # 打开一个文件 file.write(response.text) # 向文件写入response 提示错&#xff1a; UnicodeEncodeError: ‘gbk’ codec can’t encode character ‘\xe5’ in po…

PyTorch深度学习框架60天进阶学习计划 - 第59天模型鲁棒性(一):对抗样本生成机理与PGD攻击详解

PyTorch深度学习框架60天进阶学习计划 - 第59天模型鲁棒性&#xff08;一&#xff09;&#xff1a;对抗样本生成机理与PGD攻击详解 &#x1f3af; 第一部分&#xff1a;对抗样本的魔法世界 哈喽各位"反黑客"学员&#xff01;欢迎来到第59天的课程&#xff01;今天我…

kibana和elasticsearch安装

1、elasticsearch 6.8.23 安装包下载地址&#xff1a; Elasticsearch 6.8.23 | Elastic 通过网盘分享的文件&#xff1a;elasticsearch-6.8.23.zip 链接: https://pan.baidu.com/s/1D2SrJ8nVBlqC1QNswmMJXg?pwd1234 提取码: 1234 2、kibana 6.8.23 安装包下载地址&#xff…

vue3 el-table row-class-name 行字体颜色失效

在使用 Vue 3 中的 el-table 组件时&#xff0c;如果你遇到了 row-class-name 属性设置的行颜色失效&#xff0c;并被 el-table 的默认样式覆盖的问题&#xff0c;通常是因为 CSS 优先级或者样式冲突导致的。这里有几个方法可以帮助你解决这个问题&#xff1a; 1. 增加 CSS 优…

【跨界新视野】信号处理遇上VR/AR:下一代沉浸体验的核心技术与您的发表蓝海

导语&#xff1a; 元宇宙概念虽经历起伏&#xff0c;但其底层支撑技术——信号处理&#xff08;Signal Processing&#xff09;与虚拟/增强现实&#xff08;VR/AR&#xff09; 的融合创新正蓬勃发展。从高保真音效定位、脑机接口信号解析&#xff0c;到实时三维重建与交互渲染&…

VMware 2025安装教程(附安装包)VMware 2025下载详细安装图文教程

文章目录 引言第A部分&#xff1a;vmware虚拟机安装包的获取与准备第1步&#xff1a;下载VMware虚拟机安装程序 第B部分&#xff1a;VMware虚拟机安装步骤第3步&#xff1a;启动安装向导第4步&#xff1a;同意软件许可协议第5步&#xff1a;设定程序安装路径第6步&#xff1a;配…

wsl2 用桥接方式连网

安装 Hyper-V windows 家庭版怎么安装 Hyper-V-CSDN博客 用管理员打开 PowerShell 执行 Get-NetAdapter 出系统所有的网卡&#xff0c;记住想要桥接的网卡名称 无线网名称一般为 WLAN&#xff0c;有线网名称一般为 以太网&#xff0c;我的是 以太网 2 执行 Get-VMSwitch 查…

<tauri><threejs><rust><GUI>基于tauri和threejs,实现一个3D图形浏览程序

前言 本专栏是基于rust和tauri&#xff0c;由于tauri是前、后端结合的GUI框架&#xff0c;既可以直接生成包含前端代码的文件&#xff0c;也可以在已有的前端项目上集成tauri框架&#xff0c;将前端页面化为桌面GUI。 发文平台 CSDN 环境配置 系统&#xff1a;windows 10 …

C++基础之指针

文章目录 指针介绍 C指针的定义与用法指针的定义指针的基本操作指针的常见用法1. 动态内存分配2. 指针与数组3. 指针作为函数参数&#xff08;传址调用&#xff09;4. 函数返回指针 特殊指针类型智能指针&#xff08;C11起&#xff09;2.入门代码3.总结 指针介绍 C指针的定义与…

基于存储过程的MySQL自动化DDL同步系统设计

在现代SaaS与微服务架构中&#xff0c;数据库结构的自动化管理成为保障系统迭代效率与数据一致性的关键一环。本文将围绕如何通过 MySQL 存储过程构建一个自动建表、字段同步、索引维护、错误日志记录于一体的 DDL 自动同步系统&#xff0c;提供一套完整的工程化实现方案。 一…

【cmake学习】添加库文件

文章目录 目的一、原理二、步骤1.修改CMakeList2.main函数如下3.编译运行 目的 上一篇 学习了使用cmake 构建多源文件工程在项目开发工程中&#xff0c;一般都会生成库文件或者调用其它的一些库文件&#xff0c;所以我们要学习一下简单生成和使用库文件这里主要介绍 add_libra…

Docker容器化部署实战:Spring Boot + MySQL + Nginx 一键部署完整指南

📖 前言 容器化技术已经成为现代软件部署的标准实践。作为一名DevOps工程师,我在过去几年中参与了数十个项目的容器化改造,深刻体会到Docker在提升部署效率、环境一致性和运维便利性方面的巨大价值。 今天我将通过一个完整的实战案例,详细展示如何使用Docker部署一个包含…

分布式选举算法<一> Bully算法

分布式选举算法详解&#xff1a;Bully算法 引言 在分布式系统中&#xff0c;节点故障是不可避免的。当主节点&#xff08;Leader&#xff09;发生故障时&#xff0c;系统需要快速选举出新的主节点来保证服务的连续性。Bully算法是一种经典的分布式选举算法&#xff0c;以其简…

高效调试 AI 大模型 API:用 Apipost 实现 SSE 流式解析与可视化

借助 AI 大模型的实时接口&#xff08;如 OpenAI GPT 或其他第三方模型 API&#xff09;&#xff0c;开发者可以通过 SSE&#xff08;Server-Sent Events&#xff09;流式处理数据&#xff0c;实时获取模型的逐步输出。这一技术已广泛应用于实时问答、代码生成等领域。本文将基…

【网络产品经营】园区网络

园区网络的产品经营逻辑发生显著变化&#xff0c;从传统的“连接功能”导向转向“业务体验驱动”&#xff0c;并结合行业场景化需求、技术架构革新及智能化能力提升&#xff0c;形成多维度的产品策略升级。 一、技术架构变革&#xff1a;从多层复杂到极简全光 传统架构的瓶颈与…

EasyExcel 4.X 读写数据

文章目录 EasyExcel与SpringBoot集成读数据读取数据的流程定义实体类简单读取自定义监听器 读取指定sheet和所有sheet多行头读取数据格式转换列表数据实体类自定义转换器自定义监听器数据读取 写数据简单数据写出存储到磁盘返回前端下载 写出指定列宽&#xff0c;和数值精度丢失…