温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架

什么是Blazor

Blazor是一个使用.NET生成交互式客户端WebUI的框架:

  • 使用C#代替JavaScript来创建信息丰富的交互式UI。

  • 共享使用.NET编写的服务器端和客户端应用逻辑。

  • 将UI呈现为HTML和CSS,以支持众多浏览器,其中包括移动浏览器。

  • 与新式托管平台(如Docker)集成。

基于.Net Core提供客户端Web开发的优势

使用.NET进行客户端Web开发可提供以下优势:

  • 使用C#代替JavaScript来编写代码。

  • 利用现有的.NET库生态系统。

  • 在服务器和客户端之间共享应用逻辑。

  • 受益于.NET的性能、可靠性和安全性。

  • 在Windows、Linux和macOS上使用VisualStudio保持高效工作。

  • 以一组稳定、功能丰富且易用的通用语言、框架和工具为基础来进行生成。

Blazor组件

Blazor应用基于组件。Blazor中的组件是指UI元素,例如页面、对话框或数据输入窗体。

组件是内置到.NET程序集的.NET C#类,它们用于:

  • 定义灵活的UI呈现逻辑。

  • 处理用户事件。

  • 可以嵌套和重用。

  • 可作为Razor类库或NuGet包共享和分发。

组件类通常以Razor标记页(文件扩展名为.razor)的形式编写。Blazor中的组件有时被称为Razor组件。Razor是一种语法,用于将HTML标记与专为提高开发人员工作效率而设计的C#代码结合在一起。借助Razor,可使用Visual Studio中的IntelliSense编程支持在同一文件中的HTML标记与C#之间切换。Razor Pages和MVC也使用Razor。与基于请求/响应模型生成的Razor PagesMVC不同,组件专门用于处理客户端UI逻辑和构成。

Blazor使用UI构成的自然HTML标记。下面的Razor标记演示了一个组件(Dialog.razor),它显示一个对话框,并处理在用户选择按钮时发生的事件:

<div class="card" style="width:22rem"><div class="card-body"><h3 class="card-title">@Title</h3><p class="card-text">@ChildContent</p><button @onclick="OnYes">Yes!</button></div>
</div>@code {[Parameter]public RenderFragment ChildContent { get; set; }[Parameter]public string Title { get; set; }private void OnYes(){Console.WriteLine("Write to the console in C#! 'Yes' button selected.");}
}

在上述示例中,OnYes是由按钮的onclick事件触发的C#方法。对话框的文本(ChildContent)和标题(Title)由在其UI中使用此组件的下述组件提供。

使用HTML标记将Dialog组件嵌入到另一个组件中。在以下示例中,Index组件(Pages/Index.razor)使用前面的Dialog组件。标记的Title属性向Dialog组件的Title属性传递标题的值。Dialog组件的文本(ChildContent)由<Dialog>元素的内容设置。向Index组件添加Dialog组件后,Visual Studio中的IntelliSense可加快使用语法和参数补全进行开发的速度。

@page "/"<h1>Hello, world!</h1><p>Welcome to your new app.
</p><Dialog Title="Learn More">Do you want to <i>learn more</i> about Blazor?
</Dialog>

在浏览器中访问父级Index组件时,将呈现该对话框。当用户选择此按钮时,浏览器的开发人员工具控制台会显示由OnYes方法编写的消息:

组件呈现为浏览器文档对象模型(DOM)的内存中表现形式,它被称为“呈现树”,用于以灵活高效的方式更新UI。

文档对象模型 (DOM) 是HTML和XML文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。简言之,它会将web页面和脚本或程序语言连接起来。

一个web页面是一个文档。这个文档可以在浏览器窗口或作为HTML源码显示出来。但上述两个情况中都是同一份文档。文档对象模型(DOM)提供了对同一份文档的另一种表现,存储和操作的方式。DOM是web页面的完全的面向对象表述,它能够使用如 JavaScript等脚本语言进行修改。

Blazor Web Assembly

