2024年8月

在前端开发中,持久化数据存储是一个非常常见的需求。为了实现这一点,浏览器提供了多种方式,包括 Cookie、localStorage 和 sessionStorage。这三者各有优劣,适用于不同的场景

1. Cookie

Cookie
是浏览器存储少量数据的一种机制,通常由服务器生成并发送到客户端。每次客户端向同一域名发起请求时,Cookie 都会自动附带在请求头中发送到服务器。

如图所示:

特点:

  • 数据大小限制
    :单个 Cookie 的数据大小限制通常在 4KB 左右。
  • 生命周期
    :Cookie 可以设置
    expires

    max-age
    属性来控制其有效期,默认情况下,Cookie 会在会话结束(即浏览器关闭)后删除。
  • 作用域
    :Cookie 与特定的域名和路径关联,可以通过设置
    domain

    path
    来控制它的作用范围。
  • 安全性
    :可以通过
    Secure
    标记仅允许在 HTTPS 连接中传输 Cookie,还可以通过
    HttpOnly
    标记使 Cookie 无法被 JavaScript 访问,增加安全性。

应用场景:

  • 会话管理
    :例如,登录状态的保持。
  • 用户偏好
    :例如,保存用户的语言设置。
  • 跟踪用户行为
    :例如,第三方分析工具使用 Cookie 进行用户跟踪。

示例:

//设置一个 Cookie
document.cookie = "username=John; expires=Fri, 31 Dec 2024 23:59:59 GMT; path=/";//读取 Cookie
const cookies = document.cookie.split("; ");
cookies.forEach(cookie
=>{
const [key, value]
= cookie.split("=");
console.log(`${key}: ${value}`);
});
//删除 Cookie document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";

2. localStorage

localStorage
是 HTML5 引入的一种 Web 存储机制,用于持久化保存客户端数据。它的存储是基于键值对的,并且不同域名的 localStorage 是独立的。

特点:

  • 数据大小限制
    :通常为 5MB。
  • 生命周期
    :localStorage 中的数据没有过期时间,除非手动删除,否则数据会一直存在。
  • 作用域
    :localStorage 只能在同一域名下的所有页面共享。

应用场景:

  • 长期保存的数据
    :例如,用户的设置、主题选择等不需要频繁更改的数据。
  • 离线 Web 应用
    :可以用于保存用户在离线时生成的数据。

示例:

//设置数据
localStorage.setItem('theme', 'dark');//读取数据
const theme = localStorage.getItem('theme');
console.log(theme);
//输出 'dark' //删除数据 localStorage.removeItem('theme');//清空所有数据 localStorage.clear();

3. sessionStorage

sessionStorage
也是 HTML5 引入的 Web 存储机制,与 localStorage 类似,但它的生命周期仅限于浏览器会话期间。关闭浏览器标签页或窗口后,sessionStorage 中的数据就会被清除。

特点:

  • 数据大小限制
    :通常为 5MB。
  • 生命周期
    :数据在页面会话期间有效,页面关闭后数据即被删除。
  • 作用域
    :sessionStorage 只能在同一窗口或标签页中共享,不同的窗口或标签页之间的数据互不影响。

应用场景:

  • 临时保存的数据
    :例如,表单数据的临时保存,以防止页面刷新导致的数据丢失。
  • 页面间的数据传递
    :例如,在多步表单中,传递各步之间的数据。

示例:

//设置数据
sessionStorage.setItem('sessionData', 'temporaryData');//读取数据
const data = sessionStorage.getItem('sessionData');
console.log(data);
//输出 'temporaryData' //删除数据 sessionStorage.removeItem('sessionData');//清空所有数据 sessionStorage.clear();

4. 区别总结:

特性 Cookie localStorage sessionStorage
数据大小限制 约 4KB 约 5MB 约 5MB
生命周期 可设置过期时间 持久保存,除非手动删除 仅在页面会话期间有效
作用域 与域名、路径相关联 同一域名下的所有页面共享 仅在同一窗口或标签页中共享
是否随请求发送 每次请求都会自动附带发送
常见应用场景 会话管理、用户偏好、跟踪用户 长期保存的数据、离线 Web 应用 临时保存的数据、页面间数据传递

