[{"data":1,"prerenderedAt":1005},["ShallowReactive",2],{"post-thinking/component-encapsulation-1":3},{"id":4,"title":5,"body":6,"date":995,"description":996,"extension":997,"meta":998,"navigation":95,"path":999,"seo":1000,"stem":1001,"tags":1002,"__hash__":1004},"content/thinking/组件封装的思考-上.md","组件封装的思考-上",{"type":7,"value":8,"toc":988},"minimark",[9,13,17,21,24,27,31,34,430,433,446,449,454,457,460,463,721,981,984],[10,11,12],"h2",{"id":12},"组件封装",[14,15,16],"h3",{"id":16},"为什么需要封装组件",[18,19,20],"p",{},"显而易见，封装组件可以用于重用；统一的组件也方便管理与维护",[18,22,23],{},"那么一个页面如果有五个弹窗，功能各异、且与当前页面业务高度耦合，封装成组件后很难被其他页面重用。这时还要不要为了“重用”而把这些弹窗抽离出来？",[18,25,26],{},"对一个业务复杂的页面，把这些块拆成组件几乎是必然的。可见这时封装的目的并不主要是重用，而是为了降低单文件、单页面的复杂度——把一大团逻辑拆解，每块有名字、有边界，读起来和维护起来都更轻松",[14,28,30],{"id":29},"理想化的反面一个看起来完整的组件","“理想化”的反面：一个看起来完整的组件",[18,32,33],{},"这里有一个组件，功能完整、逻辑清晰：展示用户，展示关注按钮，点击则进行关注",[35,36,41],"pre",{"className":37,"code":38,"language":39,"meta":40,"style":40},"language-vue shiki shiki-themes github-light github-dark","\u003Cscript setup lang=\"ts\">\nimport { useUserStore } from '@/store/user'\n\nconst props = defineProps\u003C{\n  user: {\n    id: string\n    name: string\n    avatar: string\n  }\n  showFollow?: boolean\n}>()\n\nconst userStore = useUserStore()\n\nconst isFollowing = computed(() =>\n  userStore.followingIds.includes(props.user.id)\n)\n\nasync function handleFollow() {\n  await userStore.follow(props.user.id)\n}\n\u003C/script>\n\n\u003Ctemplate>\n  \u003Cdiv class=\"user-card\">\n    \u003Cimg :src=\"user.avatar\">\n    \u003Cdiv>{{ user.name }}\u003C/div>\n\n    \u003Cbutton v-if=\"showFollow\" @click=\"handleFollow\">\n      {{ isFollowing ? '已关注' : '关注' }}\n    \u003C/button>\n  \u003C/div>\n\u003C/template>\n","vue","",[42,43,44,74,90,97,116,129,140,150,160,166,178,184,189,205,210,229,241,247,252,267,281,287,297,302,312,331,350,364,369,395,401,411,421],"code",{"__ignoreMap":40},[45,46,49,53,57,61,64,67,71],"span",{"class":47,"line":48},"line",1,[45,50,52],{"class":51},"sVt8B","\u003C",[45,54,56],{"class":55},"s9eBZ","script",[45,58,60],{"class":59},"sScJk"," setup",[45,62,63],{"class":59}," lang",[45,65,66],{"class":51},"=",[45,68,70],{"class":69},"sZZnC","\"ts\"",[45,72,73],{"class":51},">\n",[45,75,77,81,84,87],{"class":47,"line":76},2,[45,78,80],{"class":79},"szBVR","import",[45,82,83],{"class":51}," { useUserStore } ",[45,85,86],{"class":79},"from",[45,88,89],{"class":69}," '@/store/user'\n",[45,91,93],{"class":47,"line":92},3,[45,94,96],{"emptyLinePlaceholder":95},true,"\n",[45,98,100,103,107,110,113],{"class":47,"line":99},4,[45,101,102],{"class":79},"const",[45,104,106],{"class":105},"sj4cs"," props",[45,108,109],{"class":79}," =",[45,111,112],{"class":59}," defineProps",[45,114,115],{"class":51},"\u003C{\n",[45,117,119,123,126],{"class":47,"line":118},5,[45,120,122],{"class":121},"s4XuR","  user",[45,124,125],{"class":79},":",[45,127,128],{"class":51}," {\n",[45,130,132,135,137],{"class":47,"line":131},6,[45,133,134],{"class":121},"    id",[45,136,125],{"class":79},[45,138,139],{"class":105}," string\n",[45,141,143,146,148],{"class":47,"line":142},7,[45,144,145],{"class":121},"    name",[45,147,125],{"class":79},[45,149,139],{"class":105},[45,151,153,156,158],{"class":47,"line":152},8,[45,154,155],{"class":121},"    avatar",[45,157,125],{"class":79},[45,159,139],{"class":105},[45,161,163],{"class":47,"line":162},9,[45,164,165],{"class":51},"  }\n",[45,167,169,172,175],{"class":47,"line":168},10,[45,170,171],{"class":121},"  showFollow",[45,173,174],{"class":79},"?:",[45,176,177],{"class":105}," boolean\n",[45,179,181],{"class":47,"line":180},11,[45,182,183],{"class":51},"}>()\n",[45,185,187],{"class":47,"line":186},12,[45,188,96],{"emptyLinePlaceholder":95},[45,190,192,194,197,199,202],{"class":47,"line":191},13,[45,193,102],{"class":79},[45,195,196],{"class":105}," userStore",[45,198,109],{"class":79},[45,200,201],{"class":59}," useUserStore",[45,203,204],{"class":51},"()\n",[45,206,208],{"class":47,"line":207},14,[45,209,96],{"emptyLinePlaceholder":95},[45,211,213,215,218,220,223,226],{"class":47,"line":212},15,[45,214,102],{"class":79},[45,216,217],{"class":105}," isFollowing",[45,219,109],{"class":79},[45,221,222],{"class":59}," computed",[45,224,225],{"class":51},"(() ",[45,227,228],{"class":79},"=>\n",[45,230,232,235,238],{"class":47,"line":231},16,[45,233,234],{"class":51},"  userStore.followingIds.",[45,236,237],{"class":59},"includes",[45,239,240],{"class":51},"(props.user.id)\n",[45,242,244],{"class":47,"line":243},17,[45,245,246],{"class":51},")\n",[45,248,250],{"class":47,"line":249},18,[45,251,96],{"emptyLinePlaceholder":95},[45,253,255,258,261,264],{"class":47,"line":254},19,[45,256,257],{"class":79},"async",[45,259,260],{"class":79}," function",[45,262,263],{"class":59}," handleFollow",[45,265,266],{"class":51},"() {\n",[45,268,270,273,276,279],{"class":47,"line":269},20,[45,271,272],{"class":79},"  await",[45,274,275],{"class":51}," userStore.",[45,277,278],{"class":59},"follow",[45,280,240],{"class":51},[45,282,284],{"class":47,"line":283},21,[45,285,286],{"class":51},"}\n",[45,288,290,293,295],{"class":47,"line":289},22,[45,291,292],{"class":51},"\u003C/",[45,294,56],{"class":55},[45,296,73],{"class":51},[45,298,300],{"class":47,"line":299},23,[45,301,96],{"emptyLinePlaceholder":95},[45,303,305,307,310],{"class":47,"line":304},24,[45,306,52],{"class":51},[45,308,309],{"class":55},"template",[45,311,73],{"class":51},[45,313,315,318,321,324,326,329],{"class":47,"line":314},25,[45,316,317],{"class":51},"  \u003C",[45,319,320],{"class":55},"div",[45,322,323],{"class":59}," class",[45,325,66],{"class":51},[45,327,328],{"class":69},"\"user-card\"",[45,330,73],{"class":51},[45,332,334,337,340,343,345,348],{"class":47,"line":333},26,[45,335,336],{"class":51},"    \u003C",[45,338,339],{"class":55},"img",[45,341,342],{"class":59}," :src",[45,344,66],{"class":51},[45,346,347],{"class":69},"\"user.avatar\"",[45,349,73],{"class":51},[45,351,353,355,357,360,362],{"class":47,"line":352},27,[45,354,336],{"class":51},[45,356,320],{"class":55},[45,358,359],{"class":51},">{{ user.name }}\u003C/",[45,361,320],{"class":55},[45,363,73],{"class":51},[45,365,367],{"class":47,"line":366},28,[45,368,96],{"emptyLinePlaceholder":95},[45,370,372,374,377,380,382,385,388,390,393],{"class":47,"line":371},29,[45,373,336],{"class":51},[45,375,376],{"class":55},"button",[45,378,379],{"class":59}," v-if",[45,381,66],{"class":51},[45,383,384],{"class":69},"\"showFollow\"",[45,386,387],{"class":59}," @click",[45,389,66],{"class":51},[45,391,392],{"class":69},"\"handleFollow\"",[45,394,73],{"class":51},[45,396,398],{"class":47,"line":397},30,[45,399,400],{"class":51},"      {{ isFollowing ? '已关注' : '关注' }}\n",[45,402,404,407,409],{"class":47,"line":403},31,[45,405,406],{"class":51},"    \u003C/",[45,408,376],{"class":55},[45,410,73],{"class":51},[45,412,414,417,419],{"class":47,"line":413},32,[45,415,416],{"class":51},"  \u003C/",[45,418,320],{"class":55},[45,420,73],{"class":51},[45,422,424,426,428],{"class":47,"line":423},33,[45,425,292],{"class":51},[45,427,309],{"class":55},[45,429,73],{"class":51},[18,431,432],{},"但它并不够好——问题不在组件是否简单易懂，而在边界：父组件从 props 的输入，并不是这个组件的全部“输入”；子组件产生的，也不只是 UI 和事件",[434,435,436,440,443],"ul",{},[437,438,439],"li",{},"输入不够明确。除了父组件传入的 props，它还依赖 useUserStore() 里的 followingIds。若只看 defineProps，无法得知完整输入",[437,441,442],{},"输出不清晰。点击后的结果写进了全局 Store，而不是通过返回值或事件让父组件显式处理。父组件无法通过props推断结果（为什么要推断结果，就好比debugger时，无法仅凭父组件传入的props判断子组件的结果）",[437,444,445],{},"职责不够单一。从 props 看，它只展示 user 与是否显示关注按钮；实际上“是否已关注”和“点击后的关注行为”都依赖 userStore 。如果修改关注的数据来源，子组件内部也需要改动；同时单元测试时也很难脱离 Store",[18,447,448],{},"理想情况下：组件对外主要是“给定 props，产出 UI；需要外界协作时，通过事件交出去”。若一个组件不涉及状态管理，就可以表示为",[18,450,451],{},[42,452,453],{},"{ UI, events } ≈ f(props)",[18,455,456],{},"在组件里使用状态管理，f 就不再只是 props 的函数。封装组件与控制边界，就是方便通过组件的输入输出看出依赖关系。组件就不应该使用状态管理吗，在于我们如何权衡状态管理带来的隐式依赖关系与状态管道能够减轻的复杂度，比如登录状态仍需状态管理",[14,458,459],{"id":459},"理想化的组件",[18,461,462],{},"通过props输入、通过事件输出",[35,464,466],{"className":37,"code":465,"language":39,"meta":40,"style":40},"\u003Cscript setup lang=\"ts\">\nconst props = defineProps\u003C{\n  user: {\n    id: string\n    name: string\n    avatar: string\n  }\n  showFollow?: boolean\n  isFollowing: boolean\n}>()\n\nconst emit = defineEmits\u003C{\n  (e: 'follow'): void\n}>()\n\u003C/script>\n\n\u003Ctemplate>\n  \u003Cdiv class=\"user-card\">\n    \u003Cimg :src=\"props.user.avatar\" :alt=\"props.user.name\">\n    \u003Cdiv>{{ props.user.name }}\u003C/div>\n\n    \u003Cbutton v-if=\"props.showFollow\" @click=\"emit('follow')\">\n      {{ props.isFollowing ? '已关注' : '关注' }}\n    \u003C/button>\n  \u003C/div>\n\u003C/template>\n",[42,467,468,484,496,504,512,520,528,532,540,549,553,557,571,592,596,604,608,616,630,653,666,670,692,697,705,713],{"__ignoreMap":40},[45,469,470,472,474,476,478,480,482],{"class":47,"line":48},[45,471,52],{"class":51},[45,473,56],{"class":55},[45,475,60],{"class":59},[45,477,63],{"class":59},[45,479,66],{"class":51},[45,481,70],{"class":69},[45,483,73],{"class":51},[45,485,486,488,490,492,494],{"class":47,"line":76},[45,487,102],{"class":79},[45,489,106],{"class":105},[45,491,109],{"class":79},[45,493,112],{"class":59},[45,495,115],{"class":51},[45,497,498,500,502],{"class":47,"line":92},[45,499,122],{"class":121},[45,501,125],{"class":79},[45,503,128],{"class":51},[45,505,506,508,510],{"class":47,"line":99},[45,507,134],{"class":121},[45,509,125],{"class":79},[45,511,139],{"class":105},[45,513,514,516,518],{"class":47,"line":118},[45,515,145],{"class":121},[45,517,125],{"class":79},[45,519,139],{"class":105},[45,521,522,524,526],{"class":47,"line":131},[45,523,155],{"class":121},[45,525,125],{"class":79},[45,527,139],{"class":105},[45,529,530],{"class":47,"line":142},[45,531,165],{"class":51},[45,533,534,536,538],{"class":47,"line":152},[45,535,171],{"class":121},[45,537,174],{"class":79},[45,539,177],{"class":105},[45,541,542,545,547],{"class":47,"line":162},[45,543,544],{"class":121},"  isFollowing",[45,546,125],{"class":79},[45,548,177],{"class":105},[45,550,551],{"class":47,"line":168},[45,552,183],{"class":51},[45,554,555],{"class":47,"line":180},[45,556,96],{"emptyLinePlaceholder":95},[45,558,559,561,564,566,569],{"class":47,"line":186},[45,560,102],{"class":79},[45,562,563],{"class":105}," emit",[45,565,109],{"class":79},[45,567,568],{"class":59}," defineEmits",[45,570,115],{"class":51},[45,572,573,576,579,581,584,587,589],{"class":47,"line":191},[45,574,575],{"class":51},"  (",[45,577,578],{"class":121},"e",[45,580,125],{"class":79},[45,582,583],{"class":69}," 'follow'",[45,585,586],{"class":51},")",[45,588,125],{"class":79},[45,590,591],{"class":105}," void\n",[45,593,594],{"class":47,"line":207},[45,595,183],{"class":51},[45,597,598,600,602],{"class":47,"line":212},[45,599,292],{"class":51},[45,601,56],{"class":55},[45,603,73],{"class":51},[45,605,606],{"class":47,"line":231},[45,607,96],{"emptyLinePlaceholder":95},[45,609,610,612,614],{"class":47,"line":243},[45,611,52],{"class":51},[45,613,309],{"class":55},[45,615,73],{"class":51},[45,617,618,620,622,624,626,628],{"class":47,"line":249},[45,619,317],{"class":51},[45,621,320],{"class":55},[45,623,323],{"class":59},[45,625,66],{"class":51},[45,627,328],{"class":69},[45,629,73],{"class":51},[45,631,632,634,636,638,640,643,646,648,651],{"class":47,"line":254},[45,633,336],{"class":51},[45,635,339],{"class":55},[45,637,342],{"class":59},[45,639,66],{"class":51},[45,641,642],{"class":69},"\"props.user.avatar\"",[45,644,645],{"class":59}," :alt",[45,647,66],{"class":51},[45,649,650],{"class":69},"\"props.user.name\"",[45,652,73],{"class":51},[45,654,655,657,659,662,664],{"class":47,"line":269},[45,656,336],{"class":51},[45,658,320],{"class":55},[45,660,661],{"class":51},">{{ props.user.name }}\u003C/",[45,663,320],{"class":55},[45,665,73],{"class":51},[45,667,668],{"class":47,"line":283},[45,669,96],{"emptyLinePlaceholder":95},[45,671,672,674,676,678,680,683,685,687,690],{"class":47,"line":289},[45,673,336],{"class":51},[45,675,376],{"class":55},[45,677,379],{"class":59},[45,679,66],{"class":51},[45,681,682],{"class":69},"\"props.showFollow\"",[45,684,387],{"class":59},[45,686,66],{"class":51},[45,688,689],{"class":69},"\"emit('follow')\"",[45,691,73],{"class":51},[45,693,694],{"class":47,"line":299},[45,695,696],{"class":51},"      {{ props.isFollowing ? '已关注' : '关注' }}\n",[45,698,699,701,703],{"class":47,"line":304},[45,700,406],{"class":51},[45,702,376],{"class":55},[45,704,73],{"class":51},[45,706,707,709,711],{"class":47,"line":314},[45,708,416],{"class":51},[45,710,320],{"class":55},[45,712,73],{"class":51},[45,714,715,717,719],{"class":47,"line":333},[45,716,292],{"class":51},[45,718,309],{"class":55},[45,720,73],{"class":51},[35,722,724],{"className":37,"code":723,"language":39,"meta":40,"style":40},"\u003Cscript setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useUserStore } from '@/store/user'\nimport UserCard from './UserCard.vue'\n\nconst props = defineProps\u003C{\n  user: {\n    id: string\n    name: string\n    avatar: string\n  }\n}>()\n\nconst userStore = useUserStore()\n\nconst isFollowing = computed(() =>\n  userStore.followingIds.includes(props.user.id)\n)\n\nasync function handleFollow() {\n  await userStore.follow(props.user.id)\n}\n\u003C/script>\n\n\u003Ctemplate>\n  \u003CUserCard\n    :user=\"user\"\n    :is-following=\"isFollowing\"\n    show-follow\n    @follow=\"handleFollow\"\n  />\n\u003C/template>\n",[42,725,726,742,754,764,776,780,792,800,808,816,824,828,832,836,848,852,866,874,878,882,892,902,906,914,918,926,933,943,953,958,968,973],{"__ignoreMap":40},[45,727,728,730,732,734,736,738,740],{"class":47,"line":48},[45,729,52],{"class":51},[45,731,56],{"class":55},[45,733,60],{"class":59},[45,735,63],{"class":59},[45,737,66],{"class":51},[45,739,70],{"class":69},[45,741,73],{"class":51},[45,743,744,746,749,751],{"class":47,"line":76},[45,745,80],{"class":79},[45,747,748],{"class":51}," { computed } ",[45,750,86],{"class":79},[45,752,753],{"class":69}," 'vue'\n",[45,755,756,758,760,762],{"class":47,"line":92},[45,757,80],{"class":79},[45,759,83],{"class":51},[45,761,86],{"class":79},[45,763,89],{"class":69},[45,765,766,768,771,773],{"class":47,"line":99},[45,767,80],{"class":79},[45,769,770],{"class":51}," UserCard ",[45,772,86],{"class":79},[45,774,775],{"class":69}," './UserCard.vue'\n",[45,777,778],{"class":47,"line":118},[45,779,96],{"emptyLinePlaceholder":95},[45,781,782,784,786,788,790],{"class":47,"line":131},[45,783,102],{"class":79},[45,785,106],{"class":105},[45,787,109],{"class":79},[45,789,112],{"class":59},[45,791,115],{"class":51},[45,793,794,796,798],{"class":47,"line":142},[45,795,122],{"class":121},[45,797,125],{"class":79},[45,799,128],{"class":51},[45,801,802,804,806],{"class":47,"line":152},[45,803,134],{"class":121},[45,805,125],{"class":79},[45,807,139],{"class":105},[45,809,810,812,814],{"class":47,"line":162},[45,811,145],{"class":121},[45,813,125],{"class":79},[45,815,139],{"class":105},[45,817,818,820,822],{"class":47,"line":168},[45,819,155],{"class":121},[45,821,125],{"class":79},[45,823,139],{"class":105},[45,825,826],{"class":47,"line":180},[45,827,165],{"class":51},[45,829,830],{"class":47,"line":186},[45,831,183],{"class":51},[45,833,834],{"class":47,"line":191},[45,835,96],{"emptyLinePlaceholder":95},[45,837,838,840,842,844,846],{"class":47,"line":207},[45,839,102],{"class":79},[45,841,196],{"class":105},[45,843,109],{"class":79},[45,845,201],{"class":59},[45,847,204],{"class":51},[45,849,850],{"class":47,"line":212},[45,851,96],{"emptyLinePlaceholder":95},[45,853,854,856,858,860,862,864],{"class":47,"line":231},[45,855,102],{"class":79},[45,857,217],{"class":105},[45,859,109],{"class":79},[45,861,222],{"class":59},[45,863,225],{"class":51},[45,865,228],{"class":79},[45,867,868,870,872],{"class":47,"line":243},[45,869,234],{"class":51},[45,871,237],{"class":59},[45,873,240],{"class":51},[45,875,876],{"class":47,"line":249},[45,877,246],{"class":51},[45,879,880],{"class":47,"line":254},[45,881,96],{"emptyLinePlaceholder":95},[45,883,884,886,888,890],{"class":47,"line":269},[45,885,257],{"class":79},[45,887,260],{"class":79},[45,889,263],{"class":59},[45,891,266],{"class":51},[45,893,894,896,898,900],{"class":47,"line":283},[45,895,272],{"class":79},[45,897,275],{"class":51},[45,899,278],{"class":59},[45,901,240],{"class":51},[45,903,904],{"class":47,"line":289},[45,905,286],{"class":51},[45,907,908,910,912],{"class":47,"line":299},[45,909,292],{"class":51},[45,911,56],{"class":55},[45,913,73],{"class":51},[45,915,916],{"class":47,"line":304},[45,917,96],{"emptyLinePlaceholder":95},[45,919,920,922,924],{"class":47,"line":314},[45,921,52],{"class":51},[45,923,309],{"class":55},[45,925,73],{"class":51},[45,927,928,930],{"class":47,"line":333},[45,929,317],{"class":51},[45,931,932],{"class":55},"UserCard\n",[45,934,935,938,940],{"class":47,"line":352},[45,936,937],{"class":59},"    :user",[45,939,66],{"class":51},[45,941,942],{"class":69},"\"user\"\n",[45,944,945,948,950],{"class":47,"line":366},[45,946,947],{"class":59},"    :is-following",[45,949,66],{"class":51},[45,951,952],{"class":69},"\"isFollowing\"\n",[45,954,955],{"class":47,"line":371},[45,956,957],{"class":59},"    show-follow\n",[45,959,960,963,965],{"class":47,"line":397},[45,961,962],{"class":59},"    @follow",[45,964,66],{"class":51},[45,966,967],{"class":69},"\"handleFollow\"\n",[45,969,970],{"class":47,"line":403},[45,971,972],{"class":51},"  />\n",[45,974,975,977,979],{"class":47,"line":413},[45,976,292],{"class":51},[45,978,309],{"class":55},[45,980,73],{"class":51},[18,982,983],{},"使用状态管理可能会让代码量减少，但代码量少并不意味着简单，上面之前的例子中，想要复用或修改功能就需要付出额外的代价",[985,986,987],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":40,"searchDepth":99,"depth":99,"links":989},[990],{"id":12,"depth":76,"text":12,"children":991},[992,993,994],{"id":16,"depth":92,"text":16},{"id":29,"depth":92,"text":30},{"id":459,"depth":92,"text":459},"2026-04-16","一个组件肯定是要降低复杂度，如何封装才能降低复杂度","md",{},"/thinking/component-encapsulation-1",{"title":5,"description":996},"thinking/组件封装的思考-上",[1003],"Encapsulation","EpM8UaHm_fr1vCQ2O1ad292NOX7VP06VAJhK7-Vwy6w",1776757930084]