Capz*@SbxXMXhns49uzB?4K&WU!+-9AzSL3Nvu^*W!8c5S0TIH_O7>&+(GwMu0bmy$hG_{wslhav#0&R+26R+tFk>0^PFPyxW6o;
ztL2;?QSYCzoY+U`38b^u$wHO)H4Fa8gYG89SkttK^_yPao^o@ji3)E6>2b&@K#8`v
zLGb-~R0^lCxuRgD))iIf9{lb42l50`y@sXcN9~wAmMD1=rIKc>x9h*44V`m+#u`c!
z{!i44fsGz+dV_N{qxddg&7~g>N8>eAV`ka_a{c2DKn?Z=-i>)b`q51LQy!OJFj(>Z
z9ndIUyo!bPw+4my(|*OxP*ZElhQg#O5i6TqGB@*dd~`ppdVJ;M@^|Rph^CnZ9FUY^
zQsa8_bb^9cJeE;VRW@+FdM^Q2JtdNoZ7k{Kj
z9Fv}_IJBCiiomTt(SAla$k3v_2OoDRAg{`B;!6lCc0pSVn`pqFz54TUI)421Wt>~w
zua*Y(+&Y^awEas7wx${vX_9}D`9ek1>N&h!J=Z(`p5%r(LlN7lIo6CED-#!rFE%Qo
z*ljM+e^9el&Du1S7<>AkEop-KwI>VDy#1(VmYbCDQysnPt(QccMyJ`NglbKMVsMW&
z#vzE@&dwF}=*+68*2hJ`%SSEwPJ6zQ*kT5S*TRP67c(AX4NrS_74CXvg*kF^vVg3c
zrPVb=tHSEpoxbp%Kl#GE&+o~DxF|moU*+^flPp#Ud-QFIMrfz8+mW)2i>Ji
zExt@23-M#VSbU(KCy*dO*BVjt(+SrQ5u|Zp4zqJfxa?0JOo^#^M19ezF$FdyAN*P&
z{FgOsG3Z{x3W+H7q*G5tizuBcy;P*Bfk||1Uy{e(Ag?qxt|eC_jw2244?A0n^k_w(
zrSms~y{%Z9b8;R^p5yr%N&-vsLWDnqCx$q4gyPc~B}3R2s)2`2iUVWmSCF&!@T|`-
zFs+~GUf@SSZ&Ngv-Cv=Mhw^Z~;Ss%Cqj_zJIQ1y$^pyRjthD-arLG`=IXr6n%N(=<
zKkqEp_@%OXcnH*=`LN8`Q>VVVsFu%$sKKBA#?-ApTG=+in{7V0g3UJ+!-%j>=-Kbu4sb*!`V>sFB(h9
zk^F&i#X+BQez|ev{_w7w!IyBm9BM+s_x7${!bxNoFeY{un#9<3XT}TNe;-vi_3L1)
z6&ULI!Eoy8R12Li-e!Q6Uftl6;8Hh#Kp6VoCsO@_X
zWWjSB7*=H-Ld)R*C_&z?sBmZuzsl(E-m^#%j6%q$V=nsxxXyPuVq&A`)
zWKp3s36XB=OPW*AWXSN#@?P;u45&B_00)`pNXe7g6k+RH|`FzBbIq;
zSUOP+n{!2rh--T*ohP(9KYXygqKPR+2|-@y$ss=p6?q-)v#5bF)ikY>_MLNS9qKC>C2nsMUyS<#Xa43^sCH^~
z`0YVx%027v9_#Z&V?=GbF;l=*_Gro-kmK)1q;J52K5=f^i@$ztbgg6d$)o3b(&xk5
zQa^o7k|H~nRPzINio?iL3)Fu%vF5n&L>1=4O-WM2G
zDMJ0%ie`DNuRdE`Gb}aQhjuvV>)DnNI0%0-o(h;Nb2ft#>!z*mAQjZ%5`qlb;|UHM
z8kn{RH*&%_FJ&Jo=5#Th7eK8PWX(7F!QdBGq@!KeCpH*`r_yiDe-p=T{>Eb{3KwYP
za)j1O+-;C)woTTQZ|d|UX5P$DxW}O7Ep~?H<%#*jVQ($h>rgoFfpXxigl&k+WPjUn
z;|TzE_JFyz6(t^Y`yfYf(!cl*V^5(ZFP=XF?Ww7`5h<=Fzq77$r@^0iIhun}3w
zS~kkz?hvidq2V-KZm9YQzMEN5ISD5PzVb@_(#wCBeiUYx;VBiB2cp=qaXO73bLNXWTR)q5
z@OWDYc#`Q)t@qvhlZxL^Dtzc}H~p5|TGCVee1FmfSkSzO)@ftMlrN-|7$Ms0A)f<&
z&BPiuq0lT(LsU-#%iTGrrlO#wI-x?fzSrJw5NMAa-gujgsecRg+_Q9cwn}e~Rj;iC;ed_|ZBTgOXJ&Q_7Tr}x63*L0BK4AiqNbj<^WOtDr>}+u^5*#m(%mkm=sOfHA
zNOl4u;Q5Z$E;Rn9;2j$foVb|zQirH5Ntt{@?l7jKq5^KE<&&Rt84>QPe1@tg@9x~w
z`pu$_vb}R+v#&Puifg8y%K@~db5Ag4;}>%w?;ZagReKs;xxOd>QgV)eQSeGP^N7(#
z@?x9W+GPWo2$S@*asAA7sxbKK7Tgu5j>~ai)}=D|fC)J5E(>(m?SQ6|@Qw4ppCy?q
z*SV6{6}06bs`nl*+Y#Z6u`sEG$FKm8g#J!E`8ue5XRp==n5Dsk*DDvt2t$|Z?;0Ee
z&PoP<5E@*iwl@F_x%p++UrAcsLdE^g-xx_6F)10Huh@fvpop>mkDyv?Rd3tM@@jWG5au|^_f@x{Gg%?b;HQ!3nd^imG#M5a`PRpQF9{+-d_iGWM#u8
zH-AJdy#vrr4O7W~^Ih$Vl=gS#33JmxhMbL{?JN_UH+KQaJoN9I_+Lc%?aGYM!_efu
z6>^*Td0oB+geQBc{?k$Uw@w=m*#t&>&@l?{zGcb#0zQ8Kx
zi`<&V2S6Y9=sP=dWnTp5F>kJ=vCc=gwK^s2-%SGV)Z=1&&kS>28WM{oR3OMP3e1(}
zcoPYMSjTp23l@cNp29)^nwFym056zHt9xS(gT1oBZZ;vH(K;Pjf?Lh!hX@kCYxH^g
zjqUqxQ6(V`$TE9->A6UwY!T3$aSg48fB^|BuzQGhsTQ$y(+jdC{>K2~KeuYU!`gLd
zsZaMla*n-KX_)Qx
zk6mMdja)TX0J?+y#CF|qcJpJ7<$TfzOJP9no&FJi-Pt^!8FZK5^Dvi=Yqvi6J1fa`
z{5;`RVtQJ{LI_0!jGYQy^0?r2t2LeRjkS|(H0@nSB^QA2jV3WU2)^zt;$*GU3xBaz
z#e*KrZ!y|(q|$2(ALS3@81~kFX|TDx2z-k~cj~=-H|+;`%!m2sHS{(g1IKtL%%sah
z{zJLhWw{A$B50gnXBLIu*BozeQv`M!Au}M~JDdkUHm6n;G|jw=QaA0ARBd3s$Hvmp
zvYdM8%}|&{mbN!mv_Ey$q#XQ~*b4IOLx`8@I{4J3w2fRiemsFA60ezlFumQzoG*X=
zayFU(angRU%e}w+A@M+`c4YM>45ISW!u2X2;A_Z;IR=66V#-UZAgcI>hXezM7F2;iqPQn8f=``Om6ss3o1x14X`DVs)mhZos9)
z*^&~YLCGG6taF^U7F6zY{_S^WxcHnjfGpv5LjC!&_KDgxpJDDez&@0M@D{U*{Ct0A
z?o5L_PjYVl%4!{n+`2FeX=!6ewf-585w#lDE+KGI=YeGlTjh>bohYGR=cFUZ7lY6n
zFV?3DTB*+1mtCQ-$?DP4V&YkC9-yjaKfe+EA^G#w19BG!|M;M=u^y?ObzXV_zU=pUh?qYZcI~nqRfU2Y
z`Zf53dGwC?UOnQ-LQ2d+RiSiK-J3zOTg@{2kaP=J9HeU%cFvQ70#(9|PowxJ!Nj5)
zA@LQRzg-45rik%Jkl&X4KpqQ1a%EG;n)f-O@=GJ0SI9`H_MfNjSA{4y*W0rUN9UJJ
zH5Op#qsNc?_nt&4#!)x-Tu*r**7iwAx?)y+YIlFiO1Xo#5T)8r%}0wgC2SrOkn@)b
z94`ZyK!gEivp{potfG=?NPZCV{_W!BoA82q05PKDrh@<2W45S($Rg+KF0+t%MIrTI
zC=++MSR?Z#-*9aetT&~&3;P_*aF)i%o
zXI(V)Y-xL7o`XlG>am5BTuPpTlOYAH$PX_V&>>GV9rm~$4zE`ZPv!bK4Po;DqfNrE
zU;g0SfSe#5mnUvULBQbwxBpn%Z=CJ5|L@^}cc-m;PC1Mu`}{wMKRRwP`E2a#vIvn^
z86yQ+t56
z=FXwr`KP;fCjZ)q6Gh}aq<Jd!`TO6`J(
zhC7rDeYOPCT(v`oYI%bANFO4A6RU;s5%6TwNV#nm_QCKl2rCShuE&%1nsmM!UGfJn
zkK#A0{|rU8|H57mjTtkF{ZEC^OBd4J30Fadj&NgaC7?6^Ab2byzKr|Uw@;cQ1p^hC
zIvxGPI}AY{G2Vco1(R~#ZWQkwU#v9B1T5tW83bh`FkIeSsPhBw8>jnXP28R0(q6kx
zm$y_N^3DMz#SCMQE`O-*O5P*u6RFrQau)nwfWD_56o{P^ncubXA@6)I#7@GhBSgkH
zpWpZA0kU1Z!j!_a?0tJk_$8DVJ{{
z>D!=Q1d!pQU_%Hnx${R>K}3?tY0F7FR*~UL9cu7hP;xw{gqz}3!O1H!sTVleNpJG|
zs^L7EmauUqhjSyFVzO45a-Pii)Ss)UI-KMpwSRww%u&>p#_*)UmR*L>0Z@zOq~H37
zQ_Dh#ixmPSI2k@2bFcSokF=)}B-WiN3Pq46oP!F4APL)$TbAzw>B+O%{I6j6ACUFt
zYvkL;7Dw40s&wlvTAX3W%XHKX#|o4KNou7PeTRiD5)6)0-Kj{U$;7TK73&mm7{
z_~*h2$+BUQmN%<_7Y5hOhw<6nw5K_+LBu_QKyve%P0=BgC%$(Wo|R?eFjO?4$P$
zlM($Mb$wU!+WUg0V`{o<{3Y}Ks7$f!QGZ5pA63<6aQ`?b^N*O5MLR0Bt87di{l~c}
zARwC!ty2Ls2u3%|KI7IY2!+=oKLft1-TKnFh*y^lFGT>9lC$H~cBbR_XOvs&fV$GS
zKyW19MQN-!zF{HBcW!P>sC1-W
zgp2I2xa52Q{8L9|{M&8mXsax|rHB-mwjeO71|QC6!-%b+)mKECbkdqg(4ZU*j96?G
zrTk58plcsq14WxUi^
zPqzoD^&}p4zc(Gz6&hMsA#-oM(%}VJ37!wA*(fo3p0?S9%9ngP^+Ddw4MaUkCj?0)
zOHx}=W%*8fkkaOWuqC@?&$V|6%n;7%R4UVJxenS=8kNgXoUi%j`Z3-VXPklX{
z?vBqw0s0X0vfjnBiin__!~sI%S!Q(2e-aP7=xm1`SOFD!KuY?t&>u#D7syfjW}9>1
zPmqRc^HM5}S^jffCQ7~iWzG7!DK(2`l2>PuMEs=Qtc*a`7d=K-Jm8b!zL}jzP(sr8FA=
zs6P9snk0{X=nmP}v8+BNdYbZ3ZD(oV8LJe-3GXO)L%~SXmA^o>-O$A~HCFp2d7?C>
zUmf{8)S2zzIbe)5Cd$oW!Q*d;%fKU55wDNxl;I+289NU~Zkc)i)}p_OAqsy87Fzm(
z=r8H7o_cShs10%Y>O3_8G4`iiHzYpk|JwdS>v+#66@6C8gy!hTj~gl7Ip8!_YzWty
zCYMyBFB|kFhU5DlStr&UeYR^zKC!Ru=poMU0BZd>{NLGIgLo{DA70y_$Em
z2E~EfAA2xgLMUIB)YxW1M(m9qryyyWV{CD9sKVTc?!
z1ksv%WCGX{EE`b3#AqkCnu@>qkqgQ
zH%NTr2`&{dmWC=>3+aDx!0S_Xe%&mI;q=E`lV!<3g7JH1p|!*vZ?^?*^~od4fmpIr
zn{$$Aa1^7xIJWnTh@{edKruW?a!f8e=Iy-a%%zpilp^wtAG)6706m4y>cCK&_Qm9zr<)yFK=0_M672)TZujRI=0;-
zaih{2^OoE#Zj|joBzq<-;4vm&;3`bW)j
z9J6DFH@l>BojF13h*y*BTyg#A5lMb^eX!6xug^JZHu~PY%<;l5Wz_WJ63ODxqZbX!
zUB5j9f3sEk`f}pFM~o6*9=_h6t%+xg{#tfZeHJUEuq!-yEc_MQYtsPo{_Pm3C?*{i
zu=xRT3DN`qym3Cq0hbipn>-`0T;KFp5a(7{b==JK*+Sc9QsQS(LBQie2?4=JKuF_S
z%C>RZjVt|vzdWk%agTN#GoBkmfmtH2n7+KwhEi0J5GWcWjy{YL`|hk3v*-WSUW0y^
z>R?MYH$>isJGY{S8simKmsiB2u`3Jj7>X7c>Y&|*{XLE7r!u?#dT?HlbaPx$;^c
zAwS=&@2pFH%So-Is>85ZBw>&A`eN%+8%@N7=9%=K7&w-ZoKUrVU$Lme8e)JOwlH|`%n9`F#2Hz>
z4xyBCx$p1ABJrE|MkS@Lko%<%f~~AUVo%&cw3$CYZdQlRr#b+AjT9X6u>;PI2dw}%
zz{ul2f|c1+^{XV_{jY&X|AXusjI1E&1xQWR40K}(3m669@)vPimZO&B$gVpJZnbB8
zy-T^iLex7R9rN5p%sg9|I+Ev>hS{j~;9f;kt~g
z5fZ@UR$&ON_+*w14@4ln7?AYX@h2h-ZiHw=%t7MbrAEQ
zgnVho
zYk-igZ)RlksG=D9*Yg7);g#w3c$fU!)yHT=mdsUc-x7f#I5(@fTrJ
zU9~N21=&buHhMTwuCIp?|C@!jWRBkksLYgM!|aNbwb#U#xQ+|GuDQ_y7^@X5ew2!p
z)wEtgn~0=k{b~V9HJq`}KSWUTuu4eBZBWgvtD*u`4!CD8JF%ri>m-&9E(==uNzT)u
z7DR&UvHzb3*~fqkd|moqsFCfXB
zyZ$GrqY+8JM{HbiNnury;0557Uzi2CWg*tg(4bZwYnRz-Ebw3mVmw$ZrJvLL;jv5U
z4~m_w=ET6ULn7(|z!^oB1X$nvy8qsq1fy)4{i_y;(lb(i_wOx>``*xE@Mdb#YRv)u
zXNP$#*E*ziW{Wuthw|TtSmCVVd|Y&fOZ@_2RpsLwRC7!g#Sr-zs$R-k_J$}mr$Q4P
z&kemeYlN`v@pwIU)lM;<-c&yKh&a&8>E$5=Zb#RD1~_j$yKoe}3OmP@vlR;uroLA6
zqyv!`q|BWPBSD9N=U@Is4FuFv9b=Cmr<)IbG?OHm>jsZ-(Y+*fDE^h=T<|4&yJP0Y
zcL@h;WQGwz{dUUv$#M&t_sHItEsP*V7_F^BcjfFjgi(35Mv(|;i7#+iM?~(rYf$^0
zgu`X&Pk*RA0<;^KrX4e~GLikO#~l)7y6syd(u*P>6f}JpWle$VR77W
z`lOr&^2%C+leLtr)N1fISX=O9LBlN18DH(qgl7nT+eTpP`RkjVX_!`vFxlvsT|uRW
zr2ObynnT&gmtb-0fV-F}8sM&=K6N#7==tNDZBbgKWo<37bB|Q
zn?KY#FQ;NTpA=s;8AB)0%oP5p{#(mN7W}U^&O559YzyOvg(_tLgGd|oS%x;kfC&g;
zKoJB%MMjYliZlrdgd#`)1w=$ZhmjHp&7p=O2oZv`#Da7|2rYpaAwnodq=c4t5**)~
zS@Z8*cV*pkbI(3|fBUz;^JkZMSPO`1>X)K>W45}*KM{dl!7oFqnI@-X%lc`5uvL#`
zPn@D7IVk9PbV@Pnjc05DGQ2}0$)+5xcRhM3V;^G{zq?rB1KtZB(o~!@Jo_-EkbNgz
z#jj!5r(cOw=l59u`0AVKW%4Q^O0zIXd}N66DoDh}%}ZTM66VUS5~yu6h9emJ*DXzs
z21ZinZd`Cl>>mtgxLbRRiem8P!}9G8)qgSZ9WT?C*q{1p)vq%{
z$`%Sg1q1My>9T!MAaIiyKJ#^!xWH}^Usw9&0@Q&YC?^2?_$otb4s#2>NoDoKcC_rG
zRSV`VHC&K9;Z=^MxC-VjD)f~GGOCwtflxZ?;a`p1_<}M|fIG1Rkb7&E;!;PxNYHm_
zbzK@UdS#!In8AF!dM`smj_y<$Q7{)2g2SdF4p*-duPsi6rKb}#R8W^E@w=OK;%zo0
zCKd`fFlj(qC;JY|4T?O29Hcu5rEfc7Dccv=CX}Z?<@d(rkb+6Qe4XN={}~UWPiqqSh7*@yX2QU
zui78B^!(1q?==3#$cvcr82LZLYEj65MLgigA)1`L4^f3^q#9~Vlmn{-xjk;hp?CdW
z+Bpm_WbqnI)V=z*^$N+!U_O#nQ2Y6xvUff0y;o|XL5f;;Ro&b9ZgQuRN|TA(-TQUQ
z|JRrJOTTy2DR(c@DE%$FD>c1%?RQN^_|3-p%8kk-OC_;hUE!kr{^bQtsJ0yfF4%z`
z$4a;=x$>$M|Nm6-x86V{H_$#h^iU?{l_s41wfL4r`-bjyg!sn6eTn_oQm?@%h3plt
zHJRjnf$xZaVJ8}pfj9KkvX!PHwUeQ-J(x1OS*wjiDif77$KLHWBS<=F;6
zDKlNg-X6;*qI;;=z9c=`dz?n%ci`n;?uQ<
zZ|La;KGmJFhnQ8{78w;Wz=G=I4leSN!)zJbT~0Dg-8DSdoGLKd^-)d$jmmU>m?ich
zIZ*Ax^bHv_laM5fTZf$=Gx&P`m*r>99zB|(u(RJY);zgaTjlDzb(dcAc~PSlEhfP1jlEs
zod)`1G9Q8O`)sY{{>*_N`(ye9;F{S&%dj%|0o?07?w0AE39%d8Q2l=XJPnvt1eCs&
z|MkJX$}qgVQ)YH@qST01O)wQP{p6|QrwW1;~{W1%r9o2%SB7zo>
zJe=EQ*XmY9p{%schAKo(Uba+lDM4*I6v&KH5|&S#i5)YBqKBZ!%&XtB{=ZeSntyhChBg&fLlC^1}#RZD3!1;gie
z)?5hU6{_7~5q@MLtmbjXlNV>Tvx68FXWn%`@!E(($KA^;;%5Jz7AF`x5PbFpvQEA$
znNr4xDDhm+y60X{2SJ`r!<{s<8Mg-kdcbTHR#xY`>cOEgLH1uND}Ezzy>2^w0qa+c
z&PAO&sUFFb>TA%aHYFcO{poup^s}|R0b@`v*E}YN?bED&{Pz2;m;mUCf$b1YH6`5z
z`nPfGNs`yCp@U&v&YUY13*!;&IkN<~`5V%RA}9*N8qL)!H9oM*01eYhDF9``1*n=s
z!*YSh0chkBh^I!m&))8`S(g94&wdWju^{3^(#1=7T~Hu(^HE?s?~j|IW@i+Q1!qCi
zH*|UTO~q`H1h{|j=!{}RHNwmaA(F+`eQ~d~4oL07s~Z>$!U_^=Exx(#12Od#^Z`|?
zO?3CSW7vpGaxq+#16H46wtI&szSxAQdzMQQr@X?;AlN3xNqW-g(JAj2q!T!&pY}sQ
z|KKB^BZpQ6PXv_*Ze{v<`1PTQLusLXJ#i`8k-Vn_+(d;DR%&9VRXoUe)Ay`~h?`V+{emX;B
z%9T4}dqcP|wrbLehWwjPQKJNCglOgXh8__v?EMgBtfujN{)wA@!{U|s
zAy=f(Z2fbKys}~AS*}xshav4N5Z)*3b3flKdP+~SR?^bI4b65*mXLm1B#7|*I)WYb
zGB+pLEA@$48=Nb&21xzsCevImAg6QuxnljynqLMBUAWnB<{8MQ13@CN_qRCL#c2N(
zpI$hjoXNODs||NNZ2YE#9On;x#Yw7AAObJIZi4vg;+2b&RJJj28T3AjDD}w}A&WrS
z`fK;H#_+3YDQJ##ZWY!)gv%P~>>_!IU47+X06BP
z5d``+qTMFbkm(-XO4k$$92eXs2Of2*3Rxfdc`1cb;Hp3-bkY?FJj*Z@3zC;ip0Y&G
z3wg&G)Xl>+g2FP=GZ&f-b35(OswxV{%d_VP^U(#X_+^kOHq#L#OJQ8jrI%aps@CLt
zyy6J0&p;_fb5R%Pos}joMWt(MF}l}v&8Pb{w3-q}L(I3!30K65
zh1e;~_e|^oPi;%%cID;4d7KkDAm%eu>F)CbxA#3oy%6H_(6y~26TZMKErlFeC<#0{
zIXHd=K8Dffngg{e=xkv7hQ_BPm>pvZIR0_Ioz>x&o#zHRe$6CT(X3e*i%B0?9B;G8
zgag})hE~n)@-5S!(*i^ 现如今的开发,比如是内部使用的管理平台这种项目大都时间比较仓仓促。实际上来说在使用了webpack + vue 这一套来开发的话已经大大了提高了效率。但是对于我们的开发层面。还是有很多地方可以再次提高我们的项目开发效率,让我们更加专注于业务。毕竟时间就是生命,下面我们挨个来探讨。
+
+## 巧用Webpack
+`Webpack`是实现我们恰前端项目工程化的基础,但其实她的用处远不仅仅如此,我们可以通过`Webpack`来帮我们做一些自动化的事情。首先我们要了解`require.context()`这个API
+
+### `require.context()`
+> 您可以使用[require.context()](https://webpack.js.org/guides/dependency-management/#require-context)函数创建自己的上下文。 它允许您传入一个目录进行搜索,一个标志指示是否应该搜索子目录,还有一个正则表达式来匹配文件。
+
+其实是`Webpack`通过解析 `require()` 的调用,提取出来如下这些信息:
+```bash
+Directory: ./template
+Regular expression: /^.*\.ejs$/
+```
+然后来创建我们自己的上下文,什么意思呢,就是`我们可以通过这个方法筛选出来我们需要的文件并且读取`
+
+下面我们来简单看一看使用:
+```js
+/**
+* @param directory 要搜索的文件夹目录不能是变量,否则在编译阶段无法定位目录
+* @param useSubdirectories 是否搜索子目录
+* @param regExp 匹配文件的正则表达式
+* @return function 返回一个具有 resolve, keys, id 三个属性的方法
+ resolve() 它返回请求被解析后得到的模块 id
+ keys() 它返回一个数组,由所有符合上下文模块处理的请求组成。
+ id 是上下文模块里面所包含的模块 id. 它可能在你使用 module.hot.accept 的时候被用到
+*/
+require.context('demo', useSubdirectories = false, regExp = /\.js$/)
+// (创建了)一个包含了 demo 文件夹(不包含子目录)下面的、所有文件名以 `js` 结尾的、能被 require 请求到的文件的上下文。
+```
+不要困惑,接下来我们来探讨在项目中怎么用。
+### 组织路由
+对于`Vue`中的路由,大家都很熟悉,类似于声明式的配置文件,其实已经很简洁了。现在我们来让他更简洁
+
+1. 分割路由
+
+ 首先为了方便我们管理,我们把`router`目录下的文件分割为以下结构
+ ```js
+ router // 路由文件夹
+ |__index.js // 路由组织器:用来初始化路由等等
+ |__common.js // 通用路由:声明通用路由
+ |__modules // 业务逻辑模块:所以的业务逻辑模块
+ |__index.js // 自动化处理文件:自动引入路由的核心文件
+ |__home.js // 业务模块home:业务模块
+ |__a.js // 业务模块a
+
+ ```
+2. `modules`文件夹中处理业务模块
+
+ `modules`文件夹中存放着我们所有的业务逻辑模块,至于业务逻辑模块怎么分,我相信大家自然有自己的一套标准。我们通过上面提到的`require.context()`接下来编写自动化的核心部分`index.js`。
+ ```js
+ const files = require.context('.', true, /\.js$/)
+
+ console.log(files.keys()) // ["./home.js"] 返回一个数组
+ let configRouters = []
+ /**
+ * inject routers
+ */
+ files.keys().forEach(key => {
+ if (key === './index.js') return
+ configRouters = configRouters.concat(files(key).default) // 读取出文件中的default模块
+ })
+ export default configRouters // 抛出一个Vue-router期待的结构的数组
+ ```
+ 自动化部分写完了,那业务组件部分怎么写? 这就更简单了
+ ```js
+ import Frame from '@/views/frame/Frame'
+ import Home from '@/views/index/index'
+ export default [
+ // 首页
+ {
+ path: '/index',
+ name: '首页',
+ redirect: '/index',
+ component: Frame,
+ children: [ // 嵌套路由
+ {
+ path: '',
+ component: Home
+ }
+ ]
+ }
+ ]
+ ```
+3. `common`路由处理
+ 我们的项目中有一大堆的公共路由需要处理比如`404`阿,`503`阿等等路由我们都在`common.js`中进行处理。
+ ```js
+ export default [
+ // 默认页面
+ {
+ path: '/',
+ redirect: '/index',
+ hidden:true
+ },
+ // 无权限页面
+ {
+ path: '/nopermission',
+ name: 'nopermission',
+ component: () => import('@/views/NoPermission')
+ },
+ // 404
+ {
+ path: '*',
+ name: 'lost',
+ component: () => import('@/views/404')
+ }
+ ]
+ ```
+4. 路由初始化
+ 这是我们的最后一步了,用来初始化我们的项目路由
+ ```js
+ import Vue from 'vue'
+ import VueRouter from 'vue-router'
+ import RouterConfig from './modules' // 引入业务逻辑模块
+ import CommonRouters from './common' // 引入通用模块
+ Vue.use(VueRouter)
+ export default new VueRouter({
+ mode: 'history',// 需要服务端支持
+ scrollBehavior: () => ({ y: 0 }),
+ routes: RouterConfig.concat(CommonRouters)
+ })
+ ```
+ 估计有些朋友代码写到这还不知道到底这样做好处在哪里。我们来描述一个场景,比如按照这种结构来划分模块。正常的情况是我们创建完`home.js`要手动的把这个模块`import`到路由文件声明的地方去使用。但是有了上面的`index.js`,在使用的时候你只需要去创建一个`home.js`并抛出一个符合`VueRouter`规范的数组,剩下的就不用管了。`import RouterConfig from './modules' // 引入业务逻辑模块` 已经帮你处理完了,说洋气一点就是去中心化了。
+
+### 全局组件统一声明
+同样的道理,有了上面的经验,我们照葫芦画瓢来处理一下我们的全局组件。这就没什么可说的了,直接上核心代码
+1. 组织结构
+ ```js
+ router // 组件文件夹
+ |__xxx.vue // 其他组件
+ |__global //
+ |__index.js // 自动化处理文件
+ |__demo.vue // 全局demo组件
+ ```
+2. `global`处理
+ ```js
+ import Vue from 'vue'
+ let contexts = require.context('.', false, /\.vue$/)
+ contexts.keys().forEach(component => {
+ let componentEntity = contexts(component).default
+ // 使用内置的组件名称 进行全局组件注册
+ Vue.component(componentEntity.name, componentEntity)
+ })
+ ```
+3. 使用和说明
+
+ 这个使用起来就更简单了,直接在`app.js`引用这个文件就行。
+
+ **注意**:我之前看到网上有些人做法是理由组件名去区分全局组件和普通组件,然后通过正则去判断需不需要全局注册。我是直接把全局的组件放到`global`文件夹下,然后组件的注册名称直接使用`component.name`。至于使用哪种方式就比较看个人了。
+
+## 充分利用NodeJS
+放着`node`这么好得东西不用真是有点浪费,那么我们来看看`node`能为我们增加效率做出什么贡献。
+
+有这么一个场景,我们每次创建模块的时候都要新建一个`vue`文件和对应的`router`配置,而且新页面的大部分东西都还差不多,还得去复制粘贴别得页面。这想想就有点`low`。那既然有了`node`我们可不可以通过`node`来做这写乱七八糟得事情? 下面来把我们的想法付诸于显示。
+
+我们实现这个功能主要要借助`Node`的[fs](http://nodejs.cn/api/fs.html)和[process](http://nodejs.cn/api/process.html), 感兴趣的话可以深入研究一下。
+
+首先我们要编写我们的`node`脚本,这里是一个比较简单的版本。什么验证文件夹或者文件的都没有,只是来实现我们这个想法:
+```js
+/*
+ * fast add new module script
+ */
+const path = require('path')
+const fs = require('fs')
+const chalk = require('chalk')
+const reslove = file => path.resolve(__dirname, '../src', file)
+// symbol const
+const RouterSymbol = Symbol('router'),
+ ViewsSymbol = Symbol('views')
+// root path
+const rootPath = {
+ [RouterSymbol]: reslove('router/modules'),
+ [ViewsSymbol]: reslove('views')
+}
+//loggs
+const errorLog = error => console.log(chalk.red(`${error}`))
+const defaultLog = log => console.log(chalk.green(`${log}`))
+// module name
+let moduleName = new String()
+let fileType = new String()
+//const string
+const vueFile = module => (`
+
+
+
+
+
+
+`)
+// route file
+const routerFile = module => (`// write your comment here...
+export default [
+ {
+ path: '/${module}',
+ name: '',
+ redirect: '/${module}',
+ component: () => import('@/views/frame/Frame'),
+ children: [
+ {
+ path: '',
+ fullPath: '',
+ name: '',
+ component: () => import('@/views/${module}/index')
+ }
+ ]
+ }
+]
+`)
+/**
+ * generate file
+ * @param {*} filePath
+ * @param {*} content
+ * @param {*} dirPath
+ */
+const generateFile = async (filePath, content, dirPath = '') =>{
+ try {
+ // create file if file not exit
+ if (dirPath !== '' && ! await fs.existsSync(dirPath)) {
+ await fs.mkdirSync(dirPath)
+ defaultLog(`created ${dirPath}`)
+ }
+ if (! await fs.existsSync(filePath)) {
+ // create file
+ await fs.openSync(filePath, 'w')
+ defaultLog(`created ${filePath}`)
+ }
+ await fs.writeFileSync(filePath, content, 'utf8')
+ } catch (error) {
+ errorLog(error)
+ }
+}
+// module-method map
+const generates = new Map([
+ ['view', async (module) => {
+ // module file
+ const filePath = path.join(rootPath[ViewsSymbol], module)
+ const vuePath = path.join(filePath, '/index.vue')
+ await generateFile(vuePath, vueFile(module), filePath)
+ }],
+ // router is not need new folder
+ ['router',async (module) => {
+ const routerPath = path.join(rootPath[RouterSymbol], `/${module}.js`)
+ await generateFile(routerPath, routerFile(module))
+ }]
+])
+defaultLog(`请输入模块名称(英文):`)
+// files
+const files = ['view', 'router']
+// 和命令行进行交互 获取的创建的模块名称
+process.stdin.on('data', (chunk) => {
+ try {
+ if (!moduleName) {
+ moduleName = chunk
+ } else {
+ chunk = chunk.slice(0,-2) // delete /n
+ defaultLog(`new module name is ${chunk}`)
+ files.forEach(async (el, index) => {
+ // 执行创建语句
+ await generates.get(`${el}`).call(null, chunk.toString())
+ if (index === files.length-1) {
+ process.stdin.emit('end')
+ }
+ })
+ }
+ } catch (error) {
+ errorLog(error)
+ }
+})
+process.stdin.on('end', () => {
+ defaultLog('create module success')
+})
+```
+下面我们看使用的流程
+![Vue](./node-vue.jpg 'Vue')
+这样我们就分别创建了`vue`和`router`的文件,而且已经注入了内容。按照我们提前声明的组件
+
+**注意:这只是一个简单的思路,通过Node强大的文件处理能力,我们能做的事情远不止这些。**
+
+## 充分发挥Mixins的威力
+`Vue`中的`混入`[mixins](https://cn.vuejs.org/v2/guide/mixins.html)是一种提供分发 `Vue` 组件中可复用功能的非常灵活的方式。听说在3.0版本中可能会用Hooks的形式实现,但这并不妨碍它的强大。基础部分的可以看[这里](https://github.com/QDMarkMan/CodeBlog/blob/master/Vue/Vue%E5%BC%80%E5%8F%91%E4%B8%AD%E9%97%AE%E9%A2%98%E9%9B%86%E9%94%A6.md)。这里主要来讨论`mixins`能在什么情景下帮助我们。
+
+
+比如我们的大量的表格页面,仔细一扒拉你发现非常多的东西都是可以复用的例如`分页`,`表格高度`,`加载方法`, `laoding声明`等一大堆的东西。下面我们来整理出来一个简单的`list.vue`
+```js
+const list = {
+ data () {
+ return {
+ // 这些东西我们在list中处理,就不需要在每个页面再去手动的做这个了。
+ loading: false, // 伴随loading状态
+ pageNo: 1, // 页码
+ pageSize: 15, // 页长
+ totalCount: 0, // 总个数
+ pageSizes: [15, 20, 25, 30], //页长数
+ pageLayout: 'total, sizes, prev, pager, next, jumper', // 分页布局
+ list: []
+ }
+ },
+ methods: {
+ // 分页回掉事件
+ handleSizeChange(val) {
+ this.pageSize = val
+ // todo
+ },
+ handleCurrentChange (val) {
+ this.pageNo = val
+ // todo
+ },
+ /**
+ * 表格数据请求成功的回调 处理完公共的部分(分页,loading取消)之后把控制权交给页面
+ * @param {*} apiResult
+ * @returns {*} promise
+ */
+ listSuccessCb (apiResult = {}) {
+ return new Promise((reslove, reject) => {
+ let tempList = [] // 临时list
+ try {
+ this.loading = false
+ // todo
+ // 直接抛出
+ reslove(tempList)
+ } catch (error) {
+ reject(error)
+ }
+ })
+ },
+ /**
+ * 处理异常情况
+ * ==> 简单处理 仅仅是对表格处理为空以及取消loading
+ */
+ listExceptionCb (error) {
+ this.loading = false
+ console.error(error)
+ }
+ },
+ created() {
+ // 这个生命周期是在使用组件的生命周期之前
+ this.$nextTick().then(() => {
+ // todo
+ })
+ }
+}
+export default list
+```
+下面我们直接在组件中使用这个`mixins`
+```js
+import mixin from '@/mixins/list' // 引入
+import {getList} from '@/api/demo'
+export default {
+ name: 'mixins-demo',
+ mixins: [mixin], // 使用mixins
+ data () {
+ return {
+ }
+ },
+ methods: {
+ // 加载列表
+ load () {
+ const para = {
+ }
+ this.loading = true
+ getList(para).then((result) => {
+ this.listSuccessCb(result).then((list) => {
+ this.list = list
+ }).catch((err) => {
+ console.log(err)
+ })
+ }).catch((err) => {
+ this.listExceptionCb(err)
+ })
+ }
+ },
+ created() {
+ this.load()
+ }
+}
+
+```
+使用了`mixins`之后一个简单的有`loadoing`, `分页`,`数据`的表格大概就只需要上面这些代码。
+
+**注意:** `mixins`它固然是简单的,但是注释和引用一定要做好,不然的话新成员进入团队大概是一脸的懵逼,而且也不利于后期的维护。也是一把双刃剑。另外:全局`mixins`一定要慎用,如果不是必须要用的话我还是不建议使用。
+
+## 进一步对组件进行封装
+
+大家都知道组件化的最大的好处就是高度的可复用性和灵活性。但是组件怎么封装好,封装到什么程度让我们更方便。这是没有标准的答案的。我们只有根据`高内聚,低耦合`的这个指导思想来对我们的业务通用组件来进行封装,让我们的业务页面结构更加的简洁,加快我们的开发效率。封装多一点的话页面可能会变成这样:
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+有什么东西一目了然。
+
+### 无状态组件
+最容易勾起我们封装欲望的就是无状态`HTML`组件,例如我们出去`header`, `menu`之后的`content`部分。没有什么需要复杂的交互,但是我们每个页面又都得写。你说不拿它开刀拿谁开🔪
+```html
+
+
+
+```
+上面这个处理非常的简单,但是你在项目中会非常频繁的使用过到,那么这个封装就很有必要了。
+
+### ElementUI table组件封装
+
+`ElementUI`中得组件其实已经封装得很优秀了,但是表格使用得时候还是有一堆得代码在我看来是不需要在业务中重复写得。封装到靠配置来进行表格得书写得一步我觉得就差不多了,下面是一个小`demo`
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+```js
+export default {
+ name: 'base-table',
+ props: {
+ // 核心数据
+ list: {
+ type: Array,
+ default: () => []
+ },
+ // columns
+ columns: {
+ type: Array,
+ required: true,
+ default: () => []
+ }
+ },
+ data () {
+ return {
+ tableHeight: xxx
+ }
+ },
+ methods: {
+ // 处理点击事件
+ handleClick(action, data) {
+ // emit事件
+ this.$emit(`${action.emitKey}`, data)
+ }
+ }
+}
+```
+使用:
+```html
+
+
+
+
+ {{scope.row}}
+
+
+
+
+
+ xxx
+
+
+
+```
+```js
+export default {
+ name: 'table-demo',
+ data () {
+ return {
+ // 表格头部配置
+ headers: [
+ { key: 'xxx', title: '测试' },
+ { title: 'xxx', hidden: true, slot: 'demoslot'},
+ {
+ title: '操作', type: 'operate',
+ operates: [
+ {name: '详情',emitKey: 'view'}
+ ]
+ }
+ ]
+ }
+ },
+ methods: {
+ viewCb(){
+ // todo
+ },
+ defaultSlot(){
+ // todo
+ }
+ }
+}
+```
+这样封装过的表格,应付起来基本的一些需求问题应该不大。
+
+# 总结
+
+这些东西并不是什么语法糖,是真正可以在项目中加快我们的效率。让我们的自己乃至整个团队从繁杂的重复复制粘贴中解脱一点。至于速度和质量的问题。我是觉得使用公共组件质量可控性会更高一些。我建议公共得东西注释一定要写得全面和详细,这样可以极大的降低我们的交流成本。至于组件的封装还是要看你的业务。
+
+示例代码还在整理中。。。
+
+[原文地址](https://github.com/QDMarkMan/CodeBlog/blob/master/Javascript/这篇文章只讲单例模式.md) 如果觉得有用得话给个⭐吧
\ No newline at end of file