[{"data":1,"prerenderedAt":182},["ShallowReactive",2],{"content:\u002Fposts\u002F2025\u002Fclean-vue-component":3,"surround:\u002Fposts\u002F2025\u002Fclean-vue-component":170},{"id":4,"title":5,"body":6,"canonical":149,"categories":150,"date":152,"description":153,"draft":154,"extension":155,"image":156,"meta":157,"navigation":158,"path":159,"permalink":149,"readingTime":160,"recommend":149,"references":149,"seo":165,"sitemap":166,"stem":167,"tags":168,"type":149,"updated":152,"__hash__":169},"content\u002Fposts\u002F2025\u002Fclean-vue-component.md","如何写出干净的组件",{"type":7,"value":8,"toc":138},"minimark",[9,13,17,20,26,38,46,49,59,63,69,76,79,85,91,94,98,104,110,113,117,120,123,129,132],[10,11,12],"h2",{"id":12},"全局单例状态",[14,15,16],"p",{},"我们写组件时，有时会遇到需要将数据通过 props 层层向下传递，或者是 emit 通过事件层层向上传递的情况。或者会遇到同级组件之间需要共享一些数据。",[14,18,19],{},"为了避免这种情况，我们可以使用全局单例状态来管理数据。",[21,22,23],"blockquote",{},[14,24,25],{},"当然在 Vue3 中，我们可以使用 Pinia 来进行此操作。",[27,28,35],"pre",{"className":29,"code":31,"filename":32,"language":33,"meta":34},[30],"language-ts","import { ref, toRefs } from 'vue'\n\nconst globalState = ref({\n    darkMode: false,\n    sidebarCollapsed: false,\n    theme: 'green',\n})\n\nexport default () => {\n    \u002F\u002F 一些逻辑处理\n\n    return {\n        ...toRefs(globalState)\n    }\n}\n","useSettings.ts","ts","",[36,37,31],"code",{"__ignoreMap":34},[27,39,44],{"className":40,"code":42,"language":43,"meta":34},[41],"language-vue","\u003Cscript setup lang=\"ts\">\nimport useSettings from '@\u002Fcomposables\u002FuseSettings'\n\nconst { darkMode, sidebarCollapsed, theme } = useSettings()\nfunction toggleDarkMode() {\n    darkMode.value = !darkMode.value\n}\n\u003C\u002Fscript>\n","vue",[36,45,42],{"__ignoreMap":34},[10,47,48],{"id":48},"传递整个对象",[50,51,52,56],"ol",{},[53,54,55],"li",{},"将整个数据对象作为 prop 传递，而不是逐个字段传递。我们经常会遇到添加一些字段到组件中，这样会导致 props 的数量不断增加。\n为了避免这种情况，我们可以将整个对象传递给组件。",[53,57,58],{},"这样我们可以复用 TypeScript 的类型定义到组件中。",[60,61,62],"h4",{"id":62},"之前",[27,64,67],{"className":65,"code":66,"language":43,"meta":34},[41],"\u003Ctemplate>\n    \u003CArticle\n        :title=\"article.title\"\n        :content=\"article.content\"\n    \u002F>\n\u003C\u002Ftemplate>\n",[36,68,66],{"__ignoreMap":34},[27,70,74],{"className":71,"code":72,"filename":73,"language":43,"meta":34},[41],"\u003Cscript setup lang=\"ts\">\nimport { IArticle } from '@\u002Ftypes\u002Farticle'\n\nconst props = defineProps\u003C{\n    title: IArticle['title']\n    content: IArticle['content']\n}>()\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n\u003C!-- 内部实现 -->\n\u003C\u002Ftemplate>\n","Article.vue",[36,75,72],{"__ignoreMap":34},[60,77,78],{"id":78},"之后",[27,80,83],{"className":81,"code":82,"language":43,"meta":34},[41],"\u003Ctemplate>\n    \u003CArticle :article=\"article\" \u002F>\n\u003C\u002Ftemplate>\n",[36,84,82],{"__ignoreMap":34},[27,86,89],{"className":87,"code":88,"filename":73,"language":43,"meta":34},[41],"\u003Cscript setup lang=\"ts\">\nimport { IArticle } from '@\u002Ftypes\u002Farticle'\n\nconst props = defineProps\u003C{\n    article: IArticle\n}>()\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n\u003C!-- 内部实现 -->\n\u003C\u002Ftemplate>\n",[36,90,88],{"__ignoreMap":34},[14,92,93],{},"如果此时我们的 article 要增加一个创建日期的字段，旧的写法需要修改 Article.vue 的 props 定义，而新的写法只需要修改 Article.vue 的展示逻辑即可（因为我们的类型是全局复用的）。",[10,95,97],{"id":96},"使用不同的组件处理-v-if-分支","使用不同的组件处理 v-if 分支",[27,99,102],{"className":100,"code":101,"language":43,"meta":34},[41],"\u003Ctemplate>\n    \u003Cdiv v-if=\"showSomething\">\n        \u003Cdiv>一些代码，很长很长\u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n    \u003Cdiv v-else>\n        \u003Cdiv>另一些代码，很长很长\u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[36,103,101],{"__ignoreMap":34},[27,105,108],{"className":106,"code":107,"language":43,"meta":34},[41],"\u003Ctemplate>\n    \u003Cdiv v-if=\"showSomething\">\n        \u003CComponentA \u002F>\n    \u003C\u002Fdiv>\n    \u003Cdiv v-else>\n        \u003CComponentB \u002F>\n    \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[36,109,107],{"__ignoreMap":34},[14,111,112],{},"每一个分支都会做不同的事，所以将他们拆分成不同的组件是更好的选择。\n这样不仅会使每个组件专注于特定的任务，还可以提高代码的可读性和可维护性。",[10,114,116],{"id":115},"将使用-v-for-的组件提取成-list-组件单独维护","将使用 v-for 的组件提取成 List 组件单独维护",[14,118,119],{},"有时候我们并不关心组件的循环的细节，我们可以将它提取成一个 List 组件来单独维护。",[14,121,122],{},"Before",[27,124,127],{"className":125,"code":126,"language":43,"meta":34},[41],"\u003Ctemplate>\n    \u003CArticle v-for=\"article in articles\" :key=\"article.id\" :article=\"article\" \u002F>\n\u003C\u002Ftemplate>\n",[36,128,126],{"__ignoreMap":34},[14,130,131],{},"After",[27,133,136],{"className":134,"code":135,"language":43,"meta":34},[41],"\u003Ctemplate>\n    \u003CArticleList :articles=\"articles\" \u002F>\n\u003C\u002Ftemplate>\n",[36,137,135],{"__ignoreMap":34},{"title":34,"searchDepth":139,"depth":139,"links":140},4,[141,143,147,148],{"id":12,"depth":142,"text":12},2,{"id":48,"depth":142,"text":48,"children":144},[145,146],{"id":62,"depth":139,"text":62},{"id":78,"depth":139,"text":78},{"id":96,"depth":142,"text":97},{"id":115,"depth":142,"text":116},null,[151],"代码","2025-07-10 17:10:24","本文讲述一部分使用 Vue 的小技巧，帮助你写出更干净的组件。",false,"md","https:\u002F\u002Fbitmc.uno\u002Fpicgo\u002Fclean-vue-component.png",{},true,"\u002Fposts\u002F2025\u002Fclean-vue-component",{"text":161,"minutes":162,"time":163,"words":164},"3 min read",2.87,172200,574,{"title":5,"description":153},{"loc":159},"posts\u002F2025\u002Fclean-vue-component",[],"qTS0OzD4gyBytfnJfASk_9QiCuvY9V3HCMbEJw-_4Qo",[171,176],{"title":172,"path":173,"stem":174,"date":175,"type":149,"children":-1},"为什么升级至 Nuxt Content v3?","\u002Fposts\u002F2025\u002Fwhy-migrate-to-nuxt-content-v3","posts\u002F2025\u002Fwhy-migrate-to-nuxt-content-v3","2025-06-18 11:19:28",{"title":177,"path":178,"stem":179,"date":180,"type":181,"children":-1},"乙巳年六月廿四","\u002Fposts\u002F2025\u002F0718-life","posts\u002F2025\u002F0718-life","2025-07-18 17:21:11","story",1789642589169]