[{"data":1,"prerenderedAt":82},["ShallowReactive",2],{"content:\u002Farticles:about-renovate":3},{"item":4,"md":17,"html":18,"menu":19,"excerpt":37,"related":38},{"title":5,"len":6,"tags":7,"id":11,"time":12,"modifyTime":13,"showComments":14,"encrypt":15,"customSlug":16},"关于本站的重构 (又双叒叕重构了)",1503,[8,9,10],"前端","vue","杂谈",8500,1741528184917,1759579038298,true,false,"about-renovate",null,"\u003Cp data-marked-line=\"1\">&emsp;&emsp;最近把博客从内到外翻新了一遍，不水一篇文章说不过去\u003Cimg src=\"\u002Fsticker\u002Faru\u002F129.png\" alt=\"sticker\"\u002F>。主要改了三个地方：重新封装了hook逻辑;增加了部分单元测试和e2e测试;从sass迁移到了tailwindcss。\u003C\u002Fp>\n\u003Ch2 data-marked-line=\"2\">\u003Csup class=\"fake-head\" id=\"%E5%B0%81%E8%A3%85hook\">\u003C\u002Fsup>\u003Ca class=\"header-link\" href=\"#%E5%B0%81%E8%A3%85hook\">封装hook\u003C\u002Fa>\u003C\u002Fh2>\u003Cp data-marked-line=\"3\">&emsp;&emsp;众所周知vue一直强调的是简单，不搞react那一套，但自从vue3组合式api出现后，也渐渐变成了react的形状\u003Cimg src=\"\u002Fsticker\u002Faru\u002F23.png\" alt=\"sticker\"\u002F>。三年前写这个博客的时候，组合式逻辑用得比较烂，可读性和健壮性简直就是一坨\u003Cimg src=\"\u002Fsticker\u002Faru\u002F94.png\" alt=\"sticker\"\u002F>。大概是这样，一大堆逻辑揉在一起 ：\u003C\u002Fp>\n\u003Cpre data-marked-line=\"4\" data-lang=\"ts\" data-shiki>\u003Ccode class=\"language-ts\">\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\">export\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\"> const\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1;--shiki-dark:#61AFEF\"> useManageDetail\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#56B6C2\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\"> async\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\"> () \u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\">=>\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5;--shiki-dark:#E5C07B\"> encryptor\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#56B6C2\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1;--shiki-dark:#61AFEF\"> useEncryptor\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5;--shiki-dark:#E5C07B\"> id\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#56B6C2\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1;--shiki-dark:#61AFEF\"> useRoute\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">().\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E5C07B\">params\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">.\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E06C75\">id\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5;--shiki-dark:#E5C07B\"> list\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#56B6C2\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1;--shiki-dark:#61AFEF\"> fetchList\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5;--shiki-dark:#E5C07B\"> decryptedList\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#56B6C2\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E5C07B\"> encryptor\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1;--shiki-dark:#61AFEF\">decrypt\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">(\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E06C75\">list\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5;--shiki-dark:#E5C07B\"> item\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#56B6C2\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E5C07B\"> list\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1;--shiki-dark:#61AFEF\">find\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">(\u003C\u002Fspan>\u003Cspan style=\"color:#E36209;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">i\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\"> =>\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E5C07B\"> i\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">.\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E06C75\">id\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#56B6C2\"> ===\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E06C75\"> id\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5;--shiki-dark:#E5C07B\"> editingItem\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#56B6C2\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1;--shiki-dark:#61AFEF\"> ref\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">(\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1;--shiki-dark:#61AFEF\">deepClone\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">(\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E06C75\">item\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">));\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5;--shiki-dark:#E5C07B\"> decryptedItem\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#56B6C2\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E5C07B\"> encryptor\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1;--shiki-dark:#61AFEF\">decrypt\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">(\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E06C75\">item\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5;--shiki-dark:#E5C07B\"> md\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#56B6C2\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1;--shiki-dark:#61AFEF\"> fetchMarkdown\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">(\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E06C75\">id\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\">    const\u003C\u002Fspan>\u003Cspan style=\"color:#005CC5;--shiki-dark:#E5C07B\"> decryptedMd\u003C\u002Fspan>\u003Cspan style=\"color:#D73A49;--shiki-dark:#56B6C2\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E5C07B\"> encryptor\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">.\u003C\u002Fspan>\u003Cspan style=\"color:#6F42C1;--shiki-dark:#61AFEF\">decrypt\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">(\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#E06C75\">md\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D73A49;--shiki-dark:#C678DD\">    return\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E;--shiki-dark:#E06C75\">        list\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E;--shiki-dark:#E06C75\">        decryptedList\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E;--shiki-dark:#E06C75\">        decryptedItem\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E;--shiki-dark:#E06C75\">        item\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E;--shiki-dark:#E06C75\">        editingItem\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E;--shiki-dark:#E06C75\">        decryptedMd\u003C\u002Fspan>\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">    }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#24292E;--shiki-dark:#ABB2BF\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp data-marked-line=\"26\">&emsp;&emsp;这此重构主要封装了一些更抽象更通用的逻辑，它们有一个特点：只干一件事，输出一定只和输出有关。我这次主要做了一些简单的封装，具体在：\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fyunyuyuan\u002Fnuxt3-blog\u002Ftree\u002Fmaster\u002Futils\u002Fhooks\" target=\"_blank\">hooks\u003C\u002Fa>\u003C\u002Fp>\n\u003Ch2 data-marked-line=\"27\">\u003Csup class=\"fake-head\" id=\"%E5%8D%95%E6%B5%8B\u002Fe2e%E6%B5%8B%E8%AF%95\">\u003C\u002Fsup>\u003Ca class=\"header-link\" href=\"#%E5%8D%95%E6%B5%8B\u002Fe2e%E6%B5%8B%E8%AF%95\">单测\u002Fe2e测试\u003C\u002Fa>\u003C\u002Fh2>\u003Cp data-marked-line=\"28\">&emsp;&emsp;其实重构的目的就是为了写测试，如果不重构，那么实在无从下手写测试\u003Cimg src=\"\u002Fsticker\u002Fyellow-face\u002F30.png\" alt=\"sticker\"\u002F>。这次主要给封装的hooks写了单元测试，另外写了部分管理页面的e2e测试。\u003C\u002Fp>\n\u003Ch4 data-marked-line=\"30\">\u003Csup class=\"fake-head\" id=\"%E7%BB%99hooks%E5%86%99%E5%8D%95%E6%B5%8B\">\u003C\u002Fsup>\u003Ca class=\"header-link\" href=\"#%E7%BB%99hooks%E5%86%99%E5%8D%95%E6%B5%8B\">给hooks写单测\u003C\u002Fa>\u003C\u002Fh4>\u003Cp data-marked-line=\"31\">&emsp;&emsp;我的心得是：怎么从一段很长的逻辑中封装代码？想想提取出来封装的部分能否被单元测试覆盖。和react hooks的区别是，vue中的hooks会使用响应式的ref来承载数据，调用者可能会修改ref.value，所以要更加小心确保数据流向\u002F操作的正确性。\u003C\u002Fp>\n\u003Ch4 data-marked-line=\"32\">\u003Csup class=\"fake-head\" id=\"e2e%E6%B5%8B%E8%AF%95\">\u003C\u002Fsup>\u003Ca class=\"header-link\" href=\"#e2e%E6%B5%8B%E8%AF%95\">e2e测试\u003C\u002Fa>\u003C\u002Fh4>\u003Cp data-marked-line=\"33\">&emsp;&emsp;使用playwright做e2e测试，上手较简单，e2e测试能保障一些基础的逻辑是正常的。\u003C\u002Fp>\n\u003Ch2 data-marked-line=\"34\">\u003Csup class=\"fake-head\" id=\"%E5%A4%96%E8%A7%82%E9%87%8D%E6%9E%84\">\u003C\u002Fsup>\u003Ca class=\"header-link\" href=\"#%E5%A4%96%E8%A7%82%E9%87%8D%E6%9E%84\">外观重构\u003C\u002Fa>\u003C\u002Fh2>\u003Cp data-marked-line=\"35\">&emsp;&emsp;博客的整体外观也都翻新了一遍。之前的外观得益于我狗屎一样的css天赋，太不入眼了。现在正好claude 3.7 sonnet出来了，听说写代码贼厉害，于是让它给我写样式，没想到效果出奇的好。本次重构，几乎所有样式都是3.7 sonnet写的。\n&emsp;&emsp;从sass换成tailwindcss + css-modules后，感觉到代码清净了许多。\u003C\u002Fp>\n",[20,24,27,31,34],{"size":21,"text":22,"url":23},"big","封装hook","%E5%B0%81%E8%A3%85hook",{"size":21,"text":25,"url":26},"单测\u002Fe2e测试","%E5%8D%95%E6%B5%8B\u002Fe2e%E6%B5%8B%E8%AF%95",{"size":28,"text":29,"url":30},"small","给hooks写单测","%E7%BB%99hooks%E5%86%99%E5%8D%95%E6%B5%8B",{"size":28,"text":32,"url":33},"e2e测试","e2e%E6%B5%8B%E8%AF%95",{"size":21,"text":35,"url":36},"外观重构","%E5%A4%96%E8%A7%82%E9%87%8D%E6%9E%84","最近把博客从内到外翻新了一遍，不水一篇文章说不过去 。主要改了三个地方：重新封装了hook逻辑;增加了部分单元测试和e2e测试;从sass迁移到了tailwindcss。 封装hook 众所周知vue一直强调的是简单，不搞react那一套，但自从vue3组合式api出现后，也渐渐变成了react的形…",[39,48,55,63,73],{"item":40,"count":47},{"title":41,"len":42,"tags":43,"id":44,"time":45,"modifyTime":45,"encrypt":15,"showComments":14,"customSlug":46},"vue3用于管理axios异步请求一致性的功能函数",3227,[9,8],9820,1725014139074,"",2,{"item":49,"count":47},{"title":50,"len":51,"tags":52,"id":53,"time":54,"modifyTime":54,"encrypt":15,"showComments":14,"customSlug":46},"Nuxt3创建SSE server以及client的简明教程",1905,[8,9],5449,1720261091923,{"item":56,"count":47},{"title":57,"len":58,"tags":59,"id":60,"time":61,"modifyTime":62,"encrypt":15,"showComments":14,"customSlug":46},"再重写blog，以及新手建站教程",4053,[10,8],6562,1638440183244,1692684771441,{"item":64,"count":72},{"title":65,"len":66,"tags":67,"id":68,"customSlug":69,"time":70,"modifyTime":71,"showComments":14,"encrypt":15},"个人 vide coding 的经历",1156,[10],8485,"vibe-coding",1787219870808,1787408949138,1,{"item":74,"count":72},{"title":75,"len":76,"tags":77,"id":79,"time":80,"modifyTime":81,"showComments":14,"encrypt":15,"customSlug":46},"用React实现跟随鼠标的3D透视效果",863,[8,78],"react",6856,1731479185023,1734350101562,1793351205603]