PS:图片来源于B站技术蛋老师,侵删

什么是Web Component

Web Component是一套Web浏览器的技术和规范,能够让开发者定制自己的HTML元素

来自
MDN
的描述:

Web Component 是一套不同的技术,允许你创建可重用的定制元素(它们的功能封装在你的代码之外)并且在你的 web 应用中使用它们。

Web Component由三项技术组成:

  • Custom element(自定义元素):创建一个自定义元素,并自定义其行为。

  • Shadow DOM(影子 DOM):将若干元素封装成独立的DOM,并且与主文档DOM分开呈现,互不影响。

  • HTML template(HTML 模板):用于定义可重用的HTML,在HTML中使用类似于前端框架(如Vue)中的模板,一次定义可重用代码,涉及到两个HTML标签:<template> 和 <slot>

废话不多说,让我们以一个自定义一个GitHub标签快速入门

快速入门

声明式地创建HTML模板

和往常我们书写HTML类似,唯一不同点便是以<template>包裹:

<template id="template_github_icon">
	<a href="https://github.com/martixjohn" style="display: block; width: 100%; height: 100%" target="_blank">
		<svg style="width: 100%; height: 100%"  aria-hidden="true" viewBox="0 0 24 24" version="1.1" width="32" height="32">
			<path fill="currentColor"
					d="M12.5.75C6.146.75 1 5.896 1 12.25c0 5.089 3.292 9.387 7.863 10.91.575.101.79-.244.79-.546 0-.273-.014-1.178-.014-2.142-2.889.532-3.636-.704-3.866-1.35-.13-.331-.69-1.352-1.18-1.625-.402-.216-.977-.748-.014-.762.906-.014 1.553.834 1.769 1.179 1.035 1.74 2.688 1.25 3.349.948.1-.747.402-1.25.733-1.538-2.559-.287-5.232-1.279-5.232-5.678 0-1.25.445-2.285 1.178-3.09-.115-.288-.517-1.467.115-3.048 0 0 .963-.302 3.163 1.179.92-.259 1.897-.388 2.875-.388.977 0 1.955.13 2.875.388 2.2-1.495 3.162-1.179 3.162-1.179.633 1.581.23 2.76.115 3.048.733.805 1.179 1.825 1.179 3.09 0 4.413-2.688 5.39-5.247 5.678.417.36.776 1.05.776 2.128 0 1.538-.014 2.774-.014 3.162 0 .302.216.662.79.547C20.709 21.637 24 17.324 24 12.25 24 5.896 18.854.75 12.5.75Z">
			</path>
		</svg>
	</a>
	<style>
		a {
			display: block;
		}
		a > svg {
			color: #333;
			transition: all .3s;
		}
		a:hover > svg{
			color: #000;
			filter: drop-shadow(5px 5px 10px rgba(0,0,0,0.2));
		}
	</style>
</template>

这里实质上是一个超链接包裹了一个SVG图形,图形是我们的GitHub图标。

你也许发现了:

  • template
    标签含有
    id
    ,这是为了后续使用JavaScript去引用它并定义元素。

  • 这里创建了一个
    style
    标签并编写了CSS样式,甚至直接使用元素选择器而没有以一个className或者id去应用样式,有人会问这样会不会导致和页面冲突。

    答案是
    不会
    ,这里的样式局限于这个模板内部,和外部DOM是隔离的。

使用JavaScript API定义和注册我们的元素

// customElements.define()
customElements.define(
	// 元素名,必须是Kebab case命名
	// 目的是在页面中以<github-icon />去引用
	"github-icon",
	// 定义类,需要继承自HTMLElement
	class extends HTMLElement {
		// 构造器
		constructor() {
			// 必须调用父级构造
			super();

			// 获取上一步定义的template模板
			const template = document.getElementById("template_github_icon");
			// 获取模板内容
			const templateContent = template.content;

			// 获取本元素的影子DOM树根,mode为true表示以后可以通过JavaScript直接外部访问根节点
			const shadowRoot = this.attachShadow({ mode: "open" });

			// 将template的内容克隆并附加到shadowRoot,
			shadowRoot.appendChild(
				// true表示深拷贝
				templateContent.cloneNode(true)
			);
		}
	}
);

