首页 文章 精选 留言 我的

精选列表

搜索[快速入门],共10000篇文章
优秀的个人博客,低调大师

Tailwind CSS 2.2 发布,快速构建 UI 的 CSS 框架

Tailwind CSS 2.2 正式发布,该版本是有史以来功能最丰富的 Tailwind 版本之一,该版本更新内容如下: 全新改进的Tailwind CLI 我们以性能优先的思维方式从头开始重写了 Tailwind CLI 工具,同时还增加了对一堆新功能的支持: npx tailwindcss -o dist/tailwind.css --watch --jit --purge="./src/**/*.html" 以下是一些亮点: 无需安装或配置——只需 npx tailwindcss -o output.css 就能从任何地方编译 Tailwind。甚至可以使用该 -jit 标志启用 JIT 模式并使用该 -purge 选项传入内容文件,而无需创建配置文件; Watch 模式 —— 这样就可以在进行任何更改时自动重建 CSS; JIT 性能优化 —— 由于我们的 CLI 是特定于 Tailwind 的,我们能够进行大量优化,使其成为在 JIT 模式下编译 CSS 的最快构建工具; 缩小支持 —— 现在可以使用 cssnano 通过添加 -minify 标志来缩小你的 CSS; PostCSS 插件支持 —— 新的 CLI 将读取并尊重使用 postcss.config.js 文件配置的任何额外插件; 它与以前的 CLI 完全兼容,因此如果您已经设置了任何脚本,您应该能够升级到 v2.2,而无需对脚本进行任何更改。 伪元素变体前后 此功能仅在 Just-in-Time 模式下可用; 多年来很多用户一直想要这个功能,现在它终于来了!我们添加了对样式伪元素的第一方支持,例如before和after: <div class="before:block before:bg-blue-500 after:flex after:bg-pink-300"></div> 我们会在用户使用 before 或 after 变体时自动设置 content: "" 以确保呈现元素,但用户可以使用 content 具有完全任意值支持的新实用程序覆盖它: <div class="before:content-['hello'] before:block ..."></div> 用户甚至可以使用 CSS attr() 函数从属性中获取内容: <div before="hello world" class="before:content-[attr(before)] before:block ..."></div> 当内容中有空格时,这会非常有用,因为在 CSS 类名称中不能使用空格。 首字母/行变体 此功能仅在 Just-in-Time 模式下可用; 我们为first-letter和first-line伪元素添加了变体,因此您可以执行首字下沉之类的操作: <p class="first-letter:text-4xl first-letter:font-bold first-letter:float-left"> The night was March 31, 1996, and it was finally time for Bret Hart to face off against Shawn Michaels in the long anticipated Iron Man match — a 60 minute war of endurance where the man who scored the most number of falls would walk away as the WWF World Heavyweight Champion. </p> We've added a newselectionvariant that makes it super easy to style highlighted to match your design: 选定的文本变体 此功能仅在 Just-in-Time 模式下可用; 我们添加了一个新的selection变体,使突出显示的样式变得非常容易以匹配设计: <p class="selection:bg-pink-200"> After nearly a grueling hour of warfare with neither man scoring a fall, Hart locked in the Sharpshooter, his signature submission hold. As Michaels screamed in pain, the crowd were certain that Hart was about to walk away from WrestleMania XII as the still-World Heavyweight Champion. </p> 我们甚至以这样的方式构建了这个功能,它可以应用于父元素并向下级联,因此您可以通过将实用程序应用于正文来为整个站点设置高亮颜色: <body class="selection:bg-pink-200"> <!-- ... --> <p> But Michaels didn't give up — he held on until the bell rang and the designated 60 minutes was up. Hart walked away content, thinking that without a clear winner, the title was his to hold. He was not prepared for what would happen next, when Gorilla Monsoon declared the match would continue under sudden death rules. </p> </body> 详尽的伪类支持 此功能仅在 Just in Time 模式下可用; 在这个版本中,我们基本上为每个我们能想到的缺失的伪类添加了变体: only(only-child) first-of-type last-of-type only-of-type target default indeterminate placeholder-shown autofill required valid invalid in-range out-of-range 列表中个人最喜欢的是 placeholder-shown ——当与新的 siblings 选择器变体结合时,它可以做一些很酷的事情,比如浮动标签: <div class="relative"> <input id="name" class="peer ..."> <label for="name" class="peer-placeholder-shown:top-4 peer-focus:top-0 ..."> </div> 修复和改进 除了此版本引入的新功能外,我们还修复了一些可能困扰您的小问题。以下是自上次发布以来我们所做的修复和改进的列表: JIT:支持应用重要的实用程序变体; JIT:改进对 Svelte 类绑定的支持; JIT:完善calc和 var 在任意值的支持 当转变不透明度时,转换hsl 颜色为hsla 而不是rgba ; 修复backdropBlur未生成; 改进 animation 值解析; 散列配置时忽略未知对象类型; 确保为具有 order-dependent 的实用程序的插件正确分组变体; 解决相对于tailwind.config.js而不是当前工作目录的清除路径; JIT:当节点临时目录保存在与项目本身不同的驱动器上时修复临时文件存储; 支持 border-opacity 实用程序和默认border实用程序 JIT:修复扩展@tailwind指令的源映射 JIT:折叠相邻规则时忽略空格; JIT:使用自定义分隔符时正确生成组父类; JIT:修复多个group变体的错误堆叠; JIT:修复由于保留未使用的上下文而导致的内存泄漏; 更多详情可查看:https://blog.tailwindcss.com/tailwindcss-2-2

