├── assets ├── 浮动如何工作 │ ├── 1.png │ ├── 4.png │ ├── 5.png │ ├── 6.png │ ├── 3.1.png │ ├── 3.2.png │ ├── clear-left.png │ └── clear-only-left.png ├── Medium图片加载模式 │ ├── medium-codepen.png │ ├── medium-placeholder.png │ └── google-images-placeholder.png ├── Aligning Text Smartly in CSS │ └── smart-text-alignment1.png └── What are CSS Modules and why do we need them? │ └── devtools.png ├── D3数据绑定(Data Join) ├── 数据绑定(Data Join).pdf ├── resources │ ├── 04DEC69A3C2DEDA5A4D53498E58E34A8.jpg │ ├── 1542C02CCA35201C28B20FC678D63B4F.jpg │ ├── 2F56859869DE44F8B4BD35E91EE0995D.jpg │ ├── AADA008DF9FC795C84F53C6E584FC17F.jpg │ └── B5954156DB042D466A47460E429A1AFB.jpg └── 数据绑定(Data Join).md ├── Notes ├── (Wating 译) position sticky scroll-to-top-then-fixed in pure CSS.md └── (wating译)Create a Masked Background Effect With CSS.md ├── (译)浮动如何工作 ├── resources │ ├── 47DA75D281581EB02A37B845235844B7.png │ ├── 4AB4CFD9AEF9E9887DDBB88EF18C68B7.png │ ├── 649CDF66F7A4EF965BE3ED4BE2A0C076.png │ ├── 71385E9749EFC1C742C5817BED06B517.png │ ├── 71AC15206FD8584EE101FE404CEDA60C.png │ ├── 98CCF9932DCB1193B0ACC115C6C5A7F3.png │ ├── A83F47285953F203A542F08D5AF5E24D.png │ └── D5234070AA4B725A7C729C1E8A46997B.png └── (译)浮动如何工作.md ├── (译)calc()如何工作 ├── resources │ └── 256631EEDD51A1C975F87B4D9968DCBD.png └── (译)calc()如何工作.md ├── All About Scale ├── resources │ ├── 00AC53CCB0E60DAE78601D008A330DD2.jpg │ ├── 2B72CCCD983037D48DA4BE8C84986679.jpg │ ├── 58364E51BB965A3B373FF03AE903B378.jpg │ ├── 76B8DDF6B72ECDBE35D5E90BB815044E.jpg │ ├── 77ABF4C7DE077DA3AABB50477118CB96.jpg │ ├── 80AAEE96189C177B6B55AB26F2876BFD.jpg │ ├── 814C566470B70DD9842153B31DFE3371.jpg │ ├── 88115E5C690B5E7E771A6B8E117D6D32.jpg │ ├── 8ADC1C01BC6EE4A96AFB7465D1BF70B1.jpg │ ├── 8BA5AA3083122EF3600EEE863BA2436F.jpg │ ├── 90C7A7FEB981E17F299A9DEE3F1D21AC.jpg │ ├── 958F68E12E5B5EEDE95DB98FEBAB4257.jpg │ ├── A3FD7BC43B87EE5CA1273F14486736FA.jpg │ ├── AD49AFB571F27382B24FF02264127D11.jpg │ ├── B94D1E47287872078676C8004E533C6A.jpg │ ├── D2D06F62089CA3DD9EBB213C9A6E9141.jpg │ └── EC39D4E27AF6F426998A8A993E588E35.jpg └── All About Scale.md ├── (译)Medium图片加载模式 ├── resources │ ├── 696FCA181E755D5A905F1F83DAFD5DAD.png │ ├── A83270C0F3F66F140BF8BEE934283EE1.png │ └── C4B1AEAA770FB1F8F8DBBB944CA02342.png └── (译)Medium图片加载模式.md ├── (译)理解浏览器的关键渲染路径 ├── resources │ ├── 1E528A75297C9F4B6566DE7E99897BEB.jpg │ ├── 33522AF207FEA0A173E582C7AA4F7427.jpg │ ├── 37531F7B63C81CA9F5E9DE2DC5D06104.jpg │ ├── 52A7B7356D2DE5A100FD0417C732F2BE.jpg │ └── ADDE5C06B4F85308DD405103BC6DCFF1.jpg └── (译)理解浏览器的关键渲染路径.md ├── (译)[D3可视化] 理解数据绑定 ├── resources │ └── E54011E49D927BE97F22604AD6328BEB.jpg └── [可视化D3] 理解数据绑定.md ├── (译)如何处理React中的状态信息 ├── resources │ ├── 0C9039AEEC66BC21665D2706CAEB7BC7.jpg │ ├── 381DBDECF1E5C7B9D479FFC4B9ABE8FB.jpg │ ├── 4E396749CCB87E7982D6F3E978EF229E.jpg │ └── 80DA629F694F0DBB9B5C85C29C065C2D.jpg └── (译)如何处理React中的状态信息.md ├── (译)深入React的children ├── resources │ ├── 003CCE0F944F22C9B2061ED2F817EAC4.jpg │ ├── 406E678AF57519D5DD376790636FDFC8.jpg │ ├── 9A7AD2CBEFAE715079D5130F9D12DCEE.jpg │ ├── BC70E781BC90C42110A8ED2F58B6AE38.jpg │ ├── C544037C8BFEB16594B37B5353AE3516.jpg │ ├── D92089868E199196ADAB5F22B056B2F1.jpg │ ├── DAF4A478E8E2EAA604D6784B9BB29A3D.jpg │ └── F641FFC827F310757F879579FFD81ADD.jpg └── (译)深入React的children.md ├── React 无状态组件: 你忽视掉的9个优点 ├── resources │ └── 21FDDE03858A6573994890CF7AB621D3.jpg └── React 无状态组件 你忽视掉的9个优点.md ├── (译)异步 vs 延迟 JavaScript ├── resources │ ├── 082B354AD417431DE637427DA8206970.jpg │ ├── 111A1AE2581280E5372AD3D2BA088272.jpg │ ├── 57E4C3703F7830609482D0C2913BBB3D.jpg │ ├── 6DE7A0141B14CB773082DD2E8FAFFB94.jpg │ └── E67BD3F73E80EE297848C18DAB29EAEA.jpg └── (译)异步 vs 延迟 JavaScript.md ├── (译)应用Index 作为 key属性值是反模式 ├── resources │ └── 3C2CBF91987508040B42EBDE8644C996.jpg └── (译)应用Index 作为 key属性值是反模式.md ├── [可视化]SVG径向渐变(radialGradient) ├── resources │ ├── 05CCE669285FD5CDF4526F6F9A97F9F5.jpg │ ├── 1C18818464D35FF2B18954B4DEEA64B2.jpg │ ├── 31719A9E336A1396DFF2A5C3A3136483.jpg │ ├── 31BB170061C8E731C490F2C32F8771C4.jpg │ ├── D663AD93E2C1BECF4ACE6929EDA24071.jpg │ └── EE64BD13E2B35A62EAE73CA649DD8AB2.jpg └── [可视化]SVG径向渐变(radialGradient).md ├── [可视化]SVG线性渐变(linearGradient) ├── resources │ ├── 23D3BA32B6A21F7C3321A4FA1B12B556.jpg │ ├── 385FD4405E06C590C8E4E18D3FEA1AC7.jpg │ ├── 3996FC94CDC9D3E1E067BC134B2D20F2.jpg │ ├── 3EAF806A229B22AEE6620EB7A780AF6F.jpg │ ├── 3FDE8D639AD26F649067642EFFA2B454.jpg │ ├── 45C216A5864D22F20633B9534061A4DB.jpg │ ├── BFC9852EB884B08B66CC3042F682781A.jpg │ ├── C240F04F61B943EBF7B227708834D7F2.jpg │ ├── CAAA58C4CC130279783086E6860668D9.jpg │ ├── CEB510CF468A71CACCAF6DA15F12AB53.jpg │ └── D5EFC532794E5F083DBF61433A3F3F04.jpg └── [可视化]SVG线性渐变(linearGradient).md ├── (译)What are CSS Modules and why do we need them? ├── resources │ └── 33634704E521458996F2F64AE77CAC60.png └── (译)What are CSS Modules and why do we need them.md ├── README.md ├── (译)到底要不要用伪元素? └── (译)到底要不要用伪元素?.md ├── ES6小抄(:-D) └── ES6小抄( -D).md ├── (译)函数--JavaScript第一公民 └── (译)函数--JavaScript第一公民.md ├── RXJS入门 └── RXJs.md ├── (译)Prototypes in JavaScript └── (译)Prototypes in JavaScript.md ├── (译)JSTips(41-) └── (译)JSTips(41-).md ├── (译)ES6小抄(:-D) └── (译)ES6小抄( -D).md ├── React-Router V4 简单实现 └── React-Router V4 简单实现.md └── (译)JavaScript面试必知必会 └── JavaScript面试必知必会.md /assets/浮动如何工作/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/assets/浮动如何工作/1.png -------------------------------------------------------------------------------- /assets/浮动如何工作/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/assets/浮动如何工作/4.png -------------------------------------------------------------------------------- /assets/浮动如何工作/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/assets/浮动如何工作/5.png -------------------------------------------------------------------------------- /assets/浮动如何工作/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/assets/浮动如何工作/6.png -------------------------------------------------------------------------------- /assets/浮动如何工作/3.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/assets/浮动如何工作/3.1.png -------------------------------------------------------------------------------- /assets/浮动如何工作/3.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/assets/浮动如何工作/3.2.png -------------------------------------------------------------------------------- /assets/浮动如何工作/clear-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/assets/浮动如何工作/clear-left.png -------------------------------------------------------------------------------- /assets/浮动如何工作/clear-only-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/assets/浮动如何工作/clear-only-left.png -------------------------------------------------------------------------------- /D3数据绑定(Data Join)/数据绑定(Data Join).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/D3数据绑定(Data Join)/数据绑定(Data Join).pdf -------------------------------------------------------------------------------- /assets/Medium图片加载模式/medium-codepen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/assets/Medium图片加载模式/medium-codepen.png -------------------------------------------------------------------------------- /assets/Medium图片加载模式/medium-placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/assets/Medium图片加载模式/medium-placeholder.png -------------------------------------------------------------------------------- /assets/Medium图片加载模式/google-images-placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/assets/Medium图片加载模式/google-images-placeholder.png -------------------------------------------------------------------------------- /Notes/(Wating 译) position sticky scroll-to-top-then-fixed in pure CSS.md: -------------------------------------------------------------------------------- 1 | [原文地址](http://thenewcode.com/1052/position-sticky-scroll-to-top-then-fixed-in-pure-CSS) -------------------------------------------------------------------------------- /Notes/(wating译)Create a Masked Background Effect With CSS.md: -------------------------------------------------------------------------------- 1 | [原文地址]() -------------------------------------------------------------------------------- /(译)浮动如何工作/resources/47DA75D281581EB02A37B845235844B7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)浮动如何工作/resources/47DA75D281581EB02A37B845235844B7.png -------------------------------------------------------------------------------- /(译)浮动如何工作/resources/4AB4CFD9AEF9E9887DDBB88EF18C68B7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)浮动如何工作/resources/4AB4CFD9AEF9E9887DDBB88EF18C68B7.png -------------------------------------------------------------------------------- /(译)浮动如何工作/resources/649CDF66F7A4EF965BE3ED4BE2A0C076.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)浮动如何工作/resources/649CDF66F7A4EF965BE3ED4BE2A0C076.png -------------------------------------------------------------------------------- /(译)浮动如何工作/resources/71385E9749EFC1C742C5817BED06B517.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)浮动如何工作/resources/71385E9749EFC1C742C5817BED06B517.png -------------------------------------------------------------------------------- /(译)浮动如何工作/resources/71AC15206FD8584EE101FE404CEDA60C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)浮动如何工作/resources/71AC15206FD8584EE101FE404CEDA60C.png -------------------------------------------------------------------------------- /(译)浮动如何工作/resources/98CCF9932DCB1193B0ACC115C6C5A7F3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)浮动如何工作/resources/98CCF9932DCB1193B0ACC115C6C5A7F3.png -------------------------------------------------------------------------------- /(译)浮动如何工作/resources/A83F47285953F203A542F08D5AF5E24D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)浮动如何工作/resources/A83F47285953F203A542F08D5AF5E24D.png -------------------------------------------------------------------------------- /(译)浮动如何工作/resources/D5234070AA4B725A7C729C1E8A46997B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)浮动如何工作/resources/D5234070AA4B725A7C729C1E8A46997B.png -------------------------------------------------------------------------------- /(译)calc()如何工作/resources/256631EEDD51A1C975F87B4D9968DCBD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)calc()如何工作/resources/256631EEDD51A1C975F87B4D9968DCBD.png -------------------------------------------------------------------------------- /All About Scale/resources/00AC53CCB0E60DAE78601D008A330DD2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/00AC53CCB0E60DAE78601D008A330DD2.jpg -------------------------------------------------------------------------------- /All About Scale/resources/2B72CCCD983037D48DA4BE8C84986679.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/2B72CCCD983037D48DA4BE8C84986679.jpg -------------------------------------------------------------------------------- /All About Scale/resources/58364E51BB965A3B373FF03AE903B378.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/58364E51BB965A3B373FF03AE903B378.jpg -------------------------------------------------------------------------------- /All About Scale/resources/76B8DDF6B72ECDBE35D5E90BB815044E.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/76B8DDF6B72ECDBE35D5E90BB815044E.jpg -------------------------------------------------------------------------------- /All About Scale/resources/77ABF4C7DE077DA3AABB50477118CB96.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/77ABF4C7DE077DA3AABB50477118CB96.jpg -------------------------------------------------------------------------------- /All About Scale/resources/80AAEE96189C177B6B55AB26F2876BFD.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/80AAEE96189C177B6B55AB26F2876BFD.jpg -------------------------------------------------------------------------------- /All About Scale/resources/814C566470B70DD9842153B31DFE3371.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/814C566470B70DD9842153B31DFE3371.jpg -------------------------------------------------------------------------------- /All About Scale/resources/88115E5C690B5E7E771A6B8E117D6D32.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/88115E5C690B5E7E771A6B8E117D6D32.jpg -------------------------------------------------------------------------------- /All About Scale/resources/8ADC1C01BC6EE4A96AFB7465D1BF70B1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/8ADC1C01BC6EE4A96AFB7465D1BF70B1.jpg -------------------------------------------------------------------------------- /All About Scale/resources/8BA5AA3083122EF3600EEE863BA2436F.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/8BA5AA3083122EF3600EEE863BA2436F.jpg -------------------------------------------------------------------------------- /All About Scale/resources/90C7A7FEB981E17F299A9DEE3F1D21AC.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/90C7A7FEB981E17F299A9DEE3F1D21AC.jpg -------------------------------------------------------------------------------- /All About Scale/resources/958F68E12E5B5EEDE95DB98FEBAB4257.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/958F68E12E5B5EEDE95DB98FEBAB4257.jpg -------------------------------------------------------------------------------- /All About Scale/resources/A3FD7BC43B87EE5CA1273F14486736FA.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/A3FD7BC43B87EE5CA1273F14486736FA.jpg -------------------------------------------------------------------------------- /All About Scale/resources/AD49AFB571F27382B24FF02264127D11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/AD49AFB571F27382B24FF02264127D11.jpg -------------------------------------------------------------------------------- /All About Scale/resources/B94D1E47287872078676C8004E533C6A.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/B94D1E47287872078676C8004E533C6A.jpg -------------------------------------------------------------------------------- /All About Scale/resources/D2D06F62089CA3DD9EBB213C9A6E9141.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/D2D06F62089CA3DD9EBB213C9A6E9141.jpg -------------------------------------------------------------------------------- /All About Scale/resources/EC39D4E27AF6F426998A8A993E588E35.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/All About Scale/resources/EC39D4E27AF6F426998A8A993E588E35.jpg -------------------------------------------------------------------------------- /assets/Aligning Text Smartly in CSS/smart-text-alignment1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/assets/Aligning Text Smartly in CSS/smart-text-alignment1.png -------------------------------------------------------------------------------- /(译)Medium图片加载模式/resources/696FCA181E755D5A905F1F83DAFD5DAD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)Medium图片加载模式/resources/696FCA181E755D5A905F1F83DAFD5DAD.png -------------------------------------------------------------------------------- /(译)Medium图片加载模式/resources/A83270C0F3F66F140BF8BEE934283EE1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)Medium图片加载模式/resources/A83270C0F3F66F140BF8BEE934283EE1.png -------------------------------------------------------------------------------- /(译)Medium图片加载模式/resources/C4B1AEAA770FB1F8F8DBBB944CA02342.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)Medium图片加载模式/resources/C4B1AEAA770FB1F8F8DBBB944CA02342.png -------------------------------------------------------------------------------- /(译)理解浏览器的关键渲染路径/resources/1E528A75297C9F4B6566DE7E99897BEB.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)理解浏览器的关键渲染路径/resources/1E528A75297C9F4B6566DE7E99897BEB.jpg -------------------------------------------------------------------------------- /(译)理解浏览器的关键渲染路径/resources/33522AF207FEA0A173E582C7AA4F7427.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)理解浏览器的关键渲染路径/resources/33522AF207FEA0A173E582C7AA4F7427.jpg -------------------------------------------------------------------------------- /(译)理解浏览器的关键渲染路径/resources/37531F7B63C81CA9F5E9DE2DC5D06104.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)理解浏览器的关键渲染路径/resources/37531F7B63C81CA9F5E9DE2DC5D06104.jpg -------------------------------------------------------------------------------- /(译)理解浏览器的关键渲染路径/resources/52A7B7356D2DE5A100FD0417C732F2BE.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)理解浏览器的关键渲染路径/resources/52A7B7356D2DE5A100FD0417C732F2BE.jpg -------------------------------------------------------------------------------- /(译)理解浏览器的关键渲染路径/resources/ADDE5C06B4F85308DD405103BC6DCFF1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)理解浏览器的关键渲染路径/resources/ADDE5C06B4F85308DD405103BC6DCFF1.jpg -------------------------------------------------------------------------------- /(译)[D3可视化] 理解数据绑定/resources/E54011E49D927BE97F22604AD6328BEB.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)[D3可视化] 理解数据绑定/resources/E54011E49D927BE97F22604AD6328BEB.jpg -------------------------------------------------------------------------------- /(译)如何处理React中的状态信息/resources/0C9039AEEC66BC21665D2706CAEB7BC7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)如何处理React中的状态信息/resources/0C9039AEEC66BC21665D2706CAEB7BC7.jpg -------------------------------------------------------------------------------- /(译)如何处理React中的状态信息/resources/381DBDECF1E5C7B9D479FFC4B9ABE8FB.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)如何处理React中的状态信息/resources/381DBDECF1E5C7B9D479FFC4B9ABE8FB.jpg -------------------------------------------------------------------------------- /(译)如何处理React中的状态信息/resources/4E396749CCB87E7982D6F3E978EF229E.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)如何处理React中的状态信息/resources/4E396749CCB87E7982D6F3E978EF229E.jpg -------------------------------------------------------------------------------- /(译)如何处理React中的状态信息/resources/80DA629F694F0DBB9B5C85C29C065C2D.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)如何处理React中的状态信息/resources/80DA629F694F0DBB9B5C85C29C065C2D.jpg -------------------------------------------------------------------------------- /D3数据绑定(Data Join)/resources/04DEC69A3C2DEDA5A4D53498E58E34A8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/D3数据绑定(Data Join)/resources/04DEC69A3C2DEDA5A4D53498E58E34A8.jpg -------------------------------------------------------------------------------- /D3数据绑定(Data Join)/resources/1542C02CCA35201C28B20FC678D63B4F.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/D3数据绑定(Data Join)/resources/1542C02CCA35201C28B20FC678D63B4F.jpg -------------------------------------------------------------------------------- /D3数据绑定(Data Join)/resources/2F56859869DE44F8B4BD35E91EE0995D.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/D3数据绑定(Data Join)/resources/2F56859869DE44F8B4BD35E91EE0995D.jpg -------------------------------------------------------------------------------- /D3数据绑定(Data Join)/resources/AADA008DF9FC795C84F53C6E584FC17F.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/D3数据绑定(Data Join)/resources/AADA008DF9FC795C84F53C6E584FC17F.jpg -------------------------------------------------------------------------------- /D3数据绑定(Data Join)/resources/B5954156DB042D466A47460E429A1AFB.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/D3数据绑定(Data Join)/resources/B5954156DB042D466A47460E429A1AFB.jpg -------------------------------------------------------------------------------- /assets/What are CSS Modules and why do we need them?/devtools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/assets/What are CSS Modules and why do we need them?/devtools.png -------------------------------------------------------------------------------- /(译)深入React的children/resources/003CCE0F944F22C9B2061ED2F817EAC4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)深入React的children/resources/003CCE0F944F22C9B2061ED2F817EAC4.jpg -------------------------------------------------------------------------------- /(译)深入React的children/resources/406E678AF57519D5DD376790636FDFC8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)深入React的children/resources/406E678AF57519D5DD376790636FDFC8.jpg -------------------------------------------------------------------------------- /(译)深入React的children/resources/9A7AD2CBEFAE715079D5130F9D12DCEE.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)深入React的children/resources/9A7AD2CBEFAE715079D5130F9D12DCEE.jpg -------------------------------------------------------------------------------- /(译)深入React的children/resources/BC70E781BC90C42110A8ED2F58B6AE38.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)深入React的children/resources/BC70E781BC90C42110A8ED2F58B6AE38.jpg -------------------------------------------------------------------------------- /(译)深入React的children/resources/C544037C8BFEB16594B37B5353AE3516.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)深入React的children/resources/C544037C8BFEB16594B37B5353AE3516.jpg -------------------------------------------------------------------------------- /(译)深入React的children/resources/D92089868E199196ADAB5F22B056B2F1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)深入React的children/resources/D92089868E199196ADAB5F22B056B2F1.jpg -------------------------------------------------------------------------------- /(译)深入React的children/resources/DAF4A478E8E2EAA604D6784B9BB29A3D.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)深入React的children/resources/DAF4A478E8E2EAA604D6784B9BB29A3D.jpg -------------------------------------------------------------------------------- /(译)深入React的children/resources/F641FFC827F310757F879579FFD81ADD.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)深入React的children/resources/F641FFC827F310757F879579FFD81ADD.jpg -------------------------------------------------------------------------------- /React 无状态组件: 你忽视掉的9个优点/resources/21FDDE03858A6573994890CF7AB621D3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/React 无状态组件: 你忽视掉的9个优点/resources/21FDDE03858A6573994890CF7AB621D3.jpg -------------------------------------------------------------------------------- /(译)异步 vs 延迟 JavaScript/resources/082B354AD417431DE637427DA8206970.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)异步 vs 延迟 JavaScript/resources/082B354AD417431DE637427DA8206970.jpg -------------------------------------------------------------------------------- /(译)异步 vs 延迟 JavaScript/resources/111A1AE2581280E5372AD3D2BA088272.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)异步 vs 延迟 JavaScript/resources/111A1AE2581280E5372AD3D2BA088272.jpg -------------------------------------------------------------------------------- /(译)异步 vs 延迟 JavaScript/resources/57E4C3703F7830609482D0C2913BBB3D.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)异步 vs 延迟 JavaScript/resources/57E4C3703F7830609482D0C2913BBB3D.jpg -------------------------------------------------------------------------------- /(译)异步 vs 延迟 JavaScript/resources/6DE7A0141B14CB773082DD2E8FAFFB94.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)异步 vs 延迟 JavaScript/resources/6DE7A0141B14CB773082DD2E8FAFFB94.jpg -------------------------------------------------------------------------------- /(译)异步 vs 延迟 JavaScript/resources/E67BD3F73E80EE297848C18DAB29EAEA.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)异步 vs 延迟 JavaScript/resources/E67BD3F73E80EE297848C18DAB29EAEA.jpg -------------------------------------------------------------------------------- /(译)应用Index 作为 key属性值是反模式/resources/3C2CBF91987508040B42EBDE8644C996.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)应用Index 作为 key属性值是反模式/resources/3C2CBF91987508040B42EBDE8644C996.jpg -------------------------------------------------------------------------------- /[可视化]SVG径向渐变(radialGradient)/resources/05CCE669285FD5CDF4526F6F9A97F9F5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG径向渐变(radialGradient)/resources/05CCE669285FD5CDF4526F6F9A97F9F5.jpg -------------------------------------------------------------------------------- /[可视化]SVG径向渐变(radialGradient)/resources/1C18818464D35FF2B18954B4DEEA64B2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG径向渐变(radialGradient)/resources/1C18818464D35FF2B18954B4DEEA64B2.jpg -------------------------------------------------------------------------------- /[可视化]SVG径向渐变(radialGradient)/resources/31719A9E336A1396DFF2A5C3A3136483.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG径向渐变(radialGradient)/resources/31719A9E336A1396DFF2A5C3A3136483.jpg -------------------------------------------------------------------------------- /[可视化]SVG径向渐变(radialGradient)/resources/31BB170061C8E731C490F2C32F8771C4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG径向渐变(radialGradient)/resources/31BB170061C8E731C490F2C32F8771C4.jpg -------------------------------------------------------------------------------- /[可视化]SVG径向渐变(radialGradient)/resources/D663AD93E2C1BECF4ACE6929EDA24071.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG径向渐变(radialGradient)/resources/D663AD93E2C1BECF4ACE6929EDA24071.jpg -------------------------------------------------------------------------------- /[可视化]SVG径向渐变(radialGradient)/resources/EE64BD13E2B35A62EAE73CA649DD8AB2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG径向渐变(radialGradient)/resources/EE64BD13E2B35A62EAE73CA649DD8AB2.jpg -------------------------------------------------------------------------------- /[可视化]SVG线性渐变(linearGradient)/resources/23D3BA32B6A21F7C3321A4FA1B12B556.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG线性渐变(linearGradient)/resources/23D3BA32B6A21F7C3321A4FA1B12B556.jpg -------------------------------------------------------------------------------- /[可视化]SVG线性渐变(linearGradient)/resources/385FD4405E06C590C8E4E18D3FEA1AC7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG线性渐变(linearGradient)/resources/385FD4405E06C590C8E4E18D3FEA1AC7.jpg -------------------------------------------------------------------------------- /[可视化]SVG线性渐变(linearGradient)/resources/3996FC94CDC9D3E1E067BC134B2D20F2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG线性渐变(linearGradient)/resources/3996FC94CDC9D3E1E067BC134B2D20F2.jpg -------------------------------------------------------------------------------- /[可视化]SVG线性渐变(linearGradient)/resources/3EAF806A229B22AEE6620EB7A780AF6F.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG线性渐变(linearGradient)/resources/3EAF806A229B22AEE6620EB7A780AF6F.jpg -------------------------------------------------------------------------------- /[可视化]SVG线性渐变(linearGradient)/resources/3FDE8D639AD26F649067642EFFA2B454.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG线性渐变(linearGradient)/resources/3FDE8D639AD26F649067642EFFA2B454.jpg -------------------------------------------------------------------------------- /[可视化]SVG线性渐变(linearGradient)/resources/45C216A5864D22F20633B9534061A4DB.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG线性渐变(linearGradient)/resources/45C216A5864D22F20633B9534061A4DB.jpg -------------------------------------------------------------------------------- /[可视化]SVG线性渐变(linearGradient)/resources/BFC9852EB884B08B66CC3042F682781A.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG线性渐变(linearGradient)/resources/BFC9852EB884B08B66CC3042F682781A.jpg -------------------------------------------------------------------------------- /[可视化]SVG线性渐变(linearGradient)/resources/C240F04F61B943EBF7B227708834D7F2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG线性渐变(linearGradient)/resources/C240F04F61B943EBF7B227708834D7F2.jpg -------------------------------------------------------------------------------- /[可视化]SVG线性渐变(linearGradient)/resources/CAAA58C4CC130279783086E6860668D9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG线性渐变(linearGradient)/resources/CAAA58C4CC130279783086E6860668D9.jpg -------------------------------------------------------------------------------- /[可视化]SVG线性渐变(linearGradient)/resources/CEB510CF468A71CACCAF6DA15F12AB53.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG线性渐变(linearGradient)/resources/CEB510CF468A71CACCAF6DA15F12AB53.jpg -------------------------------------------------------------------------------- /[可视化]SVG线性渐变(linearGradient)/resources/D5EFC532794E5F083DBF61433A3F3F04.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/[可视化]SVG线性渐变(linearGradient)/resources/D5EFC532794E5F083DBF61433A3F3F04.jpg -------------------------------------------------------------------------------- /(译)What are CSS Modules and why do we need them?/resources/33634704E521458996F2F64AE77CAC60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lx7575000/Translation/HEAD/(译)What are CSS Modules and why do we need them?/resources/33634704E521458996F2F64AE77CAC60.png -------------------------------------------------------------------------------- /React 无状态组件: 你忽视掉的9个优点/React 无状态组件 你忽视掉的9个优点.md: -------------------------------------------------------------------------------- 1 | React .14版本引入了一种简单定义无状态组件的方法。该组件通过使用纯JavaScript函数的形式来定义。 2 | **如下图所示:** 3 | ![](resources/21FDDE03858A6573994890CF7AB621D3.jpg) 4 | 5 | 初见上述两种方法感觉相差不大,但是消除的问题却很多。 6 | 7 | ##No Class Needed 8 | 坦白来说,我觉得ES6的`class`语法糖有些过于复杂,在此使用纯函数更可取些。在上例中消除相关的构造函数`constructor`和`extends`使其更简洁。 9 | 10 | ##No `this` Keyword 11 | 如上例所示,无状态组件就只是个函数。因此,令人费解的**`this`**关键字就可以被避免掉了。使整个组件更加简单且容易理解,比较下列两种点击处理方法: 12 | ```JavaScript 13 | onClick={this.sayHi.bind(this)}>Say Hi 14 | onClick={sayHi}>Say Hi 15 | ``` 16 | 在无状态组件中,`bind`关键字不是必需的。临时类不需使用`bind`方法来绑定`this`上下文。可以避免掉令许多开发人员困惑的`this`关键字,是很赞的。 17 | 18 | ##Enforced Best Practice 19 | 无状态组件通常被用于**简单显示组件**。它 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Translation 2 | 对一些外文文章进行翻译 3 | 4 | **目前翻译的有:** 5 | 1. [JSTips](https://github.com/loverajoel/jstips) 6 | 2. [Functions as First Class Citizens in Javascript](http://ryanchristiani.com/functions-as-first-class-citizens-in-javascript/) 7 | 3. [Index as a key is an anti-pattern](https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318#.c3cauisl3) 8 | 4. [es6-cheatsheet](https://github.com/DrkSephy/es6-cheatsheet) //更新部分 9 | 5. JavaScript面试必知必会(标题党) 10 | 6. 浮动如何工作 11 | 7. Medium图片加载模式 12 | 8. 到底要不要用伪元素? 13 | 9. Prototypes in JavaScript 14 | 10. React中,应用index作为key值是反模式 // 需要重新校对 15 | 11. What are CSS Modules and why do we need them? //未校对 16 | 17 | 18 | 如果你有觉得好的前端文章可以发给我,我会尝试进行翻译 :) 19 | -------------------------------------------------------------------------------- /(译)到底要不要用伪元素?/(译)到底要不要用伪元素?.md: -------------------------------------------------------------------------------- 1 | [原文地址](https://adactio.com/journal/10000) 2 | 3 | 我喜欢CSS的伪元素。我在设计交互接口时候通常用他们增强效果。 4 | 通常会为`form`相关的元素添加伪元素,例如`:valid,:invalid, :requrired, :in-range `[等等](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes)。 5 | 假设我想要基于输入情况调整标签的外观。我可能会令`input`如下所示: 6 | 7 | ```html 8 | 9 | ``` 10 | 11 | 然后,我可以在输入内容符合我要求时,添加CSS样式使整个输入框边框为绿色。 12 | 13 | ```css 14 | input:valid { 15 | border: 1px solid green; 16 | } 17 | ``` 18 | 19 | 他起作用了!但是令人蛋疼的一点是当用户继续输入内容的时候边框会改变(当输入@标签时,边框会变绿)。这样会导致注意力分散。 20 | 我的需求很简单,只希望输入内容有效且当输入框不再被关注时边框才会变绿。幸运的是,最后两个词('not'和'focused')可以清楚的映射到一些伪元素`:not`和`focus`。 21 | 22 | ```css 23 | input:not(:focus):valid { 24 | border: 1px solid green; 25 | } 26 | ``` 27 | 28 | 如果我真的想要,我可以在表单变展示一个图标。这么做仅仅需要使用一个伪元素:`:after`。 29 | 30 | ```css 31 | input:not(:focus):valid::after { 32 | content: '✓'; 33 | } 34 | ``` 35 | 36 | 但是,没有显示出来诶!这是因为你不可以添加一个生成内容替换原生表单内容。我需要添加常规元素到标签当中: 37 | 38 | ```html 39 | 40 | 41 | ``` 42 | 43 | 这样我才可以添加预期内容。 44 | 45 | ```css 46 | input:not(:focus):valid + span::after { 47 | content: '✓'; 48 | } 49 | ``` 50 | 51 | 但是这么做感觉很讨厌。 52 | 53 | (译者)写在最后:作为英语四级勉强过线选手,如果翻译有不到位地方,请多包涵。如若不能包涵就请跟着链接跳转看原文。当然,如果你感觉文章内容不错,就我给个star吧。 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /ES6小抄(:-D)/ES6小抄( -D).md: -------------------------------------------------------------------------------- 1 | # ES6小抄(:-D) 2 | 3 | [原文地址](https://github.com/DrkSephy/es6-cheatsheet) 4 | 5 | #1 `var` VS `let`/`const` 6 | 7 | 在JavaScript中除了**var类型**外,我们现在还可以使用`let`和`const`两种新类型进行变量声明了。与`var`不同,`let`和`const`类型会按照定义的顺序产生变量,而`var`在作用域任意位置定义都可。 8 | 9 | ```js 10 | //var 的例子 11 | var snack = 'Meow Mix'; 12 | 13 | function getFood(food) { 14 | if (food) { 15 | var snack = 'Friskies'; 16 | return snack; 17 | } 18 | return snack; 19 | } 20 | 21 | getFood(false); // undefined 22 | 23 | //我们改为使用let 代替 var 24 | let snack = 'Meow Mix'; 25 | 26 | function getFood(food) { 27 | if (food) { 28 | let snack = 'Friskies'; 29 | return snack; 30 | } 31 | return snack; 32 | } 33 | 34 | getFood(false); // 'Meow Mix' 35 | ``` 36 | 37 | 当我在使用`let`替换`var`重构代码时,我们需要更加小心了。因为类型作用域的问题会导致很多意想不到的麻烦。 38 | 39 | **Note:** `let`和`const`类型会限定自身的有效作用域,因此,当在定义变量**之前**引用所定义的变量时会产生**引用错误** 40 | 41 | ```js 42 | console.log(x); 43 | 44 | let x = 'hi'; // ReferenceError: x is not defined 45 | ``` 46 | 47 | **最佳实践** 48 | 使用`var`声明变量当对代码进行重构时,需要仔细判断其作用范围。因此,对于新的项目,建议使用`let`声明变量,使用`const`声明不允许改变的常量。 49 | 50 | #2 使用块作用域替换**IIFES** 51 | 使用**立即执行函数表达式**的一种方式是将其包含在小括号当中。在ES6中,我们可以创建一个非基于函数作用域形式的块级作用域。 52 | 53 | ```js 54 | (function () { 55 | var food = 'Meow Mix'; 56 | }()); 57 | 58 | console.log(food); // Reference Error 59 | //ES6 60 | { 61 | let food = 'Meow Mix'; 62 | } 63 | 64 | console.log(food); // Reference Error 65 | ``` -------------------------------------------------------------------------------- /(译)应用Index 作为 key属性值是反模式/(译)应用Index 作为 key属性值是反模式.md: -------------------------------------------------------------------------------- 1 | [原文地址](https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318#.jadd313vz) 2 | 3 | 经常可以看到开发者们在编写`React`代码render一个列表时使用对象元素的*index* 来作为其**key**属性值。 4 | 5 | ```js 6 | {todos.map((todo, index) => 7 | 9 | )} 10 | ``` 11 | 12 | 这样看起来很优雅,并且解决了React的警告问题。然而,真正危险之处就在此: 13 | **它可能会导致你的应用展示的数据与预期不符。** 14 | 15 | 在此我要解释一下,**key**属性在`React`当中的作用就是确定DOM元素。当你在列表中添加或删除一个元素时会发生什么?如果**key**属性和之前的`React`假设的DOM元素的组件**key**值表示相同时。它就不一定正确了。 16 | 我写了一个简单的[例子](http://output.jsbin.com/wohima),来说明这么做的危险。 17 | 18 | ![](resources/3C2CBF91987508040B42EBDE8644C996.jpg) 19 | 20 | 根据例子我们看到,`React`会在我们没有给**key**属性赋值的时候使用**index**来进行赋值。然而,它同时也会提醒你这么做不是最优选择。如果你在你自己的`React`项目中应用了这最简单方法,记住上面例子,会导致不可预计的结果。 21 | 22 | ##Better 23 | 24 | 列表中的每个元素都应该赋一个独一无二且持久保持的**key**值。最理想的赋值方式是是当元素被创建时就进行**key**赋值。我们可以使用以下方式。 25 | 26 | ```js 27 | {todos.map((todo) => 28 | 30 | )} 31 | ``` 32 | 33 | 我们通过递增的形式给每个元素赋值,声明一个全局index变量,并确保任意两个元素持有不用的**ID**属性 34 | 35 | ```js 36 | todoCounter = 1; 37 | function createNewTodo(text) { 38 | return { 39 | completed: false, 40 | id: todoCounter++, 41 | text 42 | } 43 | } 44 | ``` 45 | 46 | ##Much Better 47 | 我们可以使用一种更加健壮的方式来进行元素的**id**赋值,比如我们可以使用[shortid](https://www.npmjs.com/package/shortid)。它能快速产生“长度短、无序、url独一无二且友好的”**id**值。 48 | 49 | ```js 50 | var shortid = require('shortid'); 51 | function createNewTodo(text) { 52 | return { 53 | completed: false, 54 | id: shortid.generate(), 55 | text 56 | } 57 | } 58 | ``` 59 | 60 | (译者)写在最后:作为英语四级勉强过线选手,如果翻译有不到位地方,请多包涵。如若不能包涵就请跟着链接跳转看原文。当然,如果你感觉文章内容不错,就我给个star吧。 -------------------------------------------------------------------------------- /(译)异步 vs 延迟 JavaScript/(译)异步 vs 延迟 JavaScript.md: -------------------------------------------------------------------------------- 1 | #异步 vs 延迟 JavaScript 2 | > 承接上一篇翻译《理解渲染关键路径》,对其中JavaScript脚本解析时发生的阻塞情况提出优化方案。 3 | 4 | 如果我们需要加载多个JavaScript文件时,以上行为会导致首次渲染时间难以确定,尽管首页的显示不一定依赖所有的JS文件。 5 | 6 | 幸运的是,` 118 | 119 | 120 | ``` 121 | 可以看关于页面加载时的事件日志,以下是我们获得的: 122 | ![](resources/ADDE5C06B4F85308DD405103BC6DCFF1.jpg) 123 | 124 | 1. 发送请求:发送`GET`请求index.html 125 | 2. 解析HTML然后发送请求:开始解析HTML并构建DOM,然后发送`GET`请求style.css和main.js。 126 | 3. 解析样式表:根据style.css生成CSSOM 127 | 4. 执行计算脚本:执行main.js 128 | 5. 布局:基于HTML的元视窗标签,生成布局 129 | 6. 绘制页面:绘制网页 130 | 131 | [原文链接:Understanding the Critical Rendering Path](https://bitsofco.de/understanding-the-critical-rendering-path/) 132 | 133 | -------------------------------------------------------------------------------- /RXJS入门/RXJs.md: -------------------------------------------------------------------------------- 1 | ##Rx.Observable 2 | ###create(fn) 3 | 通过Rx.Observable.create创建返回一个**Observable**对象。create中传入参数为函数,Observable对象会在subscribe时候执行该函数,如果该函数有返回值,会返回到subscribe方法当中。 4 | 5 | ```JS 6 | let foo = Rx.Observable.create(() => next('Hello Rx')); 7 | foo.subscribe(v => console.log(v)) //=> 'Hello Rx' 8 | ``` 9 | 除了上述方法,还可以使用**new**来创建`Observable`对象 10 | ```Js 11 | let foo = new Rx.Observable(fn); 12 | const handler = { 13 | next: function(x) { console.log('next ' + x);}, 14 | error: function(err) { console.log('error ' + err)}, 15 | complete: function() { console.log('done');} 16 | } 17 | foo.subscribe(handler); 18 | ``` 19 | ###of(arg1, arg2, arg3, ...) 20 | Rx.Observable.of()方法中会传入若干参数,当执行subscribe方法时会将这若干个参数返回,最后会传出`complete(完成)`状态信息,表示该Observable对象执行结束。 21 | ```JS 22 | let foo = Rx.Observable.of(1, 2, 3, 4, 5); 23 | foo.subscribe( v => console.log(v), 24 | err => console.log('error' + err), 25 | () => console.log('complete done !') ) 26 | // => 1 27 | // => 2 28 | // => 3 29 | // => 4 30 | // => 5 31 | // => 'complete done !' 32 | ``` 33 | ###fromArray 34 | 在`Rx.Observable.of()`中连传参数是不是很蛋疼?`fromArray`方法来解决你的难言之隐,现在只需要在`Rx.Observable.fromArray()`中传入一个数组可以达到和`of`方法一样的效果了。 35 | ```JS 36 | const arr = [1, 2, 3, 4, 5] 37 | let foo = Rx.Observable.of(arr); 38 | foo.subscribe( v => console.log(v), 39 | err => console.log('error' + err), 40 | () => console.log('complete done !') ) 41 | // => 1 42 | // => 2 43 | // => 3 44 | // => 4 45 | // => 5 46 | // => 'complete done !' 47 | ``` 48 | ###from 49 | 既然`fromArray`方法都这么好用,`from`方法看起来会更厉害的样子。没错,`Rx.Observable.from`方法中可以传入数组、类数组对象、Promise,iterable对象(generator方法返回值)或Observable对象。 50 | 同理,在`subscribe`方法中会依次执行并根据处理函数进行处理。 51 | 52 | ```JS 53 | function *generator() { 54 | yield 10; 55 | yield 20; 56 | yield 30; 57 | } 58 | let iterator = generator(); 59 | let foo = Rx.Observable.from(iterator); 60 | foo.subscribe( v => console.log(v), 61 | err => console.log('error' + err), 62 | () => console.log('complete done !') ) 63 | // => 10 64 | // => 20 65 | // => 30 66 | // => 'complete done !' 67 | ``` 68 | ###fromEventPattern & fromEvent 69 | `fromEvenetPattern`方法中传入事件的添加、移除操作方法,具体的处理方法,同样在`subscribe`方法中完成。 70 | 下面为`fromEventPattern`方法的原理简单实现。 71 | ```Js 72 | function fromEventPattern(add, remove) { 73 | return Rx.Observable.create(function (observer) { 74 | add(function(ev) { 75 | observer.next(ev); 76 | }); 77 | }); 78 | } 79 | ``` 80 | 相对该方法,更推荐使用封装版本的`fromEvent`方法。 81 | `Rx.Observable.fromEvent(DOM, Event)`该方法分别传入需要监听的DOM节点,和需要监听的事件类型。 82 | ```Js 83 | let foo = Rx.Observable.fromEvent(document.querySelector('#submit'), 'click'); 84 | foo.subscribe(() => console.log('click ')); 85 | // => 'click ' 86 | ``` 87 | 88 | ###timer & interval 89 | `timer`和`interval`方法都可以传入时间间隔参数,在固定时间内触发事件。 90 | 91 | `timer(startTime, intervalTime)`中可以设定事件触发的具体时间**startTime**后才开始执行。 92 | 93 | ##in deepth 94 | ###mapTo 95 | `mapTo`方法和`map`相似,在每次执行时候返回一个值。不过与它不同的点在于,`mapTo`每次返回的是传递给它的常量值。 96 | ```Js 97 | let foo = Rx.Observable.interval(1000); //每1秒执行一次 98 | let mapTo = foo.mapTo('Hello'); 99 | mapTo.subscribe( x => console.log(x)); 100 | //每一秒输出一个'Hello' 101 | ``` 102 | ###do 103 | `do`方法通常用于Debug。 104 | 它会拦截源Observable对象传递的值,然后执行传递给`do`方法的函数,传递的方法建议不要有返回值,因为会被忽略掉。`Observable`对象返回的仍然是之前传入的值。 105 | ```Js 106 | let foo = Rx.Observable.interval(1000).take(4) 107 | .do( x => console.log(x)); 108 | foo.subscribe({ 109 | next: (x) => console.log('next' + x), 110 | error: (err) => console.log('error'), 111 | complete: (x) => console.log('done') 112 | }); 113 | // => 0 114 | // => next 0 115 | // => 1 116 | // => next 1 117 | // => 2 118 | // => next 2 119 | // => 3 120 | // => next 3 121 | // => done 122 | ``` 123 | ###take 124 | `take`方法传入整数参数,会返回该数量的数据。 125 | ```Js 126 | let interval = Rx.Observable.interval(1000).take(5); 127 | interval.subscribe(x => console.log(x)); // 0 - 1 - 2 - 3 - 4 128 | ``` 129 | ###takeLast || last 130 | 与`take`类似,不过返回的是倒数的几个数据。**并且,这些数据是在最后结束的时候同时返回。**`last`是其缩写。 131 | ```Js 132 | let many = Rx.Observable.range(1, 100); 133 | let lastThree = many.takeLast(3); 134 | lastThree.subscribe( x => console.log(x)); // 98|99|100 135 | ``` 136 | ###concat || startWith 137 | 与数组的`concat`方法类似,不过此处在后面添加的是`Observable`对象的事件流。 138 | `startWith`方法与`concat`相似,不过就是将事件(数据)流添加在了前面。 139 | 140 | ```Js 141 | let two = Rx.Observable.interval(2000).take(4); 142 | // --0--1--2--3 143 | let four = Rx.Observable.interval(4000).take(4); 144 | // ----0----1----2----3 145 | let TwoFour = two.concat(four); 146 | TwoFour.subscribe(x => console.log(x)); 147 | //--0--1--2--3----0----1----2----3 148 | let FourTwo = four.concat(two); 149 | //----0----1----2----3--0--1--2--3 150 | let sTwoFour = four.startWith(two); 151 | //--0--1--2--3----0----1----2----3 152 | let sFourTwo = two.startWith(four); 153 | //----0----1----2----3--0--1--2--3 154 | ``` 155 | ###merge 156 | `merge`方法会将多个`Observable`对象的事件(数据)流合并到同一条流中。 157 | ```JS 158 | let two = Rx.Observable.interval(2000).take(4); 159 | // --0--1--2--3 160 | let four = Rx.Observable.interval(4000).take(4); 161 | // ----0----1----2----3 162 | let merge = two.merge(four); 163 | // --0-01--21--3-2----3 164 | ``` 165 | ###skip 166 | `skip(n)`方法传入整数,跳过`Observable`对象的前n个事件(数据)。 167 | ```Js 168 | let foo = Rx.Observable.interval(1000).take(10).skip(5); 169 | foo.subscribe(x => console.log(x)); // ----------5-6-7-8-9 170 | ``` -------------------------------------------------------------------------------- /(译)Prototypes in JavaScript/(译)Prototypes in JavaScript.md: -------------------------------------------------------------------------------- 1 | [原文地址](http://code.tutsplus.com/tutorials/prototypes-in-javascript--net-24949) 2 | 3 | 当你在JavaScript中定义方法时,它会预先定义一些属性,例如其中的`prototype`。在本文中,我会详细介绍它和它的使用方法。 4 | 5 | #什么是Prototype? 6 | `prototype`属性被初始化为空对象,不过可以被添加各种属性在其中。 7 | 8 | ```js 9 | var myObject = function(name){ 10 | this.name = name; 11 | return this; 12 | }; 13 | 14 | console.log(typeof myObject.prototype); // object 15 | 16 | myObject.prototype.getName = function(){ 17 | return this.name; 18 | }; 19 | ``` 20 | 21 | 在上文的代码段中创建了一个方法,但是我们调用`myObject()`,它会返回`window`对象。这是因为它被定义在全局作用域中,`this`因此会返回全局对象,表示其未被实例化。 22 | 23 | ```js 24 | console.log(myObject() === window); // true 25 | ``` 26 | 27 | #隐式链接 28 | > JavaScript中的每个对象都有一个隐式链接 29 | 在我们继续这一话题之前,我们会先讨论下使原型生效的隐式链接。 30 | 31 | JavaScript中的每个对象在被定义或实例化时都有一个“秘密”对象被添加进来,关键字为:`__proto__`;这就是为什么原型链会起作用了。然而,在你的应用中使用`__proto__`并不是一个好想法,因为它还没有被所有浏览器中支持(目前应该都支持了)。 32 | `__proto__`属性和对象的`prototype`属性不同,它们是两种不同的属性,这点一定要明确!现在我来解释,当我创建`myObject`方法时,我定义了一个`Function`类型的对象。 33 | 34 | ```js 35 | console.log(typeof myObject) //function 36 | ``` 37 | 38 | `Function`类型是在JavaScript中是一种会被预先定义的类型,并且它含有自己的属性(例如:`length`和`arguments`)和方法(例如:`call`和`apply`)还有**对象**属性,例如`__proto__`链接。这说明JavaScript引擎中的某个地方,有类似如下代码。 39 | 40 | ```js 41 | Function.prototype = { 42 | arguments: null, 43 | length: 0, 44 | call: function(){ 45 | // secret code 46 | }, 47 | apply: function(){ 48 | // secret code 49 | } 50 | ... 51 | } 52 | ``` 53 | 54 | 事实上,上述代码过于简单,仅仅是为了展示原型链如何工作的。 55 | 因此,我们定义`myObject`方法,给其设定了参数`name`,但是我们没有设定其他属性,例如`length`或方法例如`call`。但是它是如何如下运行情况的呢? 56 | 57 | ```js 58 | console.log(myObject.length); // 1 (being the amount of available arguments) 59 | ``` 60 | 61 | 这是因为,当我们定义了`myObject`,它同时生成一个`__proto__`属性,并给其赋值`Function.prototype`。因此,当我们想要调用`myObject.length`时,它会通过`myObject`的原型链寻找`length`属性,但是发现`myObject`并没有定义该属性。因此它通过原型链经过`__proto__`链接向上查找,并返回属性。 62 | 你或许会好奇,为什么`length`属性值为**1**,不是其他属性。这是由于事实上`myObject`是`Function`的一个实例。 63 | 64 | ```js 65 | console.log(myObject instanceof Function); // true 66 | console.log(myObject === Function); // false 67 | ``` 68 | 69 | 当一个对象实例被创建,`__proto__`属性会更新指向构造器的原型。在本例中,它是`Function`。 70 | 71 | ```js 72 | console.log(myObject.__proto__ === Function.prototype) // true 73 | ``` 74 | 75 | 除此之外,当创建一个新的`Function`对象时,`Function`构造器会查找参数数量,并且相应更新`this.length`属性,因此此处为**1**。 76 | 当我们使用`new`关键字创建一个新的`myObject`实例时,`__proto__`会指向`myObject.prototype`。认为`myObject`是新实例的构造器。 77 | 78 | ```js 79 | var myInstance = new myObject(“foo”); 80 | console.log(myInstance.__proto__ === myObject.prototype); // true 81 | ``` 82 | 83 | 如上面访问`Function.prototype`中的原生代码,例如`call`和`apply`。我们现在在新实例中可以访问`myObject`的方法`getName`。 84 | 85 | ```js 86 | console.log(myInstance.getName()); // foo 87 | 88 | var mySecondInstance = new myObject(“bar”); 89 | 90 | console.log(mySecondInstance.getName()); // bar 91 | console.log(myInstance.getName()); // foo 92 | ``` 93 | 94 | #为什么使用`prototype`更好? 95 | 当我们创建一个画图游戏时,同时需要许多对象。每个对象都具有其自己的属性,比如坐标**x**,**y**,长宽**width**,**height**以及其他类型属性。 96 | 我们或许会下面这么做: 97 | 98 | ```js 99 | var GameObject1 = { 100 | x: Math.floor((Math.random() * myCanvasWidth) + 1), 101 | y: Math.floor((Math.random() * myCanvasHeight) + 1), 102 | width: 10, 103 | height: 10, 104 | draw: function(){ 105 | myCanvasContext.fillRect(this.x, this.y, this.width, this.height); 106 | } 107 | ... 108 | }; 109 | 110 | var GameObject2 = { 111 | x: Math.floor((Math.random() * myCanvasWidth) + 1), 112 | y: Math.floor((Math.random() * myCanvasHeight) + 1), 113 | width: 10, 114 | height: 10, 115 | draw: function(){ 116 | myCanvasContext.fillRect(this.x, this.y, this.width, this.height); 117 | } 118 | ... 119 | }; 120 | ``` 121 | 122 | 100遍啊,100遍!! 123 | 这么做会令内存中存在100个对象,分别拥有各自的方法(虽然他们都相同,但是仍然会占用100份内存)。这么做一定不符合我们所期望的,毕竟这会导致内存占用过大,程序运行缓慢。 124 | 这么做很苦逼,毕竟上百个各不相同的对象需要向上搜索方法。因此,我推荐使用`prototype`,在同一对象上定义统一方法。 125 | 126 | #如何使用`prototype`? 127 | 为使应用尽可能运行的快(做到最佳实践),我们可以(重新)定义`GameObject`的原型属性,每个`GameObject`的实例都会通过`GameObject.prototype`索引其原型方法进行使用。 128 | 129 | ```js 130 | // define the GameObject constructor function 131 | var GameObject = function(width, height) { 132 | this.x = Math.floor((Math.random() * myCanvasWidth) + 1); 133 | this.y = Math.floor((Math.random() * myCanvasHeight) + 1); 134 | this.width = width; 135 | this.height = height; 136 | return this; 137 | }; 138 | 139 | // (re)define the GameObject prototype object 140 | GameObject.prototype = { 141 | x: 0, 142 | y: 0, 143 | width: 5, 144 | width: 5, 145 | draw: function() { 146 | myCanvasContext.fillRect(this.x, this.y, this.width, this.height); 147 | } 148 | }; 149 | ``` 150 | 151 | 下面我们可以实例化对象100遍了。 152 | 153 | ```js 154 | var x = 100, 155 | arrayOfGameObjects = []; 156 | 157 | do { 158 | arrayOfGameObjects.push(new GameObject(10, 10)); 159 | } while(x--); 160 | ``` 161 | 162 | 现在,我们有一份具有100个`GameObject`实例对象的数组了,它们原型链上分享同一份`draw`方法(真心够节省内存了)。 163 | 当我们调用`draw`方法时,它们会索引同一个方法。 164 | 165 | ```js 166 | var GameLoop = function() { 167 | for(gameObject in arrayOfGameObjects) { 168 | gameObject.draw(); 169 | } 170 | }; 171 | ``` 172 | 173 | #原型是一个实时对象 174 | 对象的原型可以说是动态的,当我们创建了所有实例后,我们希望除了画矩形,我们还想要画圆,因此我们可以相应更新`GameObject.prototype.draw`方法。 175 | 176 | ```js 177 | GameObject.prototype.draw = function() { 178 | myCanvasContext.arc(this.x, this.y, this.width, 0, Math.PI*2, true); 179 | } 180 | ``` 181 | 182 | 现在,之前和之后创建的`GameObject`实例都可以画圆了。 183 | #更新原生对象 184 | 我们可以通过`prototype`更新原生对象的方法。 185 | 186 | ```js 187 | if(!String.prototype.trim) { 188 | String.prototype.trim = function() { 189 | return this.replace(/^\s+|\s+$/g, ‘’); 190 | }; 191 | } 192 | ``` 193 | 194 | (译者)写在最后:作为英语四级勉强过线选手,如果翻译有不到位地方,请多包涵。如若不能包涵就请跟着链接跳转看原文。当然,如果你感觉文章内容不错,就我给个star吧。 -------------------------------------------------------------------------------- /(译)Medium图片加载模式/(译)Medium图片加载模式.md: -------------------------------------------------------------------------------- 1 | [原文地址](https://jmperezperez.com/medium-image-progressive-loading-placeholder/) 2 | **翻译地址**:https://github.com/lx7575000/Translation 3 | 4 | 译者注:感谢xiaoxin38250(微信)帅哥的卖力校对,否则这篇文章读起来会更烂。 5 | 6 | 我在[Medium]()浏览帖子的时候发现他们的图片加载效果真的很赞诶。首先载入一个低像素的模糊图片,然后逐渐转变为高清大图。这个过程体验真的很好,所以我希望能够明白他们是使用什么方法做到的。 7 | 8 | ![medium-placeholder.png](resources/C4B1AEAA770FB1F8F8DBBB944CA02342.png) 9 | 10 | ##Medium的技术 11 | 我使用[WebPageTest]()测试这个[页面](https://medium.com/backchannel/exclusive-why-apple-is-still-sweating-the-details-on-imac-531a95e50c91)的载入过程。如果你希望能够测试同样效果,可以打开Medium的页面,禁用cache减慢图片申请加载的过程,所以加载出原图的时间会稍久。这样就可以清楚看到整个图片的加载效果。 12 | 13 | **具体执行过程** 14 | 15 | 1. 使用`div`限定好图片展示的区域,Medium使用`
`标签并加入`padding-bottom`样式设定对应图片的展示尺寸。通过这样占位的方式可以防止在图片加载后出现整体页面**回流**的情况。这种方法通常被称为[intrinsic placeholders](http://daverupert.com/2015/12/intrinsic-placeholders-with-picture/) 16 | 17 | 2. **加载小尺寸(像素低)的图片**,此时网页会先请求一个像素质量较低的小号缩略图(大小为原图的20%).这个小图片使用``标签,因此浏览器会在标签加载完成后,立即请求图片资源。 18 | 19 | 3. 只要图片加载完成,它就会被“画”到``中。图片数据会被`main-base.bundle.js`文件中自定义的`Blur()`函数重新计算,可以看到它会产生模糊图片的效果。尽管有些不同,不过该函数与[StackBlur]()的模糊函数实现效果是相似的。**在模糊图片生成的同时,浏览器也会开始请求高清原图资源。** 20 | 21 | 4. 最后原图被加载到页面上,`canvas`会被隐藏,只展示原图。 22 | 23 | 最后的最后,感谢CSS的动画功能,上述所有转变过程会很流畅。 24 | 25 | ##Markup 26 | **整个展示图片的结构** 27 | ```HTML 28 |
29 |
30 |
31 | 32 | 33 | 34 |
36 |
37 | ``` 38 | 39 | ```HTML 40 |
41 |
42 |
43 |
44 | 45 | 46 | 47 | 48 |
49 |
50 |
51 | ``` 52 | **PS:实际图片大小要根据设备尺寸来设定。** 53 | 54 | ##尝试重新实现同样效果 55 | 我在[CodePen](http://codepen.io/jmperez/pen/yYjPER)重新通过使用`CSS`替代`canvas`实现同样的加载效果。下面的图片展示了整个加载过程中,图片的转变效果。 56 | 57 | ![medium-codepen.png](resources/696FCA181E755D5A905F1F83DAFD5DAD.png) 58 | 59 | ##这么做是否值? 60 | 很明显,现在有许多种方法来实现同样的效果。要知道在几年前如此高性能的方式实现动画和模糊效果还是不可能的。但事实上,大多数时候延迟瓶颈,并不是设备本身的原因,因此这些技巧值得我们探索。 61 | **控制加载图片过程有以下优点:** 62 | * 懒加载:使用JS来请求资源让我们可以灵活控制图片资源选择。小图可以请求同一缩略图,大图则可以根据浏览器视窗大小来选择加载尺寸不同的图片。 63 | * 更好的占位符: 相比于纯色占位符,使用缩略图添加模糊效果后会有更好的视觉效果,同时图片大小也只有2k左右不会牺牲负载。 64 | * 裁剪图片大小:Medium根据访问设备的不同,返回不同尺寸的图片,这样可以很好的优化页面的加载速度,同时避免移动设备浪费过多流量。 65 | 66 | ##其他版本 67 | 在实现Medium原方法之前,我觉得我可以在我的网站使用其他方法来实现。 68 | ###内联图片数据 69 | 我们可以在`img`中添加缩略图的**URLs**来直接请求资源。这样做虽然会增加HTML的内容,但是可以加快占位符的生成速度。浏览器加载好HTML标签就立即下载图片文件资源。加了模糊效果后图片的质量就无所谓了,我测试使用0.5k大小的图片与2k大小的图片得到相似的显示效果。 70 | ###模糊效果 71 | 默认情况下,当浏览器将一个小图像放大,它应用光滑效果处理图像的模糊效果。图像的效果也可以关闭,像QR码。 72 | >[…]the browser would render it in a way that didn’t make it look blocky[…] from [Google Developers](https://developers.google.com/web/updates/2015/01/pixelated). 73 | 74 | 它可以在Chrome、Safari和Firefox中有效,尽管光滑效果在Chrome中更有效,你可以在[这里](http://codepen.io/jmperez/full/Xmzobe/)看效果。 75 | 76 | 下面我们看看如何做到光滑效果。图片只有27px宽,并且像素非常低,将它放大会产生很可怕的效果。事实却并没有。如果上述效果能满足你的要求,那你就不需要更复杂的效果替换了。 77 | 78 | 上述图片模糊效果也可以使用[CSS Filter Effects](http://codepen.io/aniketpant/pen/DsEve)实现,它还支持IE浏览器哦(IE一生黑)。我相信Medium在使用`canvas`方法之前一定也尝试过使用这个功能更强的方法。但是可能是出于一定原因他们放弃了这一方法。**这一方法的优点是你可以设定模糊度,并且可以通过CSS达成其他目的。** 79 | 80 | 也可以使用**SVG**的filter来达成同样目的,如[The “Blur Up” Technique for Loading Background Images](https://css-tricks.com/the-blur-up-technique-for-loading-background-images/) 和 [Textured Gradients in Pure CSS](http://rentafounder.com/textured-gradients-in-pure-css/)两篇文章提到的。 81 | 82 | ##其他办法提升占位符:Google 图片搜索 83 | 当你在手机上搜索图片时,Google使用了一种简单的方法来实现图片占位。 84 | ![google-images-placeholder.png](resources/A83270C0F3F66F140BF8BEE934283EE1.png) 85 | 86 | 他们选择图片的一种主颜色,并用其作为占位块的背景色。这样做会给用户一种图片加载速度更快的体验。 87 | 88 | ##更先进的方法:Facebook的200 byte技术 89 | 年初Facebook发表过一篇["The technology behind preview photos"](https://code.facebook.com/posts/991252547593574/the-technology-behind-preview-photos/)的文章,这篇文章主要说明如何预览一个没有JPEG头的`42 * 42px`的图片。 90 | 使用场景有些不同,这“图片”被用于Facebook的手机端,它知道如何组成一个有效的JPEG图片。此处我们在Web端使用的话需要编写JavaScript代码,这样做同样会增加存储资源。当然我们可以通过在服务器端组成这个图片解决这一问题,但是这样仍需要一些JavaScript代码发送申请图片资源的请求。 91 | 92 | 无论如何,这个方法对于Web端来说有点大材小用,但我还是希望能够将其作为一个参考。[Using WebP for generating this preview images](https://jmperezperez.com/webp-placeholder-images/)同样可以节省内存,并且不需要使用如此**创造性**的解决方法。 93 | 94 | ##LQIP: Low Quality Image Placeholders 95 | 与其等待最终的图像呈现,我们可以先提供一个高度压缩的图片,然后切换到大图。这就是[LQIP](http://www.guypo.com/introducing-lqip-low-quality-image-placeholders/)方法的思路。这一方法与Medium相似,不过是使用相同尺寸,但压缩更高的图片。 96 | 97 | ##总结 98 | 随着页面加载的图片越来越多,需要勤于思考页面的加载过程。因为这会影响加载效率和用户体验。 99 | 如果你生成几个缩略图大小的图片,你可以实验使用一个非常小的图片作为背景,等待最终图片被加载出来。 100 | 101 | **其他图片加载技巧:**[ Image optimization: Lossy, lossless and other techniques. 102 | ](https://jmperezperez.com/image-optimization-lossy-lossless-techniques) 103 | 104 | (译者)写在最后:作为英语四级勉强过线选手,如果翻译有不到位地方,请多包涵。如若不能包涵就请跟着链接跳转看原文。当然,如果你感觉文章内容不错,就我给个star吧。 105 | 106 | -------------------------------------------------------------------------------- /(译)JSTips(41-)/(译)JSTips(41-).md: -------------------------------------------------------------------------------- 1 | \#41 数值数组的平均数和中位数 2 | 3 | ```js 4 | let values = [2, 56, 3, 41, 0, 4, 100, 23]; 5 | ``` 6 | 7 | 下面所有例子,都基于上述的数组。 8 | 为了求得数组平均值,我们需要加和,并且除以元素个数。 9 | * 获得数组元素个数 10 | * 加和所有元素值 11 | * 获得平均值(总和 / 个数) 12 | 13 | ```js 14 | let values = [2, 56, 3, 41, 0, 4, 100, 23]; 15 | let sum = values.reduce((pre vious, current) => current += previous); 16 | let avg = sum / values.length; 17 | // avg = 28 18 | 19 | //OR 20 | 21 | let values = [2, 56, 3, 41, 0, 4, 100, 23]; 22 | let count = values.length; 23 | values = values.reduce((previous, current) => current += previous); 24 | values /= count; 25 | // avg = 28 26 | ``` 27 | 28 | 获取中位数步骤: 29 | * 重排序数组 30 | * 获取中间值 31 | 32 | ```js 33 | let values = [2, 56, 3, 41, 0, 4, 100, 23]; 34 | values.sort((a, b) => a - b); 35 | let middle = Math.floor(values.length / 2); 36 | let median = values[middle]; 37 | // median = 23 38 | 39 | //或者使用右移操作符 40 | let values = [2, 56, 3, 41, 0, 4, 100, 23]; 41 | values.sort((a, b) => a - b); 42 | let median = values[values.length >> 1]; 43 | // median = 23 44 | ``` 45 | 46 | # 42 禁止原型链改写 47 | 通过重写原型链,攻击者可以重写代码公开和更改绑定参数。通过ES5的来开发会产生一个严重的安全漏洞。 48 | 49 | ```js 50 | // example bind polyfill 51 | function bind(fn) { 52 | var prev = Array.prototype.slice.call(arguments, 1); 53 | return function bound() { 54 | var curr = Array.prototype.slice.call(arguments, 0); 55 | var args = Array.prototype.concat.apply(prev, curr); 56 | return fn.apply(null, args); 57 | }; 58 | } 59 | 60 | // unapply-attack 61 | function unapplyAttack() { 62 | var concat = Array.prototype.concat; 63 | Array.prototype.concat = function replaceAll() { 64 | Array.prototype.concat = concat; // restore the correct version 65 | var curr = Array.prototype.slice.call(arguments, 0); 66 | var result = concat.apply([], curr); 67 | return result; 68 | }; 69 | } 70 | ``` 71 | 72 | 上面的`unapplyAttack`函数丢弃了`prev`数组,意味着函数中任意一个`.concat`方法都会导致抛出错误。 73 | 74 | 使用[Object.freeze](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)令对象不可更改,防止原型链重写。 75 | 76 | ```js 77 | (function freezePrototypes() { 78 | if (typeof Object.freeze !== 'function') { 79 | throw new Error('Missing Object.freeze'); 80 | } 81 | Object.freeze(Object.prototype); 82 | Object.freeze(Array.prototype); 83 | Object.freeze(Function.prototype); 84 | }()); 85 | ``` 86 | 87 | # 43 使用解构提取函数参数 88 | 你可能已经很熟悉ES6的解构特性,但你是否知道可以用它来取得函数传递的参数值? 89 | 90 | ```js 91 | var sayHello = function({ name, surname }) { 92 | console.log(`Hello ${name} ${surname}! How are you?`); 93 | }; 94 | 95 | sayHello({ 96 | name: 'John', 97 | surname: 'Smith' 98 | }); 99 | ``` 100 | 101 | 这方法对于接收可选对象作为参数的函数非常有用。 102 | > 切记,**解构赋值**并非在NodeJS和所有浏览器都可应用。你可以使用NodeJS的`--harmony-destructuring`标志来尝试在项目中使用。 103 | 104 | #44 了解参数传值机制 105 | 严格来说,JavaScript是基于值传递的。按照真正的条款来看,**它既是值传递也是参数传递**。想要了解传参规则,你要认真看看下列两例代码段和解释。 106 | ##例一 107 | 108 | ```js 109 | var me = { // 1 110 | 'partOf' : 'A Team' 111 | }; 112 | 113 | function myTeam(me) { // 2 114 | 115 | me = { // 3 116 | 'belongsTo' : 'A Group' 117 | }; 118 | } 119 | 120 | myTeam(me); 121 | console.log(me); // 4 : {'partOf' : 'A Team'} 122 | ``` 123 | 124 | 在上例中,当`myTeam`被调用。JavaScript传递`me`对象的引用值,因为它是一个对象和调用本身创造的**两个**对同一对象的独立引用(尽管名字相同都为`me`,误导我们认为是同一份引用)。但是引用变量本身是独立的。 125 | 当我们在**#3**为其赋值了一份新对象时,我们在`myTeam`方法中彻底更改了引用值(对象重新赋值)。但是它不会对外部的原生对象产生影响。因此,尽管作为参数被传递了,但是在函数外部,对象仍保持原值所以在**#4**处的输出仍为原值。 126 | 127 | ##例二 128 | 129 | ```js 130 | var me = { // 1 131 | 'partOf' : 'A Team' 132 | }; 133 | 134 | function myGroup(me) { // 2 135 | me.partOf = 'A Group'; // 3 136 | } 137 | 138 | myGroup(me); 139 | console.log(me); // 4 : {'partOf' : 'A Group'} 140 | ``` 141 | 142 | 我们传递对象`me`给`myTeam`函数作为参数。但是与例一不同,不是将`me`对象重新赋值为新对象。`myTeam`作用域中的对象仍与外部原生对象相关。因此,我们在函数内对对象内属性更改,会反映到外作用域的原生对象内。所以**#4**会输出这一结果。 143 | 144 | 所以,后例不能证明JavaScript参数是值传递?不,它的确是值传递。JavaScript中的对象会被以传值的形式来传引用(对象内属性存储的可以理解为是具体值的地址位置,因此以值传递到函数内,地址值不变。)。这很令人费解,我们不能很好理解什么是传引用。基于这一原因,人们更愿意称其为**共享传递** 145 | 146 | #45 计算求取数组内最大/最小值 147 | JavaScript中有两种内置方法可以计算出传入参数中的最大/小值,但是却不支持数组参数。 148 | 149 | ```js 150 | Math.max(1, 2, 3, 4); // 4 151 | Math.min(1, 2, 3, 4); // 1 152 | ``` 153 | 154 | `apply()`方法支持使用内建函数查找数组内的最值。 155 | 156 | ```js 157 | var numbers = [1, 2, 3, 4]; 158 | Math.max.apply(null, numbers) // 4 159 | Math.min.apply(null, numbers) // 1 160 | ``` 161 | 162 | 传入第一个函数用于限定作用域,在这里,这点不重要。 163 | 可以通过使用**ES7**的分隔操作符**`...`** 164 | 165 | ```js 166 | var numbers = [1, 2, 3, 4]; 167 | Math.max(...numbers) // 4 168 | Math.min(...numbers) // 1 169 | ``` 170 | 171 | #46 使用纯JS监听`documnet`准备情况 172 | 使用纯JS的跨浏览器监测查看`document`是否加载完成,通常可以使用`readyState` 173 | 174 | ```js 175 | if (document.readyState === 'complete') { 176 | // The page is fully loaded 177 | } 178 | ``` 179 | 180 | 你可以查看什么时候`document`准备就绪。 181 | 182 | ```js 183 | let stateCheck = setInterval(() => { 184 | if (document.readyState === 'complete') { 185 | clearInterval(stateCheck); 186 | // document ready 187 | } 188 | }, 100); 189 | ``` 190 | 191 | 当然,使用`onreadystatechange`也可以进行查看。 192 | 193 | ```js 194 | document.onreadystatechange = () => { 195 | if (document.readyState === 'complete') { 196 | // document ready 197 | } 198 | }; 199 | ``` 200 | 201 | 使用`document.readyState === 'interactive'`可以查看**DOM**是否就绪。 202 | 203 | #47 声明必知必会 204 | 下例中,使用不同的JavaScript方法声明变量。注释和`console.log`足够说明发生了什么。 205 | 206 | ```js 207 | //Example 1 208 | 209 | var y, x = y = 1 //== var x; var y; x = y = 1 210 | console.log('--> 1:', `x = ${x}, y = ${y}`) 211 | 212 | // Will print 213 | //--> 1: x = 1, y = 1 214 | ``` 215 | 216 | 首先我们声明两个变量 217 | 218 | ```js 219 | //Example 2 220 | 221 | ;(() => { 222 | var x = y = 2 // == var x; y = 2; 223 | console.log('2.0:', `x = ${x}, y = ${y}`) 224 | })() 225 | console.log('--> 2.1:', `x = ${x}, y = ${y}`) 226 | 227 | // Will print 228 | //2.0: x = 2, y = 2 229 | //--> 2.1: x = 1, y = 2 230 | ``` 231 | 232 | 上例2中可以发现,只有**变量y**被更改,其并没有在闭包中被重新声明。 233 | 234 | ```js 235 | //Example 3 236 | 237 | ;(() => { 238 | var x, y = 3 // == var x; var y = 3; 239 | console.log('3.0:', `x = ${x}, y = ${y}`) 240 | })() 241 | console.log('--> 3.1:', `x = ${x}, y = ${y}`) 242 | 243 | // Will print 244 | //3.0: x = undefined, y = 3 245 | //--> 3.1: x = 1, y = 2 246 | ``` 247 | 248 | 上例3中,使用`var`关键字声明了两变量。意味着,他们的值只在作用域内有效。 249 | 250 | ```js 251 | //Example 4 252 | 253 | ;(() => { 254 | var y, x = y = 4 // == var x; var y; x = y = 4 255 | console.log('4.0:', `x = ${x}, y = ${y}`) 256 | })() 257 | console.log('--> 4.1:', `x = ${x}, y = ${y}`) 258 | 259 | // Will print 260 | //4.0: x = 4, y = 4 261 | //--> 4.1: x = 1, y = 2 262 | ``` 263 | 264 | 例4中,两变量都被重新定义。由于变量优先级为**local > global**,所以**变量x,y**在局部闭包中被赋值不会影响到**全局变量的x,y**。 265 | 266 | ```js 267 | x = 5 // == x = 5 268 | console.log('--> 5:', `x = ${x}, y = ${y}`) 269 | 270 | // Will print 271 | //--> 5: x = 5, y = 2 272 | ``` -------------------------------------------------------------------------------- /D3数据绑定(Data Join)/数据绑定(Data Join).md: -------------------------------------------------------------------------------- 1 | ### 元素绑定数据 2 | 3 | 当我们使用`d3.selectAll('g')`得到一组D3选择集(D3 selection)时。我们可以给选择集合的每个元素绑定对应数据数组中的数据。这样做会让数据和图形元素之间的联系更紧密,似的数据驱动修改、更新元素更加简单明了。 4 | 5 | **例子** 6 | 7 | 一组`circle`元素 8 | 9 | ```html 10 | 11 | 12 | 13 | 14 | 15 | ``` 16 | 17 | 和一组数据元素 18 | 19 | ```js 20 | const scores = [ 21 | { 22 | "name": "Andy", 23 | "score": 25 24 | }, 25 | { 26 | "name": "Beth", 27 | "score": 39 28 | }, 29 | { 30 | "name": "Craig", 31 | "score": 42 32 | }, 33 | { 34 | "name": "Diane", 35 | "score": 35 36 | }, 37 | { 38 | "name": "Evelyn", 39 | "score": 48 40 | } 41 | ] 42 | ``` 43 | 44 | 接下来我们可以使用`.selectAll()`方法获取所有`circle`元素集合数组,并使用`.data()`方法将数据与之各个`circle`元素绑定。 45 | 46 | ```js 47 | d3.selectAll('circle') 48 | .data(scores) 49 | ``` 50 | 51 | 绑定之后我们就可以通过获取各元素绑定的数据直接操作或赋值元素的属性了: 52 | 53 | ```js 54 | d3.selectAll('circle') 55 | .attr('r', d => d.score) 56 | ``` 57 | 58 | 如下图为使用数组数据中各元素的`score`值来赋值`circle`元素的半径`r`属性。 59 | 60 | ![IMAGE](resources/1542C02CCA35201C28B20FC678D63B4F.jpg) 61 | 62 | **🌰代码** 63 | 64 | ```html 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | ``` 74 | 75 | 76 | ```js 77 | const scores = [ 78 | { 79 | "name": "Andy", 80 | "score": 25 81 | }, 82 | { 83 | "name": "Beth", 84 | "score": 39 85 | }, 86 | { 87 | "name": "Craig", 88 | "score": 42 89 | }, 90 | { 91 | "name": "Diane", 92 | "score": 35 93 | }, 94 | { 95 | "name": "Evelyn", 96 | "score": 48 97 | } 98 | ] 99 | d3.selectAll('circle') 100 | .data(scores) 101 | .enter().append('circle') 102 | .attr('cx', (d, i) => i * 120 ) 103 | .attr('r', d => d.score) 104 | ``` 105 | 106 | ### 数据绑定元素 107 | 108 | 首先我们需要有一个数组和一个元素选择集,接下来使用`.data()`方法创建两数据、元素集合之间的联系。 109 | 110 | ```js 111 | const myData = [ 10, 40, 20, 30 ]; 112 | 113 | const s = d3.selectAll('circle'); 114 | 115 | s.data(myData); 116 | ``` 117 | 118 | 不只是纯数值数组,数组元素也可以是其他类型,例如使用最多的:`Object`元素。 119 | 120 | ```js 121 | const cities = [ 122 | { name: 'London', population: 8674000}, 123 | { name: 'New York', population: 8406000}, 124 | { name: 'Sydney', population: 4293000} 125 | ]; 126 | const s = d3.selectAll('circle'); 127 | s.data(cities); 128 | ``` 129 | 130 | 你或许没有注意到,当`.data()`方法被调用进行数据绑定后d3会帮你做一些其他的事情。 131 | 132 | 这些**小事情**会在你基于数据更新元素状态时,咻咻咻的展现出来。D3真心太牛逼了! 133 | 134 | ### 数据驱动更新元素 135 | 136 | 当我们使用`.data()`方法将数据和元素绑定之后,我们就可以通过传入函数给`.style`和`.attr`等方法中修改元素的各个属性。 137 | 138 | ```js 139 | d3.selectAll('circle') 140 | .attr('r', d => d) 141 | ``` 142 | 143 | D3选择集中的每个元素都会调用这个函数,传入函数的首个参数`d`默认为绑定到元素上的数据元素,该函数方法要求有返回值:用来设定元素的样式或属性。 144 | 145 | 例如: 146 | 147 | **元素** 148 | 149 | ```html 150 | 151 | 152 | 153 | 154 | 155 | ``` 156 | 157 | **数据** 158 | 159 | ```js 160 | const myData = [ 10, 40, 20, 30, 50 ]; 161 | ``` 162 | 163 | 下面我们开始进行数据绑定: 164 | 165 | ```js 166 | const s = d3.selectAll('circle') 167 | 168 | s.data(myData) 169 | ``` 170 | 171 | 现在我们使用绑定数据的值来更新圆半径: 172 | 173 | ```js 174 | s.attr('r', function(d) { 175 | return d; 176 | }); 177 | ``` 178 | 179 | 传入给`.attr`的函数总共被调用了五次(选择集中的每个元素都会调用一次),然后每个`circle`元素的半径`r`属性依次被赋值为10、40、20、30、50。 180 | 181 | 我们也可以对返回数据进行处理再返回: 182 | 183 | ```js 184 | s.attr('r', function(d) { 185 | return 2 * d; 186 | }); 187 | ``` 188 | 189 | 也能做条件判断: 190 | 191 | ```js 192 | s.classed('high', function(d) { 193 | return d >= 0; // returns true or false 194 | }) 195 | ``` 196 | 197 | 最后可以基于传入的第二个参数index来定位`circle`元素的位置: 198 | 199 | ```js 200 | s.attr('cx', function(d, i) { 201 | return i * 120; 202 | }); 203 | ``` 204 | 全部代码: 205 | 206 | ```js 207 | 208 | var myData = [ 10, 40, 20, 30, 50 ]; 209 | 210 | var s = d3.selectAll('circle'); 211 | 212 | // Do the data join 213 | s.data(myData); 214 | 215 | // Modify the selected elements 216 | s.attr('r', function(d) { 217 | return d; 218 | }) 219 | .classed('high', function(d) { 220 | return d >= 40; 221 | }) 222 | .attr('cx', function(d, i) { 223 | return i * 120; 224 | }) 225 | ``` 226 | 227 | ![IMAGE](resources/AADA008DF9FC795C84F53C6E584FC17F.jpg) 228 | 229 | #### 对象数组 230 | 231 | 如果有一个由Object对象组成的数组,我们可以通过以下方式将其绑定: 232 | 233 | ```js 234 | const cities = [ 235 | { name: 'London', population: 8674000}, 236 | { name: 'New York', population: 8406000}, 237 | { name: 'Sydney', population: 4293000}, 238 | { name: 'Paris', population: 2244000}, 239 | { name: 'Beijing', population: 11510000} 240 | ]; 241 | 242 | const s = d3.selectAll('circle'); 243 | 244 | s.data(cities); 245 | ``` 246 | 247 | 现在我们基于绑定数据`d`来更新元素,`d`此时表示绑定在元素上的Object数据。因此选择集首个元素绑定的数据`d`是`{ name: 'London', population: 8674000}`。 248 | 249 | 通过绑定数据,设定圆半径: 250 | 251 | ```js 252 | s.attr('r', function(d) { 253 | const scaleFactor = 0.000005; 254 | return d.population * scaleFactor; 255 | }) 256 | .attr('cx', function(d, i) { 257 | return i * 120; 258 | }); 259 | ``` 260 | 261 | **效果图** 262 | 263 | ![IMAGE](resources/B5954156DB042D466A47460E429A1AFB.jpg) 264 | 265 | 266 | 当然我们不仅仅局限于修改`circle`元素,如果我们有`rect`、`text`类型的元素,我们也可以构建一个简单的柱状图。 267 | 268 | ```js 269 | const cities = [ 270 | { name: 'London', population: 8674000}, 271 | { name: 'New York', population: 8406000}, 272 | { name: 'Sydney', population: 4293000}, 273 | { name: 'Paris', population: 2244000}, 274 | { name: 'Beijing', population: 11510000} 275 | ]; 276 | 277 | // 绑定数据到rect元素上 278 | d3.selectAll('rect') 279 | .data(cities) 280 | .attr('height', 19) 281 | .attr('width', function(d) { 282 | const scaleFactor = 0.00004; 283 | return d.population * scaleFactor; 284 | }) 285 | .attr('y', function(d, i) { 286 | return i * 20; 287 | }) 288 | 289 | // 绑定数据给text元素 290 | d3.selectAll('text') 291 | .data(cities) 292 | .attr('y', function(d, i) { 293 | return i * 20 + 13; 294 | }) 295 | .attr('x', -4) 296 | .text(function(d) { 297 | return d.name; 298 | }); 299 | ``` 300 | 301 | **效果图** 302 | 303 | ![IMAGE](resources/04DEC69A3C2DEDA5A4D53498E58E34A8.jpg) 304 | 305 | ### `.data()`具体机制 306 | 307 | 当D3执行`.data()`方法绑定数据时,它会在对应元素上添加一个`__data__`属性,让后将具体数据作为属性值赋值在上面。 308 | 309 | 通过Chrome浏览器的开发者工具我们可以查看到该属性内容。 310 | 311 | ![IMAGE](resources/2F56859869DE44F8B4BD35E91EE0995D.jpg =850x318) 312 | 313 | ### `.datum()`是做啥的? 314 | 315 | 在网上有很多例子是将单个数据与一个选择集绑定在一起(可以理解为就是只绑定在根节点上)。 316 | 317 | ```js 318 | const featureCollection = {type: 'FeatureCollection', features: features}; 319 | ``` 320 | 321 | 这个时候我们就可以使用`.datum`方法来进行这样的操作。 322 | 323 | ```js 324 | d3.select('#root') 325 | .datum(featureCollection); 326 | ``` 327 | 328 | **看清楚上面代码!只有通过查找id而进行单个节点选择。** 不是`.selectAll`方法。 329 | 330 | `.datum`方法添加`__data__`属性到选择的元素上,并将`featureCollection`数据绑定到`#root`元素上。 331 | 332 | **请记得,大部分时候我们只需要使用`.data`方法来绑定数据,`.datum`方法只有在一些特殊例子中才会使用。** -------------------------------------------------------------------------------- /(译)如何处理React中的状态信息/(译)如何处理React中的状态信息.md: -------------------------------------------------------------------------------- 1 | #动机 2 | 最近,对于如何处理`React`中的状态信息有许多的争论。一些人声称`setState()`没有如期望的方式工作。你必须使用类似Flux的状态容器来具体化状态信息并且完全避免使用组件信息。 3 | 4 | 但在另一方面,仍有许多人担心上面的误解最终会变成教条。 5 | 6 | ![](resources/381DBDECF1E5C7B9D479FFC4B9ABE8FB.jpg) 7 | 8 | 因为兴趣而添加外部状态信息容器,或者由于教程告诉你要如此做听起来不是个好的技术决策标准。 9 | 清楚的说,使用类似Redux、MobX之类的外部状态容器没有错。事实上他们非常好用并且有很广泛的生态系统来适应你的需求。但事实是你不一定非要或一开始就使用他们。 10 | 11 | 如果你是在scratch上学习的React,Pete Hunt发布了[最佳建议](https://github.com/petehunt/react-howto)。甚至Redux的作者[Dan Abramov](https://medium.com/u/a3a8af6addc1)也建议: 12 | 13 | ![](resources/4E396749CCB87E7982D6F3E978EF229E.jpg) 14 | 15 | 这意味着你需要在使用Flux处理之前,能先理解如何使用React的方式处理状态信息。 16 | 17 | 不使用Flux你仍然可以开发出一个完整的应用,组件可以分为两类:[容器和表现层](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.y6t3ajszk)。这样你可以获得重用性和可维护性。这样同时也可以在后期引入Flux,迁移路径也会更清晰,在最后才需要决定使用哪种方案。 18 | 19 | 即使你已经在之前就使用了Flux,在某些情况下你仍应该使用**组件状态信息**。比如你希望跨项目分享你的组件,因此你的组件必须是独立且属性独立包含的。在此情况下,你真的不需要再使用状态容器作为依赖了。 20 | 21 | 我的观点如下: 22 | * 社区中关于如何处理React状态信息的看法,具有一定误解并且缺乏对其的充分了解。 23 | * 想要拥抱React所有功能,理解如何处理状态信息是至关重要的。 24 | * 假如不需要,千万不要添加复杂层给你的应用。切记: [simplicity matters.](https://medium.com/javascript-scene/the-single-biggest-mistake-programmers-make-every-day-62366b432308#.k2b2mk5ee)。 25 | 26 | 以下的常见FAQ的目的是降低处理React状态信息的复杂度。 27 | 28 | ##状态信息如何工作? 29 | React组件类似于状态机,用于展示用户接口信息。每个用户的动作都可能会触发状态机的改变,然后新状态会在新渲染的组件中表现出来。 30 | 31 | React存储组件状态信息在`this.state`。可以使用两种方式设定初始值给`this.state`。 32 | 33 | ```JavaScript 34 | // Using React.createClass 35 | var Counter = React.createClass({ 36 | getInitialState: function() { 37 | return {counter: 0}; 38 | }, 39 | ... 40 | }); 41 | // Using ES6 classes 42 | class Counter extends React.Component { 43 | constructor(props) { 44 | super(props); 45 | this.state = {counter: 0}; 46 | } 47 | ... 48 | } 49 | ``` 50 | 51 | 状态信息可以通过以下方式更改: 52 | ```JavaScript 53 | this.setState(data, callback); 54 | ``` 55 | 56 | 该方法会使用**data**对`this.state`数据做一次浅覆盖,然后重新渲染组件。**data**参数可以为对象或返回结果为包含对应关键字对象的方法。**callback**方法为可选的,如果我们选择传入会在组件重渲染之后执行。React会保证你状态数据的更新,所以你很少会用到回调函数。 57 | **下面让我们看下例子:** 58 | 59 | ```JavaScript 60 | class Counter extends React.Component { 61 | constructor(props) { 62 | super(props); 63 | this.state = {count: 0}; 64 | this.incrementCounter = this.updateCounter.bind(this, 1); 65 | this.decrementCounter = this.updateCounter.bind(this, -1); 66 | } 67 | 68 | render() { 69 | return ( 70 |
71 |
{this.state.count}
72 | 73 | 74 |
75 | ); 76 | } 77 | 78 | updateCounter(count) { 79 | this.setState({count: this.state.count + count}); 80 | } 81 | } 82 | ``` 83 | 84 | ###哪些信息要存放在React的状态信息中? 85 | Dan Abramov 在一条tweet中回复这一问题: 86 | 87 | ![](resources/80DA629F694F0DBB9B5C85C29C065C2D.jpg) 88 | 89 | 首先,不要复制`props`传入的参数给`state`,不管其是不是要用在`render()`方法中的。 90 | 91 | ```javascript 92 | // Don't duplicate data form props in state 93 | // Antipattern 94 | class Component extends React.Component { 95 | constructor(props) { 96 | super(props); 97 | this.state = {message: props.message}; 98 | } 99 | 100 | render() { 101 | return
{this.state.message}
; 102 | } 103 | } 104 | ``` 105 | 106 | 上述例子问题在于`state`应该在组件创建之初就被声明。当新的`props`参数传入,`state`值不变因此不会重新渲染组件。因此,此时推荐你使用`componentWillReceiveProps()`方法来更新状态重渲染组件 ---- 单一**数据来源才是王道**。因此你可以使用以下方式避免问题: 107 | 108 | ```JavaScript 109 | // Better example 110 | class Component extends React.Component { 111 | componentWillReceiveProps(...){ 112 | // do someting and return true of false 113 | // to let React know weather or not render the Component 114 | } 115 | render() { 116 | return
{this.props.message}
; 117 | } 118 | } 119 | ``` 120 | 121 | 同样当你的状态信息是基于`props`参数计算得来的时候: 122 | 123 | ```JavaScript 124 | // Don't hold state based on props calculation 125 | // Antipattern 126 | class Component extends React.Component { 127 | constructor(props) { 128 | super(props); 129 | this.state = {fullName: `${props.name} ${props.lastName}`}; 130 | } 131 | 132 | render() { 133 | return
{this.state.fullName}
; 134 | } 135 | } 136 | // Better approach 137 | class Component extends React.Component { 138 | render() { 139 | const {name, lastName} = this.props; 140 | return
{`${name} ${lastName}`}
; 141 | } 142 | } 143 | ``` 144 | 145 | 尽管基于`props`设定初始`state`没有错,但这么做的前提是需要你能了解它只是初始种子数据。 146 | ```JavaScript 147 | // Not an antipattern 148 | class Component extends React.Component { 149 | constructor(props) { 150 | super(props); 151 | this.state = {count: props.initialCount}; 152 | this.onClick = this.onClick.bind(this); 153 | } 154 | 155 | render() { 156 | return
{this.state.count}
; 157 | } 158 | 159 | onClick() { 160 | this.setState({count: this.state.count + 1}); 161 | } 162 | } 163 | ``` 164 | 165 | 最后,但并不是最不重要的一个: 166 | ```JavaScript 167 | // Don't hold state that you don't use for rendering. 168 | // Leads to unneeded re-renders and other inconsistencies. 169 | // Antipattern 170 | class Component extends React.Component { 171 | constructor(props) { 172 | super(props); 173 | this.state = {count: 0}; 174 | } 175 | 176 | render() { 177 | return
{this.state.count}
; 178 | } 179 | 180 | componentDidMount() { 181 | const interval = setInterval(() => ( 182 | this.setState({count: this.state.count + 1}) 183 | ), 1000); 184 | this.setState({interval}); 185 | } 186 | componentWillUnmount() { 187 | clearInterval(this.state.interval); 188 | } 189 | } 190 | //Better approach 191 | class Component extends React.Component { 192 | constructor(props) { 193 | super(props); 194 | this.state = {count: 0}; 195 | } 196 | 197 | render() { 198 | return
{this.state.count}
; 199 | } 200 | 201 | componentDidMount() { 202 | this._interval = setInterval(() => ( 203 | this.setState({count: this.state.count + 1}) 204 | ), 1000); 205 | } 206 | componentWillUnmount() { 207 | clearInterval(this._interval); 208 | } 209 | } 210 | ``` 211 | 212 | ###`setState()是异步的?` 213 | 当然! 214 | 当你使用`setState()`方法时,React会安排一个更新,由于需要计算因此延迟是必不可少的。React文档对这一点有所误导: 215 | ![](resources/0C9039AEEC66BC21665D2706CAEB7BC7.jpg) 216 | 显然这两句话存在矛盾,下面我们做个实验看看会发生什么: 217 | ```JavaScript 218 | class Component extends React.Component { 219 | constructor(props) { 220 | super(props); 221 | this.state = {count: 0}; 222 | this.onClick = this.onClick.bind(this); 223 | } 224 | 225 | render() { 226 | return
{this.state.count}
; 227 | } 228 | 229 | onClick() { 230 | this.setState({count: this.state.count + 1}); 231 | console.log(this.state.count); 232 | } 233 | } 234 | ``` 235 | 236 | 当组件渲染完成并且可以互动时,你会在控制台看到值的变化。**这是由于React拥有事件,并且知道如何批处理更新**。 237 | 结果:状态信息异步更新。 238 | 但是,当事件来自于外部数据源时会发生什么呢? 239 | ```JavaScript 240 | // Calling setState() twice in the same execution context is a bad // practice. It's used here for illustration purposes. Instead use // an atomic update in real code 241 | class Component extends React.Component { 242 | constructor(props) { 243 | super(props); 244 | this.state = {count: 0}; 245 | } 246 | 247 | render() { 248 | return
{this.state.count}
; 249 | } 250 | 251 | componentDidMount() { 252 | this._interval = setInterval(() => { 253 | this.setState({count: this.state.count + 1}); 254 | console.log(this.state.count); 255 | this.setState({count: this.state.count + 1}); 256 | console.log(this.state.count); 257 | }, 1000); 258 | } 259 | componentWillUnmount() { 260 | clearInterval(this._interval); 261 | } 262 | } 263 | ``` 264 | 即使在同一执行环境中调用`setState()`两次,如文档所说明的返回已有值。这是由于React不知道如何尽可能快的更新状态信息。 265 | 这一点很棘手,因此我建议一直视`setState`为异步,这样会避免麻烦。 266 | 267 | ###我听说在某些特定环境下调用`setState()`不会触发重渲染,那都有哪些情景? 268 | 1. 当你在`componentWillMount()`或`componentWillRecieveProps()`方法中调用`setState()`时,它不会触发额外的React更新批处理。 269 | 2. 当`shouldComponentUpdate()`返回`false`时,`render()`方法会完全跳过`componentWillUpdate()`和`componentDidUpdate()`方法。 270 | 271 | ##总结 272 | 在React中正确处理状态信息是个挑战,现在希望你现在能有个清晰的思路了。 273 | 274 | [How to handle state in React. The missing FAQ. 275 | ](https://medium.com/react-ecosystem/how-to-handle-state-in-react-6f2d3cd73a0c#.6nkftjnc2) 276 | 277 | -------------------------------------------------------------------------------- /(译)深入React的children/(译)深入React的children.md: -------------------------------------------------------------------------------- 1 | #深入React的`children` 2 | React设计思想的核心是组件化,通过JSX语法你可以像HTML标签一样简单的编写叠加各个组件。 3 | 4 | 当我第一次学习React,我认为"使用`props.children`"就是所有的东西了。**但是,我错了!** 5 | 6 | 因为我们现在使用的是JavaScript,所以我们可以更改子组件。通过传递特殊属性来决定是否渲染或者控制这些子组件。现在让我们发现React`children`属性的能力。 7 | 8 | #子组件 9 | 此时我们拥有一个``组件,其中可以包含``组件使用形式如下: 10 | ```JavaScript 11 | 12 | 13 | 14 | 15 | 16 | ``` 17 | ![](resources/D92089868E199196ADAB5F22B056B2F1.jpg) 18 | 此时传入了三个**`Row`**组件作为`props.children`到**`Grid`**组件当中。使用**表达式的父组件**可以渲染它的子组件。 19 | ```JavaScript 20 | class Grid extends React.Component { 21 | render() { 22 | return
{this.props.children}
23 | } 24 | } 25 | ``` 26 | 父组件同样可以在渲染之前就决定是否渲染或者操作子组件。例如``组件不会渲染它的子组件。 27 | ```JavaScript 28 | class Fullstop extends React.Component { 29 | render() { 30 | return

Hello world!

31 | } 32 | } 33 | ``` 34 | 无论给组件传入什么`children`,它永远都只会显示**Hello world!** 35 | > 上面例子中的`