Blazor Web Assembly单页应用(SPA)框架,用于使用.NET生成交互式客户端Web应用。Blazor Web Assembly使用无插件或将代码重新编译为其他语言的开放式Web标准。Blazor Web Assembly适用于所有新式Web浏览器,包括移动浏览器。

通过WebAssembly(缩写为wasm),可在Web浏览器内运行.NET代码。Web Assembly是针对快速下载和最大执行速度优化的压缩字节码格式。Web Assembly是开放的Web标准,支持用于无插件的Web浏览器。

Web Assembly代码可通过JavaScript(称为JavaScript互操作性,通常简称为JavaScript互操作或JS互操作)访问浏览器的完整功能。通过浏览器中的Web Assembly执行的.NET代码在浏览器的JavaScript沙盒中运行,沙盒提供的保护可防御客户端计算机上的恶意操作。

Blazor Web Assembly应用生成并在浏览器中运行时:

  • C#代码文件和Razor文件将被编译为.NET程序集。

  • 该程序集和.NET运行时将被下载到浏览器。

  • BlazorWebAssembly启动.NET运行时,并配置运行时,以为应用加载程序集。BlazorWebAssembly运行时使用JavaScript互操作来处理DOM操作和浏览器API调用。

已发布应用的大小(其有效负载大小)是应用可用性的关键性能因素。大型应用需要相对较长的时间才能下载到浏览器,这会损害用户体验。Blazor Web Assembly优化有效负载大小,以缩短下载时间:

  • 在中间语言(IL)裁边器发布应用时,会从应用删除未使用的代码。

  • 压缩HTTP响应。

  • .NET运行时和程序集缓存在浏览器中。

Blazor托管模型

主要的Blazor托管模型在Web Assembly上的浏览器中运行客户端。将Blazor应用、其依赖项以及.NET运行时下载到浏览器。应用将在浏览器线程中直接执行。UI更新和事件处理在同一进程中进行。应用资产作为静态文件部署到可为客户端提供静态内容的Web服务器或服务中。

如果创建了Blazor Web Assembly应用进行部署,但没有后端ASP.NET Core应用来为其文件提供服务,那么该应用被称为独立Blazor Web Assembly应用。如果创建了应用进行部署,但没有后端应用来为其文件提供服务,那么该应用被称为托管的Blazor Web Assembly应用。托管的Blazor Web Assembly Client应用通常使用WebAPI调用或SignalR(结合使用ASP.NET Core SignalRBlazor)通过网络与后端Server应用交互。

blazor.webassembly.js脚本由框架和句柄提供:

  • 下载.NET运行时、应用和应用依赖项。

  • 初始化运行应用的运行时。

Blazor Web Assembly托管模型具有以下优点:

  • 没有.NET服务器端依赖项。应用下载到客户端后即可正常运行。

  • 可充分利用客户端资源和功能。

  • 工作可从服务器转移到客户端。

  • 无需ASP.NETCoreWeb服务器即可托管应用。无服务器部署方案可行,例如通过内容分发网络(CDN)为应用提供服务的方案。

Blazor Web Assembly托管模型具有以下局限性:

  • 应用仅可使用浏览器功能。

  • 需要可用的客户端硬件和软件(例如WebAssembly支持)。

  • 下载项大小较大,应用加载耗时较长。

  • .NET运行时和工具支持不够完善。例如,.NETStandard支持和调试方面存在限制。

在传统Web应用和单页应用(SPA)之间选择

Atwood 定律:任何能够用JavaScript编写的应用程序,最终必将用JavaScript编写。- Jeff Atwood

目前可通过两种通用方法来构建Web应用程序:在服务器上执行大部分应用程序逻辑的传统Web应用程序,以及在Web浏览器中执行大部分用户界面逻辑的单页应用程序(SPA),后者主要使用WebAPI与Web服务器通信。也可以将两种方法混合使用,最简单的方法是在更大型的传统Web应用程序中托管一个或多个丰富SPA类子应用程序。

何时使用传统Web应用程序:

  • 应用程序的客户端要求简单,甚至要求只读。

  • 应用程序需在不支持JavaScript的浏览器中工作。

  • 团队不熟悉JavaScriptTypeScript开发技术。