实际上在第一步你可以不以HTML创建“模板”,而是在类的构造器中以JS自定义元素的创建过程

使用自定义元素

HTML页面上使用

和普通元素使用方式完全相同,你甚至还可以为其添加属性(attribute)

<github-icon style="width: 40px; height: 40px;"></github-icon>

JavaScript内创建

也和普通元素的创建方式相同

const element = document.createElement('github-icon');
// element.xxx=xxx

总结

以上演示了如何自定义元素,并在页面中使用他们。

Web Component的灵活和强大不止于此,你甚至还可以:

  • 使用类似于Vue中的插槽slot以替换部分不相同的代码

  • 以现有的元素为母版去扩展

  • 自定义生命周期函数

  • 响应属性变化

  • ...

如果你仔细发现的话,
本博客页面使用的GitHub图标正是一个自定义元素

参考

前言

.NET MAUI 的发布,项目中可以使用这个新的跨平台 UI 框架来轻松搭建的移动和桌面应用。

为了帮助大家更快地构建美观且功能丰富的应用,本文将推荐一款优秀的 .NET MAUI 组件库MDC-MAUI,它不仅提供了丰富的 UI 组件,而且易于集成和使用。

通过本文的介绍,希望能够帮助大家在开发过程中节省时间并提升应用的用户体验。

组件介绍

MDC-MAUI 是一个专为 .NET MAUI 开发的组件库,为每个平台提供一致的视觉效果。

该库开箱即用,提供了丰富的 UI 组件,包括按钮、卡片、导航、开关、进度条等,可以帮助我们快速构建美观且功能丰富的应用。

组件展示

布局

1、WrapLayout

WrapLayout 是一种布局容器,允许根据 Orientation 属性将项目排列成行或列。当空间被填满时,容器会自动将项目换行到新的一行或一列。

2、示例代码

 <md:WrapLayoutOrientation="Horizontal">
     <md:ChipIconData="{Static icon:Material.Add}"Text="chip" />
     <md:ChipIconData="{Static icon:Material.Add}"Text="chip" />
     <md:ChipIconData="{Static icon:Material.Add}"Text="chip" />
     <md:ChipIconData="{Static icon:Material.Add}"Text="chip" />
     <md:ChipIconData="{Static icon:Material.Add}"Text="chip" />
     <md:ChipIconData="{Static icon:Material.Add}"Text="chip" />
     <md:ChipIconData="{Static icon:Material.Add}"Text="chip" />
 </md:WrapLayout>

3、属性

按钮

1、Button

常用按钮触发 UI 中的大多数操作。

提供五种样式:填充按钮(Filled)、凸起按钮(Elevated)、填充色调按钮(Filled Tonal)、边框按钮(Outlined)和文本按钮(Text)。

2、代码示例

<md:ButtonStyle="{DynamicResource ElevatedButtonStyle}"Text="Elevated" />
<md:ButtonStyle="{DynamicResource FilledButtonStyle}"Text="Filled" />
<md:ButtonStyle="{DynamicResource FilledTonalButtonStyle}"Text="FilledTonal" />
<md:ButtonStyle="{DynamicResource OutlinedButtonStyle}"Text="Outlined" />
<md:ButtonStyle="{StaticResource TextButtonStyle}"Text="Text" />

复选框

1、CheckBox

CheckBox允许用户从列表中选择一个或多个项目,或者开启或关闭某个项目。

2、代码示例

<mdc:CheckBoxText="checkbox" />

3、属性

4、事件

进度条

1、ProgressIndicator

进度指示器实时显示流程的状态。

2、代码示例

<md:ProgressIndicatorStyle="{DynamicResource CircularProgressIndicatorStyle}" />
<md:ProgressIndicatorStyle="{DynamicResource LinearProgressIndicatorStyle}" />