`标签会渲染它的子组件"Hello world!"。 36 | 37 | ##Everything can be a child 38 | React中的子元素不强制要求为组件,它可以是任何东西。例如,我们可以传递上例中的文本元素作为子元素给``,它可以正常展示出来。 39 | ```HTML 40 | Hello world! 41 | ``` 42 | ![](resources/DAF4A478E8E2EAA604D6784B9BB29A3D.jpg) 43 | 44 | JSX会自动移除文本元素开头和结尾的空格符,同时也会将字符之间的空白符压缩为一个空格。这意味着以下例子中的文本最后会被渲染成同样。 45 | ```HTML 46 | Hello world! 47 | 48 | 49 | Hello world! 50 | 51 | 52 | 53 | Hello 54 | world! 55 | 56 | 57 | 58 | 59 | Hello world! 60 | 61 | ``` 62 | 63 | 你也可以给``中传入不同种类的子元素: 64 | ```HTML 65 | 66 | Here is a row: 67 | 68 | Here is another row: 69 | 70 | 71 | ``` 72 | ![](resources/406E678AF57519D5DD376790636FDFC8.jpg) 73 | 74 | ##方法作为子元素 75 | 可以传入JavaScript表达式做子元素。下面给一个栗子来说明如何使用函数方法作为子元素: 76 | ```JavaScript 77 | class Executioner extends React.Component { 78 | render() { 79 | // See how we're calling the child as a function? 80 | // ↓ 81 | return this.props.children() 82 | } 83 | } 84 | ``` 85 | 你需要像如下的方式来传入方法作子组件: 86 | ```HTML 87 | 88 | {() =>

Hello World!

} 89 |
90 | ``` 91 | 上面的例子当然不是有用的,只是用来说明思想。 92 | 想象一个场景,你需要从服务端拉取数据。当然有许多方法能够做到这一点,其中就可以使用方法作为子元素来作为一种模式。 93 | ```HTML 94 | 95 | {(result) =>

{result}

} 96 |
97 | ``` 98 | ##控制子元素 99 | 如果你看过React的文档,会有这么一句话:“children are an opaque data structure(子元素是一个不透明的数据结构)”。此处说明`props.children`可以是任何类型,例如数组、方法、对象等。由于可以传入任何类型,因此你无法确定。 100 | 101 | React在`React.Children`中提供了多种可用的帮助函数来控制子元素减少不必要的副作用。 102 | 103 | ###遍历子元素 104 | `React.Children`中最常用的两个方法是`React.Children.map`和`React.Children.forEach`。它们的运行方式与数组内置方法中的相似,不同之处在于当传入的子元素为方法、对象或其他类型时依然能够运行。 105 | ```JavaScript 106 | class IgnoreFirstChild extends React.Component { 107 | render() { 108 | const children = this.props.children 109 | return ( 110 |
111 | {React.Children.map(children, (child, i) => { 112 | // Ignore the first child 113 | if (i < 1) return 114 | return child 115 | })} 116 |
117 | ) 118 | } 119 | } 120 | ``` 121 | 122 | ``组件会遍历所有子元素,返回除了首元素之外的所有子元素。 123 | ```HTML 124 | 125 |

First

126 |

Second

// <- Only this is rendered 127 |
128 | ``` 129 | ![](resources/F641FFC827F310757F879579FFD81ADD.jpg) 130 | 131 | 在这一🌰种,我们也可以使用`this.props.children.map`。但如果某人传入方法来作为子元素时会怎么样?`this.props.chilcren`会使用方法来代替数组,而且会报错! 132 | ![](resources/9A7AD2CBEFAE715079D5130F9D12DCEE.jpg) 133 | 134 | 使用`React.Children.map`方法,没有任何问题。 135 | ```HTML 136 | 137 | {() =>

First

} // <- Ignored 💪 138 |
139 | ``` 140 | 141 | ###计数子元素 142 | 由于`this.props.children`可以是任意类型,因此想要知道有多少个子组件是件很困难的事。如果传入的是一个方法的话,简单的使用`this.props.children.lengt`很可能会导致程序崩溃。如果我们传入的是一个"Hello world!"的字符串作为子组件,但是`.length`会返回**12**。 143 | 这也是为什么React会提供`React.Children.count`方法的原因: 144 | ```JavaScript 145 | class ChildrenCounter extends React.Component { 146 | render() { 147 | return

React.Children.count(this.props.children)

148 | } 149 | } 150 | ``` 151 | 无论什么类型的子组件都可以,输出结果如下: 152 | ```HTML 153 | // Renders "1" 154 | 155 | Second! 156 | 157 | 158 | // Renders "2" 159 | 160 |

First

161 | 162 |
163 | 164 | // Renders "3" 165 | 166 | {() =>

First!

} 167 | Second! 168 |

Third!

169 |
170 | ``` 171 | ###转换子组件为数组 172 | 如果之前的方法都不让你满意,作为最后的方法。你可以使用`React.Children.toArray`将传入的子组件转换为数组的形式。这会很有用,例如在你想排序的情境下。 173 | ```JavaScript 174 | class Sort extends React.Component { 175 | render() { 176 | const children = React.Children.toArray(this.props.children) 177 | // Sort and render the children 178 | return

{children.sort().join(' ')}

179 | } 180 | } 181 | ``` 182 | **输出:字符串被排序,同时渲染** 183 | ```HTML 184 | 185 | // We use expression containers to make sure our strings 186 | // are passed as three children, not as one string 187 | {'bananas'}{'oranges'}{'apples'} 188 | 189 | ``` 190 | ![](resources/BC70E781BC90C42110A8ED2F58B6AE38.jpg) 191 | 192 | ##Enforcing a single child 193 | 回想之前我们写的``组件,它要求只能传入一个方法作为子组件。 194 | ```JavaScript 195 | class Executioner extends React.Component { 196 | render() { 197 | return this.props.children() 198 | } 199 | } 200 | ``` 201 | 我们可以使用`propTypes`的形式要求`props`中传入的类型。 202 | ```JavaScript 203 | Executioner.propTypes = { 204 | children: React.PropTypes.func.isRequired, 205 | } 206 | ``` 207 | 这么做会在控制台输出一条消息,通常会被开发者忽略掉,因此我们可以将渲染方法放到`React.Children.only`方法中。 208 | ```JavaScript 209 | class Executioner extends React.Component { 210 | render() { 211 | return React.Children.only(this.props.children)() 212 | } 213 | } 214 | ``` 215 | 这样会返回`this.props.children`的单一子组件。如果有多个子组件的话,会报错! 216 | 217 | ##修改子组件 218 | 我们本可以随意的渲染组件作为子元素,但仍然控制它的父组件而不是渲染出的子元素本身。为了具体说明,我们创建一个`RadioGroup`组件,其中可以多个`RadioButton`组件(渲染`