何时使用SPA:

  • 应用程序必须公开具有许多功能的丰富用户界面。

  • 团队熟悉JavaScriptTypeScriptBlazor Web Assembly开发。

  • 应用程序已为其他(内部或公共)客户端公开API。

此外,SPA框架还需要更强的体系结构和安全专业知识。相较于传统Web应用程序,SPA框架需要进行频繁的更新和使用新框架,因此改动更大。相较于传统Web应用,SPA应用程序在配置自动化生成和部署过程以及利用部署选项(如容器)方面的难度更大。

使用SPA方法改进用户体验时必须权衡这些注意事项。

传统Web应用程序、SPA或Blazor应用之间进行选择时要考虑的一些基本因素

因素传统 Web 应用单页面应用程序Blazor 应用
需要团队熟悉 JavaScript/TypeScript最低必需最低
支持不带脚本的浏览器支持不支持支持
客户端应用程序行为极少适合不必要可行
丰富而复杂的用户界面要求受限适合适合

何时选择传统Web应用

应用程序的客户端要求简单,可能要求只读

对许多Web应用程序而言,其大部分用户的主要使用方式是只读。只读(或以读取为主)应用程序往往比那些维护和操作大量状态的应用程序简单得多。例如,搜索引擎可能由一个带有文本框的入口点和用于显示搜索结果的第二页组成。匿名用户可以轻松提出请求,并且很少需要使用客户端逻辑。同样,一般而言,博客或内容管理系统中面向公众的应用程序主要包含的内容与客户端行为关系不大。此类应用程序容易构建为基于服务器的传统Web应用程序,在Web服务器上执行逻辑,并呈现要在浏览器中显示的HTML。事实上,网站的每个独特页面都有自己的URL,搜索引擎可以将其存为书签和编入索引(默认设置,无需将此功能添加为应用程序的单独功能),这也是此类情况的一个明显优势。

应用程序需在不支持JavaScript的浏览器中工作

如需在有限或不支持JavaScript的浏览器中工作的Web应用程序,则应使用传统的Web应用工作流编写(或至少可以回退到此类行为)。SPA需要客户端JavaScript才能正常工作;如果没有客户端JavaScript,SPA不是好的选择。

团队不熟悉JavaScript或TypeScript开发技术

如果团队不熟悉JavaScriptTypeScript,但熟悉服务器端Web应用程序开发,那相较于SPA,他们交付传统Web应用的速度可能更快。除非以学习SPA编程为目的,或需要SPA提供用户体验,否则对已经熟悉构建传统Web应用的团队而言,选择传统Web应用的工作效率更高。

何时选择SPA

应用程序必须公开具有许多功能的丰富用户界面

SPA可支持丰富客户端功能,当用户执行操作或在应用的各区域间导航时无需重新加载页面。SPA很少需要重新加载整个页面,因此加载速度更快,可在后台提取数据,并且对单个用户操作的响应更快。SPA支持增量更新,可保存尚未完成的窗体或文档,而无需用户单击按钮提交窗体。SPA支持丰富的客户端行为,例如拖放,比传统应用程序更容易操作。可以将SPA设计为在断开连接的模式下运行,对客户端模型进行更新,并在重新建立连接后将更新最终同步回服务器。如果应用要求包括丰富的功能,且超出了典型HTML窗体提供的功能,则选择SPA样式应用程序。

通常,SPA需要实现内置于传统Web应用中的功能,例如在反映当前操作的地址栏中显示有意义的URL(并允许用户将此URL存为书签或对其进行深层链接以便返回此URL)。SPA还应允许用户使用浏览器的后退和前进按钮寻找用户意料之中的结果。

团队熟悉JavaScript和/或TypeScript开发

编写SPA需要熟悉JavaScriptTypeScript以及客户端编程技术和库。团队应有能力像使用Angular一样使用SPA框架编写新式JavaScript

参考-SPA框架

  • Angular:https://angular.io

  • React:https://reactjs.org/

  • Vue.js:https://vuejs.org/

应用程序已为其他(内部或公共)客户端公开API