优秀的个人博客,低调大师

用 Go + WebSocket 快速实现一个 chat 服务

前言 在 go-zero 开源之后,非常多的用户询问是否可以支持以及什么时候支持 websocket,终于在 v1.1.6 里面我们从框架层面让 websocket 的支持落地了,下面我们就以 chat 作为一个示例来讲解如何用 go-zero 来实现一个 websocket 服务。 整体设计 我们以 zero-example 中的 chat 聊天室为例来一步步一讲解 websocket 的实现,分为如下几个部分: 多客户端接入 消息广播 客户端的及时上线下线 全双工通信【客户端本身是发送端,也是接收端】 先放一张图,大致的数据传输: 中间有个 select loop 就是整个 chat 的 engine。首先要支撑双方通信: 得有一个交流数据的管道。客户端只管从 管道 读取/输送数据; 客户端在线情况。不能说你下线了,还往你那传输数据; 数据流 数据流是 engine 的主要功能,先不急着看代码,我们先想 client 怎么接入并被 engine 感知: 首先是从前端发 websocket 请求; 建立连接;准备接收/发送通道; 注册到 engine; //HTML操作{js}if(window["WebSocket"]){ conn=newWebSocket("ws://"+document.location.host+"/ws"); conn.onclose=function(evt){varitem=document.createElement("div"); item.innerHTML="<b>Connectionclosed.</b>"; appendLog(item); }; ... }//路由engine.AddRoute(rest.Route{ Method:http.MethodGet, Path:"/ws", Handler:func(whttp.ResponseWriter,r*http.Request){ internal.ServeWs(hub,w,r) }, })//接入逻辑funcServeWs(hub*Hub,whttp.ResponseWriter,r*http.Request){//将http请求升级为websocket conn,err:=upgrader.Upgrade(w,r,nil) ...//构建client:hub{engine},con{websockerconn},send{channelbuff} client:=&Client{ hub:hub, conn:conn, send:make(chan[]byte,bufSize), } client.hub.register<-client//开始客户端双工的通信,接收和写入数据 goclient.writePump() goclient.readPump() }复制代码 这样,新接入的 client 就被加入到 注册 通道中。 hub engine 发出了 注册 的动作,engine 会怎么处理呢? typeHubstruct{ clientsmap[*Client]bool//上线clients broadcastchan[]byte//客户端发送的消息->广播给其他的客户端 registerchan*Client //注册channel,接收注册msg unregisterchan*Client //下线channel}func(h*Hub)Run(){ for{ select{//注册channel:存放到注册表中,数据流也就在这些client中发生caseclient:=<-h.register: h.clients[client]=true//下线channel:从注册表里面删除caseclient:=<-h.unregister: if_,ok:=h.clients[client];ok{ delete(h.clients,client) close(client.send) }//广播消息:发送给注册表中的client中,send接收到并显示到client上casemessage:=<-h.broadcast: forclient:=rangeh.clients{ select{ caseclient.send<-message: default: close(client.send) delete(h.clients,client) } } } } }复制代码 接收注册消息 -> 加入全局注册表 如果 engine.broadcast 接收到,会将 msg 传递给 注册表 的 client.sendChan 这样从 HTML -> client -> hub -> other client 的整个数据流就清晰了。 广播数据 上面说到 engine.broadcast 接收到数据,那从页面开始,数据是怎么发送到这? func(c*Client)readPump(){ ... for{//1 _,message,err:=c.conn.ReadMessage() iferr!=nil{ ifwebsocket.IsUnexpectedCloseError(err,websocket.CloseGoingAway,websocket.CloseAbnormalClosure){ log.Printf("error:%v",err) } break } message=bytes.TrimSpace(bytes.Replace(message,newline,space,-1))//2. c.hub.broadcast<-message } }复制代码 从 conn 中不断读取 msg【页面点击后传递】 将 msg 传入 engine.broadcast,从而广播到其他的 client 当出现发送异常或者是超时,异常退出时,会触发下线 client 同时要知道,此时发送消息的 client 不止有一个,可能会有很多个。那发送到其他client,client 从自己的 send channel 中读取消息即可: func(c*Client)writePump(){//写超时控制 ticker:=time.NewTicker(pingPeriod) ... for{ select{ casemessage,ok:=<-c.send://当接收消息写入时,延长写超时时间。 c.conn.SetWriteDeadline(time.Now().Add(writeWait)) ... w,err:=c.conn.NextWriter(websocket.TextMessage) ... w.Write(message) //依次读取send中消息,并write n:=len(c.send) fori:=0;i<n;i++{ w.Write(newline) w.Write(<-c.send) } ... case<-ticker.C: c.conn.SetWriteDeadline(time.Now().Add(writeWait)) ... } } }复制代码 上面也说了,send 有来自各自客户端中发送的msg:所以当检测到 send 有数据,就不断接收消息并写入当前 client;同时当写超时,会检测websocket长连接是否还存活,存活则继续读 send chan,断开则直接返回。 完整示例代码 github.com/zeromicro/z… 总结 本篇文章从使用上介绍如何结合 go-zero 开始你的 websocket 项目,开发者可以按照自己的需求改造。 关于 go-zero 更多的设计和实现文章,可以持续关注我们。 github.com/tal-tech/go… 欢迎使用 go-zero 并 star 支持我们!

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册