

中高端软件定制开发服务商

13245491521 13245491521
新年福利!TailWindCSS+Vite+Vue3打造个性化在线简历项目 点击关注公众号,“技术干货”及时达! 前言?祝大家在新的一年:大吉大利,身体健康,迎大运,发大财! 吐槽随便侃侃,无感请直接跳过到正文。 ?注册了快 7 年的账号,终于发了第一篇文 你敢信 ~~ 哈哈,今天开张了,撒花。至于契机嘛… 司倒,失业之 T_T。 最近刷看到类似的帖子也挺多的,ORZ 放心,真不是来输出负面情绪的 ~ 主菜马上就到。 y 情后各行各业都不容易啊,待了六年的公司也熬不住去年末倒下了(还有 3 个月工资拖欠着,希望仲裁给力吧)。个人也长时间呆在舒适区,大环境每况愈下,经历了这波社会毒打后,时常感到焦虑。经过了几天的 emo 期(并没有,疯狂打球笑嘻嘻 … 但心里苦)哥们已经调整好了,等你回来 「生活终归是要继续的」。 给自己放放假,调整心态,查缺补漏,为了找到新工作,自己制定了如下小目标: ? 1. 重启技术博客 https://blog.fridolph.top,坚持输出? 2. 做几个实战项目(于是这篇文就诞生了)? 3. 整理前端知识大纲,形成思维导图? 4. 逛掘金,刷面经 + 整理(有些想法,于是开了新坑,再过几天就 OK)?? 5. 找到工作转正前 封印Steam - "你算什么男人算什么男人,眼睁睁看帕鲁走却不闻不问" T_T我原本是想重构一下我之前写的在线简历,采用 Vue3 + TS + Pinia 来实现。几下敲完代码,我自己都觉得没啥东西。简历上个人作品,开源那两栏空空如也 = = 之前老刷到tailwind的文章,遂决定学习换个心态尝试学习,加到项目中,现切现做,这瓜绝对保熟。 ?之前刷到 前端发展趋势的预测 之类文,很赞同一些观点。学历,简历只是敲门砖,在这个越来越卷的环境,竞争力不足,以后还是要多关注学习下 Node、Next.js,伪全栈万金油是个可选方向。 ?通过这篇文章你可以?? 学会在项目中灵活使用 TailWindCSS?? 「了解 TailWindCSS 的核心概念」?? 获得我整理的一份 Tss 速记指南?? 随我一起学习 CSS “新” 特性?? 本项目 Vite + Vue3 实践及相关优化?? 「Fork + Star 即得一份在线简历模板」,现改现用github: https://github.com/Fridolph/my-resume在线浏览:https://resume.fridolph.top/?注:本项目使用 pnpm 作为包管理工具,请升级 Node 版本到 16.22.2 以上 ?下面是我学习 TailWindCSS 的过程,本文不会先上来讲大段概念,而是通过实际项目入手,获得正反馈后再反思、理解,并思考总结写出该篇文章。 为什么想学 TailWindCSS之前也看到过类似的文章推送,我大致的印象就是这不就是 BootStrap 嘛。毕竟,人的精力是有限的,现有的 BEM 定义 class 一把梭就挺快的,为什么还要用这种过于原子化的 CSS mixin,import 肯定又是 几百 k。 不知道屏幕前的你有没这些疑问。 每一个能够流行起来的高 Star 项目内涵都不会简单,反正练手,正好了解一番,毕竟实践过后,才有发言权不是嘛 而巧合的是,我有一个现成的案例。以前为了找工作,我也做过在线简历项目。做完新版简历后,不论是代码的提炼还是规范性方面都有了很大的提升。这也算是对过去几年的努力有个交代吧,各个方面有了一个明显的对比。 「本文中我简称 TailWindCSS 为 Tss」。可能会有误导,因此在其他地方请不要使用这个名词。 在比较的同时,我会插入一些 TailWindCSS 文档中的概念,这样更容易让我们理解和体会到 Tss 的特性。 最重要的是切入点,本文通过实际案例让你快速了解 Tss,对感兴趣的部分可以对照文档自行学习,可谓事半功倍。废话不多说,show you the code! 新旧项目对比下面开始差生示范,只对比 HTML 结构和 CSS,JS 代码就暂省略了 App.vue公共样式的维护是个问题老项目的 app.vue style 没有加 scoped,我们编写的 css,比如 .page-resume p { margin: 10px 0; } 这类代码,一不小心就会应用到其他模块中,而很难发现。命名是门学问,诸如 BEM 之类的规范有很多,这也是业界主流吧,但随着项目内容增多,样式会越来越多臃肿。 我正好遇到过项目中三人同时写一个路由下的三个子页面,都有查询和表格,另个页面是以图文为主,很多链接,提示说明。 有个同事下了如下代码: style .xxx-pagea{ color:var(--text-link)!important; } .xxx-page.title{ font-size:12px!important; } /style stylescoped /*页面相关样式*/ /style template 都是复制粘贴,page 名还没改,一旦切到这页面再切到其他页面就会覆盖某些样式 …… 产生极其强大的魔法 使用Tss,不用写CSS非常干净虽然标签里的 class 会变得很臃肿。但单看 DOM 结构,这是良好符合 WAI-ARIA 规范的。有以下好处: 不用纠结命名,从此告别 xxx-wrapper、 xxx-title、 xxx-list、 xxx-item 避免潜在的样式冲突。因为框架都给你定义好了 ?你可能会吐槽,这 html 一大堆很难维护,css 是好了可 html 又病了 ?关于这点,后续章节 @apply 或者 tailwind.config.js 可能解决,但注定要在灵活性上做一定取舍 Hobby movie 过渡如果上面的不能说服你,那这个例子可以补充一些论据。 Hobby 模块里都是一些简单的动画实现,其中 movie 在旧模块中是这么实现的: 过渡有很多重复样式,但我们第一时间很难去抽取公共样式这只是其中一个组件,我们给了不同命名来加以区分。最开始写这块的时候没想太多,也没拆分组件,一个文件几百行 css 代码出现了(屎山就是这么炼成的) 项目中 = = 动辄几百行的还算好,经常 template、js 代码加起来几百行,若是再来上千行的 css,加上项目赶工期,就更头大。项目完给时间大家自觉优化还好,但现实情况,经常继续改 bug,同时又要做新功能 … 看着那座"山",不由得一声叹息 !--神奇,我真的没写css代码,也不用去想wrapperitembox之类的命名了-- divclass="flexflex-wrapjustify-content" divclass="groupoverflow-hiddenrelativering-1ring-slate-200roundedflexitems-centerjustify-centersize-12mr-3mb-3origin-centeralign-center" Iconfontclass="size-12absoluteleft-0top-0translate-x-[10px]translate-y-1transition-transformease-linearduration-500group-hover:-translate-y-12"/ Iconfontclass="size-12absoluteleft-0top-0translate-x-[10px]translate-y-1transition-transformease-linearduration-500group-hover:-translate-y-12"/ /div /div 上手 Tss 后,最大的一个变化和惊喜就是,只要你知道你想实现什么,都可以直接用 class 实现最终效果。 ?可能会吐槽,class已经一坨完全不能看,放心,这只是开始,后面有解决方案 ?没有写一行样式,完美实现了相同的效果,而且复用性强。当你把这串 template 丢给同事,只要有 tailwind 不需要引入 css 文件,不用担心 scoped 和样式覆盖就能得到一样的效果。 并不是说 BEM 不好,我们甚至可以两者结合,如果 Tss 提供的类名不足以实现你想要的效果,可把大致布局文字颜色等先写好,再另起一个 class 继续写 CSS 即可。 对 Tss 动画感兴趣的小伙伴可参考文档,玩出更多花样 https://www.tailwindcss.cn/docs/transition-property Hobby shake 动画上面的例子可实现过渡效果了,那动画了? 在 class 里写@keyframe 嘛? 这里就延伸出 Tss 可配置文件,tailwind.config.js。不仅仅是 动画,其他类似断点,和一些自定义类名,mixin 等,我们都可根据实际情况自行添加。 原则上,能通过 base core 完成的功能就尽量别放到配置中,因为打包会生成额外的代码,除非你确定这部分会多处使用和利于抽象。 /**@type{import('tailwindcss').Config}*/ exportdefault{ theme:{ extend:{ animation:{ singerShake:'singerShakelinearinfinite', }, keyframes:{ singerShake:{ '0%,100%':{transform:'translateX(0)'}, '10%,30%,50%,70%,90%':{transform:`translateX(-2px)scale(1.05)`}, '20%,40%,60%,80%':{transform:`translateY(2px)scale(1)`}, }, }, }, }, } 在代码中直接 animate-[singerShake_3s_ease-in-out_infinite] 即可使用。至于细节和命名等看文档就好,后面的 Tss 实用指南会提到。 divclass="transition-allduration-300ease-linearorigin-centerhover:bg-slate-500hover:rounded-fullhover:text-white" Iconfont class="size-12absoluteleft-0top-1rotate-0text-centertransition-allorigin-centergroup-hover:animate-[singerShake_3s_ease-in-out_infinite]" :size="28" name="changge" / /div CSS 更可控为了最快实现一个公共列表的样式,写出这么一串样式。如果要优化,在前期,可以通过定义 class,把公共样式抽离出来。 本简历的标题 - 内容(行) - 左 label 右 text,结构也大致如此。上述样式可实现该结构,但随着项目内容变多,需求变得繁杂: label 应自适应,可以给一个最小宽度,但在移动端如果太长能换行行结构只有内容,没有 label。或 行结构只展示标题(粗体)没有 text,支持 icon作为子组件时,应该统一对齐 padding这不,html 越来越多,很多样式感觉能公共,但又不好复用。(实现开发经常遇到这类情况)与其花时间做优化,不如直接新撸来得更快 而用 Tss 这些布局-排版-文字 相关样式类名可直接写到 class 中,复用性大大增强。 divclass="magic-wrappergird-cols-3bg-whitegap-3font-boldtext-smleading-5"/div stylescoped .magic-wrapper{ /*...*/ } /style 这样的好处是我们通过 TW 抽离了很多公共样式,而真正额外的样式则是 scoped 里的,不会污染其他作用域,这部分样式代码会比一开始少很多。若其他人接手,看到这部分样式能更快知道改动效果。 到这里相信很多朋友会发问: 这和 Bootstrap 有什么区别? css 是好维护了,但 html 结构混乱得不堪入目,10 行简单结构,给你能搞出 20 行? 别急,优化的事一步步来,下个章节会结合项目实践,慢慢解释 从布局开始,更高效的响应式支持如果一个结构细节多,需要针对更多断点情况,媒体查询的代码很更让人头疼了 为了响应式布局,会引入更多的css代码Tss 实现起来非常简单快速,手敲示例代码: ?wrapper 这类命名不需要,这里只为了大家能看清楚结构和上述 css 进行对比 非常建议手敲代码,能更快上手。这里实现下图片的 CSS,放心,绝对没有添加剂! ?divclass="page-resumelg:py-[5vh]lg:px-[5%]" divclass="groupside-wrappermd:h-screenlg:h-[90vh]p-5pr-[21px]hover:pr-[15px]" div class="list-wrappermd:h-[calc(100%-262px)]overflow-hiddengroup-hover:oerflow-y-auto" divclass="hero-boxpr-[6px]"/div /div /div div class="main-wrapperlg:h-[90vh]overflow-hiddenpr-[26px]hover:overflow-y-autohover:pr-5" /div /div ?vscode安装插件后上手更佳,智能提示放心写 ?vscode安装插件后上手更佳,放心写不会错你可以试着安装 VScode 插件 Tailwind CSS IntelliSense 看到这里如果你对 md、 lg 这些名称感到似曾相识,那么文档是最终的归途 https://www.tailwindcss.cn/docs/responsive-design TailWindCSS 核心概念简历很简单,但这并不就是 Tss 最佳实践,还很多东西等待着我们挖掘 有了这样一个开局,如果你已经对 Tss 产生了兴趣,那么接下来的官网概念相信会容易接受得多 效用第一 Utility-First Fundamentals处理状态 Handling Hover, Focus, and Other States响应式设计 Responsive Design深色模式 Dark Mode重用样式 Reusing Styles添加自定义样式 Adding Custom Styles功能和指令 Functions & Directives效用第一引用下文档内容: ?您不会浪费精力发明类名。不再需要添加像 sidebar-inner-wrapper 这样的愚蠢的类名只是为了能够设计某些东西,也不再为实际上只是一个 Flex 容器的东西的完美抽象名称而烦恼。你的 CSS 停止增长。使用传统方法,每次添加新功能时,您的 CSS 文件都会变得更大。有了实用程序,一切都可以重用,因此您很少需要编写新的 CSS。做出改变感觉更安全。 CSS 是全局性的,当你做出改变时你永远不知道你会破坏什么。 HTML 中的类是本地的,因此您可以更改它们,而不必担心其他内容会被破坏。?处理状态Tss 包含几乎所有的修饰器,包括: 伪类,例如 :hover、:focus、:first-child 和 :required伪元素,例如 ::before、::after、::placeholder 和 ::selection媒体和功能查询,例如响应式断点、深色模式和偏好减少模式属性选择器,例如 [dir="rtl"] 和 [open]我们平常写样式的思路是: 1. 定义 class; 2. 添加状态; 3. 添加对应样式代码 divclass="container"/div style .container{ background-color:black; } .container:hover{ background-color:white; } /style 而Tss 则是编译成 .hover\:bg-white:hover{ --tw-bg-opacity:1; background-color:rgb(255255255/var(--tw-bg-opacity)); } 在 Tailwind 中,您不是将 hover 状态的样式添加到现有类,而是向仅在 hover 时执行某些操作的元素添加另一个类。 https://www.tailwindcss.cn/docs/hover-focus-and-other-states#quick-reference 更多可参考文档,需要时再看就好,学一点用一点会一点。 响应式设计上一快状态里也有响应式标记,这里就不多提,记住一点就好 移动优先默认情况下,Tss 使用移动优先断点系统,类似于您在 Bootstrap 等其他框架中可能使用的系统。 这意味着无前缀的实用程序(如 uppercase)对所有屏幕尺寸都有效,而带前缀的实用程序(如 md:uppercase)仅在指定的断点及以上位置生效。 深色模式暂略过,核心就是通过改变状态标记,这里挖个坑吧,后续会为简历添加深色模式。敬请期待 (新增内容)快速实现主题切换不用后续,克服困难,现在开码。 提前定义好变量,便于维护说干就干。为了更好地使用主题模式,我建议提前定义好主题相关的变量,并为这些变量添加一个 dark 的前缀(根据实际情况自行调整)。 其实官方文档就是最好的示例。当我们要实现深色模式或者多主题时,需要考虑需要改变哪些内容?我简单总结如下: 页面的大背景色(如果有的话)布局模块(如:header、main、aside、section、footer 等)的背景色模块的常态样式,如:边框(内边框、外边框还是 background-image 等)圆角等文字的颜色阴影效果其他等等...当我们考虑到以上内容之后,再来思考状态改变时的颜色,例如 hover、focus、active 等。这只是一个思路,具体设计主题系统还需要 UI 设计同学的参与,还有许多细节值得我们深入研究。这里只是一个简单的参考。 /*src/styles/var.css*/ :root{ /*theme-light*/ --page-bg:#c5dae2; --bg-hover:#f5f5f5; --text:#607d8b; --text-hover:#00bdea; --main-bg:white; --aside-bg:#f5f5f5; --scroll-piece:rgba(218,230,238,0.9); --scroll-thumb:rgba(188,198,223,0.8); --border:#e5e7eb; --focus-border:#bae6fd; --card-bg:#f0f9ff; /*dark-mode*/ --dark-page-bg:#1f2635; --dark-bg-hover:#151e31; --dark-text:rgb(145,158,175); --dark-text-hover:rgb(185,196,212); --dark-main-bg:#151e29; --dark-aside-bg:#131822; --dark-scroll-piece:rgba(18,40,54,0.9); --dark-scroll-thumb:rgba(82,86,95,0.8); --dark-border:rgb(13,39,53); --dark-focus-border:rgb(21,53,70); --dark-card-bg:#0a2c42; } 我把使用到的色彩变量,都加了对应的 dark 副本,在用到这些的地方提醒自己写一个 dark:xxx 即可 你可以点开简历,查看下效果。下面以最外层wrapper为例子: divclass="w-fullmin-h-screenmd:flexmd:justify-centermd:align-middlep-0bg-[var(--page-bg)]md:py-[5vh]md:px-[5vw]dark:bg-[var(--dark-page-bg)]dark-transition" sectionclass="relativesm:w-fullmd:w-fullmax-w-[1600px]flexflex-colmd:flex-rowjustify-centeralign-middletext-colorshadow-innersm:shadow-2xldark:shadow-neutral-700" !--内容省略-- /section /div 当主题为 dark 时,容器的背景色会变成 var(--dark-page-bg);section 默认是内阴影,dark主题后,会应用设定的 box-shadow shadow-neutral-700 tailwind 主题配置根据文档,我们需要先配置 tailwind.config.js /**@type{import('tailwindcss').Config}*/ module.exports={ darkMode:'class', //... } //名称可自行改动,具体参考文档,这里不多赘述 配置好后,只要我们在 html 标签上添加 class="dark" 并为要改变的元素上按下面的方式增加对应类名即可 !--Darkmodeenabled-- htmlclass="dark" body !--Willbeblack-- divclass="bg-whitedark:bg-black" !--...-- /div /body /html ?注意:我们的页面是 create(App).mount('#app') 为了实现上述对 html class 的添加,我们还需要进行额外的 DOM 操作 ?我添加了一个 PageTool / ThemeChange (小项目其实用不上状态管理,这里只为展示Pinia用法请勿吐槽 ) import{defineStore}from'pinia' exportconstuseCommonStore=defineStore('common',{ state:()=({ theme:'light', }), getters:{ isDark:(state)=state.theme==='dark', }, actions:{ switchTheme(){ if(!this.isDark){ this.theme='dark' document.documentElement.classList.add('dark') }else{ this.theme='light' document.documentElement.classList.remove('dark') } }, }, }) 现在我们绑定好方法就可以快速切换主题了 divclass="switch-wrap"@click="handleSwitch" Iconfontv-show="isDark"name="night-mode-fill"/ Iconfontv-show="!isDark"name="light-bulb"/ /div scriptsetuplang="ts" import{toRefs}from'vue' import{useCommonStore}from'../../../store/common' importIconfontfrom'../../Iconfont/Iconfont.vue' conststore=useCommonStore() const{isDark}=toRefs(store) consthandleSwitch=()={ store.switchTheme() } /script 综上所述,这个简历项目,在 App.vue 的结构清晰明了,只需要在 wrapper、main、aside 等地方填入相应的 dark:xxxx 即可,比如 main class="... dark:bg-[var(--dark-main-bg)] "。 优化 - 添加平滑过渡这部分代码可能会变得很冗长,慢慢地,tailwind 的这一缺点就凸显出来了。不过这并非大问题,通过使用 @layer,我们可以将这些公共样式抽离出来,这是我在项目开发过程中一点点进行优化的成果。 感兴趣可点击切换,试下效果。会了黑白主题,再添加其他自定义主题不在话下。 @tailwindbase; @tailwindcomponents; @tailwindutilities; @layercomponents{ .dark-transition{ @applytransition-colorsduration-1000ease-in-out; } } 这样再切换,我们的主题就拥有良好的过渡效果了。 重用样式上文提到实现 Hobby 模块的 movie 效果时,对 item 写了一堆样式。 divclass="flexflex-wrapjustify-content" divclass="groupoverflow-hiddenrelativering-1ring-slate-200roundedflexitems-centerjustify-centersize-12mr-3mb-3origin-centeralign-center" !--...-- /div divclass="groupoverflow-hiddenrelativering-1ring-slate-200roundedflexitems-centerjustify-centersize-12mr-3mb-3origin-centeralign-center" !--...-- /div divclass="groupoverflow-hiddenrelativering-1ring-slate-200roundedflexitems-centerjustify-centersize-12mr-3mb-3origin-centeralign-center" !--...-- /div !--很多重复结构-- /div 在项目中有 8 个 item,需要将相同的东西复制八遍吗?起初可能是这样,尽管看起来有些辣眼睛,但至少功能已经实现了。无意中翻看文档时,我发现了以下的信息: ?很多时候,类似这样的重复甚至不是真正的问题,因为它们通常都可以集中在一个地方,甚至实际上根本不存在,因为您正在迭代一组项目并且只编写一次标记。如果您只需要在单个文件中重用需要重用的样式,那么多光标编辑和循环是管理任何重复内容的最简单方法。 —— 官方文档 ?好的,给我我笑了 … 于是继续编码。 额,额 …… 当然不止是这样,我们有几种方式来优化 *: 选择器divclass="parent-compflexflex-wrapjustify-start*:overflow-hidden*:relative*:ring-1*:ring-slate-200*:rounded*:flex*:items-center*:justify-center*:size-12*:mr-3*:mb-3" divclass="child-comp"/div divclass="child-comp"/div divclass="child-comp"/div divclass="child-comp"/div divclass="child-comp"/div /div 使用@apply 提取类@tailwindbase; @tailwindcomponents; @tailwindutilities; @layercomponents{ .hobby-item{ @applyoverflow-hiddenrelativering-1ring-slate-200roundedflexitems-centerjustify-centersize-12mr-3mb-3origin-centeralign-cente; } } 笔者也只是初窥门径,还有更多用法学习,尽在官方文档(再次强调) 添加自定义样式 Adding Custom Styles如果您想更改调色板、间距比例、排版比例或断点等内容,请将自定义添加到 tailwind.config.js 文件的主题部分: /**@type{import('tailwindcss').Config}*/ exportdefault{ content:['./index.html','./src/**/*.{ts,tsx,vue}'], theme:{ container:{ padding:'1rem', }, screens:{ sm:'640px', md:'1024px', lg:'1376px', xl:'1920px', }, }, } 项目中如何优化 Tss 代码效果基本完成,可以开始优化我新建了一个 styles/tailwind.css 专门存放 Tss 相关代码 @tailwindbase; @tailwindcomponents; @tailwindutilities; @layercomponents{ .hobby-fromBottom{ @applytranslate-y-fulltransition-transformease-in-outduration-500group-hover:translate-y-0; } .hobby-fromTop{ @apply-translate-y-fulltransition-transformease-in-outduration-500group-hover:translate-y-0; } .hobby-fromLeft{ @apply-translate-x-fulltransition-transformease-in-outduration-500group-hover:translate-x-0; } .hobby-fromRight{ @applytranslate-x-fulltransition-transformease-in-outduration-500group-hover:translate-x-0; } .hobby-fadeIn{ @applytransition-opacityease-in-outduration-500opacity-0group-hover:opacity-100; } } 结构简洁多了,把布局颜色等样式代码单独写 css,过渡相关样式写到了单独的文件中便于维护。 ?需要注意的是:hobby-fromBottom 这种用法在打包后会有编译开销,实际我们只用到一次的话没必要这样使用。这里只是方便展示 ?div class="absolutew-fullh-fullp-2z-10left-0right-0top-0bottom-0roundedbg-sky-50" :class="{ 'hobby-fromBottom':transitionType==='fromBottom', 'hobby-fromTop':transitionType==='fromTop', 'hobby-fromLeft':transitionType==='fromLeft', 'hobby-fromRight':transitionType==='fromRight', 'hobby-fadeIn':transitionType==='fadeIn', }" slot/slot /div 至此已经可以回答之前的疑问了,和 Bootstrap 像吗,是的。但不仅仅是这些,Tss 不仅可定制样式,而且更加灵活,而库体积却更小。 功能和指令 Functions & DirectivesDirectives指令是自定义 Tss 特定的规则,您可以在 CSS 中使用,为项目提供特殊功能。 /** *这会注入Tailwind的基本样式以及插件 */ @tailwindbase; /** *这会注入Tailwind的组件类和任何组件类通过插件注册 */ @tailwindcomponents; /** *这会注入Tailwind的实用程序类和注册的任何实用程序类通过插件 */ @tailwindutilities; /** *使用此指令来控制Tailwind注入悬停、焦点、响应式、深色模式以及其他变体 *如果省略,Tailwind会将这些类附加到默认情况下您的样式表 */ @tailwindvariants; Tss 速记指南一个新的东西需要学习成本。看到这的你,我相信已接受 Tss,并想投入使用了。这里结合笔者的经验,整理了一些速成技巧 编写 Tss 建议遵循着以下思路和顺序来: 布局间隔 margin、padding背景边框尺寸 width、height排版(文字相关)过渡、动画其他交互cursorhover这里以组件 TitleDesc.vue 为例。简历项目中在 ProjectWrap 用到来展示标题 + 内容,结构如下: template divclass="flexflex-betweenflex-nowrapborder-b-2my-3py-2gap-x-5text-lg" divclass="text-justify" Iconfontv-if="showIcon"class="align-middle"/Iconfont spanclass="ml-1font-boldalign-middletext-[#333]"{{title}}/span /div div slotname="extra"/slot /div /div divclass="bg-graypl-3text-basetext-[#777]"{{description}}/div /template 思路有了一切都很简单,Tss 很多 Class 和原生缩写一样,很容易记,看一遍基本就会了 这里整理一些常用 和 容易错误的: 布局相关「display」 ClassPropertiesblockdisplay: block;hiddendisplay: none;inline-blockdisplay: inline-block;inlinedisplay: inline;flexdisplay: flex;griddisplay: grid;container 在当前断点下都处于 width: 100% ?gap 是真的好用,前提是在 flex 或 grid 下生效 ?「overflow」 ClassPropertiesoverflow-autooverflow: auto;overflow-hiddenoverflow: hidden;overflow-clipoverflow: clip;overflow-visibleoverflow: visible;overflow-scrolloverflow: scroll;「position」 ClassPropertiesstaticposition: static;fixedposition: fixed;absoluteposition: absolute;relativeposition: relative;stickyposition: sticky;size 尺寸这里单独说一下「Tss 里的基本单位 1rem = 16px」 这点非常重要,请记住。对于尺寸,1 TSS 标准单位大小 = 4px (0.25rem) 后面跟的 left-1、size-10 看到这种默默乘 4 就可以换算出 left-1(left:4px)、w-8(width: 32px)、mb-4(margin-bottom: 16px) ClassPropertiesm-0margin: 0;w-pxwidth: 1px;mx-automargin-left: auto;margin-right:auto;py-autopadding-top: auto;padding-bottom:autoh-fullheight: 100%;left-1/2left: 50%;排版0 就是 0pxpx 一般都是 1pxfull 表示 100%x 横坐标,如mx就是 margin-left、margin-righty 纵坐标,同上 py 就是 padding-top、padding-bottom加入 1/3 这样的,表示百分比,具体看文档若想精确的,可以自定义 -[x],如 w-[66px]、 h-[calc(100vh-50px)背景Tss 的写这类复合样式,都是要拆开写的,虽麻烦,但本质上也算是解耦嘛 后续 flex、border、transition 这类属性也类似,我们只要知道大致 value 即可,这么一想也挺好,对 CSS 越熟悉就越容易上手 Tss。 background 本身是 background-color、background-image、background-position、background-repeat、background-size 多个属性的缩写。 ClassPropertiesDescbg-nonebackground-image: none;-bg-whitebackground-color: white;颜色bg-centerbackground-position: center;位置bg-coverbackground-size: cover;尺寸bg-containbackground-size: contain;尺寸bg-no-repeatbackground-repeat: no-repeat;重复用这类属性,需要根据 bg-[效果] 带来的实际效果提炼关键点。这么想就容易上手了 Transform常用的都在这里,知道这几个即可: translate 同 left right ,直接写scale 同 opacity,需注意 Tss 里的像百分比的值都乘了 100rotate 官方只制定了几个常用的,这类自己写就好,如rotate-[46deg]skew 同上origin origin-center为 transform-origin: center;transform-gpu 就是面试中常考的的开启 gpu 加速 ?但没看到对 translate-z 的支持,perspective只能手动添加了 若有错误麻烦指正下,谢谢 ?来记点不一样的上面说了关键点在于应用 CSS 带来的实际效果。再来看下面这些,你就会容易理解得多: ClassPropertiesDescbg-whitebackground-color: white;颜色text-basefont-size: 1rem; line-height: 1.5rem;字体和行高truncateoverflow、text-ellipsis、white-space三剑客文字省略你懂的italicfont-style: italic;斜体font-boldfont-weight: 700;加粗leading-5line-height: 20px;行高text-centertext-align: center;文字居中align-middlevertical-align: middle;内联垂直对齐roundedborder-radius: 4px;-divide-x +border-right-width: 0px; border-left-width: 1px;不用单独写边框了divide-y-2 +border-top-width: 2px; border-bottom-width: 0px;不用单独写边框了outline-1outline-width: 1px;外边框,这几种根据实际需要选择即可ring-1太多省略本质为 box-shadow 模拟的边框opacity-0opacity: 0;透明opacity-100opacity: 1;不透明visiblevisibility: visible;典,虽隐藏了但保留 DOM 位置,影响回流invisiblevisibility: hidden;本质为 box-shadow 模拟的边框cursor-pointercursor: pointer;聚焦cursor-not-allowedcursor: not-allowed;禁止pointer-events-nonepointer-events: none;阻止浏览器事件select-noneuser-select: none;禁止选中?注:用 text 千万要注意line-height,虽然很想吐槽 明明是 font-size ,但整个 text 很异类. 如果只想使用 font-size 的话,直接 text-[14px] 这样就好了 ?上述这些浏览一遍就可快速上手,遇到不会的再查文档就是。 学到的 CSS 新特性1. display: flow-root;flow-root 该元素生成一个块级元素盒,其会建立一个新的块级格式化上下文,定义格式化上下文的根元素。 IE8 启动 …… 额,不是 还在用 clear 清楚浮动嘛? float 毕竟是针对内联图文的, 如果想让之后的元素不受到浮动影响,可以直接新建一个元素,并使用该属性 2. grid 布局快速上手四列布局是吧? 来了,瀑布流?不在话下 divclass="gridgrid-cols-4gap-4" div01/div !--...-- div09/div /div 更多参考:https://www.tailwindcss.cn/docs/grid-template-columns 3. scroll-behavior: smooth;论回到顶部的四种写法: jQuery.animate({scrollTop:0})window.scrollTo(0, 0)document.body.scrollTop = 0如果想丝滑滚动还要写一堆 js 代码,防抖啊,requestAnimationFrame 又给整出来了,现在不要 998,只需一句 css scroll-behavior: smooth,结合 锚点即可实现,浏览器更懂浏览器。 ?此时一位路过的朋友提出兼容 IE8(大哥现在 2024 React 都 18 了,vue 都 3 了,全民 AI 时代您还搁这 IE。抗击旧世界残党我辈义不容辞)掘金内外又瞬间充满了快活的空气 ?4. caret-color用于控制文本输入光标颜色 caret-color: orange; inputclass="caret-orange-200..."/ 5. background-clip设置元素的背景(背景图片或颜色)是否延伸到边框、内边距盒子、内容盒子下面,在这里,头像下的文字就是background-clip: text 和 linear-gradient 实现的。 更多可看文档 https://developer.mozilla.org/zh-CN/docs/Web/CSS/background-clip。 6. will-change用于优化即将发生变化的元素的动画。官方建议慎用,在明确 transition perproties 的情况下可以提升性能 7. postcss我发现两者结合已能满足大部分功能和场景,什么 sass(安装就像买彩票) scss、stylus 我都不需要了 8. 更多选择器和修饰符再帖一遍文档,真的很好用 https://www.tailwindcss.cn/docs/hover-focus-and-other-states#quick-reference 一个好的优化原则就是,能用 css 的尽量用 css 实现。 合理选择器和好处在于 它的权重和 class 都是相同的,知道这点,就可以让我们可以少写很多没必要的高权重选择器 9. 了解到 WAI-ARIA感兴趣可看我之前的一篇文,如果需要,可以向标签添加 data 和 aria 属性,结合 role,提供更好的用户可访问性。 https://blog.fridolph.top/2024/01/26/32647990-bc5d-11ee-b11d-1ddb3fe7683d/ 还有更多等待发掘HTML、CSS,简单和立即反馈,通过这次学习感觉找回了初学前端时的快乐,这算是一个意外之喜吧。 在写博客时,也发现一些可尝试的新东西,预计就随便写写 2000 字不能再多,没想到码了这么多字 ?这篇文章真是从 2000 字 - 想着扩展点吧写到 5000 字 - 好人做到底完善到 1W 字 ~ 骄傲,原来我不是文废,语文老师可以放心了! ?总结考虑到这一章节,这实质上也是对过往经验的一种总结。在我早期的项目开发中,往往采用一种即兴的方式编写 css 和模板,导致组件粒度不够细,复用性不高,同时也存在一定程度的未提取冗余样式的问题。随着项目复杂度的增加,势必出现一些无法解决的样式问题,不得不通过全局样式甚至使用“important”来进行覆盖。 随着对 Tss 的学习,加上最近也是在复习,想到就会尝试添加新的特性,不知不觉 2 天搞定的项目断断续续码了十多天,但这一过程非常享受,我重新找回了对编码的好奇心和热情。 关于技术选型本文不是说服你去用Tss,而是多一个了解,多一个待选方案 项目中添加 TSS 有一定的学习成本 刷到些评论,感觉更多的困难是能否让同事接受 TSS 的核心概念。刷文档做 demo 实际 1 天即可上手。还有另一好处是让平时不太关注 CSS 的小伙伴,(不考虑兼容性情况下)能用到一些新特性。 对于灵活性的取舍我理解熟悉 TSS 带来的高效开发和其带来的 html 臃肿问题,@apply(tailwind.config.js) 如何使用决定了我们需要牺牲怎样的灵活性以换来更高的可维护性 代码体积小,灵活度高,推荐一试从下面可看到打包后 css 代码部分很小(只编译打包了我们用到的部分)这也是与其他写好 .xs .md .m-1 .m-2 .p-b-1 .p-t-2 样式的 UI 的不同之处。 个人总结的一些开发实践对于入口文件 app.vue,应确保其作为容器组件,尽量减少业务逻辑的耦合。 在划分组件和视图时,要遵循components和 views 的原则,以减小粒度并分离业务逻辑。 善用 hooks,尤其在项目中逻辑较为简单时,例:我抽了个 useLocale hook,供参考。 在划分视图时,要保持与入口的清晰一致, 如App.vue 它会为你带来意想不到的好处。 在组件开发时不要刻意进行优化。我的建议是,待一个大的 page/view 开发结束后再考虑优化的事情 ?过早的优化属于浪费精力。但如果优化过晚,特别是在多人合作时,一些未提取的模板可能会被他人复制,然后进行修改,一旦变得不可控,进行优化就会需要更多的精力。 ?布局、文字等细节不应等到 UI 设计确定后再考虑,而应从决定支持响应式、i18n 时开始考虑。?我前公司的项目中,基本上都需要支持国际化。对于布局,务必要考虑文本所带来的影响,例如文字不固定长度,中文切换到英文长度变化带来的影响等,这些细节可以尽早地写入到 common.css 中作为公共样式。 ?过渡和动画可以起到画龙点睛的作用,但如果使用,尽量多尝试不同的 cubic-bezier。?在可控的情况下,要减少 transition-all 的使用,而以 transition-opacity、transition-transform 为例。否则,这与 TypeScript 中使用 any 有何区别呢? ?我们的项目很简单,在实际开发中远不止这些,推荐参考 dev.to 、MDN 等 终于上线啦!别高兴太早网站既然都放到了生产环境,F12 是常有的事 ... 那有必要 print 秀一波 console.log 了,啊,不是! ?小红红:停停停!兄弟,你是来捣乱的嘛? ?性能才是我们要关注的重点好吧。先来一波分析 performance. 这是我自己网站的加载情况 ?实际可自行 performance API 或运用 lighthouse 等工具。这里就简单示范下 ? 有点搞笑?!就这么少的文件,只有一个单页,怎么会加载得如此缓慢呢?代码写出来了,也在本地运行了,但放到生产环境后才发现问题如此突出。 没错,你也许以为这个项目已经完成了,但实际上,这只是一个开始。还有很长的路要走,兄弟们,我们的任务尚且艰巨。 构建优化也是为了面试,正好实践一下 = = 以前也没配过这些,vue-cli 直接搞定,反正需要啥用啥,直接看文档即可 https://cn.vitejs.dev/. 大方向嘛无外乎两点:减少构建和打包耗时,减小打包资源体积 vite-plugin-compression这点 vite 默认配置就有了,不用担心。这里我加了一个插件 compression,它的作用是打包压缩且生成 gzip,感兴趣的小伙伴自行文档 vite-plugin-chunk-splitVite 代码拆包插件。支持多种拆包策略,可避免手动操作 manualChunks 潜在的循环依赖问题。 exportdefaultdefineConfig({ plugins:[ vue(), compression(), chunkSplitPlugin({ strategy:'default', customSplitting:{ //vue相关会被打包到一个名为`render-vendor`的chunk里面(包括它们的一些依赖,如object-assign) 'vue-vendor':[/vue/,/pinia/], 'tailwind-vendor':[/tailwindcss/], 'fri-vendor':[/fri-element-plus/], //源码中目录的代码都会打包进[name]这个chunk中 styles:[/src\/styles/], locales:[/src\/locales/], }, }), ], }) 原来是之前的练手项目导致了这些问题。动态导入却没有实现只导入所需的组件和样式,导致页面大小异常庞大。(若有时间,再优化这项目吧,这里直接去掉了) 实现代码拆分(split-chunks),来减少页面加载体积。 对于使用开源 UI 库的情况,大多数都会支持这样的特性,比如 ElementPlusResolver 等,以此来解决该问题 vite-plugin-importus这里假装已经优化了:囧 (如果 UI 库支持,可实现按需加载) exportdefaultdefineConfig({ plugins:[ //... vitePluginImportus([ { libraryName:'ElementPlus', libraryDirectory:'es', style:'css', }, ]), ], }) ?其实你还可以考虑,在你的项目中并不一定需要那么大而全的 UI 或工具库。既然已经开始着手进行优化,那就一丝不苟地将这些练手用的 UI 库移除吧。 同时,在此时可以思考一下,这些库、UI 组件等是否真的是你项目中所必需的,是否存在其他更优的替代方案,是否支持按需加载等功能。 我又开始进行一番调整,将这些添加的"玩具"组件库一一移除了。 ?Vite-plugin-bundle-prefetch获取所有包含 assetDir 的包过滤目标文件(rm .map 文件或忽略旧版本)获取最终输出的 html 文件内容在头部附加 link rel="prefetch" href="xxxx"通过 prefetch 也能尽早渲染页面,从而达到优化的效果 路由按需加载 (这里没用到就略过了)?构建上还有很多,主要是根据自身实际需求来就好。「适合的就是最好的」 ? 优化后快多了不是,但还没完,别急,马上就好了,虽然我们打包了 gz 后缀,但其实还没生效呢。 请求优化由于近期正在找工作,我发现简历内容可能会需要频繁更新。为了确保浏览器不会缓存旧的信息,我采用以下缓存策略:(仅供参考,可根据你的情况调整) index.html 不使用任何缓存策略,因为文件体积本身很小js、css、pdf、md 等可能频繁变动的文件,缓存 1 天svg、jpg、pdf 和字体文件等不会经常更改的文件,缓存 7 天同时,我也开启了 gzip 压缩功能。下面是我的 nginx 配置,供大家参考: server{ server_nameresume.fridolph.top; #ssl和证书相关配置省略了 location/{ indexindex.html; add_headerCache-Control"private,no-store,no-cache,must-revalidate,proxy-revalidate"; } location~*^.+\.(jpg|png|svg|ico|woff|woff2)${ log_not_found#关闭日志 expires#缓存时间7天 add_headerCache-Controlmax-age=604800; } location~*^.+\.(css|js|md|pdf|)${ expires#可能会频繁变动的资源只缓存1天 add_headerCache-Controlmax-age=86400; } #开启gzip gzip #启用gzip压缩的最小文件,小于设置值的文件将不会压缩 gzip_min_length #gzip压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间。一般设置1和2 gzip_comp_level #进行压缩的文件类型。javascript有多种形式。其中的值可以在mime.types文件中找到。 gzip_typestext/plainapplication/javascriptapplication/x-javascripttext/cssapplication/xmlimage/jpegimage/png; #是否在httpheader中添加Vary:Accept-Encoding,建议开启 gzip_vary } 优化暂时搞定,秒开! 总体来看,作为一个“简单”的项目,我相信它应该达标了吧!呜呜呜,简历兄你完成了自己的使命,一路走好。 当然,优化远不止这么简单,这里只例举了一些常见方式,可根据需要将这些优化技巧运用到你的项目中。 再强调一下 Tss 四大核心概念:效用第一处理状态响应式设计重用样式这才是我们在项目中使用的目的,tss 只是其中一个手段。感谢您看到这里。文章内容基本结束,本文只是引子,Tss 本身不仅仅这些内容。若通过本文能引起你的兴趣并学习这也是我的荣幸。 写在最后实践才是最好的老师,通过这段时间的实践,通过不断地思考和优化项目结构、组件,以及功能的实现。尽管这只是一个简单的项目,但我已经不再是简单的复制粘贴,而是把它当成一件新鲜的事物,用来检验自己的学习成果。我发现 Tss 非常适合模块化开发,随着熟练度提高用起来也越来越顺手。 如果有同学不需要国际化的版本,可以切换到 https://github.com/Fridolph/my-resume 分支的dev/无国际化看这分支。但这个分支比较早,缺少很多细节和后续的优化,再贴一下项目地址: github: https://github.com/Fridolph/my-resume在线浏览:https://resume.fridolph.top如果您觉得这对您有所帮助,求个 Star 不过分吧! 如果有不足之处或者观点不一致的地方,请多批评指教,谢谢。 本来想拆成几篇来写,感觉没必要。一步到位,您的点赞对我来说将是最大的认可。支持一下"萌新"吧!在春节期间写文章确实不容易,感谢大家的关注和支持。 恭祝大家工作顺利,平安健康,万事如意,一帆风顺!和我一样没工作的小伙伴在新的一年能找到自己满意的工作,生活不易,共勉之! 阅读原文
| 上一篇:2024-07-25_自动驾驶的GPT时刻,来了吗?|AGI路线图 | 下一篇:2025-04-28_「金瞳奖话题合伙人」招募 ∶ 寻找非典型分享者 |
TAG标签: |
20 |
|
我们已经准备好了,你呢?
2022我们与您携手共赢,为您的企业营销保驾护航!
|
|
不达标就退款 高性价比建站 免费网站代备案 1对1原创设计服务 7×24小时售后支持 |
|
|