如果已提供一个Web API供其他客户端使用,则相较于在服务器端窗体中复制逻辑,创建一个利用这些APISPA实现更加容易。用户与应用程序交互时,SPA广泛使用Web API来查询和更新数据。

何时选择Blazor

应用程序必须公开丰富用户界面

与基于JavaScript的SPA一样,Blazor应用程序可以支持丰富的客户端行为,而无需重载页面。这些应用程序对用户的响应更快,仅获取响应给定用户交互所需的数据(或HTML)。如果设计得当,可以将服务器端Blazor应用配置为以客户端Blazor应用的形式运行,只需在此功能受支持后对它进行稍加更改即可。

与使用JavaScript或TypeScript开发相比,团队更喜欢使用.NET开发

与使用JavaScriptTypeScript等客户端语言相比,许多使用.NET和Razor的开发人员的工作效率更高。由于已经使用.NET开发了应用程序的服务器端,因此,使用Blazor可以确保团队中的每名.NET开发人员都可以理解,并可能会生成应用程序前端的行为。

Blazor Server

Blazor将组件呈现逻辑从UI更新的应用方式中分离出来。Blazor ServerASP.NET Core应用中支持在服务器上托管Razor组件。可通过SignalR连接处理UI更新。

运行时停留在服务器上并处理:

  • 执行应用的C#代码。

  • 将UI事件从浏览器发送到服务器。

  • 将UI更新应用于服务器发送回的已呈现的组件。

Blazor Server用于与浏览器通信的连接还用于处理JavaScript互操作调用。

JavaScript互操作

对于需要第三方JavaScript库和访问浏览器API的应用,组件与JavaScript进行互操作。组件能够使用JavaScript能够使用的任何库或API。C#代码可调用到JavaScript代码,而JavaScript代码可调用到C#代码。

在ASP.NET Core Blazor中从.NET方法调用JavaScript函数

https://docs.microsoft.com/zh-cn/aspnet/core/blazor/call-javascript-from-dotnet?view=aspnetcore-5.0

从ASP.NET Core Blazor中的JavaScript函数调用.NET方法

https://docs.microsoft.com/zh-cn/aspnet/core/blazor/call-dotnet-from-javascript?view=aspnetcore-5.0

Blazor支持的平台

浏览者Version
Apple Safari,包括 iOS当前†
Google Chrome,包括 Android当前†
Microsoft Edge当前†
Mozilla Firefox当前†

†最新指的是浏览器的最新版本。

Blazor模板选项

  • Blazor WebAssembly项目模板:blazorwasm

  • Blazor Server项目模板:blazorserver

创建我的第一个Blazor应用

1. 先准备".NET SDK (Software Development Kit)"环境。

如果之前没有安装的先安装这个SDK:

dotnet-sdk-5.0.202-win-x64.exe

如果已经安装过了,检查下当前版本:

dotnet --version

2. 根据Blazor项目模板创建应用

1) 命令行方式创建

dotnet new blazorserver -o BlazorApp --no-https

这里通过DOTNET-CLI执行新建项目的命令,使用的是blazorserver这个项目模板,输出项目文件夹为BlazorApp,给该项目设置为不需要HTTPS模式--no-https

如果要创建Blazor WebAssembly项目,这里将blazorserver改成blazorwasm即可。

dotnet new blazorwasm -o BlazorApp --no-https

2) Visual Studio方式创建

打开Visual Studio 2019最新版本,创建新项目,找到Blazor相关的项目模板。

  • Blazor Server应用

  • Blazor WebAssembly应用

点击下一步,输入BlazorApp的项目名称,点击下一步进行创建。

目标框架,可以选.NET Core 3.1(长期支持),也可以选择.NET 5.0(当前),去掉勾选复选框配置HTTPS,点击创建即可。

创建成功之后,会自动打开项目解决方案。

3. 运行应用

1) 命令行方式创建

如果通过命令行方式创建,运行应用只需要执行:

dotnet watch run

通过DOTNET-CLIRun命令可以运行程序,这里添加watch参数的好处就是,等下如果改动了文件,会热重载,这样调试起来就很方便。