3、属性

4、事件

导航栏

1、NavigationBar

导航栏允许用户在较小的设备上切换 UI 视图。

2、代码示例

<...xmlns:icon="clr-namespace:IconPacks.IconKind;assembly=IconPacks.Material"...>

<mdc:FABIconData="{Static icon:Material.Star}"Style="{DynamicResource SecondaryFABStyle}" />

<mdc:NavigationBar>
    <mdc:NavigationBarItemIconData="{Static icon:Material.Star}"Text="label 1">...</mdc:NavigationBarItem>
    <mdc:NavigationBarItemIconData="{Static icon:Material.Star}"Text="label 2">...</mdc:NavigationBarItem>
</mdc:NavigationBar>

3、属性

4、事件

还有很多组件,大家如果有需要可以访问在线文档(https://mdc-maui.github.io/ )学习和参考,包括组件介绍、代码示例、属性以及事件等。

组件地址

  • Github
https://github.com/mdc-maui/mdc-maui
  • 文档地址
https://mdc-maui.github.io/

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。也可以加入微信公众号
[DotNet技术匠]
社区,与其他热爱技术的同行一起交流心得,共同成长!

1、Jenkins是什么

Jenkins是一个开源的、提供友好操作界面的持续集成(CI)工具,起源于Hudson,主要用于持续、自动的构建/测试软件项目、监控外部任务的运行。

Jenkins用Java语言编写,可在Tomcat等流行的servlet容器中运行,也可独立运行。通常与版本管理工具(SCM)、构建工具结合使用。Jenkins可以很好的支持各种语言的项目构建,也完全兼容Maven、Ant、Gradle等多种第三方构建工具,同时跟SVN、GIT等常用的版本控制工具无缝集成,也支持直接对接GitHub等源代码托管网站。

2、Jenkins部署架构概述

Jenkins部署分为以下两种模式:

  • 一种是直接使用单Master安装Jenkins,直接进行任务管理和业务构建发布,但可能存在一定的生产安全风险。
  • 一种是Master加Agent模式。Master节点主要是处理调度构建作业,把构建分发到Agent实际执行,监视Agent的状态。业务构建发布的工作交给Agent进行,即执行Master分配的任务,并返回任务的进度和结果。

Jenkins的Master和Agent均可安装在虚拟机或容器中,且组合形式可多样。

3、Jenkins部署架构详解

3.1 单节点架构(单Master)

单Master安装Jenkins,直接进行任务管理和业务构建发布。虚拟机单Master安装Jenkins可以参考《
Centos7下安装配置最新版本Jenkins(2.452.3)
》这篇博文。

对于某些特定场景,单节点不足以满足需求:

  • 如果所有执行程序都忙于处理构建任务,则作业(Job)必须等待。
  • 当项目的数量或负载增加时,很可能会耗尽资源。

为了恢复并运行Jenkins基础设施,需要通过增加内存、CPU等来增强服务器,而这不具备可扩展性,必须根据需求维护和升级服务器。

在维护升级过程中,构建环境将被关闭,作业不得不停止,整个Jenkins基础设施将不可用。

这种单节点架构会造成系统经常处于idle状态,分配给Jenkins环境的资源在这种状态下也没法被充分利用。

单节点架构还会引入安全问题,因为Jenkins用户对所有资源和工作空间都拥有完全的权限。

由于这些原因,Jenkins支持分布式架构,其中构建项目的工作负载被委托给多个Jenkins代理。

3.2 分布式架构(Master加Agent)

Master节点主要是处理调度构建作业,把构建分发到Agent实际执行,监视Agent的状态。业务构建发布的工作交给Agent进行,即执行Master分配的任务,并返回任务的进度和结果。

Jenkins的Master和Agent均可安装在虚拟机或容器中,您可根据自身需求选择其中一种方案执行:

3.2.1 Agent类别

3.2.1.1 固定Agent

Agent一直运行,任务构建完成后不会销毁,创建完成后将一直占用集群资源,配置过程较简单。每个Agent可以存在多个Executor,具体的数量应该根据Agent所在主机的系统资源来设定。

  1. Linux Jenkins(常用);
  2. Windows Jenkins;
  3. 容器化方式。
注意 1:很多的构建步骤,有可能会通过运行shell命令进行,于是此时要确保在虚拟机或Container内部有可用的命令,比如流水线中需要执行mvn命令,需要在虚拟机或Container镜像内安装配置好maven工具。

3.2.1.2 动态Agent

构建任务时动态创建Agent容器,并在任务构建完成后销毁容器,可实现资源动态分配,资源利用率高,但是配置过程较为复杂。可以把每个Agent视作一个动态的Executor。

依赖的环境:
云,通过Jenkins Controller(即Jenkins主服务器)与云环境进行交互以管理这些动态Agent。Jenkins Controller通过API(依赖插件)与云提供商的服务进行通信,发送请求以创建新的资源(如虚拟机或容器)、配置这些资源以作为Jenkins Agent运行,以及在Job完成后销毁这些资源。这些API调用允许Jenkins Controller自动化整个流程,从资源的创建到销毁,从而实现了Agent的动态管理。

  1. Docker Plugin,基于配置的Docker Host,按需要创建容器运行Agent,需要事先配置好容器模板;
  2. Kubernetes Plugin(常用),基于配置的Kubernetes,按需要创建pod运行Agent,需要事先配置pod模板。
注意 1:Controller自身既可以部署在k8s上,也完全可以运行在k8s外。

下面以动态Agent(k8s集群)Jenkins分布式结构图为例展示下Jenkins分布式架构。

3.2.2 Jenkins分布式结构特点

主节点负责(也叫Controller节点):

  1. 调度构建作业。
  2. 将构建作业分发给代理实际执行。
  3. 监视从节点(Slave),并根据需要停止其工作。

Jenkins代理负责(也叫Slave节点):

  1. 从主节点接收请求或工作,代理的工作就是按命令行事。
  2. 可以将工作配置为始终在特定代理上执行。
  3. 主节点将利用其资源来处理HTTP请求和管理构建环境,构建的实际执行将委托给代理。

通过这种配置,可以横向扩展Jenkins架构,其中Jenkins将安装在单个节点上。

主要参考:
https://support.huaweicloud.com/bestpractice-cce/cce_bestpractice_0066.html

这个观点在卡内基梅隆大学与谷歌研究人员合作文章

《Using an LLM to Help With Code Understanding》

中提出。

论文地址:
https://dl.acm.org/doi/abs/10.1145/3597503.3639187

摘要

理解代码非常具有挑战性,尤其是在新且复杂的开发环境中。代码注释和文档可以帮助,但通常资源不足或难以导航。大型语言模型(LLMs)正在彻底改变编写代码的过程。它们是否能同样助力于理解代码?

本研究提供了LLM为基础的对话型用户界面的首次研究,该界面直接嵌入IDE(集成开发环境)中,旨在促进代码的理解。

我们的IDE插件使用OpenAI的GPT-3.5-turbo模型查询四项高级请求,用户无需编写明确的提示即可完成这些请求:解释高亮代码段、提供代码中使用的API详情、解释特定领域的术语以及提供API的使用示例。

该插件还支持开放式提示,这些提示会自动根据正在编辑的程序对LLM进行上下文化。

我们将这个系统在32位参与者中进行用户研究评价,结果显示使用我们的插件可以比网页搜索更加促进任务的完成。

我们还详细分析了开发人员如何使用我们的系统,以及他们认为系统有用的方式。其中发现,学生和专业人员使用系统及从中获得的利益有所不同。

我们总结指出,与大型语言模型进行在IDE中直接、无需提示的交互是工具构建者探索的一个有希望的未来方向。

介绍

构建和维护软件系统需要对代码库有深刻的理解。因此,开发人员要花费大量的时间来搜索和搜集他们所需的信息,并组织和消化他们找到的所需要的信息。

理解代码是一项艰巨的任务,开发人员需要吸收大量的有关代码语义、使用的API细微之处以及相关领域的专业知识的信息。

这些信息通常散落在多个来源中,对于开发者,尤其是初学者或那些与不熟悉的API协同工作的开发者来说,要找到需要的信息会变得非常困难。此外,大部分相关的信息大多未得到充分的文档化,或者散布在不同的格式和介质中,最终导致信息过时。

随着大型语言模型(LLM)驱动的代码生成工具的兴起,对代码理解的信息支持的需求显然也在增加。

这些工具能够自动生成代码,即使是那些编程技巧有限或者对特定领域知识了解不多的开发者也能获得有效的结果。然而,这种便利性往往伴随着代价——开发者可能会得到完全不懂的代码。

的确,对LLM代码生成工具的早期研究发现,开发人员在调试由LLM生成的代码时会遇到困难,并且很容易感到沮丧。

幸运的是,LLMs(大型语言模型)在这个领域也提供了一个机会,即通过提供面向开发者的即需即用的基于代码生成的信息支持,帮助他们处理遇到的不熟悉代码问题。

与一般的网络搜索查询相比,LLM(大型语言模型)提示可以让开发者提供更多的上下文信息。这实际上能够使他们获取到更加精确地符合自己具体需求的信息。相较于从网络上获取大量信息然后再筛选出符合特定需求的内容,使用LLM提示在时间投入上可能更加节省。

开发人员确实开始大规模使用像ChatGPT这样的基于网络的会话LLM工具来获取编程支持,但这种设置需要他们在切换上下文时再将相关上下文从集成开发环境中复制到聊天系统中以获得支持。

为了探究生成式信息支持直接在开发者的编程环境中的应用潜力,我们开发了一个名为GILT(Generation-based Information-support with LLM Technology)的原型工具。

GILT能够生成个性化的、即时的信息,并将其与用户的本地编码环境相结合。我们通过在提供给后台语言模型(LLM)的提示中融入这些信息,将这种方法与LLM的交互变得更为自然。这种方式还引入了一种全新的交互方式,无需提供提示。这一设计旨在减轻那些对特定领域或编程知识了解有限的开发人员在编写提示时所承受的认知负担。

鉴于利用大型语言模型(LLM)提供信息支持(而非仅代码生成)的最佳实践知识尚不充分,我们进行了一项探索性用户研究,共有32名参与者被分配任务:理解并扩展涉及新领域概念以及Python数据可视化和3D渲染API的陌生代码这段充满挑战性的任务。我们的研究通过比较在一个代码编辑器内部使用带有LLM助手的效果,在网络浏览器中直接搜索网页的效果,以及在两者之间测量任务完成率和代码理解程度来进行量化对比。此外,我们通过定性研究参与者如何使用这两个工具,以及他们对这一新型交互模式的总体满意度来深入探讨。

具体来说,我们回答了以下三个研究问题:

  1. GILT在面对陌生代码时,对开发者理解程度、任务完成时间以及任务完成率的影响有多大?
  2. 开发人员如何与GILT进行互动,不同参与者之间有何差异?
  3. 开发人员如何看待GILT的有用性?

我们的结果证实,在使用GILT(Generation-based Information-support with LLM Technology)来完成任务时,相较于进行网页搜索,我们确实取得了统计意义上显著的优势,显示了这种资讯支援的实用性。然而,我们并未在时间效率及理解深度上发现同样的提升,这为我们未来改进留下了空间。我们还发现,这种效益的幅度在学生和专业人士之间有所差异,并对此进行了探讨。

结论

我们进行了一项用户研究,旨在调查使用大型语言模型(LLMs)进行生成式信息支持以帮助开发者理解代码的有效性。借助我们的内嵌IDE原型工具GILT,我们展示了这种方法显著增强了开发者完成任务的能力,与传统的基于搜索的信息获取相比。同时,我们也发现在学生和专业人士之间,开发者可以从工具中获得的好处程度不同,他们与工具的交互方式也基于自己的学习风格和对其他AI工具的熟悉度不同。