怎样用html if语句语句上传详情图以便减小占用的内存

&h2&为什么我要写这一篇关于 Flex 布局的教程?&/h2&&p&&b&因为它十分简单灵活,区区简单几行代码就可以实现各种页面的的布局,以前我在学习页面布局的时候我深受其 float、display、position 这些属性的困扰。然而学习 Flex 布局,你只要学习几个 CSS 属性,就可以写出简洁优雅复杂的页面布局。&/b&&/p&&h2&本教程适合人群:&/h2&&ol&&li&前端小白,不太明白页面布局技巧,但想通过简单的学习学会如何进行页面布局&/li&&li&学过但是不太熟悉 Flex 布局,需要教程来巩固回顾 Flex 布局的知识点&/li&&li&项目不考虑兼容 IE 低版本浏览器,想简单优雅地写出漂亮的页面布局&/li&&/ol&&p&废话就不多说了,我将尽可能地用简洁明了的言语来描述 Flex 布局,看完你会收获的。&/p&&h2&Flex 基本概念:&/h2&&figure&&img src=&/v2-54a0fc96ef4f455aefb8ee4bc133291b_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&563& data-rawheight=&333& class=&origin_image zh-lightbox-thumb& width=&563& data-original=&/v2-54a0fc96ef4f455aefb8ee4bc133291b_r.jpg&&&/figure&&p&在 flex 容器中默认存在两条轴,水平主轴(main axis) 和垂直的交叉轴(cross axis),这是默认的设置,当然你可以通过修改使垂直方向变为主轴,水平方向变为交叉轴,这个我们后面再说。&/p&&p&在容器中的每个单元块被称之为 flex item,每个项目占据的主轴空间为 (main size), 占据的交叉轴的空间为 (cross size)。&/p&&p&这里需要强调,不能先入为主认为宽度就是 main size,高度就是 cross size,这个还要取决于你主轴的方向,如果你垂直方向是主轴,那么项目的高度就是 main size。&/p&&h2&Flex 容器:&/h2&&p&首先,实现 flex 布局需要先指定一个容器,任何一个容器都可以被置顶为 flex 布局,这样容器内部的元素就可以使用 flex 来进行布局。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.container {
display: flex | inline-
//可以有两种取值
&/code&&/pre&&/div&&p&分别生成一个块状或行内的 flex 容器盒子。简单说来,如果你使用块元素如 div,你就可以使用 flex,而如果你使用行内元素,你可以使用 inline-flex。&/p&&p&&b&需要注意的是:当时设置 flex 布局之后,子元素的 float、clear、vertical-align 的属性将会失效。&/b&&/p&&p&有下面六种属性可以设置在容器上,它们分别是:&/p&&ol&&li&flex-direction&/li&&li&flex-wrap&/li&&li&flex-flow&/li&&li&justify-content&/li&&li&align-items&/li&&li&align-content&/li&&/ol&&p&&b&1. flex-direction: 决定主轴的方向(即项目的排列方向)&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.container {
flex-direction: row | row-reverse | column | column-
&/code&&/pre&&/div&&p&默认值:row,主轴为水平方向,起点在左端。&/p&&figure&&img src=&/v2-aedc6f1b28d5b4f7082e91_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&736& data-rawheight=&254& class=&origin_image zh-lightbox-thumb& width=&736& data-original=&/v2-aedc6f1b28d5b4f7082e91_r.jpg&&&/figure&&p&row-reverse:主轴为水平方向,起点在右端&/p&&figure&&img src=&/v2-215c34eddb552cfa148a_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&750& data-rawheight=&256& class=&origin_image zh-lightbox-thumb& width=&750& data-original=&/v2-215c34eddb552cfa148a_r.jpg&&&/figure&&p&column:主轴为垂直方向,起点在上沿&/p&&figure&&img src=&/v2-33efe75d166ad_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1214& data-rawheight=&738& class=&origin_image zh-lightbox-thumb& width=&1214& data-original=&/v2-33efe75d166ad_r.jpg&&&/figure&&p&column-reverse:主轴为垂直方向,起点在下沿&/p&&figure&&img src=&/v2-fb7eee11e75b127b_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1350& data-rawheight=&727& class=&origin_image zh-lightbox-thumb& width=&1350& data-original=&/v2-fb7eee11e75b127b_r.jpg&&&/figure&&p&&b&2. flex-wrap: 决定容器内项目是否可换行&/b&&/p&&p&默认情况下,项目都排在主轴线上,使用 flex-wrap 可实现项目的换行。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.container {
flex-wrap: nowrap | wrap | wrap-
&/code&&/pre&&/div&&p&默认值:nowrap 不换行,即当主轴尺寸固定时,当空间不足时,项目尺寸会随之调整而并不会挤到下一行。&/p&&figure&&img src=&/v2-ad83decf2f0df3_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1228& data-rawheight=&238& class=&origin_image zh-lightbox-thumb& width=&1228& data-original=&/v2-ad83decf2f0df3_r.jpg&&&/figure&&p&wrap:项目主轴总尺寸超出容器时换行,第一行在上方&/p&&figure&&img src=&/v2-e8179aab00cacda8168651_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&728& data-rawheight=&492& class=&origin_image zh-lightbox-thumb& width=&728& data-original=&/v2-e8179aab00cacda8168651_r.jpg&&&/figure&&p&wrap-reverse:换行,第一行在下方&/p&&figure&&img src=&/v2-91c53ebfab39_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&744& data-rawheight=&496& class=&origin_image zh-lightbox-thumb& width=&744& data-original=&/v2-91c53ebfab39_r.jpg&&&/figure&&p&&b&3. flex-flow: flex-direction 和 flex-wrap 的简写形式&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.container {
flex-flow: &flex-direction& || &flex-wrap&;
&/code&&/pre&&/div&&p&默认值为: row nowrap,感觉没什么卵用,老老实实分开写就好了。这样就不用记住这个属性了。&br&&/p&&p&&b&4. justify-content:定义了项目在主轴的对齐方式。&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.container {
justify-content: flex-start | flex-end | center | space-between | space-
&/code&&/pre&&/div&&p&&b&建立在主轴为水平方向时测试,即 flex-direction: row&/b&&/p&&p&默认值: flex-start 左对齐&br&&/p&&p&&br&&/p&&figure&&img src=&/v2-1bafabaeb0_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&2452& data-rawheight=&232& class=&origin_image zh-lightbox-thumb& width=&2452& data-original=&/v2-1bafabaeb0_r.jpg&&&/figure&&p&flex-end:右对齐&/p&&p&&br&&/p&&figure&&img src=&/v2-8bca7c22eee7b2_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&2526& data-rawheight=&252& class=&origin_image zh-lightbox-thumb& width=&2526& data-original=&/v2-8bca7c22eee7b2_r.jpg&&&/figure&&p&center:居中&/p&&p&&br&&/p&&figure&&img src=&/v2-dea82c75d35f532d35a52d1f9c1c762b_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&2520& data-rawheight=&266& class=&origin_image zh-lightbox-thumb& width=&2520& data-original=&/v2-dea82c75d35f532d35a52d1f9c1c762b_r.jpg&&&/figure&&p&space-between:两端对齐,项目之间的间隔相等,即剩余空间等分成间隙。&/p&&p&&br&&/p&&figure&&img src=&/v2-eadd8d7a1fcb5b0ad6f96a8_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&2524& data-rawheight=&262& class=&origin_image zh-lightbox-thumb& width=&2524& data-original=&/v2-eadd8d7a1fcb5b0ad6f96a8_r.jpg&&&/figure&&p&space-around:每个项目两侧的间隔相等,所以项目之间的间隔比项目与边缘的间隔大一倍。&/p&&p&&br&&/p&&figure&&img src=&/v2-42aff52768bdd55238eb0c_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&2510& data-rawheight=&254& class=&origin_image zh-lightbox-thumb& width=&2510& data-original=&/v2-42aff52768bdd55238eb0c_r.jpg&&&/figure&&p&&b&5. align-items: 定义了项目在交叉轴上的对齐方式&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.container {
align-items: flex-start | flex-end | center | baseline |
&/code&&/pre&&/div&&p&&b&建立在主轴为水平方向时测试,即 flex-direction: row&/b&&/p&&p&默认值为 stretch 即如果项目未设置高度或者设为 auto,将占满整个容器的高度。&/p&&p&&br&&/p&&figure&&img src=&/v2-0ccededf0844aaa3a08926d_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1210& data-rawheight=&448& class=&origin_image zh-lightbox-thumb& width=&1210& data-original=&/v2-0ccededf0844aaa3a08926d_r.jpg&&&/figure&&p&假设容器高度设置为 100px,而项目都没有设置高度的情况下,则项目的高度也为 100px。&/p&&p&flex-start:交叉轴的起点对齐&br&&/p&&figure&&img src=&/v2-26d9e85039beedd78e6e8a_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1222& data-rawheight=&646& class=&origin_image zh-lightbox-thumb& width=&1222& data-original=&/v2-26d9e85039beedd78e6e8a_r.jpg&&&/figure&&p&假设容器高度设置为 100px,而项目分别为 20px, 40px, 60px, 80px, 100px, 则如上图显示。&/p&&p&flex-end:交叉轴的终点对齐&br&&/p&&figure&&img src=&/v2-8b65ee47b9ef4e4b01b3_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1194& data-rawheight=&636& class=&origin_image zh-lightbox-thumb& width=&1194& data-original=&/v2-8b65ee47b9ef4e4b01b3_r.jpg&&&/figure&&p&center:交叉轴的中点对齐&/p&&p&&br&&/p&&figure&&img src=&/v2-7bb9dadf8f2_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1200& data-rawheight=&638& class=&origin_image zh-lightbox-thumb& width=&1200& data-original=&/v2-7bb9dadf8f2_r.jpg&&&/figure&&p&baseline: 项目的第一行文字的基线对齐&/p&&figure&&img src=&/v2-abf7acdddaee_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1218& data-rawheight=&626& class=&origin_image zh-lightbox-thumb& width=&1218& data-original=&/v2-abf7acdddaee_r.jpg&&&/figure&&p&以文字的底部为主,仔细看图可以理解。&/p&&p&&b&6. align-content: 定义了多根轴线的对齐方式,如果项目只有一根轴线,那么该属性将不起作用&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.container {
align-content: flex-start | flex-end | center | space-between | space-around |
&/code&&/pre&&/div&&p&这个这样理解:&/p&&p&当你 flex-wrap 设置为 nowrap 的时候,容器仅存在一根轴线,因为项目不会换行,就不会产生多条轴线。&/p&&p&当你 flex-wrap 设置为 wrap 的时候,容器可能会出现多条轴线,这时候你就需要去设置多条轴线之间的对齐方式了。&/p&&p&建立在主轴为水平方向时测试,即 flex-direction: row, flex-wrap: wrap&/p&&p&默认值为 stretch,看下面的图就很好理解了&/p&&figure&&img src=&/v2-cb8b731bc213cd1caab514e5_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&895& data-rawheight=&656& class=&origin_image zh-lightbox-thumb& width=&895& data-original=&/v2-cb8b731bc213cd1caab514e5_r.jpg&&&/figure&&p&从图可以看出又三条轴线(因为容器宽度有限),当值为 stretch 时会三条轴线平分容器的垂直方向上的空间。&/p&&p&值得注意的是,虽然在每条轴线上项目的默认值也为 stretch,但是由于我每个项目我都设置了高度,所以它并没有撑开整个容器。如果项目不设置高度的话就会变成下面这样:&/p&&figure&&img src=&/v2-2d5feceece695fb84fd650fc49164bd6_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&963& data-rawheight=&649& class=&origin_image zh-lightbox-thumb& width=&963& data-original=&/v2-2d5feceece695fb84fd650fc49164bd6_r.jpg&&&/figure&&p&这个我在前面也有提到(align-items),这里重点还是理解三条轴线会平分垂直轴上的空间。&/p&&p&flex-start:轴线全部在交叉轴上的起点对齐&br&&/p&&figure&&img src=&/v2-61d92d7dc68e3d7d415a_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&879& data-rawheight=&650& class=&origin_image zh-lightbox-thumb& width=&879& data-original=&/v2-61d92d7dc68e3d7d415a_r.jpg&&&/figure&&p&flex-end:轴线全部在交叉轴上的终点对齐&/p&&figure&&img src=&/v2-0a0a7f10c50596aade787ae11b7b0a75_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&907& data-rawheight=&649& class=&origin_image zh-lightbox-thumb& width=&907& data-original=&/v2-0a0a7f10c50596aade787ae11b7b0a75_r.jpg&&&/figure&&p&center:轴线全部在交叉轴上的中间对齐&/p&&figure&&img src=&/v2-dcf53fce8dbcde7da9c677dd1a033860_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&906& data-rawheight=&652& class=&origin_image zh-lightbox-thumb& width=&906& data-original=&/v2-dcf53fce8dbcde7da9c677dd1a033860_r.jpg&&&/figure&&p&space-between:轴线两端对齐,之间的间隔相等,即剩余空间等分成间隙。&/p&&figure&&img src=&/v2-de08d45d3d6df4c5401d0d_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&886& data-rawheight=&645& class=&origin_image zh-lightbox-thumb& width=&886& data-original=&/v2-de08d45d3d6df4c5401d0d_r.jpg&&&/figure&&p&space-around:每个轴线两侧的间隔相等,所以轴线之间的间隔比轴线与边缘的间隔大一倍。&/p&&figure&&img src=&/v2-7c4d5c01f3851a3cec7f8487c6edb21d_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&904& data-rawheight=&647& class=&origin_image zh-lightbox-thumb& width=&904& data-original=&/v2-7c4d5c01f3851a3cec7f8487c6edb21d_r.jpg&&&/figure&&p&到这里关于容器上的所有属性都讲完了,接下来就来讲讲关于在 flex item 上的属性。&/p&&h2&Flex 项目属性:&/h2&&p&有六种属性可运用在 item 项目上:&/p&&ol&&li&order&/li&&li&flex-basis&/li&&li&flex-grow&/li&&li&flex-shrink&/li&&li&flex&/li&&li&align-self&/li&&/ol&&p&&b&1. order: 定义项目在容器中的排列顺序,数值越小,排列越靠前,默认值为 0&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.item {
order: &integer&;
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&/v2-dc496b3a0e6_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1258& data-rawheight=&272& class=&origin_image zh-lightbox-thumb& width=&1258& data-original=&/v2-dc496b3a0e6_r.jpg&&&/figure&&p&在 HTML 结构中,虽然 -2,-1 的 item 排在后面,但是由于分别设置了 order,使之能够排到最前面。&/p&&p&&b&2. flex-basis: 定义了在分配多余空间之前,项目占据的主轴空间,浏览器根据这个属性,计算主轴是否有多余空间&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.item {
flex-basis: &length& |
&/code&&/pre&&/div&&p&默认值:auto,即项目本来的大小, 这时候 item 的宽高取决于 width 或 height 的值。&br&&/p&&p&&b&当主轴为水平方向的时候,当设置了 flex-basis,项目的宽度设置值会失效,flex-basis 需要跟 flex-grow 和 flex-shrink 配合使用才能发挥效果。&/b&&/p&&ul&&li&当 flex-basis 值为 0 % 时,是把该项目视为零尺寸的,故即使声明该尺寸为 140px,也并没有什么用。&/li&&li&当 flex-basis 值为 auto 时,则跟根据尺寸的设定值(假如为 100px),则这 100px 不会纳入剩余空间。&/li&&/ul&&p&3&b&. flex-grow: 定义项目的放大比例&br&&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.item {
flex-grow: &number&;
&/code&&/pre&&/div&&p&默认值为 0,即如果存在剩余空间,也不放大&/p&&figure&&img src=&/v2-5ffab4a9dfd88c3_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&2518& data-rawheight=&492& class=&origin_image zh-lightbox-thumb& width=&2518& data-original=&/v2-5ffab4a9dfd88c3_r.jpg&&&/figure&&p&当所有的项目都以 flex-basis 的值进行排列后,仍有剩余空间,那么这时候 flex-grow 就会发挥作用了。&/p&&p&如果所有项目的 flex-grow 属性都为 1,则它们将等分剩余空间。(如果有的话)&/p&&p&如果一个项目的 flex-grow 属性为 2,其他项目都为 1,则前者占据的剩余空间将比其他项多一倍。&br&&/p&&p&当然如果当所有项目以 flex-basis 的值排列完后发现空间不够了,且 flex-wrap:nowrap 时,此时 flex-grow 则不起作用了,这时候就需要接下来的这个属性。&/p&&p&&b&4. flex-shrink: 定义了项目的缩小比例&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.item {
flex-shrink: &number&;
&/code&&/pre&&/div&&p&默认值: 1,即如果空间不足,该项目将缩小,负值对该属性无效。&br&&/p&&figure&&img src=&/v2-383ec4f84e6a85406dbcaf_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&471& data-rawheight=&254& class=&origin_image zh-lightbox-thumb& width=&471& data-original=&/v2-383ec4f84e6a85406dbcaf_r.jpg&&&/figure&&p&这里可以看出,虽然每个项目都设置了宽度为 50px,但是由于自身容器宽度只有 200px,这时候每个项目会被同比例进行缩小,因为默认值为 1。&/p&&p&同理可得:&/p&&p&如果所有项目的 flex-shrink 属性都为 1,当空间不足时,都将等比例缩小。
&/p&&p&如果一个项目的 flex-shrink 属性为 0,其他项目都为 1,则空间不足时,前者不缩小。&br&&/p&&p&&b&5. flex: flex-grow, flex-shrink 和 flex-basis的简写&/b& &/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.item{
flex: none | [ &'flex-grow'& &'flex-shrink'&? || &'flex-basis'& ]
&/code&&/pre&&/div&&p&flex 的默认值是以上三个属性值的组合。假设以上三个属性同样取默认值,则 flex 的默认值是 0 1 auto。&/p&&p&有关快捷值:auto (1 1 auto) 和 none (0 0 auto)&br&&/p&&p&关于 flex 取值,还有许多特殊的情况,可以按以下来进行划分:&/p&&ul&&li&当 flex 取值为一个非负数字,则该数字为 flex-grow 值,flex-shrink 取 1,flex-basis 取 0%,如下是等同的:&br&&/li&&/ul&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.item {flex: 1;}
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
&/code&&/pre&&/div&&ul&&li&当 flex 取值为 0 时,对应的三个值分别为 0 1 0%&/li&&/ul&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.item {flex: 0;}
flex-grow: 0;
flex-shrink: 1;
flex-basis: 0%;
&/code&&/pre&&/div&&ul&&li&当 flex 取值为一个长度或百分比,则视为 flex-basis 值,flex-grow 取 1,flex-shrink 取 1,有如下等同情况(注意 0% 是一个百分比而不是一个非负数字)&br&&/li&&/ul&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.item-1 {flex: 0%;}
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
.item-2 {flex: 24}
flex-grow: 1;
flex-shrink: 1;
flex-basis: 24
&/code&&/pre&&/div&&ul&&li&当 flex 取值为两个非负数字,则分别视为 flex-grow 和 flex-shrink 的值,flex-basis 取 0%,如下是等同的:&br&&/li&&/ul&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.item {flex: 2 3;}
flex-grow: 2;
flex-shrink: 3;
flex-basis: 0%;
&/code&&/pre&&/div&&ul&&li&当 flex 取值为一个非负数字和一个长度或百分比,则分别视为 flex-grow 和 flex-basis 的值,flex-shrink 取 1,如下是等同的:&br&&/li&&/ul&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.item {flex: 11 32}
flex-grow: 11;
flex-shrink: 1;
flex-basis: 32
&/code&&/pre&&/div&&p&建议优先使用这个属性,而不是单独写三个分离的属性。&br&&/p&&p&grow 和 shrink 是一对双胞胎,grow 表示伸张因子,shrink 表示是收缩因子。&br&&/p&&p&grow 在 flex 容器下的子元素的宽度和比容器和小的时候起作用。 grow 定义了子元素的尺寸增长因子,容器中除去子元素之和剩下的尺寸会按照各个子元素的 grow 值进行平分加大各个子元素上。&br&&/p&&p&另外感谢 &a class=&member_mention& href=&/people/06a7d40bbed3d06c00adc& data-hash=&06a7d40bbed3d06c00adc& data-hovercard=&p$b$06a7d40bbed3d06c00adc&&@王嘉成&/a& 在评论区的补充说明容器的 flex-wrap 与子项的 flex-shrink、flex-grow 之间的关系:&/p&&ol&&li&当 flex-wrap 为 wrap | wrap-reverse,且子项宽度和不及父容器宽度时,flex-grow 会起作用,子项会根据 flex-grow 设定的值放大(为0的项不放大)&/li&&li&当 flex-wrap 为 wrap | wrap-reverse,且子项宽度和超过父容器宽度时,首先一定会换行,换行后,每一行的右端都可能会有剩余空间(最后一行包含的子项可能比前几行少,所以剩余空间可能会更大),这时 flex-grow 会起作用,若当前行所有子项的 flex-grow 都为0,则剩余空间保留,若当前行存在一个子项的 flex-grow 不为0,则剩余空间会被 flex-grow 不为0的子项占据&/li&&li&当 flex-wrap 为 nowrap,且子项宽度和不及父容器宽度时,flex-grow 会起作用,子项会根据 flex-grow 设定的值放大(为0的项不放大)&/li&&li&当 flex-wrap 为 nowrap,且子项宽度和超过父容器宽度时,flex-shrink 会起作用,子项会根据 flex-shrink 设定的值进行缩小(为0的项不缩小)。但这里有一个较为特殊情况,就是当这一行所有子项 flex-shrink 都为0时,也就是说所有的子项都不能缩小,就会出现讨厌的横向滚动条&/li&&li&总结上面四点,可以看出不管在什么情况下,在同一时间,flex-shrink 和 flex-grow 只有一个能起作用,这其中的道理细想起来也很浅显:空间足够时,flex-grow 就有发挥的余地,而空间不足时,flex-shrink 就能起作用。当然,flex-wrap 的值为 wrap | wrap-reverse 时,表明可以换行,既然可以换行,一般情况下空间就总是足够的,flex-shrink 当然就不会起作用&/li&&/ol&&p&&b&6. align-self: 允许单个项目有与其他项目不一样的对齐方式&/b&&/p&&p&单个项目覆盖 align-items 定义的属性&/p&&p&默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.item {
align-self: auto | flex-start | flex-end | center | baseline |
&/code&&/pre&&/div&&p&这个跟 align-items 属性时一样的,只不过 align-self 是对单个项目生效的,而 align-items 则是对容器下的所有项目生效的。&/p&&p&&br&&/p&&figure&&img src=&/v2-2516cddfbbabaef96fd6dfab4eb71757_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&611& data-rawheight=&344& class=&origin_image zh-lightbox-thumb& width=&611& data-original=&/v2-2516cddfbbabaef96fd6dfab4eb71757_r.jpg&&&/figure&&p&容器 align-items 设置为 flex-start,而第三个项目的 align-self 值为 flex-end。&/p&&p&&b&关于 Flex 布局的语法基础就讲到这里,相信能看到这里的你一定会有挺多收获。&/b&&/p&&p&&b&如果你看完还是一头雾水的话,没关系,过两天花半小时再看一遍,一定能够理解的。&/b&&/p&&p&&br&&/p&&p&&b&作者:林东洲&/b&&/p&&p&&b&更多技术干货敬请关注云栖社区知乎机构号:&a href=&/org/a-li-yun-yun-qi-she-qu-48& class=&internal&&阿里云云栖社区 - 知乎&/a&&/b&&/p&&p&&/p&&p&&/p&
为什么我要写这一篇关于 Flex 布局的教程?因为它十分简单灵活,区区简单几行代码就可以实现各种页面的的布局,以前我在学习页面布局的时候我深受其 float、display、position 这些属性的困扰。然而学习 Flex 布局,你只要学习几个 CSS 属性,就可以写出简…
&figure&&img src=&/50/v2-4e62cf9a220_b.jpg& data-rawwidth=&1024& data-rawheight=&714& class=&origin_image zh-lightbox-thumb& width=&1024& data-original=&/50/v2-4e62cf9a220_r.jpg&&&/figure&&p&&b&作者:stormzhang&/b&&/p&&p&&b&来源:微信公众号 stormzhang&/b&&/p&&p&&b&更多精彩文章,关注专栏:&/b&&a href=&/passer& class=&internal&&学习编程 - 知乎专栏&/a&&/p&&p&&br&&/p&&p&看完昨天的文章「&a href=&/?target=http%3A//mp./s%3F__biz%3DMzA4NTQwNDcyMA%3D%3D%26mid%3D%26idx%3D1%26sn%3D9aceac07d272e4f857a5ff%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&从0开始学习 GitHub 系列之「初识 GitHub」&i class=&icon-external&&&/i&&/a&」估计不少人已经开始期待我继续更新了,这不赶紧马不停蹄,加班加点给你们更新了第二篇。在更新本篇文章之前先回答昨天大家留言的两个问题:
&/p&&p&&b&GitHub 需要翻墙么?&/b&&/p&&p&印象中 GitHub 之前确实总是断断续续的访问不了,不过在13年初的时候有段时间最严重,一度被封了,当时李开复老师再也忍无可忍,公开发了一条抗议 GitHub 被封的微博,这事我印象很深,因为我是12年底加入的 GitHub ,那时候简直像遇到世外桃源一般,但是也深受老是访问不了的困扰,很多人早就对这件事怨声载道了,加上李开复老师的声讨,这一下就炸开了锅,微博上纷纷转发谴责,算的上是整个IT界的大新闻,后来因为这事影响太大了,没过几天 GitHub 就可以正常访问了,这里真的要感谢李开复老师敢于站出来的勇气,可以这么说,如果没有 GitHub ,中国的编程水平起码要倒退好多年!&/p&&p&&br&&/p&&p&因为 GitHub 的影响力太大,基本上是各种黑客攻击的对象,所以现在偶尔也会有宕机访问不了的情况,但是好在不会被封,所以大家不用担心,访问 GitHub 不用翻墙,只是可能访问速度稍慢些,另外为了维护一个和谐的环境,这里也呼吁大家不要在 GitHub 上发表任何关于政治的言论与文章,在 GitHub 上我们只是单纯的技术交流,无关政治,在复杂的大环境下,希望 GitHub 永远是我们程序员的一片净土!&/p&&p&&br&&/p&&p&&b&英语差、0基础学得会么?&/b&&/p&&p&这个也是不少人问我的,GitHub 虽然都是英文,但是对英语水平的要求不是那么高,都是些简单的单词,遇到不会的查一下就行了,你觉得很难只是你对英文网站反射性的抵触而已,相信我,跟着我的详细教程,我的文章面向从没有接触过甚至没有听过 GitHub 的同学,一步步教你由浅入深。如果你学不会,那么来打我,不过我这么帅,你也不忍心!&/p&&p&&br&&/p&&p&好了,废话不多说,咱们进入正文!&/p&&p&&br&&/p&&h2&&b&1. 注册 GitHub&/b&&/h2&&p&&b&先去 GitHub 官网「&a href=&/?target=https%3A///& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&How people build software · GitHub&i class=&icon-external&&&/i&&/a&」注册「Sign Up」个账号,注册页面如下:&/b&&/p&&p&&br&&/p&&p&&br&&/p&&figure&&img src=&/575f663f8e7843f9bcd48d65c49f17b4_b.png& data-rawwidth=&640& data-rawheight=&539& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&/575f663f8e7843f9bcd48d65c49f17b4_r.png&&&/figure&&p&&br&&/p&&p&这个应该没啥说的,需要填用户名、邮箱、密码,值得一提的用户名请不要那么随便,最好取的这个名字就是你以后常用的用户名了,也强烈建议你各大社交账号都用一样的用户名,这样识别度较高,比如我的博客域名、GitHub、知乎等其他社交账号 ID 都是 stormzhang ,微博是因为被占用了,无奈换了个id,而且这个用户名以后在 GitHub 搭建博客的时候默认给你生成的博客地址就是 &a href=&/?target=http%3A//username.github.io/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&username.github.io&i class=&icon-external&&&/i&&/a& ,所以给自己取个好点的用户名吧。&/p&&p&&br&&/p&&p&&b&填好用户名、邮箱、密码紧接着到这一步:&/b& &/p&&p&&br&&/p&&p&&br&&/p&&figure&&img src=&/b2aefa60ae2b762fc4c508ca78f63243_b.png& data-rawwidth=&640& data-rawheight=&450& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&/b2aefa60ae2b762fc4c508ca78f63243_r.png&&&/figure&&p&&br&&/p&&p&这个是什么意思呢?GitHub 有两种,一种是公开,这种是免费的,就是你创建的项目是开放的,所有人都能看得到;另一种是私有,这种是收费的,这种一般是很多企业在使用 GitHub 的私有仓库在托管自己的项目,这也是 GitHub 的一种盈利模式对于个人你就直接默认选择公开的就行了。&/p&&p&&br&&/p&&h2&&b&2. 认识 GitHub&/b&&/h2&&p&注册成功之后你会到 GitHub 的主页面来:&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&figure&&img src=&/7afaead74d4a7c3a25f018a02159e8ac_b.png& data-rawwidth=&640& data-rawheight=&290& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&/7afaead74d4a7c3a25f018a02159e8ac_r.png&&&/figure&&p&你如果是新注册的可能看到的跟我不一样,因为你们新用户,没有自己的项目,没有关注的人,所以只有一个导航栏。&/p&&p&&br&&/p&&ul&&li&导航栏,从左到右依次是 GitHub 主页按钮、搜索框、PR、Issues、Gist(这些概念后面会讲的)、消息提醒、创建项目按钮、我的账号相关。&/li&&/ul&&p&&br&&/p&&ul&&li&我的 Timeline,这部分你可以理解成微博,就是你关注的一些人的活动会出现在这里,比如如果你们关注我了,那么以后我 star、fork 了某些项目就会出现在你的时间线里。&/li&&/ul&&p&&br&&/p&&ul&&li&我的项目,这部分就不用说了,如果你创建了项目,就里就可以快捷访问。&/li&&/ul&&p&&br&&/p&&p&&br&&/p&&h2&&b&3. GitHub 主页&/b&&/h2&&p&点击下图的 Your profile 菜单进入到你的个人 GitHub 主页。&/p&&p&&br&&/p&&p&&br&&/p&&figure&&img src=&/816e66b3be1c9ff674ca8667d4dfe8ff_b.png& data-rawwidth=&640& data-rawheight=&273& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&/816e66b3be1c9ff674ca8667d4dfe8ff_r.png&&&/figure&&p&&br&&/p&&p&还是以我的 GitHub 主页为例:&/p&&p&&br&&/p&&p&&br&&/p&&figure&&img src=&/40ec1a172c5cdb7f8dc261a8_b.png& data-rawwidth=&640& data-rawheight=&359& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&/40ec1a172c5cdb7f8dc261a8_r.png&&&/figure&&p&&br&&/p&&p&这么详细应该不会看不懂吧?只不过你的账号可能没有这么丰富,因为你可能啥也没做过,但是如果做全了基本上就会看到跟我一样的了。&/p&&p&&br&&/p&&h2&&b&4. 设置你的 GitHub&/b&&/h2&&p&如果你是新注册的 GitHub 账号,是不是觉得很简陋?虽然你没有自己的项目,但是第一步起码要先完善自己的信息,点击如下的 Settings 菜单:&/p&&p&&br&&/p&&p&&br&&/p&&figure&&img src=&/bace4500dd_b.png& data-rawwidth=&640& data-rawheight=&245& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&/bace4500dd_r.png&&&/figure&&p&&br&&/p&&p&到设置页面来设置一些基本信息:&/p&&p&&br&&/p&&p&&br&&/p&&figure&&img src=&/c3f5e5d02c8db15324ce_b.png& data-rawwidth=&640& data-rawheight=&414& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&/c3f5e5d02c8db15324ce_r.png&&&/figure&&p&&br&&/p&&p&像头像、Name 建议要设置一个常用的,这两个很有识别性,公开的邮箱也要设置一个,这样那些企业啊、猎头啊就通过这个公开邮箱去联系你,友情提醒:别在 GitHub 把自己的 QQ 邮箱放上去,不显得太 low 了么?没有 gmail 邮箱,起码也得注册个 foxmail、163 邮箱之类的吧。&/p&&p&&br&&/p&&p&&br&&/p&&h2&&b&5. GitHub 基本概念&/b&&/h2&&p&上面认识了 GitHub 的基本面貌之后,你需要了解一些 GitHub 的基本概念,这些概念是你经常会接触并遇到的。&/p&&p&&br&&/p&&p&&b&Repository&/b&&/p&&p&仓库的意思,即你的项目,你想在 GitHub 上开源一个项目,那就必须要新建一个 Repository ,如果你开源的项目多了,你就拥有了多个 Repositories 。&/p&&p&&br&&/p&&p&&b&Issue&/b& &/p&&p&问题的意思,举个例子,就是你开源了一个项目,别人发现你的项目中有bug,或者哪些地方做的不够好,他就可以给你提个 Issue ,即问题,提的问题多了,也就是 Issues ,然后你看到了这些问题就可以去逐个修复,修复ok了就可以一个个的 Close 掉。
&/p&&p&&br&&/p&&p&&b&Star&/b&&/p&&p&这个好理解,就是给项目点赞,但是在 GitHub 上的点赞远比微博、知乎点赞难的多,如果你有一个项目获得100个star都算很不容易了!&/p&&p&&br&&/p&&p&&b&Fork&/b&&/p&&p&这个不好翻译,如果实在要翻译我把他翻译成分叉,什么意思呢?你开源了一个项目,别人想在你这个项目的基础上做些改进,然后应用到自己的项目中,这个时候他就可以 Fork 你的项目,这个时候他的 GitHub 主页上就多了一个项目,只不过这个项目是基于你的项目基础(本质上是在原有项目的基础上新建了一个分支,分支的概念后面会在讲解Git的时候说到),他就可以随心所欲的去改进,但是丝毫不会影响原有项目的代码与结构。&/p&&p&&br&&/p&&p&&b&Pull Request&/b&&/p&&p&发起请求,这个其实是基于 Fork 的,还是上面那个例子,如果别人在你基础上做了改进,后来觉得改进的很不错,应该要把这些改进让更多的人收益,于是就想把自己的改进合并到原有项目里,这个时候他就可以发起一个 Pull Request(简称PR) ,原有项目创建人,也就是你,就可以收到这个请求,这个时候你会仔细review他的代码,并且测试觉得OK了,就会接受他的PR,这个时候他做的改进原有项目就会拥有了。&/p&&p&&br&&/p&&p&&b&Watch&/b&&/p&&p&这个也好理解就是观察,如果你 Watch 了某个项目,那么以后只要这个项目有任何更新,你都会第一时间收到关于这个项目的通知提醒。&/p&&p&&br&&/p&&p&&b&Gist&/b&&/p&&p&有些时候你没有项目可以开源,只是单纯的想分享一些代码片段,那这个时候 Gist 就派上用场了!&/p&&p&&br&&/p&&h2&&b&6. 创建自己的项目&/b&&/h2&&p&点击顶部导航栏的 + 可以快速创建一个项目,如下图:&/p&&p&&br&&/p&&p&&br&&/p&&figure&&img src=&/f1a7ac4df9e23f016de402_b.png& data-rawwidth=&640& data-rawheight=&380& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&/f1a7ac4df9e23f016de402_r.png&&&/figure&&p&&br&&/p&&p&创建一个项目需要填写如上的几部分:项目名、项目描述与简单的介绍,你不付费没法选择私有的,所以接着只能选择 public 的,之后勾选「Initialize this repository with a README」,这样你就拥有了你的第一个 GitHub 项目:&/p&&p&&br&&/p&&p&&br&&/p&&figure&&img src=&/08bfdabfdd584_b.png& data-rawwidth=&640& data-rawheight=&361& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&/08bfdabfdd584_r.png&&&/figure&&p&&br&&/p&&p&可以看到这个项目只包含了一个 &a href=&/?target=http%3A//readme.md/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&README.md&i class=&icon-external&&&/i&&/a& 文件,但是它已经是一个完整的 Git 仓库了,你可以通过对它进行一些操作,如watch、star、fork,还可以 clone 或者下载下来。&/p&&p&&br&&/p&&p&这里提一下 &a href=&/?target=http%3A//readme.md/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&README.md&i class=&icon-external&&&/i&&/a& ,GitHub 上所有关于项目的详细介绍以及 Wiki 都是基于 Markdown 的,甚至之后在 GitHub 上搭建博客,写博客也是如此,所以如果还不懂 Markdown 语法的,建议先去学习下。推荐一篇学习 Markdown 的文章给你们:&/p&&p&&br&&/p&&p&&a href=&/?target=http%3A///p/q81RER& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&献给写作者的 Markdown 新手指南&i class=&icon-external&&&/i&&/a&&/p&&p&&br&&/p&&h2&&b&7. 总结&/b&&/h2&&p&相信看完以上文章你已经基本算是了解 GitHub 的基本概念并且正式加入 GitHub 这个大家庭了,之后会有更深入的文章介绍 Git、介绍对项目的常用操作、介绍如何给开源项目提交代码、介绍如何协同合作甚至怎么搭建博客等,敬请期待吧!&/p&&p&&/p&
作者:stormzhang来源:微信公众号 stormzhang更多精彩文章,关注专栏: 看完昨天的文章「」估计不少人已经开始期待我继续更新了,这不赶紧马不停蹄,加班加点给你们更新了第二篇。在更新本篇…
&figure&&img src=&/50/v2-5e678fb5ebb_b.png& data-rawwidth=&900& data-rawheight=&385& class=&origin_image zh-lightbox-thumb& width=&900& data-original=&/50/v2-5e678fb5ebb_r.png&&&/figure&&p&相信每一个程序猿都听说过 GitHub 了,简单来说 GitHub 是一个主要提供基于 Git 来进行版本控制的项目托管服务的网站,她是世界上最大的开源软件社区,世界各地的程序猿在 GitHub 上开源自己的项目,关注和参与自己感兴趣的开源项目,嗯,同时 GitHub 还是世界上最大的同性交友网站。&/p&&h2&什么是 GitHub&/h2&&p&先来了解下 Git 和 GitHub 到底是个什么关系吧~&/p&&a href=&/?target=https%3A///p/4346/read& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&大白话解释 Git 和 GitHub&i class=&icon-external&&&/i&&/a&&blockquote&&p&本文旨在使用通俗易懂的文字,讲解版本控制背后的理论,以便你能对程序员们如何工作有个全局概念。&/p&&/blockquote&&p&求职面试时,你肯定看到过或者听说过在 GitHub 上有开源项目或是参加过别人的开源项目是加分项,甚至有面试官要求提供 GitHub 账号地址,那么 GitHub 到底为什么这么重要呢?&/p&&a href=&/?target=https%3A///p/2531& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&[码农必知]GitHub&i class=&icon-external&&&/i&&/a&&blockquote&&p&知乎上面有人总结了 GitHub 的基本功能:&/p&&ul&&li&GitHub 是社交网站,具有和社交网站相同的好友、评论、赞、讨论等功能。&/li&&li&任何人均可参与其他人的代码仓库的开发。(当然不能直接改人家的代码。)&/li&&li&协同开发与编程,而且支持互相评论。&/li&&li&通过 Git 版本控制系统来提高生产力。&/li&&/ul&&/blockquote&&h2&GitHub 入门&/h2&&p&非常给力的从 0 开始系列,还不太熟悉的小伙伴们赶紧来学习 GitHub 吧!&/p&&a href=&/?target=https%3A///a/1489& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&从0开始学习 GitHub 系列之「初识 GitHub」&i class=&icon-external&&&/i&&/a&&blockquote&&p&我是从小白一路过来的,很能理解你们内心的感受与困惑,因为这些阶段都是我自己亲身经历过的,所以我写的文章都会从你们的角度去出发,并且我对文章高要求,除了排版、配图很用心外,文章的内容每次写完我都会亲自看三四遍,确保不会出现误导以及你们理解不了的情况,你们看的很轻松易懂的文章其实因为我背后做了很多的功课。&/p&&/blockquote&&a href=&/?target=https%3A///a/1460& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&从0开始学习 GitHub 系列之「加入 GitHub」&i class=&icon-external&&&/i&&/a&&blockquote&&ul&&li&注册 GitHub&/li&&li&认识 GitHub&/li&&li&GitHub 主页&/li&&li&设置你的 GitHub&/li&&li&GitHub 基本概念&/li&&li&创建自己的项目&/li&&/ul&&/blockquote&&a href=&/?target=https%3A///a/3232& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&从0开始学习 GitHub 系列之「Git 速成」&i class=&icon-external&&&/i&&/a&&blockquote&&p&GitHub 是基于 Git 的,所以也就意味着 Git 是基础,如果你不会 Git ,那么接下来你完全继续不下去,所以今天的教程就来说说 Git ,当然关于 Git 的知识单凭一篇文章肯定说不完的,我这篇文章先介绍一些最基本的、最常用的一些 Git 知识,争取让你们 Git 速成。&/p&&/blockquote&&a href=&/?target=https%3A///a/3288& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&从0开始学习 GitHub 系列之「向GitHub 提交代码」&i class=&icon-external&&&/i&&/a&&blockquote&&p&上一篇文章只介绍了对本地 Git 仓库的基本操作,今天我就来介绍下如何跟远程仓库一起协作,教你们向 GitHub 上提交你们的第一行代码!&/p&&ul&&li&SSH&/li&&li&生成SSH key&/li&&li&GitHub 上添加 SSH key&/li&&li&Push & Pull&/li&&li&提交代码&/li&&/ul&&/blockquote&&a href=&/?target=https%3A///a/9506& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&从0开始学习 GitHub 系列之「Git 进阶」&i class=&icon-external&&&/i&&/a&&blockquote&&p&关于 Git 相信大家看了之前一系列的文章已经初步会使用了, 但是关于Git还有很多知识与技巧是你不知道的,今天就来给大家介绍下一些 Git 进阶的知识。&/p&&ul&&li&用户名和邮箱&/li&&li&alias&/li&&li&其他配置&/li&&li&diff&/li&&li&checkout&/li&&li&stash&/li&&li&merge & rebase&/li&&li&解决冲突&/li&&/ul&&/blockquote&&h2&SSH 深入研究&/h2&&blockquote&&p&SSH 是一种网络协议,用于计算机之间的加密登录。目前是每一台 Linux 电脑的标准配置。而大多数 Git 服务器都会选择使用 SSH 公钥来进行授权,所以想要在 GitHub 提交代码的第一步就是要先添加 SSH key 配置。&/p&&/blockquote&&a href=&/?target=https%3A///p/6148/read& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&SSH相关知识&i class=&icon-external&&&/i&&/a&&blockquote&&p&SSH是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用SSH协议可以有效防止远程管理过程中的信息泄露问题。通过SSH可以对所有传输的数据进行加密,也能够防止DNS欺骗和IP欺骗。&/p&&/blockquote&&a href=&/?target=https%3A///a/9677& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Git自由之章 - 关于 SSH 公钥&i class=&icon-external&&&/i&&/a&&blockquote&&p&简单来说,SSH提供了两种级别的安全验证:&/p&&ul&&li&第一种级别是基于密码的安全验证,知道账号和密码,就可以登陆到远程主机。 Team的开发工作中,就是使用这种方式登陆编译服务器,或者开发机器。因为是在内网中,这种级别的安全验证已经足够了。&/li&&li&第二种级别是基于Public-key cryptography (公开密匙加密)机制的安全验证。&/li&&/ul&&/blockquote&&a href=&/?target=https%3A///a/7424& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&(Git 学习)Git SSH Key 创建步骤&i class=&icon-external&&&/i&&/a&&blockquote&&p&首先:查看你是否有../ssh 这个文件;
怎么查看;找到你的git安装目录,在安装目录下查看是否./ssh&/p&&/blockquote&&a href=&/?target=https%3A///a/5526& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&如何优雅地连接ssh&i class=&icon-external&&&/i&&/a&&blockquote&&p&作为一个开发者,经常要面对管理一大堆服务器的情况,对unix类服务器,我们一般用ssh连接来管理。那么你一般怎么连接ssh,输入密码?弱爆了,既难得记,又不安全。现在俺们都用证书来连接&/p&&/blockquote&&a href=&/?target=https%3A///a/9374& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&ssh登录的调试方法和常见问题&i class=&icon-external&&&/i&&/a&&blockquote&&p&ssh登录服务器是程序猿日常生活必不可少的一部分,也时不时的会遇到自己配置ssh登录的问题,拿日常使用的git来讲,不管使用github也好,还是自己搭建的gitlab等等,如果不能很好的理解ssh的原理,极容易遇到各种问题。这篇文章就尝试向大家简单讲解下ssh的原理、调试方式和常见问题。这里要讲的主要是免密码登录,也就是使用密钥登录的方式。&/p&&/blockquote&&p&下面这个问题相信一定有小伙伴遇到过。&/p&&a href=&/?target=https%3A///a/5592& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&解决向github提交代码不用输入帐号密码&i class=&icon-external&&&/i&&/a&&blockquote&&p&方案一与方案二都是创建 .git-credential 文件并写入用户信息,一个是手动创建,一个命令创建。&/p&&/blockquote&&a href=&/?target=https%3A///a/7713& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&git:如何管理本机的多个ssh密钥&i class=&icon-external&&&/i&&/a&&blockquote&&p&我们可能会需要在一台电脑上以不同的github账户去使用git,这时就需要去解决如何管理本机上的多个ssh key的问题了。&/p&&/blockquote&&a href=&/?target=https%3A///a/0544& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&git/ssh捋不清的几个问题&i class=&icon-external&&&/i&&/a&&blockquote&&p&主要是 windows 用户会遇到很多纠结的问题,linux/unix 用户属于这方面的高端用户,应该有能力处理此类问题,而且网络上也有很多解决方案,本文的受众是 windows 用户。由于今天配置了一下午,虽说配置过程基本搞清楚,懒得重新配置一遍,所以文中皆以文字形式叙述,没有截图。&/p&&/blockquote&&h2&个人博客&/h2&&blockquote&&p&GitHub Pages 是通过我们的网站托管和发布的公共网页。
你可以通过在线生成器创建和发布GitHub Pages页面。如果你偏爱本地操作,你可以使用Mac和Windows的GUI软件,或者是命令行。&/p&&/blockquote&&h3&GitHub Pages&/h3&&a href=&/?target=https%3A///a/3246& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Github 是如何用 Github 撰写 Github 文档的&i class=&icon-external&&&/i&&/a&&blockquote&&p&文档团队通过 Github 利用 Github 的工作流程(译者注:即前文提到的 Markdown 编写内容,PR 提交等),Jekyll 以及 Github Pages 服务来提供一个高质量的文档。Github Pages 提供给我们文档团队的好处同样对每一个运行 Github Pages 的站点都是可用的。&/p&&/blockquote&&a href=&/?target=https%3A///a/1418& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&使用github的pages服务建立项目主页的注意事项&i class=&icon-external&&&/i&&/a&&blockquote&&ul&&li&确保你的&a href=&/?target=http%3A//username.github.io& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&username.github.io&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a&不会跳到别的站点&/li&&li&解决gh-pages分支clone到本地后出现push冲突&/li&&/ul&&/blockquote&&p&有任何问题,可以查看帮助文档。&/p&&a href=&/?target=https%3A///a/6905& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&翻译自 GitHub Pages的 Help 页面(仍在更新中)&i class=&icon-external&&&/i&&/a&&h3&Jekyll&/h3&&p&又一个系列教程。&/p&&a href=&/?target=https%3A///a/6011& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&使用Jekyll在Github上搭建个人博客(环境搭建)&i class=&icon-external&&&/i&&/a&&blockquote&&p&Jekyll将原始文本根据一定规则转换成静态的网页和博客。但这个转换并不是简单的字符串替换就了事了,而是首先读取各个文件中的内容,根据配置文件中描述的参数在内存中构建一个巨大的对象存储整个博客的信息,然后再将这些信息根据配置文件中定义的输出方式来生成具体的HTML文件。整个项目是由Ruby写的,所以若需要在本地调试则需要安装Ruby。&/p&&/blockquote&&a href=&/?target=https%3A///a/6013& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&使用Jekyll在Github上搭建个人博客(博客编写)&i class=&icon-external&&&/i&&/a&&blockquote&&p&这篇文章主要介绍博客内容的编写及本地测试,内容主要来自Jekyll的文档、Liquid的文档&/p&&/blockquote&&a href=&/?target=https%3A///a/6015& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&使用Jekyll在Github上搭建个人博客(分页实现)&i class=&icon-external&&&/i&&/a&&blockquote&&p&之前已经介绍了如何搭建环境和如何创建整个博客项目,并编写了博文,这篇文章主要就是介绍分页功能如何通过jekyll实现。&/p&&/blockquote&&a href=&/?target=https%3A///a/6017& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&使用Jekyll在Github上搭建个人博客(文章分类索引)&i class=&icon-external&&&/i&&/a&&blockquote&&ul&&li&使用Category分类&/li&&li&使用文章标签索引文章&/li&&/ul&&/blockquote&&a href=&/?target=https%3A///a/6019& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&使用Jekyll在Github上搭建个人博客(将本地博客上传至github)&i class=&icon-external&&&/i&&/a&&blockquote&&ul&&li&预先准备&/li&&li&对已有项目进行git初始化&/li&&li&创建一个名为gh-pages的分支&/li&&li&发布&/li&&li&上传到github&/li&&li&修改后提交&/li&&/ul&&/blockquote&&h3&hexo&/h3&&p&hexo,更快,更轻,更简洁。你值得拥有~&/p&&a href=&/?target=https%3A///a/8953& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&使用Github搭建静态博客(Hexo)&i class=&icon-external&&&/i&&/a&&blockquote&&p&之前我一直在使用wordpress(下称wp),就在前些日子,我爱上了markdown,但在wp上又没找到完美一点兼容markdown的插件。慢慢地,越来越觉得wp很臃肿,最终,我选择了放弃它了。现在,我选择了一个基于node.js的小萝莉hexo。&/p&&/blockquote&&a href=&/?target=https%3A///a/3715& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&途牛原创|如何使用 hexo+github 搭建个人博客&i class=&icon-external&&&/i&&/a&&blockquote&&p&要想搭建漂亮的 blog,还需要模板系统,官方推荐的是 jekyll,但是配置稍复杂,今天推荐另一个选择 —— hexo,一个简单地、轻量地、基于 Node 的一个静态博客框架。&/p&&/blockquote&&a href=&/?target=https%3A///a/3053& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&使用 hexo + github pages快速搭建个人博客&i class=&icon-external&&&/i&&/a&&blockquote&&p&Hexo是一个基于Nodejs快速简洁高效的博客框架,Hexo使用Markdown语法来编辑文章,只需要几秒钟的时间就可以成生静态的网页。整个系统就是一个博客系统。&/p&&/blockquote&&h3&Github Issues&/h3&&p&嗯,是的,github issues 还可以这样用。&/p&&a href=&/?target=https%3A///a/0568& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&基于 Github Issues 的单页面静态博客&i class=&icon-external&&&/i&&/a&&blockquote&&p&Wordpress 、Typecho 太重,还要买 VPS、部署服务器环境、安装插件、主题,太折腾人,于是我想,完全可以利用 Github 提供的 API 来实现一个只有一个静态页面的博客,具体思路如下:&/p&&ul&&li&作者在 Github issues 上写文章(写 issues)&/li&&li&博客页面通过 JS Ajax 请求 Github API 来获取文章内容,进行页面的渲染&/li&&li&通过社会化评论插件实现评论功能&/li&&/ul&&p&于是花了几天时间实现了这个设想&/p&&/blockquote&&a href=&/?target=https%3A///p/7081/read& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Gitment:使用 GitHub Issues 搭建评论系统&i class=&icon-external&&&/i&&/a&&blockquote&&p&Gitment 是作者实现的一款基于 GitHub Issues 的评论系统。支持在前端直接引入,不需要任何后端代码。可以在页面进行登录、查看、评论、点赞等操作,同时有完整的 Markdown / GFM 和代码高亮支持。尤为适合各种基于 GitHub Pages 的静态博客或项目页面。&/p&&/blockquote&&h2&展示自己的项目&/h2&&a href=&/?target=https%3A///a/9130& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&用Github Pages展示你的项目&i class=&icon-external&&&/i&&/a&&blockquote&&p&Github Pages,让用户能够自定义项目首页,同时,让其编写的网页能够通过域名访问直接展示出来。Github Pages被当作是用户编写的、托管在github上的静态网页,Github提供了一定的空间供开发者存放静态网页。&/p&&/blockquote&&a href=&/?target=https%3A///a/5992& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&如何在github上创建个人项目的在线演示demo&i class=&icon-external&&&/i&&/a&&blockquote&&p&在github上搜索相关项目时会发现,有的项目不光写了一手好文档并且还给出了项目的在线运行Demo。事实胜于雄辩,一个在线演示可能给项目带来更好的印象分。如何在github上维护自己个人项目源代码的同时并生成项目主页呢?&/p&&/blockquote&&a href=&/?target=https%3A///a/4336& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&用github来展示你的前端页面吧&i class=&icon-external&&&/i&&/a&&blockquote&&p&经常会有人问我如何才能将自己做的静态页面放到网上供他人欣赏,是不是需要自己有一个服务器,是不是还要搞个域名才能访问?对于以上问题我都会回答:用github来展示你的前端页面吧。&/p&&/blockquote&&h2&优秀的开源项目&/h2&&a href=&/?target=https%3A///a/5248& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&大牛公司github官网整理&i class=&icon-external&&&/i&&/a&&br&&a href=&/?target=https%3A///p/0675/read& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&2016 年度 GitHub 上 Stars 最多的10个项目&i class=&icon-external&&&/i&&/a&&br&&a href=&/?target=https%3A///a/7798& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&工作中经常用到github上优秀、实用、轻量级、无依赖的插件和库&i class=&icon-external&&&/i&&/a&&br&&a href=&/?target=https%3A///a/4472& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&github上值得关注的前端项目&i class=&icon-external&&&/i&&/a&&br&&a href=&/?target=https%3A///a/5948& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&react闲谈——推荐几个github上超级star的异步插件&i class=&icon-external&&&/i&&/a&&br&&h2&GitHub 助攻利器&/h2&&a href=&/?target=https%3A///a/2540& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&用Node.js做一个GitHub爬虫&i class=&icon-external&&&/i&&/a&&blockquote&&p&用Node.js写了一个爬虫,可以获取GitHub各种编程语言star数前十的库&/p&&/blockquote&&a href=&/?target=https%3A///a/2990& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&分享一个自己写的github-trending小工具&i class=&icon-external&&&/i&&/a&&blockquote&&p&Github Trending基本上是我每天都会浏览的网页,上面会及时发布一些GIthub上比较有潜力的项目,或者说每日Star数增量排行榜。
不过由于Github Trending经常会实时更新,即使你访问得再勤,难免还是会错过一些你感兴趣的项目,为此不少人都想出了自己的解决办法,例如josephyzhou,他的github-trending 项目得到了众多人的青睐,我仔细阅读了他的源码 (Go),发现实现也较为简单, 就用Python 重写了一下,发现代码少了好多,详见 我的 github-trending。&/p&&/blockquote&&a href=&/?target=https%3A///p/5834/read& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&专门为Github党打造的超级无敌Chrome插件&i class=&icon-external&&&/i&&/a&&blockquote&&p&作为GitHub党,分享一些好用的Chrome插件,帮助增强Github功能。标题名称在Chrome插件商场搜索,即可安装对应的插件。&/p&&/blockquote&&a href=&/?target=https%3A///p/6770/read& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&如果你用GitHub,可以这样提高效率 | BlueSun&i class=&icon-external&&&/i&&/a&&blockquote&&p&迁移到Github之后,我们开始接入各方工具,提高我们的工作效率(钱可不能白花啊)。&/p&&/blockquote&&a href=&/?target=https%3A///a/1099& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Git-WebHook 自动化部署工具 - 支持Github / GitLab / Gogs / GitOsc&i class=&icon-external&&&/i&&/a&&blockquote&&p&Git WebHook 是一个使用 Python Flask + SQLAchemy + Celery + Redis + React 开发的用于迅速搭建并使用 WebHook 进行自动化部署和运维系统,支持:Github / GitLab / Gogs / GitOsc。&/p&&/blockquote&&a href=&/?target=https%3A///a/4686& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【Chrome插件】Github Travis Stat&i class=&icon-external&&&/i&&/a&&blockquote&&p&最近自己写了一个Chrome浏览器扩展/插件(github repo),并将其发布到了谷歌官方商店(chrome web store),该插件为github上的仓库提供travis-ci运行状态和运行时间的图表,你可以直观地了解到哪些仓库(自己或者别人的)开通了travis-ci的build,还可以看到特定repo近十次build的时间和状态变化,鼠标置于具体build上,还可查看具体build时间和message,点击还可以进入特定的travis-ci build页面。&/p&&/blockquote&&a href=&/?target=https%3A///a/4416& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Chrome插件 GitHub-Chart Commits3D直方图视图&i class=&icon-external&&&/i&&/a&&blockquote&&p&现在没有多少人不用github,使用频率很高,首页的contributions对于我们了解自己和别人的提交记录比较有帮助,简直是交友神器,修改成立体直方图以后更加直观。&/p&&/blockquote&&a href=&/?target=https%3A///a/7085& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&[开源] 分享自己用的 GitHub 分组管理工具.&i class=&icon-external&&&/i&&/a&&blockquote&&p&我们平时搜索发现 GitHub 上的不错的 Repo 就点 Star 的方式收藏了起来,想哪天会用到,但真的要用时也想不起来叫什么了,而且越收藏就越多,找出来也很费劲的,网友呼吁 GitHub 出个 Tag 的功能,但官方似乎已经回应不会做此功能了。&/p&&/blockquote&&a href=&/?target=https%3A///a/8777& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Markcook 1.2,超轻的开源markdown编辑器&i class=&icon-external&&&/i&&/a&&blockquote&&p&使用了vue.js+webpack进行开发和构建。非常的简单,高效,没有多余的东西。&/p&&/blockquote&&a href=&/?target=https%3A///a/2628& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&保存代码段的利器Gist & GistBox&i class=&icon-external&&&/i&&/a&&blockquote&&p&GitHub提供的Gist服务简直是保存代码段的神器!可以把gist当做一个小型仓库,具有版本控制,markdown。从网上的搜索的结果来看,好像在10年就推出了这项服务,真是知道的太晚了!请允许我大呼『工具改变生活!』『工具改变程序员的生活!』&/p&&/blockquote&&h2&GitHub 小贴士&/h2&&a href=&/?target=https%3A///a/9780& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&github emoji 表情列表&i class=&icon-external&&&/i&&/a&&br&&a href=&/?target=https%3A///a/0252& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&关于 Git 和 Github 你不知道的十件事&i class=&icon-external&&&/i&&/a&&br&&a href=&/?target=https%3A///p/8723/read& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&github博客绑定个性域名&i class=&icon-external&&&/i&&/a&&br&&a href=&/?target=https%3A///a/0290& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&程序员必备技能:在Github上部署自己的简历&i class=&icon-external&&&/i&&/a&&br&&a href=&/?target=https%3A///p/2731/read& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&第三方登入例子-GitHub授权登入(node-koa)&i class=&icon-external&&&/i&&/a&&br&&a href=&/?target=https%3A///a/4521& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Github用法总结(持续更新)&i class=&icon-external&&&/i&&/a&&br&&a href=&/?target=https%3A///p/3982/read& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&跟着 Github 学习 Restful HTTP API 设计&i class=&icon-external&&&/i&&/a&&br&&a href=&/?target=https%3A///a/1562& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Markdown的各种扩展&i class=&icon-external&&&/i&&/a&&br&&a href=&/?target=https%3A///a/9149& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&GitHub:技巧集合&i class=&icon-external&&&/i&&/a&&br&&a href=&/?target=https%3A///a/6969& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&单个GitHub帐号下添加多个GitHub Pages的相关问题&i class=&icon-external&&&/i&&/a&&br&&a href=&/?target=https%3A///a/5735& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&面试经:GitHub&i class=&icon-external&&&/i&&/a&&blockquote&&p&&strong&# SegmentFault 技术周刊 #&/strong&&/p&&p&「技术周刊」是社区特别推出的技术内容系列,一周一主题。周刊筛选的每篇内容,是作者的独到见解,踩坑总结和经验分享。&/p&&p&每周四更新,欢迎「&a href=&/?target=https%3A///blog/weekly& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&关注&i class=&icon-external&&&/i&&/a&」或者「&a href=&/?target=https%3A///blog/weekly& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&订阅&i class=&icon-external&&&/i&&/a&」。大家也可以在评论处留言自己感兴趣的主题,推荐主题相关的优秀文章。&/p&&/blockquote&
相信每一个程序猿都听说过 GitHub 了,简单来说 GitHub 是一个主要提供基于 Git 来进行版本控制的项目托管服务的网站,她是世界上最大的开源软件社区,世界各地的程序猿在 GitHub 上开源自己的项目,关注和参与自己感兴趣的开源项目,嗯,同时 GitHub 还是…
&figure&&img src=&/50/v2-4dce785ff11ab0055d33_b.png& data-rawwidth=&967& data-rawheight=&736& class=&origin_image zh-lightbox-thumb& width=&967& data-original=&/50/v2-4dce785ff11ab0055d33_r.png&&&/figure&&h2&前言&/h2&&p&JavaScript绝对是最火的编程语言之一,一直具有很大的用户群,随着在服务端的使用(NodeJs),更是爆发了极强的生命力。编程语言分为编译型语言和解释型语言两类,编译型语言在执行之前要先进行完全编译,而解释型语言一边编译一边执行,很明显解释型语言的执行速度是慢于编译型语言的,而JavaScript就是一种解释型脚本语言,支持动态类型、弱类型、基于原型的语言,内置支持类型。鉴于JavaScript都是在前端执行,而且需要及时响应用户,这就要求JavaScript可以快速的解析及执行。&/p&&p&随着Web相关技术的发展,JavaScript所要承担的工作也越来越多,早就超越了“表单验证”的范畴,这就更需要快速的解析和执行JavaScript脚本。V8引擎就是为解决这一问题而生,在node中也是采用该引擎来解析JavaScript。&/p&&p&V8是如何使得JavaScript性能有大幅提升的呢?通过对一些书籍和文章的学习,梳理了V8的相关内容,本文将带你认识 V8。(该文在 17 年初发布于公司内网,反响不错,近来闲暇再次整理作为知乎的第一篇分享,希望帮助更多的人了解 V8 引擎。&b&转载需经过本人同意&/b&)&/p&&h2&1.渲染引擎及网页渲染&/h2&&p&浏览器自从上世纪80年代后期90年代初期诞生以来,已经得到了长足的发展,其功能也越来越丰富,包括网络、资源管理、网页浏览、多页面管理、插件和扩展、书签管理、历史记录管理、设置管理、下载管理、账户和同步、安全机制、隐私管理、外观主题、开发者工具等。在这些功能中,为用户提供网页浏览服务无疑是最重要的功能,下面将对相关内容进行介绍。&/p&&h2&1.1.渲染引擎&/h2&&p&渲染引擎:能够将HTML/CSS/JavaScript文本及相应的资源文件转换成图像结果。渲染引擎的主要作用是将资源文件转化为用户可见的结果。在浏览器的发展过程中,不同的厂商开发了不同的渲染引擎,如Tridend(IE)、Gecko(FF)、WebKit(Safari,Chrome,Andriod浏览器)等。WebKit是由苹果2005年发起的一个开源项目,引起了众多公司的重视,几年间被很多公司所采用,在移动端更占据了垄断地位。更有甚者,开发出了基于WebKit的支持HTML5的web操作系统(如:Chrome OS、Web OS)。&/p&&p&下面是WebKit的大致结构:&br&&/p&&figure&&img src=&/v2-fe2cbc2d9a437ef81dff328_b.png& data-rawwidth=&749& data-rawheight=&395& class=&origin_image zh-lightbox-thumb& width=&749& data-original=&/v2-fe2cbc2d9a437ef81dff328_r.png&&&/figure&&p&上图中实线框内模块是所有移植的共有部分,虚线框内不同的厂商可以自己实现。下面进行介绍:&/p&&ul&&li&操作系统:是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在“裸机”上的最基本的系统软件,任何其他软件都必须在操作系统的支持下才能运行。WebKit也是在操作系统上工作的。&/li&&li&第三方库,为了WebKit提供支持,如图形库、网络库、视频库等。&/li&&li&WebCore 是各个浏览器使用的共享部分,包括HTML解析器、CSS解析器、DOM和SVG等。JavaScriptCore是WebKit的默认引擎,在谷歌系列产品中被替换为V8引擎。WebKit Ports是WebKit中的非共享部分,由于平台差异、第三方库和需求的不同等原因,不同的移植导致了WebKit不同版本行为不一致,它是不同浏览器性能和功能差异的关键部分。&/li&&li&WebKit嵌入式编程接口,供浏览器调用,与移植密切相关,不同的移植有不同的接口规范。&/li&&li&测试用例,包括布局测试用例和性能测试用例,用来验证渲染结果的正确性。&/li&&/ul&&h2&1.2.网页渲染流程&/h2&&p&上面介绍了渲染引擎的各个模块,那么一张网页,要经历怎样的过程,才能抵达用户面前?&br&&/p&&figure&&img src=&/v2-ad0a86d3fafbd22658feadc3_b.png& data-rawwidth=&750& data-rawheight=&351& class=&origin_image zh-lightbox-thumb& width=&750& data-original=&/v2-ad0a86d3fafbd22658feadc3_r.png&&&/figure&&p&首先是网页内容,输入到HTML解析器,HTML解析器解析,然后构建DOM树,在这期间如果遇到JavaScript代码则交给JavaScript引擎处理;如果来自CSS解析器的样式信息,构建一个内部绘图模型。该模型由布局模块计算模型内部各个元素的位置和大小信息,最后由绘图模块完成从该模型到图像的绘制。在网页渲染的过程中,大致可分为下面3个阶段。&/p&&h2&1.2.1.从输入URL到生成DOM树&/h2&&ol&&li&地址栏输入URL,WebKit调用资源加载器加载相应资源;&/li&&li&加载器依赖网络模块建立连接,发送请求并接收答复;&/li&&li&WebKit接收各种网页或者资源数据,其中某些资源可能同步或异步获取;&/li&&li&网页交给HTML解析器转变为词语;&/li&&li&解释器根据词语构建节点,形成DOM树;&/li&&li&如果节点是JavaScript代码,调用JavaScript引擎解释并执行;&/li&&li&JavaScript代码可能会修改DOM树结构;&/li&&li&如果节点依赖其他资源,如图片\css、视频等,调用资源加载器加载它们,但这些是异步加载的,不会阻碍当前DOM树继续创建;如果是JavaScript资源URL(没有标记异步方式),则需要停止当前DOM树创建,直到JavaScript加载并被JavaScript引擎执行后才继续DOM树的创建。&/li&&/ol&&h2&1.2.2.从DOM树到构建WebKit绘图上下文&/h2&&ol&&li&CSS文件被CSS解释器解释成内部表示;&/li&&li&CSS解释器完成工作后,在DOM树上附加样式信息,生成RenderObject树;&/li&&li&RenderObject节点在创建的同时,WebKit会根据网页层次结构构建RenderLayer树,同时构建一个虚拟绘图上下文。&/li&&/ol&&h2&1.2.3.绘图上下文到最终图像呈现&/h2&&ol&&li&绘图上下文是一个与平台无关的抽象类,它将每个绘图操作桥接到不同的具体实现类,也就是绘图具体实现类;&/li&&li&绘图实现类也可能有简单的实现,也可能有复杂的实现,软件渲染、硬件渲染、合成渲染等;&/li&&li&绘图实现类将2D图形库或者3D图形库绘制结果保存,交给浏览器界面进行展示。&/li&&/ol&&p&上述是一个完整的渲染过程,现代网页很多都是动态的,随着网页与用户的交互,浏览器需要不断的重复渲染过程。&/p&&h2&1.3.JavaScript引擎&/h2&&figure&&img src=&/v2-0fe237dcfae2d34a306788_b.png& data-rawwidth=&789& data-rawheight=&272& class=&origin_image zh-lightbox-thumb& width=&789& data-original=&/v2-0fe237dcfae2d34a306788_r.png&&&/figure&&p&JavaScript本质上是一种解释型语言,与编译型语言不同的是它需要一遍执行一边解析,而编译型语言在执行时已经完成编译,可直接执行,有更快的执行速度(如上图所示)。JavaScript代码是在浏览器端解析和执行的,如果需要时间太长,会影响用户体验。那么提高JavaScript的解析速度就是当务之急。JavaScript引擎和渲染引擎的关系如下图所示:&/p&&figure&&img src=&/v2-43b71b75cd4f28db05ab967e3aad5a97_b.png& data-rawwidth=&750& data-rawheight=&176& class=&origin_image zh-lightbox-thumb& width=&750& data-original=&/v2-43b71b75cd4f28db05ab967e3aad5a97_r.png&&&/figure&&p&JavaScript语言是解释型语言,为了提高性能,引入了Java虚拟机和C++编译器中的众多技术。现在JavaScript引擎的执行过程大致是:&/p&&p&源代码-→抽象语法树-→字节码-→JIT-→本地代码(V8引擎没有中间字节码)。一段代码的抽象语法树示例如下:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&function demo(name) {
console.log(name);
&/code&&/pre&&/div&&p&抽象语法树如下:&br&&/p&&figure&&img src=&/v2-4ee7dc5cff203c41a1482b_b.png& data-rawwidth=&928& data-rawheight=&356& class=&origin_image zh-lightbox-thumb& width=&928& data-original=&/v2-4ee7dc5cff203c41a1482b_r.png&&&/figure&&p&V8更加直接的将抽象语法树通过JIT技术转换成本地代码,放弃了在字节码阶段可以进行的一些性能优化,但保证了执行速度。在V8生成本地代码后,也会通过Profiler采集一些信息,来优化本地代码。虽然,少了生成字节码这一阶段的性能优化,但极大减少了转换时间。&/p&&p&但是在2017年4月底,v8 的 5.9 版本发布了,新增了一个 Ignition 字节码解释器,将默认启动,从此之后将与JSCore有大致相同的流程。做出这一改变的原因为:(主要动机)减轻机器码占用的内存空间,即牺牲时间换空间;提高代码的启动速度;对 v8 的代码进行重构,降低 v8 的代码复杂度(&a href=&/?target=https%3A//cnodejs.org/topic/59084a9cbbaf2f3f569be482& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&V8 Ignition:JS 引擎与字节码的不解之缘 - CNode技术社区&i class=&icon-external&&&/i&&/a&)。&/p&&p&JavaScript的性能和C相比还有不小的距离,可预见的未来估计也只能接近它,而不是与它相比,这从语言类型上已经决定。下面将对V8引擎进行更为细致的介绍。&/p&&h2&2.V8引擎&/h2&&p&V8引擎是一个JavaScript引擎实现,最初由一些语言方面专家设计,后被谷歌收购,随后谷歌对其进行了开源。V8使用C++开发,,在运行JavaScript之前,相比其它的JavaScript的引擎转换成字节码或解释执行,V8将其编译成原生机器码(IA-32, x86-64, ARM, or MIPS CPUs),并且使用了如内联缓存(inline caching)等方法来提高性能。有了这些功能,JavaScript程序在V8引擎下的运行速度媲美二进制程序。V8支持众多操作系统,如windows、linux、android等,也支持其他硬件架构,如IA32,X64,ARM等,具有很好的可移植和跨平台特性。&br&V8项目代码结构如下:&br&&/p&&figure&&img src=&/v2-cb5e37b2c362adef3be6daf_b.png& data-rawwidth=&800& data-rawheight=&844& class=&origin_image zh-lightbox-thumb& width=&800& data-original=&/v2-cb5e37b2c362adef3be6daf_r.png&&&/figure&&h2&2.1.数据表示&/h2&&p&JavaScript是一种动态类型语言,在编译时并不能准确知道变量的类型,只可以在运行时确定,这就不像c++或者java等静态类型语言,在编译时候就可以确切知道变量的类型。然而,在运行时计算和决定类型,会严重影响语言性能,这也就是JavaScript运行效率比C++或者JAVA低很多的原因之一。&/p&&p&在C++中,源代码需要经过编译才能执行,在生成本地代码的过程中,变量的地址和类型已经确定,运行本地代码时利用数组和位移就可以存取变量和方法的地址,不需要再进行额外的查找,几个机器指令即可完成,节省了确定类型和地址的时间。由于JavaScript是无类型语言,那就不能像c++那样在执行时已经知道变量的类型和地址,需要临时确定。JavaScript 和C++有以下几个区别:&/p&&ul&&li&编译确定位置,C++编译阶段确定位置偏移信息,在执行时直接存取,JavaScript在执行阶段确定,而且执行期间可以修改对象属性;&/li&&li&偏移信息共享,C++有类型定义,执行时不能动态改变,可共享偏移信息,JavaScript每个对象都是自描述,属性和位置偏移信息都包含在自身的结构中;&/li&&li&偏移信息查找,C++查找偏移地址很简单,在编译代码阶段,对使用的某类型成员变量直接设置偏移位置,JavaScript中使用一个对象,需要通过属性名匹配才能找到相应的值,需要更多的操作。&/li&&/ul&&p&在代码执行过程中,变量的存取是非常普遍和频繁的,通过偏移量来存取,使用少数两个汇编指令就能完成,如果通过属性名匹配则需要更多的汇编指令,也需要更多的内存空间。示例如下:&br&&/p&&figure&&img src=&/v2-794bcbccff_b.jpg& data-rawwidth=&669& data-rawheight=&320& class=&origin_image zh-lightbox-thumb& width=&669& data-original=&/v2-794bcbccff_r.jpg&&&/figure&&p&在JavaScript中,除boolean,number,string,null,undefined这个五个简单变量外,其他的数据都是对象,V8使用一种特殊的方式来表示它们,进而优化JavaScript的内部表示问题。&/p&&p&在V8中,数据的内部表示由数据的实际内容和数据的句柄构成。数据的实际内容是变长的,类型也是不同的;句柄固定大小,包含指向数据的指针。这种设计可以方便V8进行垃圾回收和移动数据内容,如果直接使用指针的话就会出问题或者需要更大的开销,使用句柄的话,只需修改句柄中的指针即可,使用者使用的还是句柄,指针改动是对使用者透明的。&/p&&p&除少数数据(如整型数据)由handle本身存储外,其他内容限于句柄大小和变长等原因,都存储在堆中。整数直接从value中取值,然后使用一个指针指向它,可以减少内存的占用并提高访问速度。一个句柄对象的大小是4字节(32位设备)或者8字节(64位设备),而在JavaScriptCore中,使用的8个字节表示句柄。在堆中存放的对象都是4字节对齐的,所以它们指针的后两位是不需要的,V8用这两位表示数据的类型,00为整数,01为其他。&/p&&p&JavaScript对象在V8中的实现包含三个部分:隐藏类指针,这是v8为JavaScript对象创建的隐藏类;属性值表指针,指向该对象包含的属性值;元素表指针,指向该对象包含的属性。&/p&&h2&2.2.工作过程&/h2&&p&前面有过介绍,V8引擎在执行JavaScript的过程中,主要有两个阶段:编译和运行,与C++的执行前完全编译不同的是,JavaScript需要在用户使用时完成编译和执行。在V8中,JavaScript相关代码并非一下完成编译的,而是在某些代码需要执行时,才会进行编译,这就提高了响应时间,减少了时间开销。在V8引擎中,源代码先被解析器转变为抽象语法树(AST),然后使用JIT编译器的全代码生成器从AST直接生成本地可执行代码。这个过程不同于JAVA先生成字节码或中间表示,减少了AST到字节码的转换时间,提高了代码的执行速度。但由于缺少了转换为字节码这一中间过程,也就减少了优化代码的机会。&/p&&p&V8引擎编译本地代码时使用的主要类如下所示:&/p&&ul&&li&Script:表示JavaScript代码,即包含源代码,又包含编译之后生成的本地代码,即是编译入口,又是运行入口;&/li&&li&Compiler:编译器类,辅组Script类来编译生成代码,调用解释器(Parser)来生成AST和全代码生成器,将AST转变为本地代码;&/li&&li&AstNode:抽象语法树节点类,是其他所有节点的基类,包含非常多的子类,后面会针对不同的子类生成不同的本地代码;&/li&&li&AstVisitor:抽象语法树的访问者类,主要用来遍历异构的抽象语法树;&/li&&li&FullCodeGenerator:AstVisitor类的子类,通过遍历AST来为JavaScript生成本地可执行代码。&/li&&/ul&&figure&&img src=&/v2-274bcd0e43b8b718ce58de8ae51e1b70_b.png& data-rawwidth=&820& data-rawheight=&342& class=&origin_image zh-lightbox-thumb& width=&820& data-original=&/v2-274bcd0e43b8b718ce58de8ae51e1b70_r.png&&&/figure&&p&JavaScript代码编译的过程大致为:Script类调用Compiler类的Compile函数为其生成本地代码。Compile函数先使用Parser类生成AST,再使用FullCodeGenerator类来生成本地代码。本地代码与具体的硬件平台密切相关,FullCodeGenerator使用多个后端来生成与平台相匹配的本地汇编代码。由于FullCodeGenerator通过遍历AST来为每个节点生成相应的汇编代码,缺失了全局视图,节点之间的优化也就无从谈起。&/p&&p&在执行编译之前,V8会构建众多全局对象并加载一些内置的库(如math库),来构建一个运行环境。而且在JavaScript源代码中,并非所有的函数都被编译生成本地代码,而是延迟编译,在调用时才会编译。&/p&&p&由于V8缺少了生成中间代码这一环节,缺少了必要的优化,为了提升性能,V8会在生成本地代码后,使用数据分析器(profiler)采集一些信息,然后根据这些数据将本地代码进行优化,生成更高效的本地代码,这是一个逐步改进的过程。同时,当发现优化后代码的性能还不如未优化的代码,V8将退回原来的代码,也就是优化回滚。下面介绍一下运行阶段,该阶段使用的主要类如下所示:&/p&&ul&&li&Script:表示JavaScript代码,即包含源代码,又包含编译之后生成的本地代码,即是编译入口,又是运行入口;&/li&&li&Execution:运行代码的辅组类,包含一些重要函数,如Call函数,它辅组进入和执行Script代码;&/li&&li&JSFunction:需要执行的JavaScript函数表示类;&/li&&li&Runtime:运行这些本地代码的辅组类,主要提供运行时所需的辅组函数,如:属性访问、类型转换、编译、算术、位操作、比较、正则表达式等;&/li&&li&Heap:运行本地代码需要使用的内存堆类;&/li&&li&MarkCompactCollector:垃圾回收机制的主要实现类,用来标记、清除和整理等基本的垃圾回收过程;&/li&&li&SweeperThread:负责垃圾回收的线程。&/li&&/ul&&figure&&img src=&/v2-d9eaec9fcfe3_b.png& data-rawwidth=&801& data-rawheight=&307& class=&origin_image zh-lightbox-thumb& width=&801& data-original=&/v2-d9eaec9fcfe3_r.png&&&/figure&&p&先根据需要编译和生成这些本地代码,也就是使用编译阶段那些类和操作。在V8中,函数是一个基本单位,当某个JavaScript函数被调用时,V8会查找该函数是否已经生成本地代码,如果已经生成,则直接调用该函数。否则,V8引擎会生成属于该函数的本地代码。这就节约了时间,减少了处理那些使用不到的代码的时间。其次,执行编译后的代码为JavaS

我要回帖

更多关于 html 条件判断语句 的文章

 

随机推荐