运行起来之后,会看到浏览器弹出应用首页。

如果要退出运行,只需要执行如下命令即可:

Ctrl + C

2) Visual Studio方式创建

Visual Studio里面运行就很简单了,直接点运行BlazorApp或者Ctrl + F5即可。

默认会打开一个终端控制台界面,用来显示Console日志。

运行起来之后,会看到浏览器弹出应用首页。

4. 项目结构

  • Program.cs 启用这个应用服务的入口节点。

  • Startup.cs 配置应用服务和中间件的地方。

  • App.razor 应用组件的根组件,也就是组件的入口位置。

  • BlazorApp/Pages 包含一些示例页面,也是页面目录。

  • BlazorApp.csproj 描述应用项目及其依赖关系。

5. 认识首页及组件

我们看到Pages/Index.razor这个主页。

@page "/"<h1>Hello, world!</h1>Welcome to your new app.<SurveyPrompt Title="How is Blazor working for you?" />

这里已经有了SurveyPrompt这样一个组件,同时它有一个入参Title可以定制。

6. 查看子组件计数器

打开Pages/Counter.razor,这是一个计数器的组件。

@page "/counter"<h1>Counter</h1><p>Current count: @currentCount</p><button class="btn btn-primary" @onclick="IncrementCount">Click me</button>@code {private int currentCount = 0;private void IncrementCount(){currentCount++;}
}

我们可以从代码看到,顶部@page "/counter"实际上这个页面组件的目录,当我们切换到它时,路径也会变化。

每次点击Click me按钮的时候,就会从onclick事件去找到IncrementCount这个函数,在这个函数中,我们把currentCount做了加1,这时候,Current count的值会跟着刷新,可以看出只要绑定好了数据,它就会帮我们自动去更新界面显示了,还是很方便。

7. 在首页添加子组件计数器

打开Pages/Index.razor,我们在末尾追加Counter即可。

@page "/"<h1>Hello, world!</h1>Welcome to your new app.<SurveyPrompt Title="How is Blazor working for you?" /><Counter />

这时候,我们查看页面就已经可以看到它了。

8. 修改组件添加属性并使用

接下来,我们打开Pages/Counter.razor,我们给这个组件添加一个参数属性IncrementAmount,默认值是1, 这样我们可以从外部传递值进来修改它,并且我们让currentCount不再是继续加1了,而是改成加IncrementAmount的值,这样我们就可以控制每次累加的幅度。

@page "/counter"<h1>Counter</h1><p>Current count: @currentCount</p><button class="btn btn-primary" @onclick="IncrementCount">Click me</button>@code {private int currentCount = 0;[Parameter]public int IncrementAmount { get; set; } = 1;private void IncrementCount(){currentCount += IncrementAmount;}
}

然后,我们回到Pages/Index.razor,在Counter组件上给他传递IncrementAmount的值进来。

@page "/"<h1>Hello, world!</h1>Welcome to your new app.<SurveyPrompt Title="How is Blazor working for you?" /><Counter IncrementAmount="10" />

这时候,界面会自动重载,这时候,我们每次点击Click me,这个计时器组件就会加10了,哈哈,是不是很简单。

生成Blazor待办事项列表应用

1. 先准备".NET SDK (Software Development Kit)"环境。

如果之前没有安装的先安装这个SDK:

dotnet-sdk-5.0.202-win-x64.exe

如果已经安装过了,检查下当前版本:

dotnet --version

2. 创建待办事项列表Blazor应用

dotnet new blazorserver -o TodoList --no-https

通过DOTNET-CLI脚本的New命令,新建一个blazorserver项目模板,输出目录命名为TodoList,同时不需要HTTPS的支持。

3. 添加名为“Todo”的Blazor组件

cd TodoList

先切换到TodoList项目文件夹中。

dotnet new razorcomponent -n Todo -o Pages

然后,通过DOTNET-CLI脚本的New命令,输出目录为Pages,新建名为Todorazorcomponent组件。

其中-n全称为--name,用来指定创建的名称,-o全称为--output,用来指定在这个目录进行创建。

Razor组件文件名要求首字母大写。打开Pages文件夹,确认Todo组件文件名以大写字母T开头。文件名应为Todo.razor

将在项目文件夹的Pages目录中,新建得到一个Todo.razor文件。

接下来,我们需要在Todo.razor文件顶部添加针对该文件组件的路由位置。

@page "/todo"

4. 将“Todo”的Blazor组件添加到左侧导航

位于Shared文件夹的NavMenu.razor组件是控制左侧导航的,我们需要将“Todo”的Blazor组件添加到左侧导航中。

NavMenu.razor组件中,找到ul元素下的li节点,参考前面的例子,新建属于Todo组件的导航位置。

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu"><ul class="nav flex-column">...<li class="nav-item px-3"><NavLink class="nav-link" href="todo"><span class="oi oi-list-rich" aria-hidden="true"></span> ToDoList</NavLink></li></ul>
</div>

这里我们需要注意的几个关键点是,NavLinkhref需要填写组件的路由位置,其中span元素是菜单图标,紧跟着它的就是菜单名称,这里我们用ToDoList来作为菜单名称。

保存之后,我们通过执行run命令来运行,查看导航效果。

dotnet watch run

5. 添加“TodoItem”来存储待办事项数据。

这里一个小插曲就是为了更好的写出TodoItem.cs这个模型类,我遇到了两个不错的VSC插件,这里就顺带记录一下。

  • 名为C# Extensions的VSC插件,可以帮助我们支持在VSC中右键快速新建模型类和接口,有点类似VS中那种创建,至少帮你完成了当前命名空间的添加的活,所以值得推荐。

  • 名为C# XML Documentation Comments的VSC插件,平时我们在VS中写代码,习惯性的如果要添加函数或者属性的注释的话,上来就是///然后等待自动完成得到一串添加注释的注释体,这个插件就是来干这个事情的,效果还不错。

这两个插件,搜索C#这个关键词就可以看到了,基本上排在前面。

有了它们,我们创建TodoItem模型类就如虎添翼了。

在项目的Data文件夹中,我们右键,选择New C# Class,输入TodoItem,然后回车即可。

然后我们就自动完成,得到了一个基础的空的TodoItem.cs模型类,它的namespace都是已经处理好了,我觉得比手写强吧。

接下里,我们往TodoItem.cs模型类中添加两个属性(最好是走prop命令来新建),一个是Title来存储待办事项的标题,一个是IsDone来标记是否已完成该事项。

接下来,为了将来更好的阅读这个模型,我们养成一个好习惯,给对应的模型和字段都添加好注释,这时候C# XML Documentation Comments这个VSC插件就要派上用场了,通过在所需要注释代码的开头位置,输入///然后回车即可。

namespace TodoList.Data
{/// <summary>/// 待办事项/// </summary>public class TodoItem{/// <summary>/// 事项名称/// </summary>/// <value></value>public string Title { get; set; }/// <summary>/// 事项是否已完成/// </summary>/// <value></value>public bool IsDone { get; set; }}
}

参考

  • ASP.NET Core Blazor 简介

  • BlazorFluentUI

  • Blazor Webassembly Demo

  • DOM概述

  • 在传统 Web 应用和单页应用 (SPA) 之间选择

  • WebAssembly (abbreviated Wasm)

  • 从 ASP.NET Core Blazor 中的 JavaScript 函数调用 .NET 方法

  • 在 ASP.NET Core Blazor 中从 .NET 方法调用 JavaScript 函数

  • ASP.NET Core Blazor 托管模型

  • 用于 ASP.NET Core Blazor 的工具

  • Blazor Tutorial - Build your first Blazor app

  • 生成 Blazor 待办事项列表应用

  • C# Extensions - VS MarketPlace

  • C# XML Documentation Comments - VS MarketPlace

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

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

相关文章

看来要先拒绝37%的女人,才能找到真爱

全世界有3.14 % 的人已经关注了数据与算法之美在每期《非诚勿扰》节目上&#xff0c;面对一位位男嘉宾&#xff0c;24位单身女生要做出不止一次“艰难的决定”&#xff1a;到底要不要继续亮灯&#xff1f;把灯灭掉意味着放弃了这一次机会&#xff0c;继续亮灯则有可能结束节目之…

.Net日志之nlog

1. 介绍NLog是适用于各种.NET平台&#xff08;包括.NET标准&#xff09;的灵活&#xff0c;免费的日志记录平台&#xff0c;支持数据库、文件、控制台。2. 输入到文件2.1 引用nuget包<PackageReference Include"NLog" Version"4.7.6" /><PackageR…

为了证明自己有多能喝,理工科的学生竟做出这种事

全世界有3.14 % 的人已经关注了数据与算法之美当酒鬼止不住地说“我没有醉”、“再来一杯”的时候&#xff0c;他基本上已经醉得不行了。此时&#xff0c;他会说出一堆毫无逻辑的话&#xff0c;让旁人听了不知所云。这就是最为常见的酒鬼形象了。直到某一天&#xff0c;死理性派…

65 + iPhone应用程序网站创意设计灵感(上篇)

这里是一个巨大的艺术创作的iPhone APP网站设计的灵感收集。这些网站设计&#xff0c;特殊的配色方案&#xff0c;详细的图标和高品质的图形使用&#xff0c;如此精彩。希望能给你带来灵感。 Analog App Courier App Thermo App Faces Ecoki Motionoto Barista Moneybook App L…

php程序员跟java一样吗,【后端开辟】php程序员能够转java吗?

php顺序员可以转java吗&#xff1f;可以。关于专业顺序员来讲&#xff0c;在差别的开辟场景下采纳差别的编程言语是比较罕见的事变&#xff0c;所以许多顺序员在事情一段时候以后都邑控制多种差别的编程言语&#xff0c;比方不少Web顺序员都邑同时控制Java、PHP、C#等编程言语。…

你管这叫线程安全?

来来来&#xff0c;面试八股文&#xff1f;今天我们从什么叫"线程安全"聊起&#xff1f;文末"边吃边聊"。今日份的干粮&#xff1a;1.什么叫线程安全&#xff1f;2.线程安全与变量的关系&#xff1f;•变量又与堆/栈/静态存储区有密切关系什么叫线程安全&a…

经济学家告诉你,胸越大的女生越会花钱!

全世界有3.14 % 的人已经关注了数据与算法之美大概两周前回加拿大的航班上&#xff0c;我在机舱尾部跟一位空姐聊了很久。当空姐小妹双眼向下一瞥&#xff0c;略微停顿之后问我“班组要在这里呆四天&#xff0c;不知道该干什么去”的时候&#xff0c;我认认真真的为自己叹了口气…

讲100个科学道理,不如做这些有趣的理科实验!

玩具和学习看似是两个对立的东西&#xff0c;孩子天性爱玩&#xff0c;家长却希望孩子能多学习。不一定非要啃课本才能汲取知识&#xff0c;有时候&#xff0c;在轻松有趣的游戏中也能学到课堂上学不到的知识。让学习变得有趣、高效——给孩子讲100个科学道理&#xff0c;不如带…

《权力》读书笔记

1 为什么权力只为某些人所拥有我们生活在一个充满等级制度的世界里&#xff0c;等级的存在就意味着竞争&#xff0c;而且越往上&#xff0c;职位就越少&#xff0c;竞争也就越激烈。只有了解权力的原则&#xff0c;并愿意运用它们的人&#xff0c;才可以参与这样的竞争&#xf…

嘘!偷偷教你们一个在双十一省钱的办法!

各位小可爱&#xff0c;大可爱&#xff0c;大家晚上好~一年一度的双11即将到来&#xff01;&#xff01;&#xff01;小木冒着被砍头的风险为大家争取了好多好多福利绝对比平时更优惠更省钱哦&#xff01;&#xff01;&#xff01;活动时间&#xff1a;10月27日-11月11日&#…

ML.NET 示例:图像分类模型训练-首选API(基于原生TensorFlow迁移学习)

ML.NET 版本API 类型状态应用程序类型数据类型场景机器学习任务算法Microsoft.ML 1.5.0动态API最新控制台应用程序和Web应用程序图片文件图像分类基于迁移学习的TensorFlow模型再训练进行图像分类DNN架构&#xff1a;ResNet、InceptionV3、MobileNet等问题图像分类是深度学习学…

算法证明:女生遇到心动的男人一定要追!

全世界有3.14 % 的人已经关注了数据与算法之美我来讲恋爱中的博弈&#xff0c;不&#xff0c;我来讲恋爱中的算法&#xff0c;不&#xff0c;我来讲算法&#xff01;&#xff01;有个著名的问题&#xff0c;叫做 stable matching。早年是一个可爱的俄罗斯老头在图论课上教我的&…

记一次 .NET 某教育系统 异常崩溃分析

一&#xff1a;背景 1. 讲故事这篇文章起源于 搬砖队大佬 的精彩文章 WinDBg定位asp.net mvc项目异常崩溃源码位置 &#xff0c;写的非常好&#xff0c;不过美中不足的是通览全文之后&#xff0c;总觉得有那么一点不过瘾&#xff0c;就是没有把当时抛异常前的参数给找出来。。。…

Json.Net系列教程 3.Json.Net序列化和反序列化设置

上节补充首先补充一点,Json.Net是支持序列化和反序列化DataTable,DataSet,Entity Framework和NHibernate的.我举例说明DataTable的序列化和反序列化.创建一个DataTable对象,如下: DataTable dt new DataTable();DataColumn dcName new DataColumn("Name");DataColu…

5道谷歌面试题:即使是天才也要怀疑自己能力了(附答案)

全世界只有3.14 % 的人关注了数据与算法之美谷歌&#xff0c;美国的跨国科技企业&#xff0c;致力于互联网搜索、云计算、广告技术等领域&#xff0c;开发并提供大量基于互联网的产品与服务。这样一家实力雄厚前景无量的公司是众多求职者梦寐以求的地方&#xff0c;然而&#x…

[Abp vNext 源码分析] - 18. 单元测试

简介ABP vNext 框架使用 xUnit 作为单元测试组件&#xff0c;官方的所有模块都编写了大量的 单元/集成测试 确保功能正常。由于 ABP vNext 模块化系统的原因&#xff0c;开发人员在建立单元测试项目的时候需要集成 Volo.Abp.UnitTest 项目&#xff0c;这样在执行单元测试的时候…

php表格单元格怎么实现排序,javascript实现对表格元素进行排序操作

我们在上网中都能看到很多能够排序的&#xff0c;如大小、时间、价格等现在我们也试一下排序功能&#xff1a;排序的函数代码&#xff1a;里面含有点击之后排序--还原&#xff0c;和排升序和降序。function sortAge(){//对年龄进行排序&#xff0c;要先进行获得每一行对象&…

【10.29周一电商,已好】中国日历的至高境界,377张震撼级插画,美到爆!

每段时光都有属于每段时光的回忆它们是童年的纸飞机是校园时代的试卷与课本是第一次离开家乡时的兴奋与忐忑是跟某个人眼神交汇时的慌乱...回忆如此珍贵&#xff0c;以致于令我们频频回想&#xff0c;渴望着回到过去&#xff0c;与美好再度相逢。还记得文先生给大家推荐过的新一…

设置润乾报表鼠标移到格子上就显示提示内容

为了达到一定的交互性和易用性,我们一般喜欢将鼠标移动到格子上就能显示出一定的提示信息,比方说这个格子大小固定了但是里面内容超出格子了,这样我们希望鼠标移动过去后能自动提示所有的内容。用润乾报表可以这样设计&#xff1a; 比方说一个格子里面有如下内容 “这是一个很长…

ASP.NET Core 单元测试:如何Mock Url.Page()

点击上方蓝字关注“汪宇杰博客”导语在 ASP.NET Core 中&#xff0c;当你在 UrlHelperExtensions 类上使用扩展方法时&#xff0c;很难在单元测试中编写Mock。因为Moq框架不支持模拟扩展方法。问题例如&#xff0c;我的博客代码中使用了 Url.Page() 方法&#xff1a;var callba…