├── .gitignore ├── Published ├── Animation tip-Lerp.md ├── CSS Tip- Multicolor & Cutout Drop Shadows.md ├── 两端对齐几种实现方案.md ├── 3 things you didn’t know about the forEach loop in JS.md ├── javascript │ ├── Some-cool-and-awesome-JavaScript-tricks.md │ └── 10-Super-Useful-Tricks-for-JavaScript-Developers.md ├── Notched Boxes.md ├── typescript │ ├── Some-Lesser-Known-TypeScript-Features.md │ └── What’s-New-in-TypeScript-3.9.md ├── Flexbox- Don't Forget about flex-shrink.md ├── CSS Grid Layout- Fluid Columns and Better Gutters.md ├── Breaking down CSS Box Shadow vs. Drop Shadow.md ├── Quick Tip- Name Your CSS Grid Lines, Just in Case.md ├── react │ └── Creating-a-reusable-React-Query-component-for-your-REST-API.md ├── React State Management in 2020.md ├── Breaking out with CSS Grid explained.md ├── CSS Grid Layout- A Quick Start Guide.md ├── Breaking Out With CSS Grid Layout.md ├── Understanding the CSS Grid “Auto-Placement Algorithm” .md ├── css │ └── CSS-Scroll-Snap—How-It-Really-Works.md ├── Stateless functional components.md ├── Understanding-Arrow-Functions.md ├── React Hooks in TypeScript.md ├── Flexbox- space-between, Flexbox's Unsung Hero.md ├── CSS Grid Layout- Using Grid Areas.md ├── 10-New-JavaScript-Features-in-ES2020-That-You-Should-Know.md ├── CSS Grid Layout- Going Responsive With auto-fill and minmax().md └── Testing-React-with-Jest-and-Enzyme-II.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | Unpublished/ 2 | -------------------------------------------------------------------------------- /Published/Animation tip-Lerp.md: -------------------------------------------------------------------------------- 1 | 2 | ## Animation tip: Lerp 3 | ## 动画技巧:Lerp 4 | 5 | > 原文地址: [https://codepen.io/rachsmith/post/animation-tip-lerp](https://codepen.io/rachsmith/post/animation-tip-lerp) 6 | **本文版权归原作者所有,翻译仅用于学习。** 7 | 8 | ----- 9 | 10 | > Ahhhhhhhhhhh I'm blogging again on CodePen! It's been a little while, my bad. 11 | 12 | 我再次在CodePen上更新我的博客了!个人原因有段时间没更新了。 13 | 14 | > Today I want to talk about a little animation trick that I use all the time called lerp. Lerp is the nickname for Linear Interpolation between two points. It's a fairly simple effect to implement but can really improve the look of your animations if you're moving an object from a point A to point B. 15 | 16 | 今天,我想聊一聊一个有关动画的小技巧,我称它为:**Lerp**。**Lerp** 是```两点之间线性差值```的简称。这是一个相当容易实现的效果,但是如果你在A、B两点移动,会让动画体验更好。 17 | 18 | ### HOW DOES IT WORK? 19 | ### 如何工作 20 | 21 | > Given you have a current position for an object, and a position you want to move that object towards - you can linearly interpolate to a percentage of the distance between those points, and update the position by that amount on each frame. 22 | 23 | 确定一个当前位置对象和你需要移动目标位置对象。动画的每一帧,你可以按照两点之间的距离百分比来线性的更新。 24 | 25 | ``` 26 | // to run on each frame 27 | function lerp(position, targetPosition) { 28 | // update position by 20% of the distance between position and target position 29 | position.x += (targetPosition.x - position.x)*0.2; 30 | position.y += (targetPosition.y - position.y)*0.2; 31 | } 32 | ``` 33 | 34 | > By doing this, the amount the object moves becomes smaller as the distance between position and target decreases. This means the object will slow down as it gets closer to its target, creating a nice easing effect. 35 | 36 | 这么做之后,移动的距离会随着两点之间距离减少越来越小。也就是说随着越来越接近目标位置,移动对象会慢下来,这样就有一个缓冲的效果。 37 | 38 | ### Lerp in action - some examples 39 | ### Lerp的实际应用- 一些示例 40 | 41 | > Here is an example of a ball following the user's mouse or touch. If we make the ball move to the place the mouse is as soon as it moves, the ball movement can be very fast and/or disjointed. We might also be able to see separate "ball frames" if we move our mouse really fast. 42 | 43 | 这个示例中的球会跟着用户鼠标和触摸移动。当球移动某个位置时是非常快速的。甚至如果我们移动的够快,你会看到球会跟指针脱离。 44 | 45 | **Demo1** 46 | [https://codepen.io/rachsmith/pen/avXmyV](https://codepen.io/rachsmith/pen/avXmyV) 47 | 48 | > Here's the same demo, except this time we're using lerp. Instead of moving the ball right to the mouse position, we'll move it 10% of the distance towards that position on each frame. 49 | 50 | 这有一个相同的示例,但是这个示例中我用了 **Lerp**。再球向目标位置移动时,每次都是移动两点之间距离的10%。 51 | 52 | **Demo2** 53 | [https://codepen.io/rachsmith/pen/yYZapV](https://codepen.io/rachsmith/pen/yYZapV) 54 | 55 | > Notice the ball movement is a lot smoother and an overall more pleasing effect. 56 | 57 | 注意⚠️球的移动平滑了很多,并且整体效果好很多。 58 | 59 | > Here's another example of using lerp. This time we've got a scrolling indicator that updates as you scroll down the "page". 60 | 61 | 这有另外一个示例也用了 **Lerp**。当你向下滚动页面的时候,你会看到滚动指示符的位置也在更新。 62 | 63 | **Demo3** 64 | [https://codepen.io/rachsmith/pen/rOPMvz](https://codepen.io/rachsmith/pen/rOPMvz) 65 | 66 | **Demo4** 67 | [https://codepen.io/rachsmith/pen/epxdxe](https://codepen.io/rachsmith/pen/epxdxe) 68 | 69 | >If we add lerp to this example we're lerping the indicator towards the scroll percentage instead of pointing it at the actual position - this smoothes out the movement of the indicator. I also employed this technique for a [parallax scrolling example](https://codepen.io/rachsmith/full/8ed66a170bd1a9c69e9a68b87599d136) for a [previous blog post](https://codepen.io/rachsmith/post/how-to-move-elements-on-scroll-in-a-way-that-doesn-t-suck-too-bad). 70 | 71 | 如果,你的示例中用了 **Lerp** 指示符在向前移动时会平滑很多,而不是瞬间移动到实际位置。上一片文章中的滚动视差示例中我也用了 **Lerp** 72 | 73 | > So, the lerp "trick" is a great tool to have up our web animation sleeves to combat linear or jagged movement. If you have used or do use lerp in your CodePens be sure to share your examples with us in the comments below! 74 | 75 | **Lerp** 能够很好让我们的web动画平滑的移动来避免瞬间移动。如果,你在CodePens的示例中也使用了 **Lerp**,请一定要在评论中分享。 -------------------------------------------------------------------------------- /Published/CSS Tip- Multicolor & Cutout Drop Shadows.md: -------------------------------------------------------------------------------- 1 | ## CSS Tip: Multicolor & Cutout Drop Shadows 2 | ## CSS 技巧:色彩斑斓的自定义阴影 3 | 4 | > 原文地址: 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | > Box shadows are boring. You heard me. They can only use one color at a time and are [slow to animate or transition](https://alligator.io/css/transition-box-shadows). You know what would be neat? Making a drop shadow that would use the colors of the element’s background. So if the top left corner of your element was red, the top left corner of the shadow would be red. If the bottom right corner was blue, the bottom left corner of the shadow would be blue. Wouldn’t that be neat? Too bad there’s no way to do it in CSS… Oh wait, **there is**. Let’s dive in. 10 | 11 | > 盒子阴影很无聊。你听我的。他们一次只能用一种颜色,并且只能通过[animate 或者 transition 实现动画](https://alligator.io/css/transition-box-shadows)。你知道什么是整齐划一么?让阴影的颜色和元素的背景色保持一致。也就是说,如果元素左上角是红色,阴影的左上角也必须是红色;如果右下角是蓝色,阴影的右下角也必须是蓝色。这就是整齐划一。糟糕的是,在 CSS 中无法实现。等等,**有方法可以实现**。让我们一起来看看。 12 | 13 | ### The Method 14 | 15 | ### 方法 16 | 17 | Really, all we have to do is create a pseudo-element directly behind the parent element and have it inherit relevant properties, such as ```background``` and ```border-radius```. Then we add a CSS ```blur()``` filter. This creates a second copy of the element’s background and blurs it behind the element. Easy as pie. By inheriting the background and related properties, we don’t have to specify them repeatedly. 18 | 19 | 事实上,我们只需创建一个伪元素直接放置父元素后面,并继承相关属性,比如:```background``` 和 ```border-radius```。然后,我们给伪元素添加一个滤镜 ```blur()```。这会在元素后面生成一个模糊的副本。很简单吧。因为继承了背景和相关属性,我们不需要重复设置。 20 | 21 | Even better, if you want to animate / smoosh / squash the shadow in some way, you have the full power of CSS transforms and opacity available to you on the pseudo-element! 22 | 23 | 还可以更好,如果你想用某些方式让阴影实现平滑的动画效果,CSS 中的 transforms 和 opacity 属性在伪元素上完全有效。 24 | 25 | What’s the catch? **The shadow won’t display in [browsers that don’t support the CSS blur filter](https://caniuse.com/#feat=css-filters)**. 26 | 27 | 有什么问题么?**[阴影在不支持的 blur 滤镜的浏览器上不显示](https://caniuse.com/#feat=css-filters)** 28 | 29 | ### The Code 30 | 31 | ### 代码 32 | 33 | ```css 34 | /* The element that will have the blurred shadow. */ 35 | .fancy-box { 36 | /* We need to set the position value to something other than `static` 37 | * so that position: absolute for the pseudo-element will be relative 38 | * to this element. */ 39 | position: relative; 40 | 41 | /* A nice Alligator.io-themed linear gradient. */ 42 | /* This technique works with any and every background type. */ 43 | background: linear-gradient(to bottom right, rgb(107,183,86), rgb(0,143,104)); 44 | 45 | /* Whatever else you want in here. */ 46 | } 47 | 48 | /* The shadow pseudo-element. */ 49 | .fancy-box::before { 50 | content: ' '; 51 | /* Position it behind the parent. */ 52 | z-index: -1; 53 | position: absolute; 54 | top: 0; 55 | right: 0; 56 | bottom: 0; 57 | left: 0; 58 | 59 | /* Inherit the background and border radius of the parent. */ 60 | background: inherit; 61 | border-radius: inherit; 62 | 63 | /* Blur it for maximum shadowy-ness. */ 64 | filter: blur(15px); 65 | 66 | /* Hide the shadow until the element is hovered over. */ 67 | opacity: 0; 68 | transition: opacity 300ms; 69 | } 70 | 71 | /* Show the shadow on hover. */ 72 | .fancy-box:hover::before { 73 | opacity: 1; 74 | } 75 | ``` 76 | 77 | ### The Result 78 | 79 | ### 演示结果 80 | 81 | Note how it even works with transparent images! You can finally make shaped shadows! 🎉 82 | 83 | 留意下透明图片的那个是如何工作的!最终你可以实现多边形的阴影!🎉 84 | 85 | [Here's a codepen you can play around with](https://codepen.io/tribex/pen/wmjRNe). 86 | 87 | [查看 codepen 上的演示](https://codepen.io/tribex/pen/wmjRNe). 88 | 89 | So how’s the performance? Well, as long as you don’t frequently change the background or adjust the blur radius, it’s about as fast as could be! Overall the performance characteristics of this technique are comparable to the method we showed you earlier for [performant box shadow transitions](https://alligator.io/css/transition-box-shadows). 90 | 91 | 那性能如何呢?好吧,只要你不频繁的改变背景或者调整模糊半径,性能是没有问题的!总体来说这种技术的性能跟早期我们展示的[box-shadow 过渡效果](https://alligator.io/css/transition-box-shadows)是相当的。 92 | 93 | -------------------------------------------------------------------------------- /Published/两端对齐几种实现方案.md: -------------------------------------------------------------------------------- 1 | ## 两端对齐几种实现方案 2 | 3 | --------- 4 | 一天,同事问我如果实现两段对齐的方式有几种呢? 5 | 我大概想了下说:有 5 种。 6 | 今天,抽空细想了下,发现不止 5 种呢!接下来一一为大家展示下。 7 | 8 | 具体效果可以看看这里 9 | [Demo](https://jsfiddle.net/xiaoT/1twmd5xL/) 10 | 11 | 部分公共的样式 12 | ```css 13 | .demo, 14 | h4 { 15 | width: 80%; 16 | margin: 0 auto 2em; 17 | } 18 | .demo { 19 | border: 1px solid red; 20 | padding: .5em; 21 | } 22 | h4 { 23 | margin-bottom: .5em; 24 | } 25 | .inner-item { 26 | border: 1px solid blue; 27 | } 28 | ``` 29 | 30 | #### 1.text-align: justify 31 | 32 | ```html 33 |
34 |
左边 div
35 |
右边 div
36 |
37 | ``` 38 | ```css 39 | /*text align justify */ 40 | .text-align-justify { 41 | text-align: justify; 42 | text-align-last: justify; 43 | } 44 | .text-align-justify .inner-item { 45 | display: inline-block; 46 | } 47 | ``` 48 | 49 | ### 2.float 50 | 51 | ```html 52 |
53 |
左边 div
54 |
右边 div
55 |
56 | ``` 57 | ```css 58 | /* float */ 59 | .float { 60 | overflow: hidden; 61 | } 62 | .fl { 63 | float: left; 64 | } 65 | .fr { 66 | float: right; 67 | } 68 | ``` 69 | 70 | ### 3.负margin + float 71 | 72 | ```html 73 |
74 |
中间 div
75 |
左边 div
76 |
右边 div
77 |
78 | ``` 79 | 80 | ```css 81 | /* negative-margin */ 82 | .negative-margin { 83 | height: 10vw; 84 | } 85 | .negative-margin .left, 86 | .negative-margin .right, 87 | .negative-margin .main { 88 | float: left; 89 | box-sizing: border-box; 90 | } 91 | .negative-margin .left, 92 | .negative-margin .right { 93 | background-color: #fff; 94 | width: 20%; 95 | } 96 | .negative-margin .main { 97 | width: 100%; 98 | padding: 0 20%; 99 | background-color: #ccc; 100 | } 101 | .negative-margin .left { 102 | margin-left: -100%; 103 | } 104 | .negative-margin .right { 105 | margin-left: -20%; 106 | } 107 | ``` 108 | 109 | ### 4.position 110 | 111 | ```html 112 |
113 |
左边 div
114 |
右边 div
115 |
116 | ``` 117 | 118 | ```css 119 | /*position*/ 120 | .pr.demo { 121 | height: 10vw; 122 | } 123 | .pr { 124 | position: relative; 125 | } 126 | .pa { 127 | position: absolute; 128 | } 129 | .pa.right { 130 | right: .5em; 131 | } 132 | ``` 133 | 134 | ### 5.table 135 | ```html 136 |
137 |
左边 div
138 |
中间
139 |
右边 div
140 |
141 | ``` 142 | 143 | ```css 144 | /* table */ 145 | .table { 146 | display: table; 147 | } 148 | .table .inner-item { 149 | display: table-cell; 150 | } 151 | ``` 152 | 153 | ### 6.flex 154 | 155 | ```html 156 |
157 |
左边 div
158 |
右边 div
159 |
160 | ``` 161 | 162 | ```css 163 | /* flex */ 164 | .flex { 165 | display: flex; 166 | justify-content: space-between; 167 | } 168 | ``` 169 | 170 | ### 7.column 171 | 172 | ```html 173 |
174 |
左边 div
175 |
右边 div
176 |
177 | ``` 178 | 179 | ```css 180 | /* column */ 181 | .column { 182 | column-count: 2; 183 | } 184 | ``` 185 | 186 | ### 8.grid 187 | 188 | ```html 189 |
190 |
左边 div
191 |
中间
192 |
右边 div
193 |
194 | ``` 195 | 196 | ```css 197 | /* grid */ 198 | .grid { 199 | display: grid; 200 | grid-template-columns: 20% calc(100% - 40% - 1em) 20%; 201 | grid-row-start: 1; 202 | grid-row-end: 3; 203 | } 204 | ``` 205 | 206 | ### 总结 207 | 208 | 除了 [grid](https://caniuse.com/#search=grid) 和 [column](https://caniuse.com/#search=column) 的兼容问题需要注意下,其它的几种方式基本都没什么使用障碍。 209 | -------------------------------------------------------------------------------- /Published/3 things you didn’t know about the forEach loop in JS.md: -------------------------------------------------------------------------------- 1 | ## 3 things you didn’t know about the forEach loop in JS 2 | ## 3 件你不知道的 JS 中有关 forEach 的事情 3 | 4 | > 原文地址: 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | ![](https://miro.medium.com/max/1400/1*WPfN96RRpQzRMaOedN-HyA.png) 10 | 11 | Do you think you know exactly how the `forEach` loop works in JS? 12 | 13 | 你认为自己真的了解 JS 中 `forEach` 如何工作的吗? 14 | 15 | Well, these were my thoughts until recently: “just a regular`for` loop where you can easily use `break` or `return` or `continue`“. 16 | 17 | 好吧,直到最近我还是一直认为:“它就像 `for` 一样,你可以在循环中方便的使用 `break` `return` `continue`”。 18 | 19 | Today, I’ll show you 3 things which you might have not known about the `forEach` loop. 20 | 21 | 今天, 我将会告诉你 3 件你可能不知道的有关 `forEach` 的事。 22 | 23 | # 1. ‘return’ doesn’t stop looping 24 | 25 | # 1. `return` 并不会停止循环 26 | 27 | Do you think the code below would print `1 2` and then stop? 28 | 29 | 你认为下面的代码打印 `1 2` 后会停止吗? 30 | 31 | ```js 32 | array = [1, 2, 3, 4]; 33 | array.forEach(function (element) { 34 | console.log(element); 35 | 36 | if (element === 2) 37 | return; 38 | 39 | }); 40 | // Output: 1 2 3 4 41 | ``` 42 | 43 | No, **it won’t**. If you come from a [Java](https://www.geeksforgeeks.org/for-each-loop-in-java/) background, you would probably ask yourself *how is that possible?* 44 | 45 | 不会,它不会停止。如果,你有 [Java](https://www.geeksforgeeks.org/for-each-loop-in-java/) 的背景,你可能会问自己*这怎么可能?* 46 | 47 | The reason is that we are passing a **callback function** in our `forEach`function, which behaves just like a normal function and is applied to each element no matter if we `return` from one i.e. when element is 2 in our case. 48 | 49 | 这是因为我们传递给 `forEach` 回调函数导致的,它就和正常的函数一样接收每一个传递的参数,而不关心是否有 `return`。就像我们示例中一样。 50 | 51 | From the [official MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach): 52 | 53 | > There is no way to **stop** or **break** a `forEach()` loop other than by throwing an exception. *If you need such behavior, the* `forEach()` *method is the wrong tool.* 54 | 55 | 来自[ MDN 官方文档](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach): 56 | 57 | > 没有办法中止或者跳出 `forEach` 循环,除非抛出一个异常。*如果你需要这样,使用 `forEach` 就是错误的。* 58 | 59 | Let’s rewrite the code from above: 60 | 61 | 让我们来重写上面的代码: 62 | 63 | ```js 64 | const array = [1, 2, 3, 4]; 65 | const callback = function(element) { 66 | console.log(element); 67 | 68 | if (element === 2) 69 | return; // would this make a difference? no. 70 | } 71 | for (let i = 0; i < array.length; i++) { 72 | callback(array[i]); 73 | } 74 | // Output: 1 2 3 4 75 | ``` 76 | 77 | The `return`statement won’t make any difference, as **we apply the function to each element at each iteration,** hence it doesn’t care if you exited once i.e. when element is 2. 78 | 79 | 这里的 `return` 语句没什么不同,因为**每次迭代我们都会调用方法**,因此它不关心是否有退出。比如:传递 2 时。 80 | 81 | # 2. You cannot ‘break’ 82 | 83 | # 2. 不能使用 ‘break’ 84 | 85 | Do you think a`forEach` loop would `break` in the example below? 86 | 87 | 你认为下面的代码中 `forEach` 遇到 `break` 会跳出循环吗? 88 | 89 | ```js 90 | const array = [1, 2, 3, 4]; 91 | array.forEach(function(element) { 92 | console.log(element); 93 | 94 | if (element === 2) 95 | break; 96 | }); 97 | // Output: Uncaught SyntaxError: Illegal break statement 98 | ``` 99 | 100 | No, **it won’t even run** because the `break` instruction is not technically in a loop. 101 | 102 | 不会,**它甚至都不会执行**,因为 `break` 不能在循环中使用。 103 | 104 | Solution? 105 | 106 | 如何解决? 107 | 108 | Just use a normal `for` loop. Nobody would laugh at you. 109 | 110 | 就用正常的 `for` 循环即可。没人会取笑你。 111 | 112 | ```js 113 | const array = [1, 2, 3, 4];for (let i = 0; i < array.length; i++) { 114 | console.log(array[i]); 115 | 116 | if (array[i] === 2) 117 | break; 118 | }// Output: 1 2 119 | ``` 120 | 121 | # 3. You cannot ‘continue’ 122 | 123 | # 3. 不能使用 continue 124 | 125 | Do you expect the code below to skip printing `2` to the console and only show `1 3 4` ? 126 | 127 | 你是否期望以下的代码不打印 `2`,只是打印 `1 3 4` ? 128 | 129 | ```js 130 | const array = [1, 2, 3, 4]; 131 | array.forEach(function (element) { 132 | if (element === 2) 133 | continue; 134 | 135 | console.log(element); 136 | }); 137 | // Output: Uncaught SyntaxError: Illegal continue statement: no surrounding iteration statement 138 | ``` 139 | 140 | No, **it won’t even run** because the `continue` instruction is not in a loop, similar to the `break` instruction. 141 | 142 | 不会,**它不会自行**,因为,就和 `break` 一样 `continue` 也不能在循环中使用。 143 | 144 | Solution? 145 | 146 | 如何解决? 147 | 148 | Just use a normal `for` loop again. 149 | 150 | 同样,还是可以使用 `for` 循环。 151 | 152 | ```js 153 | for (let i = 0; i < array.length; i++) { 154 | if (array[i] === 2) 155 | continue; 156 | 157 | console.log(array[i]); 158 | } 159 | // Output: 1 3 4 160 | ``` 161 | 162 | That was it! Hope you learned something new today. 163 | 164 | 就这些!希望你今天学到了新的东西。 -------------------------------------------------------------------------------- /Published/javascript/Some-cool-and-awesome-JavaScript-tricks.md: -------------------------------------------------------------------------------- 1 | ## Some cool and awesome JavaScript tricks 2 | ## 一些有用的 JavaScript 技巧 3 | 4 | > 原文地址: 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | In this article, we will cover some of the cool and awesome JavaScript tricks which you may find useful at some point while coding in JavaScript. 10 | 11 | 这篇文章中,我将会介绍一些非常有用的 JavaScript 小技巧,希望对你以后的编码有帮助。 12 | 13 | ![](https://miro.medium.com/max/1400/1*H-25KB7EbSHjv70HXrdl6w.png) 14 | 15 | # Trick 1 16 | 17 | # 技巧1 18 | 19 | ## Identifying if a variable is of primitive or non-primitive data type 20 | 21 | ## 验证一个变量是原始类型,还是非原始类型 22 | 23 | There are primitive and non-primitive data types in Javascript. The primitive types include boolean, string, number, BigInt, null, Symbol and undefined. The non-primitive types include the Objects. 24 | 25 | JavaScript 中的数据类型包括:原始类型和非原始类型。原始类型又包括:boolean、string、number、BigInt、null、Symbol 和 undefined。非原始类型包括:Object。 26 | 27 | Often we might need to identify what type of value is stored in a variable — Primitive or Non-Primitive? 28 | 29 | 通常,我们需要验证变量中存储的数据类型是什么 — 原始类型还是非原始类型? 30 | 31 | Consider a variable var 32 | 33 | 看一下这个变量 34 | 35 | ```js 36 | var val; // contains either primitive or non-primitive value 37 | ``` 38 | 39 | This can be achieved with the help of a simple code snippet. 40 | 41 | 验证数据类型可以通过以下的代码实现。 42 | 43 | ```js 44 | function isPrimitive(val) { 45 | return Object(val) !== val; 46 | } 47 | ``` 48 | 49 | We are using the Object constructor to create a wrapper object for a value. 50 | 51 | 我们利用构造函数 Object 来包装变量生成一个新的对象。 52 | 53 | If the value is a primitive data type, the Object constructor creates a new wrapper object for the value. 54 | 55 | 如果,这个值是原始类型,构造函数 Object 就会创建一个新的对象。 56 | 57 | If the value is a non-primitive data type (an object), the Object constructor will give the same object. 58 | 59 | 如果,这个值是非原始类型(一个对象),构造函数 Object 就会返回同一个对象。 60 | 61 | Hence, a strict check (!== or ===) can help us identifying if a variable is of primitive or non-primitive type. 62 | 63 | 因此,一个严格的比较(!== 或者 ===)可以帮助我们来验证一个变量是原始类型还是非原始类型。 64 | 65 | # Trick 2 66 | 67 | # 技巧2 68 | 69 | ## Creating a pure object in Javascript 70 | 71 | ## 创建纯对象 72 | 73 | Before creating a pure object, let’s understand *“What is a pure object?”* 74 | 75 | 在创建纯对象之前,我们需要先理解*“什么是纯对象?”* 76 | 77 | A pure object in JavaScript means that it should not have any functions in its prototype. 78 | 79 | JavaScript 中一个纯对象意味着,它的原型链上不能包含任何的方法。 80 | 81 | An object is created with the following syntax. 82 | 83 | 创建对象的语法如下: 84 | 85 | ``` 86 | var obj = {}; 87 | ``` 88 | 89 | Upon checking the obj.__proto__ we get many functions available inside it. 90 | 91 | 通过检查 `obj.__proto__` 我们发现它有很多的方法。 92 | 93 | ![Image for post](https://miro.medium.com/max/3348/1*FS4Y23ELSNPaEibNkdOw3A.png) 94 | 95 | What if we want to create an object that does not have any of the prototype functions inside it? 96 | 97 | 如果,我们想创建一个原型链上没有任何方法的对象应该如何做呢? 98 | 99 | We can achieve this by using the Object constructor’s create method. 100 | 101 | 我们可以通过构造函数 Object 中的 create 方法来实现。 102 | 103 | ``` 104 | var obj = Object.create(null); 105 | ``` 106 | 107 | Upon checking the object’s prototype, we get the following result 108 | 109 | 检查它的原型链,我们会发现以下的结果 110 | 111 | ![Image for post](https://miro.medium.com/max/60/1*YSjxMik8NGvg2lNngLTCjg.png?q=20) 112 | 113 | ![Image for post](https://miro.medium.com/max/1148/1*YSjxMik8NGvg2lNngLTCjg.png) 114 | 115 | > An object with no prototype. 116 | > 117 | > 一个没有任何原型的对象 118 | 119 | Hence, a pure object is created. 120 | 121 | 因此,我们创建了一个纯对象。 122 | 123 | # Trick 3 124 | 125 | # 技巧3 126 | 127 | ## Removing duplicates from an array 128 | 129 | ## 移除数组中重复的数据 130 | 131 | Consider the following array 132 | 133 | 看一下这个数组 134 | 135 | ``` 136 | var arr = [1, 2, 3, 3, 4, 5, 6, 6, 7, 7, 7, 7]; 137 | ``` 138 | 139 | We can see many duplicate elements in the array. To remove the duplicate elements from the array, we can use a **Set**. 140 | 141 | 我们看到数组中存在多个重复的数据。为了从数组中移除这些重复的数据,我们可以使用 **Set**。 142 | 143 | A **Set** object lets us store unique values only. A set cannot have a duplicate value in it. Read more about it in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set). 144 | 145 | **Set** 对象只允许存储具有唯一性的值。Set 对象中不会有重复的值存在。[MDN Web 文档中](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set)可以了解更多的相关内容。 146 | 147 | To remove duplicates from the array, we write the code 148 | 149 | 用以下代码,我们就可以移除数组中重复的数据 150 | 151 | ``` 152 | const newArr = [...new Set(arr)]; 153 | ``` 154 | 155 | Here we created a new Set containing only the unique values of an array, then spread it inside a new array. 156 | 157 | 首先,我们用数组作为参数创建了一个 Set 对象,然后,用 Spread 语法生成新的数组。 158 | 159 | > The … is the Spread operator. Read more about it in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) 160 | > 161 | > ... 是 JavaScript 中展开操作符。在[MDN Web 文档](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax)中可以了解更多。 162 | 163 | As a result, we get an array with only unique values. 164 | 165 | 最终,我们得到了一个没有重复数据的数组。 -------------------------------------------------------------------------------- /Published/Notched Boxes.md: -------------------------------------------------------------------------------- 1 | ## Notched Boxes 2 | ## 切角盒子 3 | 4 | > 原文地址: 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | Say you're trying to pull off a design effect where the corner of an element are cut off. Maybe you're [a Battlestar Galactica fan](https://twitter.com/mikeBithell/status/942679894173147138)? Or maybe you just like the unusual effect of it, since it avoids looking like a typical rectangle. 10 | 11 | 假设你正尝试实现一个带切角的效果。或许你是 [Battlestar Galactica](https://twitter.com/mikeBithell/status/942679894173147138) 迷?或许你只是喜欢不寻常效果,让它看起来不一样。 12 | 13 | ![](https://res.cloudinary.com/css-tricks/image/upload/c_scale,w_910,f_auto,q_auto/v1520269162/notched_l1myqr.png) 14 | 15 | I suspect there are many ways to do it. Certainly, you could use [multiple backgrounds](https://css-tricks.com/css-basics-using-multiple-backgrounds/) to place images in the corners. You could just as well use a flexible SVG shape placed in the background. I bet there is also an exotic way to use gradients to pull it off. 16 | 17 | 我猜测有多种方式实现这种效果。当然,你可以使用 [multiple backgrounds](https://css-tricks.com/css-basics-using-multiple-backgrounds/) 在切角的地方放置图片。你也可以使用弹性的 SVG shape 做为背景。我敢打赌用渐变也可以实现。 18 | 19 | But, I like the idea of simply taking some scissors and clipping off the dang corners. We essentially can do just that thanks to [clip-path](https://css-tricks.com/almanac/properties/c/clip/). We can use the ```polygon()``` function, provide it a list of ```X``` and ```Y``` coordinates and clip away what is outside of them. 20 | 21 | 但是,我更喜欢用剪刀剪裁切角的简单想法。用 [clip-path](https://css-tricks.com/almanac/properties/c/clip/) 就可以实现。我们可以用 ```polygon()``` ,提供一系列的 ```X```、 ```Y``` 坐标,然后裁掉它们以外的部分。 22 | 23 | Check out what happens if we list three points: middle top, bottom right, bottom left. 24 | 25 | 如果我们列出三个点:中上,右下,左下。看看会发生什么。 26 | 27 | ```css 28 | .module { 29 | clip-path: 30 | polygon( 31 | 50% 0, 32 | 100% 100%, 33 | 0 100% 34 | ); 35 | } 36 | ``` 37 | 38 | ![](https://res.cloudinary.com/css-tricks/image/upload/c_scale,w_1000,f_auto,q_auto/v1520269284/triangle_ydvhy4.png) 39 | 40 | Instead of just three points, let's list all eight points needed for our notched corners. We could use pixels, but that would be dangerous. We probably don't really know the pixel width or height of the element. Even if we did, it could change. So, here it is using percentages: 41 | 42 | 让我们列出所有的8个点代替这3个点。我们可以使用像素单位,但是会有问题。我们很可能不知道 DOM 真实的 width、height。一旦我们这么做,必然会有改变。所以,我们用百分比: 43 | 44 | ```css 45 | .module { 46 | clip-path: 47 | polygon( 48 | 0% 5%, /* top left */ 49 | 5% 0%, /* top left */ 50 | 95% 0%, /* top right */ 51 | 100% 5%, /* top right */ 52 | 100% 95%, /* bottom right */ 53 | 95% 100%, /* bottom right */ 54 | 5% 100%, /* bottom left */ 55 | 0 95% /* bottom left */ 56 | ); 57 | } 58 | ``` 59 | 60 | ![](https://res.cloudinary.com/css-tricks/image/upload/c_scale,w_892,f_auto,q_auto/v1520269676/all-percentage-notches_xkmthu.png) 61 | 62 | That's OK, but notice how the notches aren't at perfect 45 degree angles. That's because the element itself isn't a square. That gets worse the less square the element is. 63 | 64 | 好了,但是,为什么切角不是完美的45度角呢。这是因为 DOM 不是正方形。如果 DOM 越接近正方形误差越小。 65 | 66 | We can use the ```calc()``` function to fix that. We'll use percentages when we have to, but just subtract from a percentage to get the position and angle we need. 67 | 68 | 我们可以用 ```calc()``` 解决这个问题。我们使用百分比,只需减去我们需要的角度就可以得到正确的位置。 69 | 70 | ```css 71 | .module { 72 | clip-path: 73 | polygon( 74 | 0% 20px, /* top left */ 75 | 20px 0%, /* top left */ 76 | calc(100% - 20px) 0%, /* top right */ 77 | 100% 20px, /* top right */ 78 | 100% calc(100% - 20px), /* bottom right */ 79 | calc(100% - 20px) 100%, /* bottom right */ 80 | 20px 100%, /* bottom left */ 81 | 0 calc(100% - 20px) /* bottom left */ 82 | ); 83 | } 84 | ``` 85 | 86 | And you know what? That number is repeated so many times that we may as well make it a [variable](https://css-tricks.com/making-custom-properties-css-variables-dynamic/). If we ever need to update the number later, then all it takes is changing it once instead of all those individual times. 87 | 88 | 你看到了吧?有个数字重复了多次,我可以把它变成一个[变量](https://css-tricks.com/making-custom-properties-css-variables-dynamic/)。如果,以后我们需要改变它,我们只需改变一个地方,其他就会自动更新。 89 | 90 | ```css 91 | .module { 92 | --notchSize: 20px; 93 | 94 | clip-path: 95 | polygon( 96 | 0% var(--notchSize), 97 | var(--notchSize) 0%, 98 | calc(100% - var(--notchSize)) 0%, 99 | 100% var(--notchSize), 100 | 100% calc(100% - var(--notchSize)), 101 | calc(100% - var(--notchSize)) 100%, 102 | var(--notchSize) 100%, 103 | 0% calc(100% - var(--notchSize)) 104 | ); 105 | } 106 | ``` 107 | 108 | [Ship it](https://codepen.io/chriscoyier/pen/yvQQxM). 109 | 110 | 111 | This may go without saying, but make sure you have enough padding to handle the clipping. If you wanna get really fancy, you might use CSS variables in your padding value as well, so the more you notch, the more padding there is. 112 | 113 | 确保有足够大的 padding 保证用来剪裁,这或许不用说。如果,你想变得更加灵活,你应该用 CSS 变量存储 padding 的值,切角越大,padding 就越大。 114 | -------------------------------------------------------------------------------- /Published/typescript/Some-Lesser-Known-TypeScript-Features.md: -------------------------------------------------------------------------------- 1 | # Some Lesser Known TypeScript Features 2 | 3 | ## 那些鲜为人知的 TypeScript 功能 4 | 5 | > 原文地址: 6 | **本文版权归原作者所有,翻译仅用于学习。** 7 | 8 | --------- 9 | 10 | In the past few years, TypeScript has become a popular way to write JavaScript apps. The language is immense and can do a lot of things. 11 | 12 | 过去的几年中,TypeScript 已经成为编写 JavaScript 应用的流行方式。这种语言非常强大,能做很多事情。 13 | 14 | ![](https://miro.medium.com/max/1400/1*ui0RIOYORyfWoOlbSDSFGA.jpeg) 15 | 16 | Here’s a short list of some rarer TypeScript features you may not be aware of to help with your development: 17 | 18 | 在这我列举了一些 TypeScript 罕见的功能,在你的开发过程中它们可以帮到你: 19 | 20 | 1. You can write numbers with underscores. For example, `1000000000` can be written as `1_000_000_000`. It will be compiled to the regular number in Javascript, but using this syntax makes things easier to read. The underscores can be placed anywhere in the number although writing `25` is more readable than `2_5`. Another good use case for this syntax is monetary amounts. `2545` may represent $25.45 in your app. This can be written as `25_45` instead. 21 | (As mentioned by a commenter on Reddit this is also a stage 2 Javascript proposal: https://github.com/tc39/proposal-numeric-separator) 22 | 23 | 你可以是用下划线的方式定义 numbers。比如:`1000000000` 可以写成 `1_000_000_000`。在 JavaScript 中它将会被编译成正常的 number,但是,这种语法让内容更易于阅读。下划线可以放在数字的任何位置,尽管,`25` 比 `2_5` 更易读。另外一个使用场景是表示货币金额。在你的应用中 `2545` 可能代表着 $25.45。因此,可以用 `25_45` 来代替。 24 | 25 | (在 Reddit 有人提到,这种语法已经是 stage 2 Javascript 提案 : https://github.com/tc39/proposal-numeric-separator) 26 | 27 | **译者注:目前已经是 stage 3(2020-05-17)** 28 | 29 | 2. If you know a variable is defined you can add a `!` after it to access it without first checking if the value is `undefined`. For example, you may be injecting props into a React component using a decorator (e.g. `@inject(router)` or `@inject(store)`). You can now write `this.props.store!.someValue` even if the definition of store is `store?: Store`. Be careful not to overuse this feature, but there are times where it comes in handy. You can read [here](https://github.com/mobxjs/mobx-react/issues/256) for further discussion of this problem. (You could always use an `if` statement too, but that’s more verbose for cases you know the if statement is truthy). 30 | 31 | 如果,你知道一个变量已经定义,你可以在变量后面添加 `!` 来访问它,而不用检查它是否为 `undefined`。例如,你通过 decorator 向 React 组件注入 props(比如:`@inject(router)` 或者 `@inject(store)`)。现在,你可以直接这么写 `this.props.store!.someValue`,即使,定义了 `store?: Store`。虽然,在某些情况下它非常方便,但是,要小心、不要过度使用这个功能。你可以在[这](https://github.com/mobxjs/mobx-react/issues/256)了解一下有关这个功能的讨论。(你还是可以使用 `if` 语句,但是,对那些明显是真值的情况,这显得有点多余) 32 | 33 | 3. You can set a variable to have type `never`. This means it can’t be set to anything. How is this useful? One place it can be useful is to check you’ve handled every possibility of a switch statement. For example: 34 | 35 | 你可以给变量设置 `never` 类型。这代表它不能被设置成任何值。这有什么用呢?这在 switch 语句中非常有用,可以用来检查是否覆盖了所有的情况。例如: 36 | 37 | ```ts 38 | export function unreachable(x : never) { 39 | throw new Error(`This should be unreachable! but got ${x}`) 40 | }const someFunction = (temperature: 'hot' | 'cold' | 'warm') => { 41 | switch (temperature) { 42 | 'hot': console.log("it's hot outside!"); break; 43 | 'cold': console.log("it's cold outside!"); break; 44 | default: unreachable(temperature); 45 | } 46 | } 47 | ``` 48 | 49 | The above code will throw a compile-time error, because it’s possible for `unreachable()` to be called. If you add a switch case for `warm` with a break after it, the compile error will go away as the default block can no longer be reached. 50 | 51 | 因为,`unreachable()` 很有可能会被调用,上面的代码将会抛出一个编译错误。如果,你在代码块中添加一段有关 `warm` 的代码,这个编译错误就会消失,default 也就不会被执行了。 52 | 53 | Another potential use case for `never` is a function containing an infinite loop or a function that always throws an exception: 54 | 55 | `never` 的另外一种使用情况是:一个无限循环的函数或者总是抛出异常的函数: 56 | 57 | ```ts 58 | function loop(fn: Function): never { 59 | while(true) fn(); 60 | } 61 | ``` 62 | 63 | Thanks to [James Meyers](https://medium.com/u/a2ed4fb0055d?source=post_page-----d067e29797d0----------------------) in the comments for these use cases. 64 | 65 | 多谢 [James Meyers](https://medium.com/u/a2ed4fb0055d?source=post_page-----d067e29797d0----------------------) 在评论中提出这些使用场景。 66 | 67 | 4. Another lesser used type you can use is `unknown`. This just means we have no idea what the item we have is. This may happen if we’re calling a third party API for example. If we try do `x.substr(0, 2)` it will throw a compile error. We can use an `unknown` variable by first doing a type check. For example, writing `if (typeof x === “string”) x.substr(0, 2)` would no longer throw an error. 68 | 69 | 另外一个少用的类型是 `unknown`。这代表着我们对当前的变量一无所知。如果,我们调用了第三方的 API 就会出现这种情况。如果,我们执行 `x.substr(0, 2)` 这条语句,它将会抛出一个编译错误。我们可以使用 `unknown` 定义变量,然后做一次类型检测。例如:`if (typeof x === “string”) x.substr(0, 2)` 这样不会抛出错误了。 70 | 71 | `unknown` is both very similar to `any` and the complete opposite. They’re similar in so far as with both types we don’t know what the type is. They’re the complete opposite in that `any` will never throw a type error, but `unknown` will always throw an error until we identify what it is. 72 | 73 | `unknown` 和 `any` 两者非常相似,又完全相反。两者在类型非常相似,我们不知道两种类型的变量是什么。但是,两者又完全相反,`any` 永远不会抛出类型错误,但是,`unknown` 总会抛出错误,直到我们明确变量是什么类型。 74 | 75 | ```ts 76 | const x: any; 77 | x.substr(0, 2); // doesn't throw a compilation error 78 | const y: unknown; 79 | y.substr(0, 2); // throws an error as we don't know what y is 80 | if (typeof y === 'string') y.substr(0, 2); // doesn't throw an error 81 | ``` 82 | 83 | 84 | 85 | Looking for some more tricks, check out this post: 86 | 87 | 更多的使用技巧,可以看以下的文章: 88 | 89 | 90 | 91 | 92 | 93 | Know any other useful TypeScript tricks that should be included? Feel free to mention them in the comments! 94 | 95 | 如果,你知道更多有关 TypeScript 的使用技巧?可以在评论中告诉我! 96 | 97 | To see more articles like this in the future, be sure to give me a follow :) 98 | 99 | 想看更多的文章,可以订阅我的博客。 100 | 101 | You can get in touch with me at [elie.tech](https://elie.tech/). 102 | 103 | 你还可以通过 [elie.tech](https://elie.tech/) 联系我。 -------------------------------------------------------------------------------- /Published/Flexbox- Don't Forget about flex-shrink.md: -------------------------------------------------------------------------------- 1 | ## Flexbox: Don't Forget about flex-shrink 2 | ## Flexbox: 不要忽略 flex-shrink 3 | 4 | > 原文地址: [https://codepen.io/noahblon/post/practical-guide-to-flexbox-dont-forget-about-flex-shrink](https://codepen.io/noahblon/post/practical-guide-to-flexbox-dont-forget-about-flex-shrink) 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | > As I learned flexbox, I was captivated by the way items grow to fit their container. But, recently I've realized its just as important to think about the way items shrink. Let me show you what I mean. 10 | 11 | 我在学习 Flexbox 时,我一直没有明白子元素是如何在父级容器中填充的。但是,最近终于明白了子元素是如何在父及容器中伸缩填充的了。让我给你们一一解释。 12 | 13 | >A typical usecase for flexbox is a set of items that we want to be spaced out evenly in a row. Something like this: 14 | 15 | 一个典型的例子:有一个 flexbox 容器,我们让它的子元素均匀的排列在一行。就像这样: 16 | 17 | **Demo1:** 18 | [https://codepen.io/xiao-T/pen/NvoNqK](https://codepen.io/xiao-T/pen/NvoNqK) 19 | > 译者注:原作者 Demo 有问题,我做了调整。具体原因原作者在下面也有提到。 20 | 21 | > We create a flex context in a container with ```display: flex```. Flex items are spaced out evenly along the main axis with ```justify-content: space-between```. Everything looks great... until we start adding more items. 22 | 23 | 我创建了一个 flexbox 容器。通过属性 ``` justify-content: space-between ``` 设置它的子元素沿着主轴方向均匀分布。一切看起来那么完美,直到我又添加了更多子元素后,就出现问题了。 24 | 25 | ** Demo2: ** 26 | [https://codepen.io/xiao-T/pen/wqNGev](https://codepen.io/xiao-T/pen/wqNGev) 27 | > 译者注:原作者 Demo 有问题,我做了调整。具体原因原作者在下面也有提到。 28 | 29 | > Ugh, the images are all squished up! This happens because by default, the value for ```flex-shrink``` on items in a flex context is 1. That means that whenever the size of a set of flex items adds up to be larger than our flex context element, the items shrink down to fit. 30 | 31 | 呃,```flex-item``` 都被挤压变形了!这是因为 ```flex-shrink``` 默认值是```1```。也就是说:如果一组 ```flex-item``` 超出了父级容器的大小,那么这些 ```flex-item``` 将被压缩,来适应父及容器的大小。 32 | 33 | >(NOTE: Since this post, Chrome has changed the way it handles images in flex context. They now maintain their minimum instrinsic size. For this reason, the images are not shrunk to fit anymore. However, the ideas behind this post is still valid.) 34 | 35 | (备注:在我写这边文章的时候,Chrome已经修改了图片在 ```flex``` 容器中的处理方式。图片并没有被压缩。不管怎么说,这并不影响以上的观点。) 36 | 37 | > 译者注:对于这点大家可以对比译者的 Demo 和原作者的 Demo。 38 | 39 | > The fix is simple: ```set flex-shrink: 0``` on the items that need to remain a fixed size. Setting overflow: auto on the container clears up the issue of the images now overflowing their container. 40 | 41 | 修复它也非常简单:只要在 ```flex-item``` 设置 ```flex-shrink: 0```,这样设置后 ```flex-item``` 并不会被压缩,而是保持原有的大小。然后,我们只需在父容器上设置 ```overflow:hidden``` 来修复那些溢出隐藏的 ```flex-item```。 42 | 43 | **Demo3** 44 | [https://codepen.io/noahblon/pen/ZGOWdj](https://codepen.io/noahblon/pen/ZGOWdj) 45 | 46 | > A slightly more complex example is this typical native mobile application style: 47 | 48 | 移动应用的布局是一个典型的略显复杂的例子: 49 | 50 | **Demo4** 51 | [https://codepen.io/noahblon/pen/BNjjvj](https://codepen.io/noahblon/pen/BNjjvj) 52 | 53 | > A fixed size header and a footer are clamped to the top and bottom of the viewport and a flexible content area fills up the remaining space. The main area should scroll when the content overflows and the header and footer should remain a fixed size. 54 | 55 | 一个固定大小的 ```header``` 和 ```footer``` 分别占据着可视窗口的顶部和底部,还有一个可伸缩的容器 ```main``` 占据了剩余的空间。```main``` 区域的内容如果过多,它是可以滚动的,但是这并不影响 ```header``` 和 ```footer``` 的大小。 56 | 57 | > To achieve this pattern we set .app to be the full size of the viewport, give it a flex context and set the ```flex-direction``` to apply vertically. Our header and footer are a fixed height, and the main content area is set to grow or shrink to fit the remaining space. Unlike ```flex-shrink```, the default value for ```flex-grow``` is 0, meaning flex items won't grow to fill space unless you tell them to. 58 | 59 | 为了实现这种布局,我新建一个 ```.app``` 元素并设置它的大小和可视窗口一样,给它设置了 ```flex``` 上下文,通过 ```flex-direction``` 控制子元素垂直排列。```header``` 和 ```footer``` 固定高度,```main``` 通过设置 ```grow``` 和 ```shrink``` 让它占据剩余的空间。```flex-grow``` 和 ```flex-shrink``` 不一样,它的默认值是```0```,也就是说,```flex-item``` 不会自动放大占据所有的空间,除非你设置 ```flex-grow``` 一个值。 60 | 61 | > But, we have a problem once we start putting in content. The elements we want to remain a fixed size start to shrink when the content in ```.main``` overflows. 62 | 63 | 但是,随着 ```.main``` 内容的增多,我发现一个问题:```header``` 和 ```footer``` 被压缩了。 64 | 65 | **Demo5** 66 | [https://codepen.io/noahblon/pen/NqrYra](https://codepen.io/noahblon/pen/NqrYra) 67 | 68 | > This happens for two reasons. First, as we already know, all flex items have a ```flex-shrink``` value of 1 by default. They will shrink if the content overflows the container setting the flex context. Secondly, the full size of the .main container is used in the flex calculation, not just the visible portion. This is because by default, the ```flex-basis``` value of a flex item is auto. The ```flex-basis``` is the size basis that is used when calculating how items flex and a value of auto means the full size is used. To fix this, we just stop the header and footer from shrinking with ```flex-shrink: 0```. 69 | 70 | 之所以会这样,有两个原因。第一,正如我们所知,所有的 ```flex-item``` 都有一个默认值 ```flex-shrink: 1```。如果内容在一个 ```flex``` 容器中溢出了,这些 ```flex-item``` 将会被压缩。第二,```.main``` 的弹性计算,并不仅仅是可见区域。这是因为 ```flex-item``` 的属性 ```flex-basis``` 的默认值是 ```auto```。通过设置 ```flex-basis``` 可以控制 ```flex-item``` 的填充模式,如果 ```flex-basis``` 的值是 ```auto``` 元素会占据所有的空间。如果想避免这种行为,我们可以只简单设置 ```header``` 和 ```footer``` 的属性 ```flex-shrink: 0``` 来禁止它们被压缩。 71 | 72 | **Demo6** 73 | [https://codepen.io/noahblon/pen/WvxzMJ](https://codepen.io/noahblon/pen/WvxzMJ) 74 | 75 | > You're going to run into problems like this often when working with flexbox. When I'm approaching a layout, I like to first think about what items need to remain a fixed size, and what items will flex. I also think about whether I need to handle overflow. With those two ideas in mind, flexbox layout becomes a matter of turning off shrinking on items that need to be a fixed size. Items that are flexible are set to grow and shrink, and overflow is handled if necesarry. 76 | 77 | 当你使用 ```flexbox``` 时会经常遇到类似的问题。当我开始写一个新的布局结构时,我首先会想一下,那些子元素需要固定大小,那些需要弹性计算。也会考虑是否需要处理溢出的内容。经过这两点的考虑,```flexbox``` 布局变成了一个子元素是否需要伸缩的问题。子元素通过设置 ```flex-grow``` 和 ```flex-shrink``` 来控制是否伸缩,在必要的情况下处理一下溢出的问题。 78 | 79 | > For more practical tips about flexbox, you can check out [my blog](https://codepen.io/noahblon/posts/popular/) or [subscribe to my feed](https://codepen.io/noahblon/public/feed/). You can also [follow me on Codepen](https://codepen.io/noahblon/). 80 | 81 | 更多有关 ```flexbox``` 的资讯,你可以[关注](https://codepen.io/noahblon/posts/popular/)或者[订阅](https://codepen.io/noahblon/public/feed/)我的博客,或者在 [Codepen](https://codepen.io/noahblon/) 上关注我。 -------------------------------------------------------------------------------- /Published/CSS Grid Layout- Fluid Columns and Better Gutters.md: -------------------------------------------------------------------------------- 1 | ## CSS Grid Layout: Fluid Columns and Better Gutters 2 | ## CSS Grid 布局:Fluid Columns and Better Gutters 3 | 4 | > 原文地址: 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | In this tutorial we’re going to take the grid from our previous tutorial and use it as a playground to look further into Grid. We’ll improve the way we define our gutters, explore flexible layouts, the *fr* unit, and introduce the ```repeat()``` function. 10 | 11 | 12 | 在这篇教程中我们将继续探讨上篇文章提到的 Grid,并用一个示例进一步了解 Grid。我们会改善定义间隙的方式,探讨弹性布局,*fr* 单位 和介绍 ```repeat()``` 方法。 13 | 14 | ### Flexible Units 15 | 16 | ### 弹性单位 17 | 18 | The whole point of Grid is to enable us to properly control layout on the web, so let’s make our static grid fluid before we go any further. If you recall, we were defining our grid with static pixel measurements: 19 | 20 | Grid 的重点是让我们正确的控制 web 布局,在进一步了解弹性布局之前,先让我们看看我们的固定布局。回想一下,我们曾经用固定像素定义的 Grid 布局: 21 | 22 | ```css 23 | grid-template-columns: 150px 150px 150px; 24 | grid-template-rows: auto auto auto; 25 | grid-gap: 20px; 26 | ``` 27 | 28 | It’s quite possible to use other units here too, such as ems, or rems for example. Or even [more unusual units like vh and vmin](https://webdesign.tutsplus.com/articles/7-css-units-you-might-not-know-about--cms-22573). 29 | 30 | 这里用其它单位也是可以的,比如:em、rem。还有[更多不常用的单位,比如:vh 和 vmin](https://webdesign.tutsplus.com/articles/7-css-units-you-might-not-know-about--cms-22573)。 31 | 32 | In this case we’re going to change our pixel units for percentages. 33 | 34 | 这个示例中我们会用百分比替换固定像素单位。 35 | 36 | ```css 37 | grid-template-columns: 33.33% 33.33% 33.33%; 38 | ``` 39 | 40 | Hmm, that’s a bit messy, but it sort of does the job. You’ll notice that the column widths now add up to 100%; our gutters will be subtracted from them automatically. ```grid-gap``` will accept fixed or flexible units, which means we can perfectly combine fluid columns and fixed gutters without any complex calculations on our part. 41 | 42 | 嗯,有点乱,但是这可以正常工作。现在,你会注意到每一行的列宽加起来正好是100%;~~间隙将会被自动的扣减~~(**译者住:根据 [DEMO](http://output.jsbin.com/mumoxaf) 发现计算每一列的宽度时,并不会扣减留白的大小,也就说:留白 + 每一行总列宽会大于100%**)。```grid-gap``` 可以接受固定和非固定单位,也就是说:不需经过复杂的计算我们可以很好的融合不固定列宽和固定留白。 43 | 44 | #### Repeat 45 | 46 | Let’s write this is a neater way, using the ```repeat()``` function: 47 | 48 | 用 ```repeat()``` 方法,我们可以写出更整洁的代码: 49 | 50 | ```css 51 | grid-template-columns: repeat(3, 33.33%); 52 | ``` 53 | 54 | This states “*repeat 33.33% three times*” giving us three columns. And we don’t even *need* the ```grid-template-rows``` declaration because the ```auto``` value is assigned as default anyway. 55 | 56 | 这句话代表:“*重复三次 33.33%*” 赋值给 ```grid-template-columns```。我们甚至*不需要*声明 ```grid-template-rows```,因为它的默认值就是 ```auto```。 57 | 58 | **Note**: when columns are defined using % values, they’ll use exactly those values and add any ```grid-gap``` on top. You’ll notice the grid above has been pushed to the right because it’s now 99.99% wide *plus* the grid-gaps. 59 | 60 | **注意**:当列宽的单位用 % 时,每一列都会根据父级精确的计算,然后总宽会在这个基础上加上 ```grid-gap```。你应该会注意到上面的 grid 布局右边有部分已经超出,这是因为这一行的总宽是 99.99% *加上* grid-gap。 61 | 62 | ### The fr Unit 63 | 64 | ### fr 单位 65 | 66 | One final improvement can be made to our simple grid, and it will solve the width problem we just mentioned; we’re going to introduce the *fr*, or *fraction* unit. A single fr unit describes “*one piece of however many pieces we’re splitting this into*”. For example, we could declare our columns using: 67 | 68 | 为了让我们的 grid 布局更加简洁我们需要进一步的改进,这也会解决刚才提到的总宽度的问题;我们会介绍 *fr* 或者*分数*单位。1 fr 代表“*整个空间被平均分配后的其中之一*”。比如:我们可以这么声明 columns: 69 | 70 | ```css 71 | grid-template-columns: 1fr 1fr 1fr; 72 | ``` 73 | 74 | Here there’s a total of three fr units, so each column would be one third wide. Here’s another example: 75 | 76 | 这里一共有 3 个 fr 单位,因此,每一列都是 1/3 。这里是另外一个示例: 77 | 78 | ```css 79 | grid-template-columns: 2fr 1fr 1fr 80 | ``` 81 | 82 | Now there’s a total of four fr units, so the first column would take up half the available width, with the other two columns each taking a quarter. 83 | 84 | 现在,一共 4 个 fr 单位,第一列是 1/2 宽,其余两列分别是 1/4 宽。 85 | 86 | These units are really powerful, especially in combination with other units of measurement: 87 | 88 | 这个单位非常有用,特别是和其它计量单位结合使用的时候: 89 | 90 | ```css 91 | grid-template-columns: 300px 1fr 3fr 20%; 92 | ``` 93 | 94 | Here we’ve declared four columns: 95 | 96 | - the first is fixed at 300px wide 97 | - the last is a flexible 20% of the grid container element wide 98 | - then the fr units are calculated, also taking gutters into account, leaving the second column with one piece of the remaining space 99 | - and the third with three pieces. 100 | 101 | 以上,我们声明了 4 列: 102 | 103 | - 第一列固定宽 300px 104 | - 最后一列是父级网格容器的 20% 105 | - 然后,每一个 fr 单位都会根据去除间隙后剩余空间计算,第二列只是其中一份 106 | - 第三列就是剩余空间的 3/4 107 | 108 | It looks like this, perfectly highlighting auto-placement as our nine items shift to fill the gaps: 109 | 110 | 看起来就像这样,9 个元素完美的自动排列,它们之间也会有留白: 111 | 112 | [DEMO](https://codepen.io/tutsplus/pen/yaavEO) 113 | 114 | But back to our original grid. Let’s replace the clumsy and inaccurate 33.33% value with 1fr: 115 | 116 | 回到原来的示例中。让我们用 1fr 代替笨拙又不正确的 33.33%: 117 | 118 | ```css 119 | grid-template-columns: repeat(3, 1fr); 120 | ``` 121 | 122 | Finished pen: 123 | 124 | 最总结果: 125 | 126 | [DEMO](https://codepen.io/tutsplus/pen/zKKRdN) 127 | 128 | ### Conclusion 129 | 130 | ### 总结 131 | 132 | So, to recap: 133 | 134 | 1. Grid will accept flexible units in combination with fixed units of measurements. 135 | 1. The ```repeat()``` function will save us time and keep our stylesheets maintainable. 136 | 1. The *fr*, or *fraction* unit is a very powerful way of describing grid templates. 137 | 138 | 概括一下: 139 | 140 | 1. Grid 中可以混合使用弹性和固定计量单位。 141 | 1. ```repeat()``` 方法可以节省我们的时间,也会让样式表更易维护。 142 | 1. *fr* 或者 *fraction* 单位在定义声明 grid templates 时非常有用。 143 | 144 | We’ve come a long way in just two tutorials, but you’re now the proud owner of a very neat and concise grid! In the next tutorial we’ll explore grid areas, taking a look at the ```span``` keyword and some practical layouts. 145 | 146 | 这两篇教程中我们走了很长一段路,你也学会了简洁有用的 grid 布局,应该为自己而自豪!接下来的教程中,我们会探讨 grid areas,看看关键字 ``span``` 和其它有用的布局。 147 | 148 | #### Useful Resources 149 | 150 | - [The `````` type and *fr* unit](https://www.w3.org/TR/2011/WD-css3-values-20110906/#proportions) on W3C 151 | - Again, follow [@rachelandrew](https://twitter.com/rachelandrew) 152 | 153 | #### 更多有用的资源 154 | 155 | - W3C 上相关 [`````` 和 *fr* 单位的介绍](https://www.w3.org/TR/2011/WD-css3-values-20110906/#proportions) 156 | - 在 twitter 上关注 [@rachelandrew](https://twitter.com/rachelandrew) -------------------------------------------------------------------------------- /Published/Breaking down CSS Box Shadow vs. Drop Shadow.md: -------------------------------------------------------------------------------- 1 | ## Breaking down CSS Box Shadow vs. Drop Shadow 2 | ## CSS Box Shadow 对比 Drop Shadow 3 | 4 | > 原文地址: [https://css-tricks.com/breaking-css-box-shadow-vs-drop-shadow/](https://css-tricks.com/breaking-css-box-shadow-vs-drop-shadow/) 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | > ***Drop shadows***. Web designers have loved them for a long time to the extent that we used to fake them with PNG images before CSS Level 3 formally introduced them to the spec as the [box-shadow](https://css-tricks.com/almanac/properties/b/box-shadow/) property. I still reach for drop shadows often in my work because they add a nice texture in some contexts, like working with largely flat designs. 10 | 11 | 阴影。在很长一段时间内 web 开发者非常喜欢用透明图片伪造,直到 CSS3 引入 [box-shadow](https://css-tricks.com/almanac/properties/b/box-shadow/)。我经常在我的工作中使用阴影,因为它们会增加内容的质感,就像大部分平面设计一样。 12 | 13 | > Not too long after ```box-shadow``` was introduced, a working draft for [CSS Filters](https://www.w3.org/TR/filter-effects-1) surfaced and, with it, a method for [drop-shadow()](https://www.w3.org/TR/filter-effects-1/#dropshadowEquivalent) that looks a lot like ```box-shadow``` at first glance. However, the two are different and it's worth comparing those differences. 14 | 15 | ```box-shadow``` 引入规范不久,就出现了有关的 [CSS Filters](https://www.w3.org/TR/filter-effects-1) 的草案,```CSS Filters``` 中有一个方法 [drop-shadow()](https://www.w3.org/TR/filter-effects-1/#dropshadowEquivalent),第一印象让人感觉和 ```box-shadow``` 非常相似。但是,它们还是有区别的,值得比较两者的不同之处。 16 | 17 | > For me, the primary difference came to light early on when I started working with ```box-shadow```. Here's a simple triangle not unlike the one I made back then. 18 | 19 | 对于我来说,他们之间的主要不同是我开始使用 ```box-shadow``` 后明白的。这是有一个简单的三角形,不像我之前做的那样。 20 | 21 | [DEMO](https://codepen.io/team/css-tricks/pen/eGXMzo) 22 | 23 | > Let's use this to break down the difference between the two. 24 | 25 | 让我用这个来对比两者之间的不同之处。 26 | 27 | ### Box Shadow 28 | 29 | ### Box Shadow 30 | 31 | > Add a ```box-shadow``` on that bad boy and this happens. 32 | 33 | 添加一个 ```box-shadow```,就会发生以下的事情。 34 | 35 | [DEMO](https://codepen.io/team/css-tricks/pen/boZvwv) 36 | 37 | > It's annoying, but makes sense. CSS uses a [box model](https://www.w3.org/TR/CSS2/box.html), where the element's edges are bound in the shape of a rectangle. Even in cases where the shape of the element does not appear to be a box, the box is still there and that is was ```box-shadow``` is applied to. This was my "[ah-ha moment](https://css-tricks.com/moment-css-started-making-sense/)" when understanding the box in ```box-shadow```. 38 | 39 | 这很烦人,但也说得通。CSS 使用 [盒模型](https://www.w3.org/TR/CSS2/box.html),DOM 的边缘被锁定在一个矩形盒子里面。尽管示例中的图形看起来并不像一个盒模型,但是盒模型还是存在的,```box-shadow``` 作用在盒模型上。这就是为什么当我理解 ```box-shadow``` 时候的[惊叹](https://css-tricks.com/moment-css-started-making-sense/)了。 40 | 41 | ### CSS Filter Drop Shadow 42 | 43 | ### CSS Filter Drop Shadow 44 | 45 | > CSS Filters are pretty awesome. Take a gander at [all the possibilities](https://css-tricks.com/almanac/properties/f/filter/) for adding visual filters on elements and marvel at how CSS suddenly starts doing a lot of things we used to have to mockup in Photoshop. 46 | 47 | CSS Filter 非常棒。在 DOM 上添加滤镜变的很容易,CSS 突然可以做很多我们曾经不得不用 Photoshop 模拟的事情。 48 | 49 | > Filters are not bound to the box model. That means the outline of our triangle is recognized and the transparency around it is ignored so that the intended shape receives the shadow. 50 | 51 | Filter 不受盒模型的约束。也就是说我们的三角形外边框是认可的,并且周围的透明部分会被忽略,阴影也会按照预期的显示。 52 | 53 | [DEMO](https://codepen.io/team/css-tricks/pen/GMexNE) 54 | 55 | ### Deciding Which Method to Use 56 | 57 | ### 决定使用哪种方式 58 | 59 | > The answer is totally up to you. The simple example of a triangle above might make it seem that ```filter: drop-shadow()``` is better, but it's not a fair comparison of the benefits or even the possibilities of both methods. It's merely an illustration of their different behaviors in a specific context. 60 | 61 | 答案完全取决于你。上面简单三角形的示例中显然 ```filter: drop-shadow()``` 会更好,但是,上面的示例对于两者优点和可能性的对比是不公平的。这仅仅是一个两者在特定场景下不同行为的示例。 62 | 63 | > Like most things in development, the answer of which method to use depends. Here's a side-by-side comparison to help distinguish the two and when it might be best to choose one over the other. 64 | 65 | 就像大多数开发中事情一样,具体使用哪种方法取决于实际情况。这有个一对一的对比,有利于帮助我们决定,如何,何时,选择哪种方法更合适。 66 | 67 | | | Box Shadow | Drop Shadow | 68 | |---------|------------|-------------| 69 | | Specification | [CSS Backgrounds and Borders Module Level 3](https://drafts.csswg.org/css-backgrounds-3/#the-box-shadow) | [Filter Effects Module Level 1](https://drafts.fxtf.org/filter-effects/#FilterProperty) | 70 | |Browser Support| [Great](http://caniuse.com/#feat=css-boxshadow) | [Good](http://caniuse.com/#feat=css-filters) | 71 | |Supports Spread Radius| Yes, as an optional fourth value | No | 72 | |Blur Radius| [Calculation is based on a pixel length](https://drafts.csswg.org/css-backgrounds-3/#shadow-blur) | [Calculation is based on the stdDeviation attribute of the SVG filter](https://drafts.fxtf.org/filter-effects/#dropshadowEquivalent) | 73 | |Supports ```inset``` shadows| Yes | No | 74 | |Performance| Not hardware accelerated | Hardware accelerated in browsers that support it. It's a heavy lift without it. | 75 | 76 | 77 | ### Wrapping Up 78 | 79 | 80 | > The difference between ```box-shadow``` and ```filter: drop-shadow()``` really boils down to the CSS box model. One sees it and the other disregards it. There are other differences that distinguish the two in terms of browser support, performance and such, but the way the two treat the box model is the key difference. 81 | 82 | ```box-shadow``` 和 ```filter: drop-shadow()``` 之间不同归根结底都是因为 CSS 盒模型。大家往往会忽略它。在那些区别中,比如:浏览器支持情况、性能等等,都是因为它们对盒模型不同的处理方式导致的。 83 | 84 | > **Update:** Amelia identified another key difference [in the comments](https://css-tricks.com/breaking-css-box-shadow-vs-drop-shadow/#comment-1612592) where the spread of the radius for ```drop-shadow()``` is calculated differently than ```box-shadow``` and even that of ```text-shadow```. That means that the spread radius you might specify in ```box-shadow``` is not one-to-one with the default spread value for ```drop-shadow```, so the two are not equal replacements of one another in some cases. 85 | 86 | **更新:**[评论中](https://css-tricks.com/breaking-css-box-shadow-vs-drop-shadow/#comment-1612592) Amelia 认为另外一个关键的不同点是:```drop-shadow()``` 在计算圆角半径是不同于 ```box-shadow``` 和 ```text-shadow``` 的。也就说:在 ```box-shadow``` 你可以指定圆角半径,但是这并不和 ```drop-shadow``` 默认值相同,因此,在某些场景下两者并不能替换。 87 | 88 | > Let's cap this off with a few other great examples illustrating that. [Lennart Schoors also has a nice write-up](http://bricss.net/post/33158273857/box-shadow-vs-filter-drop-shadow) with practical examples using tooltips and icons that we [previously](https://css-tricks.com/box-shadow-vs-filter-drop-shadow/) called out. 89 | 90 | 让我们用一些更好的示例来说明这一切。[Lennart Schoors 也写过一篇很好的文章](http://bricss.net/post/33158273857/box-shadow-vs-filter-drop-shadow)并实现了很好的示例,示例中的 icons 我[之前](https://css-tricks.com/box-shadow-vs-filter-drop-shadow/)也提到过 91 | 92 | [DEMO](https://codepen.io/Kseso/pen/Ajamv) 93 | 94 | [DEMO](https://codepen.io/qnlz/pen/bWXJwg) 95 | 96 | [DEMO](https://codepen.io/Kseso/pen/BEmev) -------------------------------------------------------------------------------- /Published/Quick Tip- Name Your CSS Grid Lines, Just in Case.md: -------------------------------------------------------------------------------- 1 | ## Quick Tip: Name Your CSS Grid Lines, Just in Case 2 | ## 小建议:为网格线命名,以防万一 3 | 4 | > 原文地址: 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | In any CSS Grid each line has an index number which we can reference to place grid items. However, we can also name each of these grid lines, making it easier to work with and maintain our grid layouts. Let’s take a look! 10 | 11 | CSS Grid 中任何的网格线都有一个索引编号,我们可以引用它们来定位元素。然而,我们还可以给每条网格线命名,以便更加方便的使用和维护 Grid 布局。接下来让我们看一看! 12 | 13 | ### Grid is Coming 14 | 15 | ### Grid 到来了 16 | 17 | The most common response to any Grid tutorial is “but when can I use this?” and it’s a fair question. The fact is: Grid is coming, and it will be here soon. 18 | 19 | 针对 Grid 常见的问题是“我什么时候才能使用呢?”,这是个很正常的问题。事实上:Grid 时代正在到来,并且很快。 20 | 21 | > “CSS Grid is going to become supported-by-default in Chrome and Firefox in March of 2017.” – [Eric Meyer](http://meyerweb.com/eric/thoughts/2016/12/05/css-grid/) 22 | 23 | > "2017年3月 CSS Grid 将在 Chrome 和 Firefox 默认支持" - [Eric Meyer](http://meyerweb.com/eric/thoughts/2016/12/05/css-grid/) 24 | 25 | If you haven’t taken a look at it yet, now’s the time! 26 | 27 | 如果,你还没有了解过,现在是该学习的时候了! 28 | 29 | [DEMO](https://webdesign.tutsplus.com/tutorials/css-grid-layout-quick-start-guide--cms-27238) 30 | 31 | [DEMO](https://webdesign.tutsplus.com/tutorials/css-grid-layout-units-of-measurement-and-basic-keywords--cms-27259) 32 | 33 | ### Grid Line Numbers 34 | 35 | ### 网格线编号 36 | 37 | When we declare a grid, each line is given an index number: 38 | 39 | 当我们声明了一个 Grid 后,每条线都会有个索引编号: 40 | 41 | ![](https://cms-assets.tutsplus.com/uploads/users/30/posts/27844/image/grid-terms-line-numbers-.svg) 42 | 43 | **Note**: Unless the layout is set with ```direction: rtl;```, these numbers begin at the top left of the grid, working their way to the bottom right. 44 | 45 | **注意**:除非声明了 ```direction: rtl;```,编号是从左上角开始,然后向右下角移动。 46 | 47 | We can reference these numbers to place grid items: 48 | 49 | 我们可以通过网格线编号定位 Grid 元素: 50 | 51 | ```css 52 | .item { 53 | grid-column: 2; 54 | grid-row: 3; 55 | } 56 | ``` 57 | 58 | In this example our ```.item``` element is positioned starting on column line 2, and row line 3: 59 | 60 | 示例中的 ```.item``` 被放置在了第二列、第三行。 61 | 62 | ![](https://cms-assets.tutsplus.com/uploads/users/30/posts/27844/image/grid-terms-line-numbers-position.svg) 63 | 64 | ### Explicit Grid Line Names 65 | 66 | ### 显式网格线命名 67 | 68 | With more complex grids, you can imagine that referencing everything by numbers might get a bit confusing. For this reason, the Grid module allows us to explicitly name our lines when we declare our grid columns and rows. 69 | 70 | 在一些复杂的网格中,可以想象的到如果通过引用网格线编号来定位会比较混乱。基于这个原因,当我们声明时 Grid 模块允许我们显式的给网格线命名。 71 | 72 | Let’s use an example like the ones we’ve used throughout this series. Here’s our basic 3×3 grid declaration: 73 | 74 | 让我们使用一个示例,就像这个系列中的示例一样。这是一个基本的 3x3 Grid 布局。 75 | 76 | ```css 77 | .grid-1 { 78 | display: grid; 79 | grid-template-columns: 100px auto 100px; 80 | grid-template-rows: 60px 130px 50px; 81 | grid-gap: 20px; 82 | } 83 | ``` 84 | 85 | Now we can wrap our column and row values with line names (whatever the heck we want), using square brackets: 86 | 87 | 现在我们可以用方括号的方式给网格线命名了(任何名字都可以): 88 | 89 | ```css 90 | .grid-1 { 91 | display: grid; 92 | grid-template-columns: [start] 100px [centre-start] auto [last-column-start] 100px [finish]; 93 | grid-template-rows: [header-start] 60px [main-start] 130px [main-end] 50px [row-end]; 94 | grid-gap: 20px; 95 | } 96 | ``` 97 | 98 | We can now position items with names, instead of numbers: 99 | 100 | 现在,我们可以用网格线名称来代替网格线编号来定位元素了: 101 | 102 | ```css 103 | .item { 104 | grid-column: centre-start; 105 | grid-row: header-start; 106 | } 107 | ``` 108 | 109 | Some pointers: 110 | 111 | - These names can be tailored to your own descriptive needs, so think logically about what will help you recognize and remember areas of the grid. 112 | - The original line numbers remain in operation, so you can still use them. 113 | - You can declare multiple names for one line, for example: ```[main-end footer-start row-5]``` etc. 114 | - Even if you name your grid lines, you’re not obliged to use them, so it’s a good “just in case” habit to get into. 115 | 116 | 一些提示: 117 | 118 | - 这些名称可以根据你的描述需求定制,因此,从逻辑上思考怎么才可以帮助你认识并记住这些网格区域。 119 | - 网格线编号还是会被保留的,你仍旧可以使用它们。 120 | - 你还可以给一条网格线定义多个名称,比如:```[main-end footer-start row-5]```。 121 | - 即使,你给网格线命名了,但是你没有义务一定使用它们,因此,这只是“以防万一”的良好习惯。 122 | 123 | 124 | ### Implicit Grid Line Names 125 | 126 | ### 隐式的网格线命名 127 | 128 | When we deliberately do things, like naming grid lines, that’s said to be *explicit*. When something is implied, but not directly stated, that’s referred to as being *implicit*. We’ve covered explicitly naming grid lines, but there are also circumstances where lines are given names implicitly. 129 | 130 | 当我们特意做了某些事情,比如:给网格线命名,也就是说这是*显式的*。如果,某些事情是隐式,没有直接说明,我们就可以称为*隐式的*。显式的网格线命名我们已经介绍过,但是,还有些情况是隐式的声明网格线名称。 131 | 132 | You may recall from a previous tutorial that it’s possible to define grid areas. 133 | 134 | 你应该记得上次教程中我们提到网格是可以定义网格区域的: 135 | 136 | [DEMO](https://webdesign.tutsplus.com/tutorials/css-grid-layout-using-grid-areas--cms-27264) 137 | 138 | We might define four grid areas like this: 139 | 140 | 我们可以像这样定义四个网格区域: 141 | 142 | ```css 143 | .grid-1 { 144 | /* ..existing styles */ 145 | 146 | grid-template-areas: "header header header" 147 | "main main sidebar" 148 | "footer footer footer"; 149 | } 150 | ``` 151 | 152 | This gives us the following: 153 | 154 | 最终结果如下: 155 | 156 | ![](https://cms-assets.tutsplus.com/uploads/users/30/posts/27844/image/grid-areas.svg) 157 | 158 | Naming a grid area ```header``` automatically assigns names to its four boundary lines too. The row lines around it become ```header-start``` and ```header-end```, and likewise the two column lines also become ```header-start``` and ```header-end```. The same applies to the other areas, which are given line names ```main-start```, ```main-end```, ```sidebar-start``` and so on. 159 | 160 | 如果,给一个网格区域命名为 ```header```,那么它周围的四条线会自动的分配相应的别名。水平的两条线就会变成 ```header-start``` 和 ```header-end```,同样垂直的两条线也会变成 ```header-start``` 和 ```header-end```。其他区域也适用同样的规则,比如 ```main-start```, ```main-end```, ```sidebar-start``` 等等。 161 | 162 | **Note**: Looking at things in reverse, explicitly adding named lines in the same format (```header-start``` and ```header-end```) will create a named grid area of ```header```. 163 | 164 | **注意**:反过来看,如果用同样的格式(```header-start``` 和 ```header-end```)给网格线命名同样会得到一个名为 ```header``` 网格区域。 165 | 166 | We can use these line names just like we have previously, to position items. And again, they exist in addition to any names you define yourself, and the original line index numbers. 167 | 168 | 我还可以像以前一样使用这些名称,定位元素。同时,不但你命名的网格线名称在,原来的网格线编号也存在。 169 | 170 | ### End of the Line 171 | 172 | ### 最后 173 | 174 | That’s it for this quick tip! Remember: get into the habit of naming your lines and areas for easier grid management and maintenance. 175 | 176 | 这只是一个小提示!记住:给网格线命名是个很好的习惯,也会让的网格更易管理和维护。 177 | -------------------------------------------------------------------------------- /Published/react/Creating-a-reusable-React-Query-component-for-your-REST-API.md: -------------------------------------------------------------------------------- 1 | # Creating a reusable React Query component for your REST API 2 | 3 | ## 为 REST API 创建可复用的 React Query 组件 4 | 5 | > 原文地址: 6 | **本文版权归原作者所有,翻译仅用于学习。** 7 | 8 | --------- 9 | 10 | ![](https://miro.medium.com/max/4800/0*AVi4Wvv_YZ7qSpAd) 11 | 12 | When implementing a new UI component I always start with the layouting and mock the server commucation by providing *defaultProps* and empty click listeners for user interactions. After completing the UI components I replace the mocked functions and props with the real thing. 13 | 14 | 每次实现一个新的 UI 组件时,我都是先实现布局,然后,mock 数据用于 *defaultProps*,并提供一个空的点击监听模拟用户交互。然后,用真实的数据替换掉 mock 的函数和 props。 15 | 16 | I reinvented the wheel over and over again in every component which consumes data from a server. Using and configuring fetch with HTTP headers, deserialization logic and handling success, error and loading states add many and often duplicate lines to your codebase. 17 | 18 | 为了实现那些需要从服务端获取数据数据的组件,我一次次的重复着相同的操作。使用和配置 HTTP headers,反序列化逻辑、处理成功或者失败的回调、loading 状态等等,这就导致了代码的重复。 19 | 20 | Wouldn’t it be nice to outsource the communication logic to a **reusable component**? 21 | 22 | 通信逻辑让可**复用的组件**来处理,是不是更好呢? 23 | 24 | ## 💪 Just do it. 25 | 26 | ## 💪 开始 27 | 28 | ![](https://miro.medium.com/max/1400/1*2Yr-Q1TTzwMgP-kCBniF4Q.png) 29 | 30 | Working on a React application which consumes an API you have to deal with a bunch of difficulties. For every request you need to handle a loading, error and success state. 31 | 32 | React 应用中那些需要使用 API 的组件需要处理大量的问题。针对每个请求,你都需要处理 loading、错误和成功的状态。 33 | 34 | Integrating these functionalities in an existing component will increase the complexity of it and does not leverage the component based approach of React. 35 | 36 | 把所有的功能整合到现有的组件中势必增加组件的复杂度,这并不符合 React 组件化思想。 37 | 38 | Computer Science isn’t a new thing anymore and we are rediscovering some rules and tools from the old days. One of them is the rule of separation of concerns. 39 | 40 | 计算机科学不再是新鲜事物,我们也发现了一些旧时代的规则和工具。其中之一就是:分离。 41 | 42 | > Write programs that do one thing and do it well — Doug McIlroy 43 | > 44 | > 编写程序只做一件事情并做好 — Doug McIlroy 45 | 46 | Let’s transfer this quote by the inventor of the Unix pipe to React components, where a component in a React application is the corresponding program in a unix system. Provide props to control the behavior of a component and use an universal interface for your output. In JavaScript our universal interface is the function type — this leads us to **Composite Components**. 47 | 48 | 我们把 Unix 管道发明者的这个理念引入到 React 组件中,React 的组件代表着 Unix 系统中的程序。通过 props 控制组件的行为,实现万能的组件。JavaScript 中通用的类型就是函数 — 这就引出了**复合组件**。 49 | 50 | ## 🔌 Provide reusable functionality with Composite Components 51 | 52 | ## 🔌 通过复合组件提供可复用的功能 53 | 54 | The composite component pattern is getting promoted by [Kent C. Dodds ](https://medium.com/u/db72389e89d8?source=post_page-----1aa91ef2551b----------------------)which leverages. another design principle in addition to the one-thing-principle: the inversion of control, which shifts the non-core functionalities to another component. 55 | 56 | 复合组件模式是由 [Kent C. Dodds ](https://medium.com/u/db72389e89d8?source=post_page-----1aa91ef2551b----------------------) 提出并推广的。除了一物理念之外的另外一种设计理念:控制权倒置,将非核心的功能转移到另外一个组件。 57 | 58 | Using a Query component gives you the ability to fetch a url — not no less. The decision which jsx-elements to render, based on the query result, is shifted to the using side. The Query component has no strong coupling to any component, not to the url nor any other prerequisite. 59 | 60 | 使用 Query 组件可以通过 URL 获取数据 — 这是基本功能。根据查询结果,使用者有权决定如何渲染 jsx 元素。Query 组件不会与任何组件、任何 URL 或者其它预设属性耦合。 61 | 62 | It is fully customizable wherever it is used. You can provide a custom deserialize function to deal with different response types like *json, text* or *xml*, check for the response status codes and alter the default behavior in place. A state reducer lets you intercept the state updates to change the Query component behavior based on the response results. 63 | 64 | 不管在什么地方使用,它完全可以定制。你可以提供一个自定义的反序例化函数来处理不同的响应类型,比如:*json、 text* 或者 *xml*,然后,检查响应状态,并在适当的位置改变默认行为。基于响应结果,state reducer 可以让你拦截状态的更新情况来改变 Query 组件的行为。 65 | 66 | The Query component is a Composite Component and additionally renders a React Context Provider which wraps its children. This enables the using side to use **Compound Components**. Let’s see this in action: 67 | 68 | Query 组件是一个复合组件,另外提供一个 React Context Provider 来包装子组件。这有利于**复合组件**的使用。我们来看看具体的操作: 69 | 70 | ![img](https://miro.medium.com/max/1400/1*2-SmVcs3FaXAh4PuXZFiZg.png) 71 | 72 | If you have dipped your toes into the GraphQL universe you may have seen one of the Query, Mutation or Subscription components provided by the awesome [react-apollo](https://www.apollographql.com/docs/react/) library. These components provide a straight forward API for integrating server communication logic in your React components — even for REST APIs with [apollo-link-rest](https://www.apollographql.com/docs/link/links/rest.html). I am totally into good developer experience when it comes to coding. But there are situations where you do not want to pull in an extra library as dependency. So let’s try to recreate a comparable developer experience on our own for a REST API. 73 | 74 | 如果,你深入了解过 GraphQL,你应该看到过由 [react-apollo](https://www.apollographql.com/docs/react/) 提供的 Query、Mutation 和 Subscription 组件。这些组件提供了简洁明了的 API,以便在 React 组件中整合服务端的通信逻辑,甚至,使用 [apollo-link-rest](https://www.apollographql.com/docs/link/links/rest.html) 可以处理 REST APIs。我非常喜欢这种良好的编码体验。但是,有些情况下,你并不希望使用这些依赖库。因此,我们可以尝试为我们的 REST API 创建类似的方案。 75 | 76 | Let’s take a look at a query component which passes additional information, like the loading and error states of the request, to the consuming child component. 77 | 78 | 我们先来看看一个 Query 组件会传入哪些额外的信息以便子组件使用,比如:loading 和请求的错误状态。 79 | 80 | ![](https://miro.medium.com/max/1400/1*WBq3Ij1QRuoH01MI_Jor6w.png) 81 | 82 | ## ⚙️ Customize its behavior 83 | 84 | ## ⚙️ 自定义 85 | 86 | The Query component is basically a small component which provides the capabilities of *fetch* as a component. Drop it somewhere in your React tree where you need data from a server and your code stays readable. 87 | 88 | Query 组件基本上就是一个组件,只是它提供了 *fetch* 的功能。React 应用中任何需要从服务器获取数据的地方都可以使用它,这样也保证了代码的可读性。 89 | 90 | Server communication does not consist just of the consuming GET request. Often you want to trigger a request on user interaction to create, update or delete an entity. 91 | 92 | 服务器通信并不是只有 GET 请求。有时,用户交互也会触发请求,以便创建、更新或者删除一个实体。 93 | 94 | We can alter the behavior of the Query component on user interaction. Basically we can alter every fetch option to be able use different HTTP methods like POST or DELETE or change the URL. 95 | 96 | 根据用户交互我们可以改变 Query 组件的行为。比如,我们可以改变每个 fetch 的选项,以便处理不同的 HTTP 方法,比如:POST、DELETE 或者改变 URL。 97 | 98 | ![](https://miro.medium.com/max/1400/1*iLz0lkMNUxBe8VoWxRoucQ.png) 99 | 100 | ## 🛍 Takeaway 101 | 102 | ## 🛍 外卖 103 | 104 | Integrating server communication into your components can clutter your code. Extract recurring request logic to a composite component to be able to reuse it in your application. This approach helps you to keep your code DRY and leverages the component based approach of React and the separation of concerns. 105 | 106 | 在组件中整合服务器通信代码会让你的代码变得混乱。把重复的请求逻辑提取到一个复合组件中,可以提高应用中代码的复用率。这种模式可以让你的代码 DRY,并利用基于组件的 React 方法和关注点的分离核心思想。 107 | 108 | ## ✍️ Try it on CodeSandbox 109 | 110 | ## ✍️ CodeSandbox 演示 111 | 112 | [Queyr Component Demo](https://codesandbox.io/s/92n5zmoq2y?from-embed=&file=/src/hooksEdition/useQuery.js) 113 | 114 | 👋 Hi! I am Tim Kolberger. I work at [Incloud](https://www.incloud.de/) in Darmstadt, Germany, as a full stack web developer. I ❤️ React, GraphQL and JavaScript. 115 | 116 | 👋 大家好!我是 Tim Kolberger。我是一名全栈 web 开发者,在德国,达姆施塔特的 [Incloud](https://www.incloud.de/) 公司工作。我喜欢 React、GraphQL 和 JavaScript。 117 | 118 | -------------------------------------------------------------------------------- /Published/React State Management in 2020.md: -------------------------------------------------------------------------------- 1 | ## React State Management in 2020 2 | ## 2020 年 React 状态管理 3 | 4 | > 原文地址: 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | **Do we still need state management frameworks like Redux and MobX?** 10 | 11 | **我们是否还需要 Redux 和 Mobx 这类的状态管理框架?** 12 | 13 | ![](https://miro.medium.com/max/1400/1*JNpk3yLpt9f4x_aEO5pa-w.jpeg) 14 | 15 | ## Introduction 16 | 17 | ## 引言 18 | 19 | The introduction of React hooks has certainly changed the perspective on state management. 20 | 21 | React hooks 的引入无疑改变的了 state 管理的现状。 22 | 23 | Before we had this feature, it was difficult to share state logic between components. Now it’s as easy as making an abstract hook for it (example: `useUserLogin`). 24 | 25 | 在此之前,很难在组件之间共享 state 相关的逻辑。现在,我们可以很简单的通过抽象一个 hook 来处理(例如:```useUserLogin```)。 26 | 27 | This raises the question, why we still need state management frameworks? In this piece, I will describe my decision-making process over where to keep `state`. I will also share my opinion as to whether we still need state management frameworks in 2020. 28 | 29 | 这就引出了问题,为什么我们还需要状态管理框架?在这篇文章中,我将展示我的决策过程:如何管理 ```state```。关于在2020年我们是否还需要 state 管理框架,我也会分享我的观点。 30 | 31 | ## What Changed? 32 | 33 | ## 有什么变化? 34 | 35 | So how did we define state before Hooks? Basically, there were two options: defining a local state in the component, or using a state management framework to set it as a global state (e.g. MobX / Redux). 36 | 37 | 在有 Hooks 之前,我们是如何定义 state 的?基本上,有两种选择:在组件内部定义本地 state,或者用一个 state 管理框架设置全局的 state (例如:Mobx/Redux)。 38 | 39 | ### Local state (before hooks) 40 | ###本地 state (hooks 之前) 41 | 42 | ```jsx 43 | export class UserList extends Component { 44 | state = { 45 | isLoading: false, 46 | hasError: false, 47 | users: [] 48 | } 49 | 50 | searchUsers(value) { 51 | this.setState({isLoading: true}); 52 | 53 | api.get(`/users?searchKey=${value}`) 54 | .then((data) => this.setState({users: data})) 55 | .catch(() => this.setState({hasError: true})) 56 | .finally(() => this.setState({loading: false})); 57 | } 58 | 59 | render() { 60 | if (this.state.isLoading) { 61 | // render loading spinner 62 | } 63 | 64 | if (this.state.hasError) { 65 | // render error message 66 | } 67 | 68 | return ( 69 |
70 | this.searchUsers(event.target.value)} /> 71 |
72 | ) 73 | 74 | } 75 | } 76 | ``` 77 | 78 | The issue with only having these two options is best described in the following scenario. Let’s say our state does not have to be global, but we may want to reuse how we define the local state in multiple components. 79 | 80 | 在接下来我们会说明只有这两个选择时带来的问题。假设,我们的 state 不必设为全局,但是,我们希望可以在多个组件复用 state,我们该如何定义本地 state。 81 | 82 | In the example above, we may want to reuse setting the loading and error state — before Hooks this was not possible. The only option we had was to make it reusable with Redux. In Redux each component which wanted to search users could simply dispatch an action (`searchUsers()`) and listen for the global state to change. 83 | 84 | 在上面的演示中,我们或许想复用 loading 和 error state,在 Hooks 之前,是不可能的。唯一的选择是需要利用 Redux 来复用它。在 Redux 中,任何需要搜索用户的组件只需简单 dispatch 一个 action(```searchUsers()```)和监听全局 state 的变化即可。 85 | 86 | However using this global state (Redux/MobX) results in a few problems: 87 | 88 | - More boilerplate code 89 | - Complicated flow 90 | - Multiple components are manipulating the global state, which may cause unwanted side effects 91 | 92 | 然而,使用这些全局 state(Redux/Mobx)会带来一些问题: 93 | 94 | - 更多的样板代码 95 | - 复杂的数据流 96 | - 多个组件同时维护全局 state,这可以能会带来意想不到的副作用。 97 | 98 | ### The solution: React Hooks! 99 | 100 | ### 解决方案:React Hooks! 101 | 102 | Thankfully React introduced hook’s in React 16.8. From that day onwards, it was possible to share state logic between multiple components. 103 | 104 | 谢天谢地 React v16.8 引入的 Hooks。从这时起,在做组件之间共享 state 相关的逻辑变得可行。 105 | 106 | In the example below, we are now able to share the loading and error behaviour: 107 | 108 | 在下面的演示中,我们可以共享 loading 和 error 的行为: 109 | 110 | ```jsx 111 | import {useState} from 'react'; 112 | 113 | const useRequestHandler = () => { 114 | const [isLoading, setLoading] = useState(false); 115 | const [hasError, setError] = useState(false); 116 | const [data, setData] = useState(null); 117 | 118 | const handleRequest = (request) => { 119 | setLoading(true); 120 | setError(false); 121 | 122 | return api.get(request) 123 | .then(setData) 124 | .catch(() => setError(true)) 125 | .finally(() => setLoading(false)) 126 | }; 127 | 128 | return {isLoading, hasError, data, handleRequest}; 129 | }; 130 | 131 | 132 | const UserList = () => { 133 | const {data, isLoading, hasError, handleRequest} = useRequestHandler(); 134 | 135 | const searchUsers = (value) => handleRequest(`/users?searchKey=${value}`); 136 | 137 | return ( 138 | 139 | {data.map(u =>

{u.name}

)} 140 |
141 | ) 142 | } 143 | ``` 144 | 145 | **Bonus**: We could also make a `useUserSearch` if multiple components wanted to offer the functionality to search through the list of users. 146 | 147 | **更多好处**:如果,多个组件需要搜索用户列表的功能,我们也可以自定义 ```useUserSearch``` hook。 148 | 149 | However, hooks are no silver bullet. Keeping state in a hook does not mean it becomes a singleton, the state is only bound to one component. There are certain uses where we might only want to keep one instance of state (for example, fetching user info only once). This is where a state management framework proves its value. 150 | 151 | 然而,hooks 并不是银弹。把 state 保存在 hook 中,并不意味着它就变成了单例对象,它只是绑定在一个组件中。在某些情况下,我们只想保留一个实例 state 对象(例如:只加载一次用户信息)。这是 state 管理框架提供的功能。 152 | 153 | ## How to Decide Where to Keep State 154 | 155 | ## 如何,何时,何地管理 state 156 | 157 | Now that it’s possible to share state logic across components, how do we decide between keeping state in components (local) or in a state management framework (global)? 158 | 159 | 现在,可以在多个组件之间共享 state 相关逻辑了,那我们怎么决定 state 保存在组件内(本地),还是保存在 state 管理框架中(全局)呢? 160 | 161 | Below is an image of my decision-making process. 162 | 163 | 下面的图片展示了我的决策过程。 164 | 165 | ![](https://miro.medium.com/max/1400/1*NPIE1cX1ofWR-_46IYikYA.png) 166 | 167 | ## What’s the Benefit of a State Management Framework? 168 | ## State 管理框架有什么好处呢? 169 | 170 | Now we know when to decide between global and local state. But why would we still use a state management framework in 2020? What’s the benefit above using React Hooks? 171 | 172 | 现在,我们知道如何在全局和本地做抉择了。但是,在2020年为什么还需要 state 管理框架呢?这相比 React Hooks 有什么好处呢? 173 | 174 | Here’s a list of benefits: 175 | 176 | - Globally defined, which means only one instance of the data 177 | - Only fetching remote data once 178 | - Extensive dev tools 179 | - Provides a standardised way of working for software engineers 180 | 181 | 有以下几个好处: 182 | 183 | - 全局定义,也代表只有一个实例对象 184 | - 只会加载一次远程数据 185 | - 开发工具的支持 186 | - 为软件工程师提供了一种标准的开发方式 187 | 188 | ## Conclusion 189 | 190 | ## 总结 191 | 192 | We’ve seen that React Hooks has shaken up the whole state management landscape. Since their introduction, it’s been easier to share state logic between components. 193 | 194 | 我们看到 React Hooks 已经搅动了 state 管理的格局。由于它们的引入,在组件之间共享 state 相关逻辑变得更加简单。 195 | 196 | However, Hooks are no silver bullet and we might still need state management frameworks. That doesn’t mean that we need to keep every state globally — most of the time it’s better to keep it at a component level. Moving state to the state management framework should only be done *when absolutely necessary.* 197 | 198 | 然而,Hooks 并不是银弹,我们仍旧需要 state 管理框架。这也并不是说要让所有的 state 都是全局的 — 大多情况下让其保留在组件之间更加好。只有在*有绝对必要的情况下*,才把 state 移动到 state 管理框架中。 -------------------------------------------------------------------------------- /Published/Breaking out with CSS Grid explained.md: -------------------------------------------------------------------------------- 1 | ## Breaking out with CSS Grid explained 2 | ## 打破边界布局 CSS Grid 讲解 3 | 4 | > 原文地址: [https://rachelandrew.co.uk/archives/2017/06/01/breaking-out-with-css-grid-explained/](https://rachelandrew.co.uk/archives/2017/06/01/breaking-out-with-css-grid-explained/) 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | > [This really nice technique for creating a full width image inside a constrained column](https://cloudfour.com/thinks/breaking-out-with-css-grid-layout/) was being shared around recently. However, what it didn’t do was explain why this technique works. As part of my attempt to remove all the “it just works magic” from these techniques I thought I would explain. 10 | 11 | 最近比较流行一项非常好的技术:[在固定宽度的容器中让图片铺满整屏](https://cloudfour.com/thinks/breaking-out-with-css-grid-layout/)。但是,文章中并没有解释原理。我尝试移除那些"这么神奇"的部分,尽可能解释是它们是如何工作的。 12 | 13 | > I’ll write more about naming when I get to that part of my series explaining the Grid Spec, however understanding this technique requires the understanding of a few things about Grid. 14 | 15 | 当我说到 Grid 规范的时候,我会介绍很多有关命名的内容。这对于理解 Grid 是有很大帮助的。 16 | 17 | ### We can position things against lines of the grid 18 | 19 | ### 在 Grid 中我可以根据网格线定位 DOM 20 | 21 | > If you have used grid at all you are probably familiar with the concept of positioning items based on line numbers. We can achieve the breakout layout using this line-based placement of items. When we create a three column grid, as in the image below, we get 4 numbered lines. The breakout item is positioned from line 1 to line 4, the content from line 2 to 3. You can also see this in a [CodePen](https://codepen.io/rachelandrew/pen/PjYGLm). 22 | 23 | 如果,你用过 Grid,那你可能会觉得这有点类似基于行号定位的概念。我们可以基于元素所在的行号实现这种打破边界的布局。当我们创建了一个三列的 Grid,就像下面的图片所示,我们得到了 4 个行号。打破边界的元素所占位置从行 1 到行 4,content 元素从行 2 到行 3。你可以看看这个[示例](https://codepen.io/rachelandrew/pen/PjYGLm)。 24 | 25 | ![](https://rachelandrew.co.uk/perch/resources/numbered-lines-1.png) 26 | 27 | > However the example tutorial doesn’t use line numbers at all. It’s neater than that and doesn’t require that you understand what number lines on the grid are. 28 | 29 | 但是,示例(**文中一开始提到的DEMO**)中并没有用到行号。那样更加整洁,不需要你去理解在 Grid 行号是什么意思。 30 | 31 | ### You can name lines 32 | 33 | ### 你可以给网格命名 34 | 35 | > You need to know that you can name lines. In my next example the lines are named, I replace numbers with names to place items on the grid. [Also demonstrated on CodePen](https://codepen.io/rachelandrew/pen/zwXwmj). 36 | 37 | 你要知道你是可以给网格命名的。在我接下来的示例中是有给网格命名的。在 Grid 中我用网格的名字代替了行号。[可以看看 CodePen 上的演示](https://codepen.io/rachelandrew/pen/zwXwmj)。 38 | 39 | ![](https://rachelandrew.co.uk/perch/resources/named-lines.png) 40 | 41 | > Is this example, as with the referenced tutorial, I have named my lines ```*-start``` and ```*-end```. This is important for the technique. Naming lines is optional as the article suggests, but the technique as described wouldn’t work without named lines. 42 | 43 | 这个示例,参考了教程,我给网格以 ```*-start``` 和 ```*-end``` 模式命名。这是很重要的一点。在教程中虽然说命名是可选的,但是,教程中描述的技术如果没有给网格命名将无法使用。 44 | 45 | > When you name lines, you can optionally name them as ```*-start``` and ```*-end``` and this gives you a little more grid magic. We get a named grid area of the main name used. Sounds odd? Take a look at the diagram below, it shows 4 named grid lines, ```main-start``` and ```main-end``` both for columns and rows. The area marked out by the intersection of these lines can now be referenced by the name ```main```. If we had named the lines ```foo-start``` and ```foo-end``` then we would have a named area called ```foo```. 46 | 47 | 当你决定给网格命名时,你可以选择 ```*-start``` 和 ```*-end``` 这种模式,这样会让你的网格系统更神奇。你会得到一个名字为 ```main``` 的网格区域。听起来很奇怪?看一看下面的图解,这里有 4 个网格名字,```main-start``` 和 ```main-end``` 对称分布在行和列上。被网格线圈出来的区域就可以被称为 ```main```。如果,我们用 ```foo-start``` 和 ```foo-end```,那么我们将得到一个名为 ```foo``` 的区域。 48 | 49 | ![](https://rachelandrew.co.uk/perch/resources/grid-area.png) 50 | 51 | > However this doesn’t get us to the technique used, which doesn’t used the named area, it is positioning against lines named ‘main’ and ‘full’ which are not defined anywhere. 52 | 53 | 然而,我们并没有这么使用,没有给那个区域命名为 ```foo``` ,我们只是定义了 ```main``` 和 ```full``` 两个区域。 54 | 55 | > We have lines named ```main-start``` and ```main-end``` for our columns, therefore a named area called ```main```. We also have lines named main that can be used for start due to the following [note in the specification for line-placement:](https://www.w3.org/TR/css-grid-1/#line-placement) 56 | 57 | 我们把列的网格线以:```main-start``` 和 ```main-end``` 命名,因此有个区域就成为 ```main```。我们[依照 line-placement 相关规范](https://www.w3.org/TR/css-grid-1/#line-placement)得到了一个名为 ```main``` 的网格。 58 | 59 | > “Note: Named grid areas automatically generate implicit named lines of this form, so specifying ```grid-row-start: foo``` will choose the ```start``` edge of that named grid area (unless another line named ```foo-start``` was explicitly specified before it).” 60 | 61 | > "提示:网格的名字是根据网格线自动生成的,因此指定: ```grid-row-start: foo``` 会选择名为 ```foo-start``` 的网格边界(除非在它之前有另外一个名为 ```foo-start``` 的网格线)。" 62 | 63 | > This means that we can set ```grid-column-start``` to ```main``` and Grid will position that item at the start edge of the area that is named ```main``` due to us having named grid lines of ```main-start``` and ```main-end```. 64 | 65 | 也就是说我们可以设置 ```grid-column-start: main```,由于我们已经有了名为 ```main-start``` 和 ```main-end``` 的网格线,所以名为 ```main``` 的区域就对应这两条线的边界所包含的区域。 66 | 67 | > What of the end line? In the tutorial the item is positioned with ```grid-column: main```. 68 | 69 | 结束边界线呢?在教程中 DOM 是用 ```grid-column: main``` 来定位的。 70 | 71 | > The final piece of the puzzle is that if the start line is a named ident (which ours is) and the end line is missing, then the end line is set to the same named ident. In [the specification for placement shorthands we can read](https://www.w3.org/TR/css-grid-1/#placement-shorthands): 72 | 73 | 最后的难题是:如果我们设置了起始位置,但是缺失结束位置,那么结束位置将和起始位置共用一个值。[在规范中有关简写我们可以发现](https://www.w3.org/TR/css-grid-1/#placement-shorthands): 74 | 75 | (**译者注:如果用户这么设置```grid-column: full```**,等价于``` grid-column-start: full;grid-column-end: full;```) 76 | 77 | > “[when using ```grid-row``` and ```grid-column``` shorthands] … When the second value is omitted, if the first value is a , the ```grid-row-end/grid-column-end``` longhand is also set to that ; otherwise, it is set to ```auto```.” 78 | 79 | > "当使用 ```grid-row``` 和 ```grid-column``` 简写时" ... 当第二值省略时,如果设置了第一个值,那么 ```grid-row-end/grid-column-end``` 将复用第一个的值;否则,将默认为 ```auto```。 80 | 81 | > This gives us a ```grid-column-end``` of ```main``` which will give us the end edge of the area called ```main``` thus our item stretches right across the grid covering all the column tracks between ```main-start``` and ```main-end```. 82 | 83 | ```grid-column-end: main```,指定了结束边界也是被称为 ```main``` 的区域,因此,我们项目中的元素横跨了 ```main-start``` 和 ```main-end``` 之间所有的区域。 84 | 85 | ![](https://rachelandrew.co.uk/perch/resources/implicit-named-lines.png) 86 | 87 | > You can see this in DevTools if you inspect the element ```grid-column-start``` and ```grid-column-end``` is ```main``` for the elements constrained by the column and ```full``` for elements constrained by the full width breakout. This is shown in the below screenshot of [this CodePen of the completed example](https://codepen.io/rachelandrew/pen/xdedMy). 88 | 89 | 通过开发者工具你可以看到,如果设置了 ```grid-column-start``` 和 ```grid-column-end``` 的值都是 ```main```,那么这个元素会受到限制,但是如果是 ```full``` 则不会受到限制。下面截图的展示了 [CodePen 完整示例效果](https://codepen.io/rachelandrew/pen/xdedMy)。 90 | 91 | ![](https://rachelandrew.co.uk/perch/resources/ff-devtools-main.png) 92 | 93 | > What this demonstrates is that when showing off a nice example it really is worth unpacking how the technique works. There is a lot to know about how line naming works, and by understanding it we can start to use this for more than just one technique. 94 | 95 | 这表明,在演示一个很好的示例时,它真正的价值:要理解时如何工作的。有很多需要你知道的,例如:如何命名,只有真正的理解它,我们才能更好的使用这项技术。 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /Published/CSS Grid Layout- A Quick Start Guide.md: -------------------------------------------------------------------------------- 1 | ## CSS Grid Layout: A Quick Start Guide 2 | ## CSS Grid 布局:快速入门指南 3 | 4 | > 原文地址: 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | How we approach layout on the web is changing, and at the forefront of that change is [CSS Grid Layout](https://www.w3.org/TR/css-grid-1/). This updated quick start guide will skip the details and nuances, instead helping you get stuck in, right now. 10 | 11 | 我们如何处理 web 布局正在发生的变化,最前沿的变化是 [CSS Grid](https://www.w3.org/TR/css-grid-1/)。这篇快速入门指南将会跳过细节,让你避免陷入困境,让我们开始。 12 | 13 | ### Your Browser 14 | 15 | ### 浏览器 16 | 17 | CSS Grid Layout (known to its friends as “Grid”) has come on leaps and bounds in the last year, and as such you’ll find [browser support](http://caniuse.com/#feat=css-grid) for it pretty solid nowadays. 18 | 19 | CSS Grid 布局(有人称它为 “Grid”)去年的发展突飞猛进,因此,现在你会发现浏览器已经有了很好的[支持](http://caniuse.com/#feat=css-grid)。 20 | 21 | ![](https://cms-assets.tutsplus.com/uploads/users/30/posts/27238/image/caniuse-grid.png) 22 | 23 | ### Setting up a Grid 24 | 25 | ### 设置 Grid 26 | 27 | Grid allows us to arrange elements on a page, according to regions created by guides. 28 | 29 | Grid 允许我们根据网格线在页面上布置元素。 30 | 31 | #### Terminology 32 | 33 | #### 术语 34 | 35 | At their simplest these guides, or *grid lines*, frame horizontal and vertical *grid tracks*. Grid tracks serve as *rows* and *columns*, with *gutters* running between them. Where horizontal and vertical grid tracks intersect, we’re left with *cells*, much like we use with tables. These are all important terms to understand. 36 | 37 | 最简单就是网格,也称为*网格线*,水平和垂直的*网格轨道*框架。网格轨道被它们之间的*间隙*分成了*行*和*列*。在网格轨道水平和垂直方向交叉的地方我们得到了*单元格*,这有点像 table。这些都是很重要的术语。 38 | 39 | In the image below you’ll see a demo grid, showing: 40 | 41 | 42 | 1. grid lines 43 | 1. columns 44 | 1. rows 45 | 1. cells 46 | 47 | 下面的图片中你将会看到一个 demo,其中展示了: 48 | 49 | 1. 网格线 50 | 1. 列 51 | 1. 行 52 | 1. 单元格 53 | 54 | ![](https://cms-assets.tutsplus.com/uploads/users/30/posts/27238/image/grid-terms-lines-rows-columns-cells-3.svg) 55 | A basic grid, highlighting grid lines, columns, rows, and cells 56 | 基本的 Grid 布局,高亮的是网格线、列、行和单元格 57 | 58 | For a graphic layout, it might look more familiar if we use exactly the same grid, but part some tracks to give us gutters between content areas. 59 | 60 | 图解中的布局,如果我们使用完全相同的网格,看起来有点类似,但是网格中的轨道可以在内容之间设置留白。 61 | 62 | 1.gutters 63 | 64 | 1.间隙 65 | 66 | ![](https://cms-assets.tutsplus.com/uploads/users/30/posts/27238/image/grid-terms-gutters-2.svg) 67 | The same grid, but this time bearing a striking resemblance to the Finnish flag 68 | 同样的网格布局,但是这次和芬兰国旗非常相似 69 | 70 | There’s one last term we need to clarify before moving on: 71 | 72 | 在我们继续之前有最后一个术语必须清楚: 73 | 74 | 1.grid area 75 | 76 | 1.网格区域 77 | 78 | ![](https://cms-assets.tutsplus.com/uploads/users/30/posts/27238/image/grid-terms-area-1.svg) 79 | One of the many possible grid areas on our demo grid 80 | 演示中众多网格区域的一部分 81 | 82 | A *grid area* is any part of our grid fenced in by four grid lines; it can comprise any number of grid cells. 83 | 84 | *网格区域*是有四条网格线围绕出来的任何区域;它可以包含任意多个单元格。 85 | 86 | Time to build this grid in the browser! Let’s begin with some markup. 87 | 88 | 是时候开始在浏览器中实现 grid 布局了!让我们开始吧。 89 | 90 | ### Grid Markup 91 | 92 | ### Grid 标记 93 | 94 | To recreate the grid above, we need a container element; anything you like: 95 | 96 | 为了实现上面的 grid 布局,我们需要一个容器;只要你喜欢,任何标记都可以: 97 | 98 | ```html 99 |
100 | 101 |
102 | ``` 103 | 104 | In it we’re going to place nine child elements. 105 | 106 | 在这个容器中我放置了 9 子元素: 107 | 108 | ```html 109 |
110 |
1
111 |
2
112 |
3
113 |
4
114 |
5
115 |
6
116 |
7
117 |
8
118 |
9
119 |
120 | ``` 121 | 122 | Fork [this starter pen](http://codepen.io/tutsplus/pen/YGWpVJ/) if you want to follow along. I’ve added some basic styles to visually differentiate each grid item. 123 | 124 | 如果,你像看效果,可以看 [codepen 的 demo](http://codepen.io/tutsplus/pen/YGWpVJ/) 。我给每个元素都添加了一些基本的样式,为了让它们之间看起有区别。 125 | 126 | ### Grid Rules 127 | 128 | ### Grid 规则 129 | 130 | Firstly we need to declare that our container element is a grid using a new value for the ```display``` property: 131 | 132 | 首先,我们需要用 ```display``` 一个新的属性把容器定义为 grid: 133 | 134 | ```css 135 | .grid-1 { 136 | display: grid; 137 | } 138 | ``` 139 | 140 | Right, that was easy. Next we need to define our grid, by stating how many grid tracks it will have, both horizontally and vertically. We do that with the ```grid-template-columns``` and ```grid-template-rows``` properties: 141 | 142 | 对,就这么简单。接下来我们需要定义我们的 grid,为了决定在水平和垂直方向分别有几个网格轨道,我们可以使用 ```grid-template-columns``` 和 ```grid-template-rows``` 两个属性: 143 | 144 | ```css 145 | .grid-1 { 146 | display: grid; 147 | grid-template-columns: 150px 150px 150px; 148 | grid-template-rows: auto auto auto; 149 | } 150 | ``` 151 | 152 | You’ll notice three values for each. The values for ```grid-template-columns``` state that “all three columns should be 150px wide”. The three values for ```grid-template-rows``` state something similar. Each one would actually be ```auto``` by default, taking height from the content, but we’ve stated them here in order to clearly visualise what’s going on. 153 | 154 | 你会注意到以上两个属性分别有三个值。```grid-template-columns``` 的值代表“三列都是 150px 宽”。```grid-template-rows``` 的值有点类似。每个值默认情况下都是 ```auto```,高度根据内容来计算,但是我们还是明确的说明了,为了更清楚的知道会发生什么。 155 | 156 | So what do we have now? 157 | 158 | 现在你想看看是什么效果吗? 159 | 160 | [Codepen Demo](https://codepen.io/tutsplus/pen/WGxorA) 161 | 162 | Each of our items has been automatically assigned a grid area in chronological order. It’s not bad, but we’re missing gutters. Time to fix that. 163 | 164 | 每个元素都自动的按照顺序分配空间。这样很好,但是,我们没有留白。现在让我们解决它。 165 | 166 | ### Mind the Gap 167 | 168 | ### 关注 Gap 169 | 170 | Grid comes with a purpose-made solution for declaring gutter measurements. We can use ```grid-column-gap``` and ```grid-row-gap```, or the shorthand ```grid-gap``` property. 171 | 172 | Grid 有专有的属性解决留白大小的问题。我们可以用属性 ```grid-column-gap``` 和 ```grid-row-gap```,简称 ```grid-gap```。 173 | 174 | Let’s add a fixed gutter of 20px to our ```.grid-1``` element. 175 | 176 | 让我们给 ```.grid-1``` 元素添加一个固定的 20px 的留白。 177 | 178 | ```css 179 | .grid-1 { 180 | display: grid; 181 | grid-template-columns: 150px 150px 150px; 182 | grid-template-rows: auto auto auto; 183 | grid-gap: 20px; 184 | } 185 | ``` 186 | 187 | And now, we’re left with a nice, neat grid: 188 | 189 | 现在,我们得到一个整齐的网格布局: 190 | 191 | [Codepen Demo](https://codepen.io/tutsplus/pen/zKqLKy) 192 | 193 | ### Conclusion 194 | 195 | ### 总结 196 | 197 | That’s it, you’re up and running with Grid! Let’s recap the four essential steps: 198 | 199 | 200 | 1. Create a container element, and declare it ```display: grid```; 201 | 1. Use that same container to define the grid tracks using the ```grid-template-columns``` and ```grid-template-rows``` properties. 202 | 1. Place child elements within the container. 203 | 1. Specify the gutter sizes using the ```grid-gap``` properties. 204 | 205 | 就这些,你现在可以使用 Grid 了!让我们来概括下四个必要的步骤: 206 | 207 | 1. 创建一个容器并声明 ```display: grid```; 208 | 1. 在同一个容器上使用属性 ```grid-template-columns``` 和 ```grid-template-rows``` 声明网格轨道。 209 | 1. 在容器中放置子元素。 210 | 1. 使用属性 ```grid-gap``` 设置留白的大小。 211 | 212 | In [the next part of this series](https://webdesign.tutsplus.com/tutorials/css-grid-layout-units-of-measurement-and-basic-keywords--cms-27259) we’ll take a deeper look at Grid’s syntax, explore flexible layouts, the *fr* unit, the ```repeat()``` function, and take our simple grid much further. See you there! 213 | 214 | 在[这个系列接下来的章节中](https://webdesign.tutsplus.com/tutorials/css-grid-layout-units-of-measurement-and-basic-keywords--cms-27259)我们将深入探讨 Grid 的语法,探索弹性布局:*fr*、```repeat()``` 方法并让我们的网格布局更进一步。到时见! 215 | 216 | 217 | 218 | -------------------------------------------------------------------------------- /Published/typescript/What’s-New-in-TypeScript-3.9.md: -------------------------------------------------------------------------------- 1 | # What’s New in TypeScript 3.9? 2 | 3 | ## TypeScript 3.9 中的新特性 4 | 5 | > 原文地址: 6 | **本文版权归原作者所有,翻译仅用于学习。** 7 | 8 | --------- 9 | 10 | ![](https://miro.medium.com/max/1400/1*b69tQHlar0EXAv39HKsgTw.jpeg) 11 | 12 | TypeScript just released its second release for the year on May 12. It’s version 3.9, which is now the stable version. In this article, I’m going to point out some of the new and exciting features of TypeScript 3.9. 13 | 14 | 5 月 12 号 TypeScript 发布了今年的第二个版本 v3.9。这是一个稳定版本。这篇文章,我将会介绍 v3.9 中引入的新功能。 15 | 16 | ## @ts-expect-error 17 | 18 | Let’s take an example where we define a function that takes two strings as parameters. 19 | 20 | 我们先看以下的示例,我们定义了一个有两个字符串参数的函数。 21 | 22 | ```ts 23 | printName(firstName: string, lastName: string) { 24 | console.log(firstName); 25 | console.log(lastName); 26 | assert(typeof firstName === "string"); 27 | assert(typeof lastName === "string"); 28 | } 29 | ``` 30 | 31 | Usually, TypeScript users will get a helpful red squiggle and an error message when they misuse this function, and JavaScript users will get an assertion error. But what will happen if we write a unit test to check this functionality? 32 | 33 | 通常,如果,TypeScript 用户错误的使用这个函数,他们会得到一个非常有用的错误提示信息,然而,JavaScript 用户将会得到一个断言错误信息。但是,如果我们为这个函数编写测试用例会发生什么呢? 34 | 35 | ``` 36 | expect(() => { 37 | printName(1234, 5678); 38 | }).toThrow(); 39 | ``` 40 | 41 | If our test is written in TS, it’ll throw an error like this: 42 | 43 | 如果,我们的测试用 TS 语法,将会抛出以下的错误信息: 44 | 45 | ``` 46 | printName(1234, 5678); 47 | // ~~~ 48 | // error: Type ‘number’ is not assignable to type ‘string’. 49 | ``` 50 | 51 | As a solution for this, version 3.9 of TypeScript brings a new feature: `// @ts-expect-error` comments. If we put this comment before a code line as a prefix, TypeScript won’t report the error. But If there’s no error, TypeScript will inform that there’s an unnecessary comment in our code, like this: `Unused '@ts-expect-error' directive`. 52 | 53 | 为了解决这种问题,TypeScript 3.9 引入了新的功能:`// @ts-expect-error` 注释。如果,我们把这个注释放在代码行前面,TypeScript 就会忽略这个错误。但是,如果没有错误,TypeScript 就会提示代码中有不必要的注释,比如:`Unused '@ts-expect-error' directive`。 54 | 55 | Another use of this `//@ts-expect-error` comment is we can use it as a suppression comment. `// @ts-ignore` is an existing comment that’s used as a suppression comment — the main difference between these two is `// @ts-ignore` will inform if the following line is error-free. 56 | 57 | 我们还可以把 `// @ts-expect-error` 做为抑制注释使用。`// @ts-ignore` 是一个早已存在的抑制注释。两者之间的区别是:~~`// @ts-ignore` 在接下来的代码行中没有错误会提示~~ 58 | 59 | (*译者注:两者之间的区别是:两者都会忽略接下来代码行中的错误,只是在没有错误的情况下 `// @ts-ignore` 不会提示:**有不必要的注释***) 60 | 61 | ## Speed Improvements 62 | ## 速度提升 63 | ![](https://miro.medium.com/max/1400/0*6LoGdsn6xLXdu2Rl) 64 | 65 | With the earlier versions of TypeScript, there were many complaints about the compilations and editing speed with packages like Material-UI. 66 | 67 | TypeScript 早期版本中使用类似 Material-UI 这种库存在很多的编译速度问题。 68 | 69 | With the new release, the TypeScript developing team has addressed this issue by optimizing several pathological cases involving large unions, intersections, conditional types, and mapped types and reduced 40% of the time in the Material-UI compilation. Also, they’ve worked on file renaming functionalities regarding editors like Visual Studio Code. 70 | 71 | 新版本中,TypeScript 开发团队针对这类问题优化了大型联合、交叉、条件和映射类型,为 Material-UI 的编译节省了 40% 的时间。同时,他们还致力于有关 Visual Studio Code 等编辑器的文件重命名功能。 72 | 73 | ## CommonJS Auto-Imports in JavaScript 74 | 75 | ## 自动引入 CommonJS 模块 76 | 77 | Previously, TypeScript always expected ECMAScript-style imports regardless of your file type. But most developers are using the CommonJS-style `require();` import instead of the ECMAScript-style modules when writing JavaScript files. 78 | 79 | 之前的版本,TypeScript 不管文件是什么类型只能引入 ECMAScript-style 的文件。但是,很多开发者还是使用 CommonJS-style `require();`,而没有使用 ECMAScript-style 的导入功能。 80 | 81 | ECMAScript style: 82 | 83 | ```js 84 | import * as fs from "fs"; 85 | ``` 86 | 87 | CommonJS style: 88 | 89 | ```js 90 | const fs = require("fs"); 91 | ``` 92 | 93 | With the latest release, TypeScript now automatically detects the types of imports you’re using to keep your file’s style clean. 94 | 95 | 最新版本中,TypeScript 会自动检测导入的类型用于保证代码的整洁。 96 | 97 | ## Improvements in Inference and Promise.all 98 | 99 | ## 改善类型推断和 Promise.all 100 | 101 | In version 3.7, TypeScript came up with an update to the declarations of functions like `Promise.all` and `Promise.race`. But there were a few complications with this update since it caused regressions when mixing in values with `null` or `undefined`. An example is given below. 102 | 103 | TypeScript v3.7 中更新了 `Promise.all` 和 `Promise.race` 的声明。但是,这次更新也带来了一些问题,因为,在同 `null` 或者 `undefined` 混合使用时会引起编译报错。下面通过示例演示一下: 104 | 105 | ```ts 106 | interface Bird{ 107 | fly(): void 108 | } 109 | interface Fish{ 110 | singKissFromARose(): void 111 | } 112 | async function animalBehaviours(birdBehaviour: Promise, fishBehaviour: Promise) { 113 | let [bird, fish] = await Promise.all([birdBehaviour, fishBehaviour]); 114 | bird.fly(); 115 | // ~~~~ 116 | // Object is possibly ‘undefined’. 117 | } 118 | ``` 119 | 120 | Although `fishBehaviour` is the one containing `undefined`, it somehow has affected the `birdBehaviour` to include `undefined` as well. So this issue is also fixed with the 3.9 release of TypeScript. 121 | 122 | 尽管,`fishBehaviour` 可能是 `undefined`,但是,还是会影响到 `birdBehaviour`。这种问题在 v3.9 中修复了。 123 | 124 | ## Code Actions Preserve New Lines 125 | 126 | ## 代码重构保留空白行 127 | 128 | ![](https://miro.medium.com/max/1400/0*eAJT01XxXK0PLh0w) 129 | 130 | Many developers like to keep new lines between separate functionality code lines, but earlier TypeScript code refactoring didn’t preserve new lines. It almost removed all blank lines between code lines. With the latest release, TypeScript has worked on this issue, and now TypeScript code refactoring is preserving new lines in your code after running a refactor. 131 | 132 | 很多开发者喜欢在每个功能代码块之间保留空白行,但是,早期的 TypeScript 代码重构不会保留空白行。它会移除所有的空白行。最新版本中,TypeScript 已经修复了这种问题,代码重构后会保留空白行。 133 | 134 | (*译者注:这个地方的提到的代码重构是指一些 IDE 附带的一些代码重构功能,比如:[VS Code](https://code.visualstudio.com/docs/editor/refactoring)*) 135 | 136 | ## Quick Fixes for Missing Return Expressions 137 | 138 | ## 快速修复缺失的 return 语句 139 | 140 | Sometimes we might forget to return the value from a function at the end of that function. So TypeScript is now providing a quick fix solution to add missing `return` statements. 141 | 142 | 有时候,我们会忘记在函数结束时返回对应的值。现在,TypeScript 提供快速修复的方案,自动添加 `return` 语句。 143 | 144 | ## Uncalled Function Checks in Conditional Expressions 145 | 146 | ## 在条件语句中检查未调用的函数 147 | 148 | After version 3.7, TypeScript checked for uncalled function checks in `if` conditions and reported errors. With the 3.9 release, this error-checking has further extended to ternary conditional statements as well. 149 | 150 | 在 v3.7 之后,TypeScript 会检查 `if` 语句中未调用的函数并提示错误。在 v3.9 中,这一功能也支持三元运算符了。 151 | 152 | ## Additional Minor Changes 153 | 154 | ## 其它的改变 155 | 156 | Other than these changes, there are some minor changes like: 157 | 158 | - `}` and `>` are now invalid JSX text characters 159 | - `export *` is retained 160 | - Getters and setters are no longer enumerable 161 | - Type parameters which extend `any` are no longer acting as `any` 162 | - More `libdom.d.ts` refinements 163 | 164 | 相比以上的改变,还有一些微不足道的改变 165 | 166 | - 在 JSX 中 `}` 和 `>` 被认为无效 167 | - `export *` 被保留 168 | - Getter 和 Setter 不在可枚举 169 | - Type parameters which extend `any` are no longer acting as `any` 170 | - `libdom.d.ts` 的改进 171 | 172 | Overall, these are the changes that we can see in the latest release of TypeScript. So if you’re a TypeScript lover, it’s always good to keep up to date with new [updates ](https://devblogs.microsoft.com/typescript/announcing-typescript-3-9)that can make your coding life easier. 173 | 174 | 总的来说,这些改变在最新版本中都可以看到。因此,如果你喜欢 TypeScript,保持更新到[最新的](https://devblogs.microsoft.com/typescript/announcing-typescript-3-9)版本,可以让编写代码更高效。 -------------------------------------------------------------------------------- /Published/Breaking Out With CSS Grid Layout.md: -------------------------------------------------------------------------------- 1 | ## Breaking Out With CSS Grid Layout 2 | ## 利用 CSS Grid 打破布局的边界 3 | 4 | > 原文地址: 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | > A while back I shared [a simple technique](https://cloudfour.com/thinks/breaking-out-with-viewport-units-and-calc/) for allowing certain elements to fill the full viewport width from within a fixed-width container: 10 | 11 | 早些时候,我分享了[一项简单的技术](https://cloudfour.com/thinks/breaking-out-with-viewport-units-and-calc/),允许某些元素即便在固定宽度的容器中,它还是会铺满全屏。 12 | 13 | ```css 14 | .u-containProse { 15 | max-width: 40em; 16 | margin-left: auto; 17 | margin-right: auto; 18 | } 19 | 20 | .u-release { 21 | margin-left: calc(-50vw + 50%); 22 | margin-right: calc(-50vw + 50%); 23 | } 24 | ``` 25 | 26 | > As concise as this technique was, it had [one big, dumb caveat](https://cloudfour.com/thinks/breaking-out-with-viewport-units-and-calc/#one-big-dumb-caveat): On some platforms, you’d see a horizontal scrollbar unless you set ```overflow-x``` to ```hidden``` on the ```body``` element. 27 | 28 | 这项技术非常简单,但是它有个隐藏的bug:在一些平台上,你将会看到有一个水平滚动条,除非你在 ```body``` 上设置 ```overflow-x: hidden```。 29 | 30 | > It’s now a year later and every modern browser supports (or [will soon support](https://wpdev.uservoice.com/forums/257854-microsoft-edge-developer/suggestions/6514853-update-css-grid)) [CSS Grid Layout](http://jensimmons.com/post/feb-27-2017/learn-css-grid) (hooray!!). I thought it might be fun to reexamine this problem with a fancy set of modern layout tools at our disposal. 31 | 32 | 一年以后的现在,每个现代浏览器都已经支持(或者[准备支持](https://wpdev.uservoice.com/forums/257854-microsoft-edge-developer/suggestions/6514853-update-css-grid))[CSS Grid](http://jensimmons.com/post/feb-27-2017/learn-css-grid)(万岁!)。我想用现在的布局技术重新审视这个问题会很有趣。 33 | 34 | ### Our Goal 35 | 36 | ### 我们的目的 37 | 38 | > In [my last article about Grid](https://cloudfour.com/thinks/first-css-grid-layout/), I mentioned how important it was to approach layout problems with fresh eyes so you aren’t misguided by years of workarounds and CSS muscle memory. So let’s review what we hope to accomplish from a *design* standpoint: 39 | 40 | 在[我上篇有关 Grid 的文章中](https://cloudfour.com/thinks/first-css-grid-layout/),我提到用新的思路解决布局问题是多么的重要,所以不要被思维定势影响你。让我们回顾一下我们希望通过设计的角度考虑问题: 41 | 42 | > - We want to limit the width of prose content [to promote readability](http://practicaltypography.com/line-length.html). 43 | > - But sometimes, the reader may benefit from an element being full-width. For example, a nice photograph or a detailed chart. 44 | 45 | - 我们希望文章的内容有一个限定的宽度,这会[有利于阅读](http://practicaltypography.com/line-length.html)。 46 | - 但是有时候,读者会从一个全屏的元素上得到收益。例如,一个漂亮的图片或者详细的图表。 47 | 48 | ![](https://29comwzoq712ml5vj5gf479x-wpengine.netdna-ssl.com/wp-content/uploads/2017/05/grid-sketch-r3.jpg) 49 | 50 | > If we sketch this out, we can see that what we’re really after isn’t so much a fixed-width container with margins… it’s more of a three-column layout, with a main column flanked by two gutters. Most content will fill only the middle portion, but our super-fancy visual content will span all three. 51 | 52 | 如果我们把我们的想法勾画出来,我们看到,这并不是一个真正固定宽度的布局,它更像是一个三列布局,中间是主要内容,两边是留白。主要的内容将在中间显示,但是我们的视觉修饰的部分将布满全屏。 53 | 54 | > With that in mind, it’s time to write some CSS! 55 | 56 | 考虑到这一点,是时候开始写 CSS 了! 57 | 58 | ### Column Like You Sees ‘Em 59 | 60 | ### 如你所见 61 | 62 | > Let’s start by styling our containing element, which will wrap the article content: 63 | 64 | 让我们开始写容器元素的样式,它将包含主要文章内容: 65 | 66 | ```css.Prose { 67 | display: grid; 68 | grid-template-columns: 69 | [full-start] minmax(1em, 1fr) 70 | [main-start] minmax(0, 40em) [main-end] 71 | minmax(1em, 1fr) [full-end]; 72 | } 73 | ``` 74 | 75 | > Here we’ve defined three columns. The first and last are our gutters, with a minimum size of ```1em``` but the ability to stretch to fill one unit of available space. Between them is our main content column, which can stretch to a maximum width of ```40em```. 76 | 77 | 我们定义了三列。第一和最后一个就是我们的留白,最小宽度是 ```1em```,但是,如果有更多的可用空间它们是可以伸缩的。在它们之间就是主要内容那一列,它的最大宽度是 ```40em```。 78 | 79 | ![](https://29comwzoq712ml5vj5gf479x-wpengine.netdna-ssl.com/wp-content/uploads/2017/05/grid-lines.svg) 80 | 81 | > We’ve also assigned names (in brackets) to [the dividing lines between columns](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Layout_using_Named_Grid_Lines). These are entirely optional, but they’ll make the rest of our styles easier to read, write and maintain. 82 | 83 | 我们给[每一列之间分割线定义名字](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Layout_using_Named_Grid_Lines)(括号内的内容)。这都是可选的,但是,这会让你的代码更容易读、写和维护。 84 | 85 | > Next, we instruct all child elements of ```Prose``` to neatly occupy our ```main``` column: 86 | 87 | 接下来,我们让 ```Prose``` 所有的元素都占据 ```main``` 那一列。 88 | 89 | ```css 90 | .Prose > * { 91 | grid-column: main; 92 | } 93 | ``` 94 | 95 | > And finally, we make a class for elements we’d like to span the full container width: 96 | 97 | 最后,我们给那些我们想让它占据全屏元素设置一个类: 98 | 99 | ```css 100 | .Prose-splash { 101 | grid-column: full; 102 | } 103 | ``` 104 | 105 | > And that’s it! Here’s the end result, no ```overflow-x``` or negative margins required: 106 | 107 | 就是这样!这是最后结果,没有 ```overflow-x```,没有负 ```margin```: 108 | 109 | [![](https://29comwzoq712ml5vj5gf479x-wpengine.netdna-ssl.com/wp-content/uploads/2017/05/grid-breakout-demo-1-r2-opt.gif)](https://codepen.io/tylersticka/pen/bWvaxP/left?editors=1100) 110 | 111 | > But that’s not all… 112 | 113 | 但,这不是全部 114 | 115 | ### Cool New Tricks 116 | 117 | ### 更酷更新的技巧 118 | 119 | > Because full-width elements are based on their container and not the viewport, this technique works great for asymmetric layouts: 120 | 121 | 因为全宽元素是基于它的容器,而不是基于可视窗口,所以这项技术对非对称布局非常有用: 122 | 123 | [![](https://29comwzoq712ml5vj5gf479x-wpengine.netdna-ssl.com/wp-content/uploads/2017/05/grid-breakout-demo-2-r2.png)](https://codepen.io/tylersticka/pen/wdmymG?editors=1100) 124 | 125 | > This also means full-width elements may reliably align with content above and below, which provides some fun opportunities for styling special elements like block-quotes or code blocks: 126 | 127 | 也就是说全宽元素可以跟上下的内容完全对其,这对于一些特定的元素,比如:引用内容和代码宽提供更有趣的可能性: 128 | 129 | [![](https://29comwzoq712ml5vj5gf479x-wpengine.netdna-ssl.com/wp-content/uploads/2017/05/grid-breakout-demo-3-r2.png)](https://codepen.io/tylersticka/pen/KmoQYy/left?editors=1100) 130 | 131 | > We can also consider utilizing the gutter space in novel ways that previously required much more hackery: 132 | 133 | 我们也可以考虑用新颖的方式利用留白部分,这在以前需要更多的 css hack 技术: 134 | 135 | [![](https://29comwzoq712ml5vj5gf479x-wpengine.netdna-ssl.com/wp-content/uploads/2017/05/grid-breakout-demo-4-r2.jpg)](https://codepen.io/tylersticka/pen/PmRRqb/left?editors=1100) 136 | 137 | ### Inevitable Downsides 138 | 139 | ### 缺点 140 | 141 | > While this technique has some really promising qualities, there are also some drawbacks to consider: 142 | 143 | 尽管这项技术非常好,但是还是有一些缺点需要考虑的: 144 | 145 | - You can’t ```float``` immediate children of an element with ```display: grid```. 146 | 147 | - 父级是 ```display: grid``` 的子元素不能使用 ```float```。 148 | 149 | - Grid is being adopted [very rapidly](http://caniuse.com/#feat=css-grid), but it’s still not as well supported as what I shared last year. 150 | 151 | - 虽然 Grid [正在接纳](http://caniuse.com/#feat=css-grid),但是在去年我分享的时候,它的支持情况并不是很好。 152 | 153 | - Many aforementioned benefits also apply to [using *:not() selectors instead](http://daverupert.com/2017/03/full-bleed-with-not/). 154 | 155 | - 上面的很多好处也适用 [ *:not() 选择器](http://daverupert.com/2017/03/full-bleed-with-not/)。 156 | 157 | > Those caveats may be deal-breakers for many, but I predict these sorts of techniques will grow more attractive as CSS Grid Layout becomes more and more prevalent. It seems only natural for our content to extend the composition of our interfaces. 158 | 159 | 对于这些警告很多人会比较在意,但是,我预测 CSS Grid 这些技术会越来越流行。 160 | 161 | > Special thanks to [Erik Jung](https://cloudfour.com/is/erik/) for his demo assistance and technical review of this article. 162 | 163 | 特别感谢 [Erik Jung](https://cloudfour.com/is/erik/) 提供的演示 Demo 和对这篇文章的技术审查。 164 | -------------------------------------------------------------------------------- /Published/Understanding the CSS Grid “Auto-Placement Algorithm” .md: -------------------------------------------------------------------------------- 1 | ## Understanding the CSS Grid “Auto-Placement Algorithm” 2 | ## 理解 CSS Grid 的 “自动排列算法” 3 | 4 | > 原文地址: 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | In one of our earlier introduction tutorials to CSS Grid we looked at [fluid columns and better gutters](https://webdesign.tutsplus.com/tutorials/css-grid-layout-units-of-measurement-and-basic-keywords--cms-27259). We learned that it isn’t necessary to specify exactly where we want to position our grid items; if we declare our grid’s properties, Grid will slot our items in according to its auto-placement algorithm. 10 | 11 | 在早期的教程中我们讨论过[fluid columns 和 better gutters](https://webdesign.tutsplus.com/tutorials/css-grid-layout-units-of-measurement-and-basic-keywords--cms-27259)。我们知道在定位排列元素的时候并不需要严格按照文档顺序逻辑排列;如果,我们声明了 Grid 的属性,它的元素安会根据自己的算法自动排列。 12 | 13 | In this tutorial we’ll take a look at how that algorithm goes about its work and how we can influence it. 14 | 15 | 在这篇教程中,我们会探讨自动排列算饭是如何工作的,我们如何控制排列算法。 16 | 17 | #### Setup 18 | 19 | #### 设置 20 | 21 | If your browser isn’t setup to support Grid you’ll need to sort that out to follow along. Read this: 22 | 23 | 如果,你的浏览器未开启对 Grid 的支持,你需要开启它。看看这个: 24 | 25 | [DEMO](https://webdesign.tutsplus.com/tutorials/css-grid-layout-quick-start-guide--cms-27238) 26 | 27 | ### It Started With a Grid 28 | 29 | ### 从 Grid 开始 30 | 31 | Here’s a demo grid to kick things off; it’s a container which we’ve declared to be ```display: grid```; and holds eighteen child elements. We’ve stated that it should have five columns, each of equal width, at least the same amount of rows, and a narrow gutter all round of 2px. 32 | 33 | 从一个 Grid 的演示开始;这个容器我们声明了 ```display: grid```;并且它有 18 子元素。容器有 5 列并且是等宽的,同样也有 5 行,每个元素之间还有 2px 的留白。 34 | 35 | ```css 36 | grid-template-columns: repeat(5, 1fr); 37 | grid-template-rows: repeat(5, 1fr); 38 | grid-gap: 2px; 39 | ``` 40 | 41 | [DEMO](https://codepen.io/tutsplus/pen/VKorxp) 42 | 43 | So far so good, and you can see that Grid has taken our eighteen items and pushed them in, working from the top left, moving across to the right, then moving down row by row. This behaviour is much like the way floats work. 44 | 45 | 目前为止没什么问题,你可以看到 Grid 容器中有 18 个元素,它们从左上角开始,向右、向下自动排列。这种行为有点类似 float。 46 | 47 | **Note**: the left-to-right behaviour would be reversed if we were dealing with a ```direction: RTL;``` layout. 48 | 49 | **注意**:如果,我们设置了 ```direction: RTL;``` 就会变成自右向左。 50 | 51 | #### Throwing a Spanner in the Works 52 | 53 | #### 从中作梗 54 | 55 | That’s all nice and neat, but let’s see what happens when our items don’t fit so perfectly. To ```.item-7``` we’ll add some rules to make it bigger by spanning two columns and two rows: 56 | 57 | 非常漂亮、整齐,但是,假如有个元素特别处理后会发生什么呢?给 ```.item-7``` 添加一些规则让它变大占用两行两列。 58 | 59 | ```css 60 | .item-7 { 61 | background: #e03f3f; 62 | grid-column: span 2; 63 | grid-row: span 2; 64 | } 65 | ``` 66 | 67 | How does that look now? 68 | 69 | 让我们看看它如何工作的? 70 | 71 | [DEMO](https://codepen.io/tutsplus/pen/XjvVgp) 72 | 73 | Not too bad! ```.item-7``` fills up more space, so ```.item-8``` and ```.item-9``` are positioned further over. ```.item-10``` then looks to see if there’s a vacant space next to ```.item-9```, and when it sees there isn’t it moves *down* a row and starts again on the far left. The other items continue to tuck in in the same way. 74 | 75 | 不算太糟糕!```.item-7``` 占用了更多的空间,因此,```.item-8``` 和 ```.item-9``` 被挤压到后面了。这时 ```.item-10``` 会先看一下 ```.item-9``` 后面是否有足够的空间,如果没有它就会向*下*移动到另外一行从左边开始排列。其它的元素也遵循同样的规则。 76 | 77 | But wait, what if we also make ```.item-9``` a little overweight? 78 | 79 | 但是等等,如果我们让 ```.item-9``` 也变大后会怎么样呢? 80 | 81 | [DEMO](https://codepen.io/tutsplus/pen/ORKzzG) 82 | 83 | Now it gets interesting; ```.item-9``` no longer fits into the column at the end so it’s pushed down to the next row. As it can’t fit in anything beyond ```.item-7``` it stays put. ```.item-10```, you might imagine, would tuck itself in underneath ```.item-6``` again, but, if you remember, it searches for a vacant column, then failing that it moves *down a row* and shunts across to the left again. This is an important concept to grasp. 84 | 85 | 现在有趣的事情发生了;```.item-9``` 不再是排在列的最后了,它被挤压到下面一行了。因为在 ```.item-7``` 之后没有足够的空间了。对于 ```.item-10``` 你想应该还是会在 ```.item-6``` 下面,但是,你要记住,它会搜索可用的空间,这时就会移动到*下一列*,再次回到了左边。这是一个非常重要的概念。 86 | 87 | ### Say “Hello” to grid-auto-flow 88 | 89 | ### 介绍 grid-auto-flow 90 | 91 | If you look at the previous demo you’ll see that ```.item-18```, upon failing to find space next to ```.item-17```, has moved down a row. We only actually defined five rows, but Grid has assumed we’ll want another row tacking on. This is owing to ```grid-auto-flow```, which belongs to the grid element, and whose default value is ```row```. We can change this value to ```column``` if we want, which would totally alter the way our grid looks: 92 | 93 | 如果,你看上一个 demo 会发现 ```.item-18``` 在 ```.item-17``` 后面没有找到足够的空间,移动到了下一行。我们仅仅定义了五行,但是 Grid 会认为需要更多的空间。这是由 Grid 容器上属性 ```grid-auto-flow``` 决定的,它的默认值是 ```row```,我们可以把它的值设置成 ```column```,这样整个 Grid 看起来就变了: 94 | 95 | [DEMO](https://codepen.io/tutsplus/pen/QKeQWE) 96 | 97 | 98 | This looks *sort of* similar, but you’ll notice that our items have slotted in top left, then moved down to fill each row, then moved across to the second column and so on. So now when an item is too big for its boots, the following item searches for the next vacant row space, then failing that shifts over to the next column. 99 | 100 | 看起来和*排序*类型,但是,你会注意到所有的元素都是从左上角开始排列的,然后向下填满每一个行,在移动到第二列,以此类推。因此,假如一个元素太大,那么它会向下一行搜索空间,如果下一行没有足够的空间,那么它就会占用下一列的空间。 101 | 102 | ### Dense Makes Sense 103 | 104 | ### 体验 Dense 105 | 106 | We can add another keyword to our ```grid-auto-flow``` property, and it’s possibly my favourite CSS keyword to date: ```dense```. Its default counterpart is ```sparse``` (my second favourite). Let’s do the following: 107 | 108 | 我们可以在属性 ```grid-auto-flow``` 中添加一个我最喜欢的 CSS 关键字:```dense```。它的默认值是 ```sparse```(我也很喜欢)。让我们看看会发生什么: 109 | 110 | ```css 111 | grid-auto-flow: row dense; 112 | ``` 113 | 114 | **Note**: we don’t need to include ```row``` here, it’s implied, but this highlights how the syntax works. 115 | 116 | **注意**:我们没有必要设置 ```row```,它是默认的,但是,为了演示语法我这里也写了。 117 | 118 | [DEMO](https://codepen.io/tutsplus/pen/ORKQmM) 119 | 120 | 121 | Now our friend ```.item-10```, upon finding that there’s no space next to ```.item-9```, first checks what’s *above* before moving to another row. 122 | 123 | 现在,元素 ```.item-10``` 发现 ```.item-9``` 后面没有足够的空间,首先,它会先检查一下*上面*的空间,然后才会移动到下一行。 124 | 125 | Thanks to this change in the placement algorithm our items are now densely packed, which gives us a more efficiently filled grid. This does mean, however, that the visual layout doesn’t necessarily reflect the document source order, which may not always be helpful to the user. 126 | 127 | 多亏了这个改变,我们的元素在排列的时候更加紧凑,让我们的网格利用率更高。也就是说,视觉布局并不一定严格遵循文档流的顺序,当然,这对用户来说不一定就是好的。 128 | 129 | ### Conclusion 130 | 131 | ### 总结 132 | 133 | Let’s recap: 134 | 135 | 136 | 1. If we haven’t specifically defined an item’s location, Grid’s auto-placement algorithm will place it in the next available (and large enough) slot. 137 | 1. Where there’s no available slot in the current row, it will begin searching the following row, even if that leaves gaps. 138 | 1. We can switch this search order by altering ```grid-auto-flow``` from ```row``` to ```column```. 139 | 1. ```grid-auto-flow``` accepts a keyword to describe the “packing” approach. By default this value is ```sparse```, but we can alter this to ```dense``` which attempts to fill in all available gaps. 140 | 141 | 让我们概括一下 142 | 143 | 1. 如果,我们特别的声明某个元素,Grid 元素会自动的排列在下一个可用空间(足够大)。 144 | 1. 如果当前行没有足够空间,它会检索下一行,并且会把留白排除在外。 145 | 1. 我们可以通过设置 ```grid-auto-flow``` ```row``` 和 ```column``` 来切换不同的检索顺序。 146 | 1. ```grid-auto-flow``` 可以通过关键字来设置”包裹“的行为。默认值是 ```sparse```,但是,我们可以把值设置成 ```dense``` 这样元素就会尝试填充所有的有效空间。 147 | 148 | #### Useful Resources 149 | 150 | - [grid-auto-flow](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow) on MDN 151 | - [The grid-auto-flow property](https://www.w3.org/TR/css-grid/#grid-auto-flow-property) specification 152 | 153 | #### 更多有用资源 154 | 155 | - MDN 上的 [grid-auto-flow](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow) 156 | - [grid-auto-flow property](https://www.w3.org/TR/css-grid/#grid-auto-flow-property) 规范 157 |   -------------------------------------------------------------------------------- /Published/css/CSS-Scroll-Snap—How-It-Really-Works.md: -------------------------------------------------------------------------------- 1 | # CSS Scroll Snap — How It Really Works 2 | 3 | ## CSS Scroll Snap 的工作模式 4 | 5 | > 原文地址: 6 | **本文版权归原作者所有,翻译仅用于学习。** 7 | 8 | --------- 9 | 10 | Remember the days you needed JS to have a nice looking scrolling on your page (gallery, slide show etc.)? Say bye bye to JS and say hi to CSS Scroll Snap. 11 | 12 | 还记不记得,为了在页面上实现优雅的滚动效果(gallery, slide 等等)需要借助 JS 的那些日子?送走 JS,投入 CSS Scroll Snap 怀抱吧。 13 | 14 | ![](https://miro.medium.com/max/1400/1*p_Gok8n-msYcAwnIwows8Q.png) 15 | 16 | Long time ago, while CSS was on level 1, we’ve introduced with a property to scroll items and snap them to their container boundaries. But just Firefox had a support of this. But nowadays, we have **`FULL BROWSERS`** support. Let’s dive in and abandon the JS to make pure CSS scrolling job. 17 | 18 | 很久以前,当时 CSS 还处于第一阶段,我们就介绍过 CSS Scroll Snap,它可以让滚动的元素紧贴容器的边界。但是,只有 Firefox 支持。到了现在,**`所有的浏览器`**都得到了支持。我们来拥抱它,放弃 JS,实现纯 CSS 的滚动效果。 19 | 20 | ## What is it good for? 21 | ## 它有什么好处? 22 | 23 | Let’s say that we have to compare items on our website. We need an item to compare with a list of items. We don’t know the length of the list but we want to see them side by side with the main item. The list is long and have a scroll (let’s say on the X axis) and we want to see each item on the list by it’s full size and not part of it while scrolling. 24 | 25 | 假设,我们需要在页面上对比一些内容。我们需要某一个项目和一个列表中所有的项目一一对比。我们不知道列表的长度,但是,我们想把整个列表中的项目和需要对比的项目并排在一起。列表太长,需要滚动(假设是在 X 轴滚动),每当页面滚动时,我们想看到的是每个项目完整的尺寸,而不是一部分。 26 | 27 | Without this CSS property, if we’ll scroll the list, we need to be gentle with the scrolling and bring the item as close as we can to the boundaries of the container. But with this property, we just need to scroll it a just over the 50% and the browser will complete the scrolling till the position we wanted. 28 | 29 | 在没有这个 CSS 属性的情况下,如果,我们需要滚动列表,必须小心翼翼的,尽可能的让某一元素贴近容器的边界。但是,通过利用这个 CSS 属性,我们只需滚动元素的 50%,然后,剩下的交给浏览器处理就好。 30 | 31 | The best example will be if you’ll take your mobile device and scroll your homepage / list of apps to left, right, up or down a bit. The screen will slide to the next “page” (if you have) and you don’t need to fully scroll it. This is the same with this CSS property. 32 | 33 | 如果,你在的移动设备上,向左、向右、向上或者向下滚动一点。整个屏幕将会滚动到”下一页“(如果,有的情况下),你并不需要滚动整个页面。这将是这个属性最好的演示场景。 34 | 35 | ## Scroll snap type 36 | 37 | With CSS scroll type property, we are declaring that the **`container`** has a **`scrolling items`** and they need to be snap to the container boundaries. We can set the snap boundaries to *`none`, `x`, `y`, `block`, `inline` or `both`* 38 | 39 | 我们定义了 **`container`** 有一组 **`scrolling items`** 元素,通过设置 CSS Scroll Type 属性,让它们在滚动时紧贴容器的边界。我们有以下几个值可选:*`none`, `x`, `y`, `block`, `inline`* 或者 *`both`* 40 | 41 | ![](https://miro.medium.com/max/1400/1*jXyv4m4mrifE5N2D4z8gJA.png) 42 | 43 | [codepen.io](https://codepen.io/chaofix/pen/ae118504b6d7185cb9fcbe92ac9e97a7) 44 | 45 | The difference between the options is: 46 | 47 | 这些选项之间的区别是: 48 | 49 | - none — no snap 50 | 51 | none — 不需要紧贴边界 52 | 53 | - x — snap to x axis 54 | 55 | x — 紧贴 x 轴边界 56 | 57 | - y — snap to y axis 58 | 59 | y — 紧贴 y 轴边界 60 | 61 | - block — snap to block axis (logical properties) — vertical axis (Same as Y axis) 62 | 63 | block — 紧贴 block 轴(逻辑属性)— 垂直轴(等同于 Y 轴) 64 | 65 | - inline — snap to inline axis (logical properties) — horizontal axis (Same as X axis) 66 | 67 | inline — 紧贴 inline 轴(逻辑属性)— 水平轴(等同于 X 轴) 68 | 69 | - both — snap to x and y (or inline and block) axis 70 | 71 | both — 紧贴 x 和 y 轴 72 | 73 | ![](https://miro.medium.com/max/1400/1*jo7P0Nnc6C9mV6Z5caT-EA.png) 74 | 75 | There is another value that you need to declare on “scroll-snap-type” and you can choose between: 76 | 77 | scroll-snap-type 中还有另外一个属性需要设置,它的值包括: 78 | 79 | - mandatory 80 | - proximity 81 | 82 | To make it simple, mandatory will continue the scrolling as soon as the item will cross 51% of it’s width (on x / inline axis) or height (on y / block axis) while proximity need the item will scroll almost to it’s entire width or height. 83 | 84 | 简单的理解就是:值为 mandatory 时,当元素滚动到自身宽度(x/inline 轴)或者高度(y/block 轴)51% 时会自动的滚动,然后,值为 proximity 时,滚动需要接近整个元素的大小才会自动贴近边界。 85 | 86 | (*译者注:对比了两种效果,没看出有什么差别。[MDN](https://developer.mozilla.org/zh-CN/docs/Web/CSS/scroll-snap-type)上的翻译也比较难以理解😂*) 87 | 88 | The syntax (and values) for scroll-snap-type will be: 89 | 90 | scroll-snap-type 的语法和选值如下所示: 91 | 92 | ``` 93 | scroll-snap-type: none | [ x | y | inline | block ] [ mandatory | proximity ]; 94 | ``` 95 | 96 | Now that we know **`where`** the items will be snap to, we can define **`how`** they will snap with scroll-snap-align on the scrolling items 97 | 98 | 现在,我们知道了滚动元素**`在哪`**紧贴边界,接下来,我们可以在滚动元素上设置 scroll-snap-align 属性来决定**`如何`**紧贴边界。 99 | 100 | ## An iOS fix 101 | ## 修复 iOS 的问题 102 | 103 | Thanks to [Denys Mishunov](https://twitter.com/mishunov) that raised this fix for iOS users 104 | To support iOS users, just add the following line 105 | 106 | 感谢 [Denys Mishunov](https://twitter.com/mishunov) 为 iOS 用户提供了这个修复方案 107 | 108 | 为了支持 iOS 用户,只需添加下面一行代码 109 | 110 | ```css 111 | -webkit-overflow-scrolling: touch; 112 | ``` 113 | 114 | So the code will look like following: 115 | 116 | 因此,我们的代码应该是这个样子: 117 | 118 | ```css 119 | .foo { 120 | scroll-snap-type: x mandatory; 121 | -webkit-overflow-scrolling: touch; 122 | } 123 | ``` 124 | 125 | ## Scroll snap align 126 | 127 | We can define the snapping to `start`, `center` or `end` 128 | 129 | 我们可以定义滚动元素如何紧贴边界,有以下几个选择:`start`, `center` 或 `end` 130 | 131 | To do that, we need to define “scroll-snap-align” on the items themselves. 132 | 133 | 为了实现相应的效果,我们需要给每个滚动元素定义 “scroll-snap-align”。 134 | 135 | If we’ll define “scroll-snap-align: start” the items will be snap to the start of the container boundaries (according the axis we choose) 136 | 137 | 如果,我们给滚动的元素定义:“scroll-snap-align: start”,那么它将会紧贴容器的边界开始位置(根据我们选择的轴来定义) 138 | 139 | ![](https://miro.medium.com/max/1400/1*NzWF7ME484zD5uA08VxoKg.png) 140 | 141 | If we’ll declare “scroll-snap-align: center;” the items will be shown on the center of the container and we’ll see the edges of the surrounding items — as you can see on the image above. 142 | 143 | 如果,我们声明了 “scroll-snap-align: center;”,那么滚动元素将会在容器中间显示,边界线围绕在元素的周围—就像你在上图中看到的一样。 144 | 145 | In the following examples you can see 3 examples of scroll-snap-type `X`, `Y` and `Both` — All of them will snap to "start". 146 | 147 | 接下来的三示例分别对应这 scroll-snap-type 的三个不同选值:`X`, `Y` 和 `Both` — 它们的 scroll-snap-align 值都为 ~~"start"~~"center"。 148 | 149 | [X 轴](https://codepen.io/chaofix/pen/7a8dad4299b4f0a035d7859a849d89e7) 150 | 151 | [Y 轴](https://codepen.io/chaofix/pen/b7a81fd833f3ab1fd7d190e74a613231) 152 | 153 | [both](https://codepen.io/chaofix/pen/206d845358b7232d935d052eb4c240e1) 154 | 155 | ## Scroll margin / Scroll padding 156 | 157 | Both of these properties — scroll-padding and scroll-margin — are acting the same as padding / margin. They let us scroll with a space. 158 | 159 | scroll-padding 和 scroll-margin 就相当于 padding / margin。可以控制滚动元素和边界之间的留白。 160 | 161 | For example, using the property “scroll-padding: 10px;” will scroll the items one by one **but** with a space of 10px from the snap type (x, y, block, inline or both) boundaries 162 | 163 | 例如:设置 “scroll-padding: 10px;”,滚动元素跟容器边界之间会有个 10px 的留白。 164 | 165 | >**These properties don’t have full supported these days** 166 | > 167 | >**目前,这些属性并没有完全支持** 168 | 169 | ## Browser support 170 | 171 | According to “[caniuse](https://caniuse.com/#feat=css-snappoints)” all of the browsers are supporting this property. 172 | 173 | 根据 “[caniuse](https://caniuse.com/#feat=css-snappoints)” 记录可以知道,现在所有的浏览器都已经支持这一属性 174 | 175 | - IE / Edge needs the prefix -ms- 176 | 177 | IE / Edge 需要前缀 -ms- 178 | 179 | - Firefox is using an old writing of this property 180 | 181 | Firefox 中可以用旧的语法 182 | 183 | ![](https://miro.medium.com/max/1400/1*kdbqfSTIGE9YKret_-dErQ.png) 184 | 185 | On the last example you can see a “slideshow” with both of the scrolling (X and Y) 186 | 187 | 最后一个示例,你将会看到一个可以垂直/水平滚动的幻灯片效果。 188 | 189 | [slides demo](https://codepen.io/chaofix/pen/6535aca9fcfa4d0ea8aca690181cc128) 190 | 191 | ## Last words 192 | ## 总结 193 | 194 | - Using this CSS property is easy 195 | 196 | CSS 属性更加容易使用 197 | 198 | - We can create scrolling galleries, slide shows, entire pages and so on quickly and easy 199 | 200 | 我们可以快速轻松的创建滚动图库、幻灯片、全屏滚动等效果 201 | 202 | - There is an issue — in my opinion — if one of the items is much bigger than the container, we can’t see the whole item — a scroll will bring us to the next item 203 | 204 | 在我们看来,依旧会有个小问题。如果,其中一个元素比容器还要大,我们并不能看到它的全部—滚动的时候将会跳转到下一个元素。 -------------------------------------------------------------------------------- /Published/Stateless functional components.md: -------------------------------------------------------------------------------- 1 | ## Stateless functional components 2 | ## 无状态功能组件 3 | 4 | > 原文地址: [http://frontendinsights.com/stateless-functional-components/](http://frontendinsights.com/stateless-functional-components/) 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | > In 2015, [Dan Abramov](https://nafrontendzie.pl/nowy-poczatek/) wrote a great article about [presentational and container components](http://medium.stfi.re/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0?sf=voozdng#.icy524ihh) in React. I like the approach presented in his article. Basically you should divide your application components into two groups – presentational ones are only responsible for presenting data and container ones which deal with the logic. If you don’t know this concept, please read Dan’s article first! Today, I will show you how to use **stateless functional components**, the feature added to [React](http://facebook.stfi.re/react/?sf=ebbplxv) in v0.14, to create these presentational components. 10 | 11 | 2015年,[Dan Abramov](https://nafrontendzie.pl/nowy-poczatek/) 写了一篇有关 [presentational and container components](http://medium.stfi.re/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0?sf=voozdng#.icy524ihh) 的文章。我喜欢他在文中提出的观点。基本上你可以将应用的组件划分两类,presentational 只是用来展示数据;container 带有业务逻辑。如果,你不明白这些概念,请先阅读 Dan 的文章。今天,我将展示如何使用**无状态功能组件**,这个功能是用来创建 presentational 组件的,在 [React](http://facebook.stfi.re/react/?sf=ebbplxv) v0.14 中添加的。 12 | 13 | > ### The previous approach 14 | 15 | ### 以前的做法 16 | 17 | > Before React v0.14 we always had to write a component by creating class and extending it from ```React.Component…``` 18 | 19 | React v0.14 之前,新建组件我们都是通过创建类并继承 ```React.Component```; 20 | 21 | > Generally speaking, the presentational component is responsible only for showing data. That’s why it only usually has the ```render``` method. It also uses values stored in ```this.props``` directly in the JSX markup. The below example shows such a presentational component: 22 | 23 | 通常来说,presentational 组件仅仅负责展示数据。这就是为什么它只有 ```render``` 方法。存储在 ```this.props``` 中的数据是可以直接在 ```JSX``` 语法使用的。接下来例子展示的就是一个 presentational 组件。 24 | 25 | ``` 26 | import React from 'react'; 27 | 28 | class EmailTable extends React.Component { 29 | render() { 30 | return ( 31 | 32 | 33 | {this.props.emails.map((item, index) => { 34 | return ( 35 | 36 | 37 | 38 | ); 39 | })} 40 | 41 |
{item.email}
42 | ); 43 | } 44 | } 45 | 46 | export default EmailTable; 47 | ``` 48 | 49 | > As you can see, the ```EmailTable``` component is only responsible for rendering the table with emails. The list of emails is available in ```this.props```. 50 | 51 | 如你所见,```EmailTable```只是用来展示 emails 表格。emails 数据是 ```this.props``` 中的一个值。 52 | 53 | ### Stateless functional components – the new approach 54 | 55 | ### 新的方式:无状态功能组件 56 | 57 | > From v0.14 of React, we can use a different syntax to create such components. The difference is that now we don’t have to declare class. We can just use the arrow function instead! What is important here is that components created this way are stateless so you can’t use the internal state of the component like you normally do in “classic” components. 58 | 59 | 自从 React v0.14 开始,我们可以使用不同的语法创建组件。并不需要我们声明一个 ```class```。可以用三角函数代替。很重要的一点:以这种方式创建的组件是**无状态**的,你不能像普通组件一样使用 ```state```。 60 | 61 | > Before I describe the main benefits of using this approach, let’s take a look at the same example as above but written using stateless functional components: 62 | 63 | 在我描述这种方式的好处之前,先让我们看看上面同样例子**无状态**的写法。 64 | 65 | ``` 66 | import React from 'react'; 67 | 68 | const EmailTable = (props) => { 69 | return ( 70 | 71 | 72 | {props.emails.map((item, index) => { 73 | return ( 74 | 75 | 76 | 77 | ); 78 | })} 79 | 80 |
{item.email}
81 | ); 82 | } 83 | 84 | export default EmailTable; 85 | ``` 86 | or we can write it even better: 87 | 88 | 我们还可以写的更好: 89 | 90 | ``` 91 | import React from 'react'; 92 | 93 | const EmailTable = ({ emails }) => { 94 | return ( 95 | 96 | 97 | {emails.map((item, index) => { 98 | return ( 99 | 100 | 101 | 102 | ); 103 | })} 104 | 105 |
{item.email}
106 | ); 107 | } 108 | 109 | export default EmailTable; 110 | ``` 111 | 112 | > Let’s discuss the first example. As you may have noticed, instead of creating a class, we just declared a constant ```EmailTable``` and assigned an arrow function to it. The function takes ```props``` as an argument so that we can access its ```props``` this way. The function just returns the JSX markup which uses the props argument instead of ```this.props```. Pretty simple, right? 113 | 114 | 让我们先看第一个例子。或许你已经注意到,我仅仅声明了一个常量 ```EmailTable``` 并给它赋值了一个三角函数,并没有新建 ```class```。函数有一个 ```props``` 参数,你可以访问这个 ```props```。函数只是返回了一段 ```JSX``` 代码片段,在这里我使用的是 ```props```,而不是 ```this.props```。很简单,对吧? 115 | 116 | > The second example shows that we can extract only these properties of ```props``` which we really use. We can do this by using the [destructing assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) in the function declaration. The ```{ emails }``` means: get the emails property from ```props``` and assign it to the new variable emails. Cool 😉 117 | 118 | 第二个例子中,我通过[解构赋值](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)的方式,在函数声明时就把需要用到的参数提取出来了。```{ emails }``` :说明把属性 ```props``` 中的 emails 赋值给一个新的变量 emails。酷😉 119 | 120 | > You may ask: what about ```propTypes```??!! Well, we can still define it: 121 | 122 | 你或许会问:那 ```propTypes``` 怎么定义呢?它可以通过以下方式定义: 123 | 124 | ``` 125 | EmailTable.propTypes = { 126 | emails: React.PropTypes.array.isRequired 127 | } 128 | ``` 129 | > It works the same with ```defaultProps```. 130 | 131 | ```defaultProps``` 可以按照同样的方式处理。 132 | 133 | ### Why is this a better approach? 134 | 135 | ### 这种方式有什么好处呢? 136 | 137 | > First of all, it simplifies presentational components and prevents us from being tempted to use the internal state or lifecycle methods. If you know that the component should be “dumb”, just use a stateless functional component and you will be safe 😉 138 | 139 | 第一:语法非常简单,避免我们使用 ```state``` 和生命周期方法。正如你所知道的 “dumb” 组件一样。使用**无状态**组件是非常安全的。 140 | 141 | > For the second one, we can read in the official React documentation: 142 | 143 | 第二:让我们看看官方文档: 144 | 145 | > In an ideal world, many of your components would be stateless functions. In the future we plan to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations. 146 | 147 | 理想的情况下,在你的应用中大部分组件都应该是**无状态**组件。在将来,我们会针对这些组件通过避免不必要的检查和内存分配,来做性能优化。 148 | 149 | > When you don’t need local state or lifecycle hooks in a component, we recommend declaring it with a function. Otherwise, we recommend to use the ES6 class syntax. 150 | 151 | 当你在一个组件中不需要本地 ```state``` 和处理生命周期的情况,我们推荐使用**无状态**组件。除此之外,还推荐使用 ```ES6 class``` 语法。 152 | 153 | > As you can see, besides recommending the use of stateless functional components, they say that we can expect that this approach will be a better choice from the performance perspective. I think it is worth using now, even if these performance optimizations are not implemented yet. Let our code be prepared! 154 | 155 | > 正如你所看到的,除了推荐使用**无状态**组件,官方还说:站在性能优化的角度,这也是明智之举。我们认为从现在开始就可以使用了,尽管官方还没有明确的性能优化。我们可以先把代码处理好。 156 | 157 | ### Summary 158 | 159 | ### 总结 160 | 161 | > I think that we should all try to follow the rules described by Dan Abramov in the article I wrote about at the beginning. And I think that stateless functional components are very helpful in achieving this. Apart from this, in the future, we can expect performance optimization related to these type of components so this is an additional reason to use them! 162 | 163 | 我认为,在我们的工作中尽量遵循 Dan Abramov 的建议。**无状态**是一种很好的处理方式。除此之外,还有另外一个原因:官方对这种组件的性能优化。 164 | 165 | > 译者注: 166 | > 扩展阅读 167 | > [http://hao.jser.com/archive/13422/](http://hao.jser.com/archive/13422/) 168 | > [https://segmentfault.com/a/1190000007786080]( 169 | https://segmentfault.com/a/1190000007786080) 170 | 171 | -------------------------------------------------------------------------------- /Published/Understanding-Arrow-Functions.md: -------------------------------------------------------------------------------- 1 | ## Understanding Arrow Functions 2 | ## 箭头函数 3 | 4 | > 原文地址: 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | In this tutorial you are going to learn the answers to the questions: “What is an arrow function in JavaScript?” and “How is an arrow function different to a regular function (keyword)?” 10 | 11 | 在这篇教程中你将会学习:“Javascript 中的箭头函数是什么?” 和 “箭头函数和正常的函数有什么不同?” 12 | 13 | An arrow function is like a normal function just with 4 key differences: 14 | 15 | 1. They have a [different syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) (duh). 16 | 2. There is no form of arrow [function declaration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function), only expressions. 17 | 3. They don’t get their own `this`. 18 | 4. They have an implicit return. 19 | 20 | 相比正常的函数箭头函数有以下 4 点不同: 21 | 22 | 1. 有特有的[语法](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) 23 | 2. 没有[函数式声明](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function),只有表达式 24 | 3. 没有自己的 `this` 25 | 4. 有一个隐式的 `return` 26 | 27 | ## 1. Different syntax 28 | 29 | ## 1. 不同的语法 30 | 31 | Here is the syntax of an arrow function compared to a regular `function`keyword. I use [Immediately Invoked Function Expression](https://developer.mozilla.org/en-US/docs/Glossary/IIFE) for both functions. 32 | 33 | 这里有箭头函数和正常关键字 `function` 语法的对比。两个函数我都用了 [IIFE](https://developer.mozilla.org/en-US/docs/Glossary/IIFE) 34 | 35 | ```js 36 | (function() { 37 | console.log('function keyword'); 38 | })(); 39 | 40 | (() => { 41 | console.log('arrow function'); 42 | })(); 43 | ``` 44 | 45 | Notice that if an arrow function takes a single argument without any fanciness like destructuring, you may omit the brackets around its parameters. 46 | 47 | 注意:如果箭头函数只有一个参数,没有任何花哨的参数,你可以省略参数周围的括号。 48 | 49 | ```js 50 | // You need brackets 51 | const noArguments = () => {}; 52 | // You can ommit the brackets. 53 | const oneArgument = n => { 54 | return n * 2; 55 | }; 56 | // You need brackets 57 | const defaultParameter = (name = 'Anon') => { 58 | return name; 59 | }; 60 | // You need brackets. 61 | const destructuringOneArgment = ({ name }) => { 62 | return name; 63 | }; 64 | // You need brackets. 65 | const moreThanOneArgument = (a, b) => { 66 | return a + b; 67 | }; 68 | ``` 69 | 70 | ## 2. Only expressions 71 | 72 | ## 2. 只有表达式 73 | 74 | You can also name a function by writing a variable name after the `function`keyword. This is called “function declaration”. There are no function declarations for arrow functions, just anonymous function expressions. 75 | 76 | 你也可以通过在关键字 `funciton` 后面添加变量给函数命名。这叫"函数式声明"。对于箭头函数不能这么做,只能用匿名函数表达式。 77 | 78 | ```js 79 | // function declaration with keyword 80 | function decleration() { 81 | console.log('function declaration with keyword'); 82 | } 83 | 84 | // function expression with keyword 85 | const keywordExpression = function() { 86 | console.log('function expression with keyword'); 87 | }; 88 | 89 | // function declaration with arrow function 90 | // 🔴 Not a thing. 91 | 92 | // function expression with arrow function 93 | const arrowExpression = () => { 94 | console.log('function expression with keyword'); 95 | }; 96 | ``` 97 | 98 | The difference between a function declaration and a function expression is that they are parsed at different times. The declaration is defined everywhere in its scope, whereas the expression is only defined when its line is reached. 99 | 100 | 函数式声明和表达式声明两者的不同之处是解析时间不同。函数式声明可以在任何地方定义,然而,表达式声明只能在定义之后才能访问。 101 | 102 | ```js 103 | declaration(); // ✅ Okay 104 | 105 | function decleration() {} 106 | 107 | foo(); // 🔴 TypeError: foo is not a function 108 | var foo = () => {}; 109 | // We could've also written var foo = function() {} 110 | bar(); // 🔴 ReferenceError: Cannot access 'bar' before initialization 111 | const bar = () => {}; 112 | ``` 113 | 114 | You can also see the difference between `const` and `var` here. Since `foo` was declared using the `var` keyword, it is hoisted, and its value is `undefined`. `foo()` tries to call `undefined`, but its obviously not a function. Since `const`doesn’t hoist invoking `bar` throws a reference error. 115 | 116 | 从这你也可以看到 `const` 和 `var` 之间的不同。由于,`foo` 是由关键字 `var` 声明的,所以,它会出现变量提升,并且它的初始值是 `undefined`。`foo()` 在尝试调用 `undefined`,显然它不是一个函数。由于,`const` 没有变量提升,执行 `bar` 会抛出一个引用错误。 117 | 118 | ## 3. No this 119 | 120 | ## 3. 没有 this 121 | 122 | Like other languages, JavaScript has a [`this` keyword](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this). There are [several ways`this` is bound explicitly or implicitly](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch1.md). We are only going to focus on the behavior relevant to arrow functions. 123 | 124 | 就像其它语言一样,Javascript 也有 [`this` 关键字](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this)。有几种[绑定 `this` 的方法:显式或者隐式](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch1.md)。我们只关注箭头函数相关的内容即可。 125 | 126 | ```js 127 | const car = { 128 | wheels: 'four', 129 | yellWheels() { 130 | return this.wheels.toUpperCase(); 131 | }, 132 | countWheels: () => { 133 | return this.wheels; 134 | }, 135 | }; 136 | 137 | car.yellWheels(); // 'FOUR' 138 | car.countWheels(); // undefined 139 | ``` 140 | 141 | Using the `function` keyword, `this` references the object. However, the arrow function doesn’t get its own `this`. Therefore `wheels` is undefined because the global object doesn’t have a property `wheels`. 142 | 143 | 使用 `function` 关键字,`this` 引用的是当前对象。然而,箭头函数则没有自己的 `this`。因此,`wheels` 是 undefined,这是因为 global 对象没有属性 `wheels`。 144 | 145 | To understand `this`, play [Eric Elliott’s “What is this?”](https://medium.com/javascript-scene/what-is-this-the-inner-workings-of-javascript-objects-d397bfa0708a). 146 | 147 | 想要更好的理解 `this`,可以查看 [Eric Elliott’s “This 是什么?”](https://medium.com/javascript-scene/what-is-this-the-inner-workings-of-javascript-objects-d397bfa0708a)。 148 | 149 | ## 4. Implicit return 150 | 151 | ## 4. 隐式的 return 152 | 153 | In the previous code snippet, we used the `return` keyword to return values from the functions. Nevertheless, arrow functions don’t need to do that. If your function body is a single expression, you can omit the curly braces and the expression gets returned automatically. 154 | 155 | 在上一段代码中,我们用 `return` 关键字从函数中返回了一个值。不过,箭头函数不需要这样做。如果,你的函数中只有一句表达式,你可以省略掉大括号,表达式会自动的返回。 156 | 157 | ```js 158 | // These two functions do the same 159 | const explicitReturn = () => { 160 | return 'foo'; 161 | }; 162 | const implicitReturn = () => 'foo'; 163 | 164 | explicitReturn(); // 'foo' 165 | implicitReturn(); // 'foo' 166 | ``` 167 | 168 | Using implicit returns, we can simplify the examples from the syntax section. 169 | 170 | 用隐式 `return` ,我们可以简化示例中的语法。 171 | 172 | ```js 173 | // Can't be simplified, no expression 174 | const noop = () => {}; 175 | 176 | // Can be simplified, return expressions 177 | const getName = (name = 'Anon') => name; 178 | const double = n => n * 2; 179 | const getNameProp = ({ name }) => name; 180 | const add = (a, b) => a + b; 181 | 182 | ``` 183 | 184 | Implicit returns become especially handy for [currying](https://en.wikipedia.org/wiki/Currying), which is when a function returns another function until it returns its final value. 185 | 186 | 隐式的 `return` 让[柯里化](https://en.wikipedia.org/wiki/Currying)变得非常简单,也就是一个函数返回另外一个函数,最终返回一个值。 187 | 188 | ```js 189 | const add = a => b => a + b; // add is a function that returns b => a + b 190 | // Read this as const add = a => (b => a + b); 191 | const inc = add(1); // inc is a function because b => a + b got returned 192 | const decr = add(-1); 193 | 194 | inc(3); // 4 because inc remembers a as 1 195 | inc(6); // 7 196 | decr(3); // 2 because decr remembers a as -1 197 | ``` 198 | 199 | `add` is a function that takes in `a` and returns a function that takes in `b` that returns the sum of `a` and `b`. The function that takes in `b` remembers `a` in its closure. 200 | 201 | `add` 是一个函数,它有一个参数 `a`,然后,返回一个参数为 `b` 的函数,最终返回 `a` 加 `b` 的和。参数为 `b` 函数会在闭包中记住 `a`。 202 | 203 | If you liked this article, you might also like [“Understanding Conditional Rendering in React”](https://geromekevin.com/understanding-conditional-rendering-in-react/) because we explore `||` and `&&` in it in-depth. 204 | 205 | 如果,你喜欢这篇文章,你或许也会喜欢[“理解 React 中的条件渲染”](https://geromekevin.com/understanding-conditional-rendering-in-react/),因为,文章中我们会深入的探讨 `||` 和 `&&`。 206 | 207 | ## Summary 208 | 209 | ##总结 210 | 211 | We understood the 4 differences between the `function` keyword and an arrow function. 212 | 213 | 我们已经明白了关键字 `function` 和箭头函数之间的 4 种不同之处。 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 记事本 2 | 3 | ## 翻译记录 4 | 5 | 6 | ### CSS 7 | 8 | 1. [Animation tip: Lerp](https://github.com/xiao-T/note/issues/2) 9 | 2. [Flexbox: Don't Forget about flex-shrink](https://github.com/xiao-T/note/issues/3) 10 | 3. [Flexbox: space-between, Flexbox's Unsung Hero](https://github.com/xiao-T/note/issues/4) 11 | 4. [如何设置 CSS 背景图中的 SVG 的颜色](https://github.com/xiao-T/note/issues/6) 12 | 5. [纯 CSS 播放/暂停 ICON](https://github.com/xiao-T/note/issues/8) 13 | 6. [是时候使用 CSS 自定义属性了](https://github.com/xiao-T/note/issues/9) 14 | 7. [CSS Box Shadow 对比 Drop Shadow](https://github.com/xiao-T/note/issues/10) 15 | 8. [打破边界布局 CSS Grid 讲解](https://github.com/xiao-T/note/issues/11) 16 | 9. [利用 CSS Grid 打破布局的边界](https://github.com/xiao-T/note/blob/master/Published/Breaking%20Out%20With%20CSS%20Grid%20Layout.md) 17 | 10. [CSS Grid 布局(1):快速入门指南](https://github.com/xiao-T/note/blob/master/Published/CSS%20Grid%20Layout-%20A%20Quick%20Start%20Guide.md) 18 | 11. [CSS Grid 布局(2):Fluid Columns and Better Gutters](https://github.com/xiao-T/note/blob/master/Published/CSS%20Grid%20Layout-%20Fluid%20Columns%20and%20Better%20Gutters.md) 19 | 12. [CSS 网格布局(3):使用网格区间](https://github.com/xiao-T/note/blob/master/Published/CSS%20Grid%20Layout-%20Using%20Grid%20Areas.md) 20 | 13. [CSS 网格布局(4):使用 auto-fill 和 minmax() 实现响应布局](https://github.com/xiao-T/note/blob/master/Published/CSS%20Grid%20Layout-%20Going%20Responsive%20With%20auto-fill%20and%20minmax().md) 21 | 14. [CSS 网格布局(5):理解 CSS Grid 的 “自动排列算法”](https://github.com/xiao-T/note/blob/master/Published/Understanding%20the%20CSS%20Grid%20%E2%80%9CAuto-Placement%20Algorithm%E2%80%9D%20.md) 22 | 15. [CSS 网格布局(6):小建议 - 为网格线命名,以防万一](https://github.com/xiao-T/note/blob/master/Published/Quick%20Tip-%20Name%20Your%20CSS%20Grid%20Lines%2C%20Just%20in%20Case.md) 23 | 16. [用 CSS 自定义属性实现强大的 Grid 组件](https://github.com/xiao-T/note/blob/master/Published/Super-Powered%20Grid%20Components%20with%20CSS%20Custom%20Properties.md) 24 | 17. [CSS 技巧:色彩斑斓的自定义阴影](https://github.com/xiao-T/note/blob/master/Published/CSS%20Tip-%20Multicolor%20%26%20Cutout%20Drop%20Shadows.md) 25 | 18. [CSS Scroll Snap 的工作模式](https://github.com/xiao-T/note/blob/master/Published/css/CSS-Scroll-Snap%E2%80%94How-It-Really-Works.md) 26 | 27 | ### JS 28 | 29 | 1. [3 件你不知道的 JS 中有关 forEach 的事情](https://github.com/xiao-T/note/blob/master/Published/3%20things%20you%20didn%E2%80%99t%20know%20about%20the%20forEach%20loop%20in%20JS.md) 30 | 2. [箭头函数](https://github.com/xiao-T/note/blob/master/Published/Understanding-Arrow-Functions.md) 31 | 3. [ES2020 中 Javascript 10 个你应该知道的新功能](https://github.com/xiao-T/note/blob/master/Published/10-New-JavaScript-Features-in-ES2020-That-You-Should-Know.md) 32 | 4. [我从来都不理解闭包](https://github.com/xiao-T/note/blob/master/Published/javascript/I-never-understood-JavaScript-closures.md) 33 | 5. [JavaScript 开发者 10 个非常有用的技巧](https://github.com/xiao-T/note/blob/master/Published/javascript/10-Super-Useful-Tricks-for-JavaScript-Developers.md) 34 | 6. [一些有用的 JavaScript 技巧](https://github.com/xiao-T/note/blob/master/Published/javascript/Some-cool-and-awesome-JavaScript-tricks.md) 35 | 36 | ### TypeScript 37 | 1. [TypeScript 中的代码清道夫:非空断言操作符](https://github.com/xiao-T/note/blob/master/Published/typescript/cleaner-typescript-with-the-non-null-assertion-operator.md) 38 | 2. [通过示例演示 TypeScript 的高级类型](https://github.com/xiao-T/note/blob/master/Published/typescript/Advanced-TypeScript-Types-with-Examples.md) 39 | 3. [那些鲜为人知的 TypeScript 功能](https://github.com/xiao-T/note/blob/master/Published/typescript/Some-Lesser-Known-TypeScript-Features.md) 40 | 4. [TypeScript 3.9 中的新特性](https://github.com/xiao-T/note/blob/master/Published/typescript/What%E2%80%99s-New-in-TypeScript-3.9.md) 41 | 42 | ### React 43 | 44 | 1. [Stateless functional components](https://github.com/xiao-T/note/issues/5) 45 | 2. [React 进阶:Container 组件](https://github.com/xiao-T/note/issues/7) 46 | 3. [ESLint + Babel + Webpack 环境下的 React 代码风格](https://github.com/xiao-T/note/blob/master/Published/React%20Code%20Style%20with%20ESLint%20%2B%20Babel%20%2B%20Webpack.md) 47 | 4. [你或许不需要派生状态](https://github.com/xiao-T/note/blob/master/Published/You%20Probably%20Don't%20Need%20Derived%20State.md) 48 | 5. [用 React 构建可复用的设计系统](https://github.com/xiao-T/note/blob/master/Published/Build%20a%20Reusable%20Design%20System%20With%20React.md) 49 | 6. [测试 React 组件(1)](https://github.com/xiao-T/note/blob/master/Published/Testing%20Components%20in%20React%20Using%20Jest-%20The%20Basics.md) 50 | 7. [测试 React 组件(2)](https://github.com/xiao-T/note/blob/master/Published/Testing%20Components%20in%20React%20Using%20Jest%20and%20Enzyme.md) 51 | 9. [在 React 16.6 中懒加载(或者预加载)组件](https://github.com/xiao-T/note/blob/master/Published/Lazy%20loading%20(and%20preloading)%20components%20in%20React%2016.6.md) 52 | 10. [在 React 如何用 TypeScrpt 处理 Refs](https://github.com/xiao-T/note/blob/master/Published/React%20Refs%20with%20TypeScript.md) 53 | 11. [TypeScript 中使用 React HOC](https://github.com/xiao-T/note/blob/master/Published/React%20Higher-Order%20Components%20in%20TypeScript.md) 54 | 12. [TypeScript 中使用 React Hooks](https://github.com/xiao-T/note/blob/master/Published/React%20Hooks%20in%20TypeScript.md) 55 | 13. [TypeScript 中使用 React Props](https://github.com/xiao-T/note/blob/master/Published/React%20Render%20Props%20in%20TypeScript.md) 56 | 13. [React 中的条件渲染](https://github.com/xiao-T/note/blob/master/Published/Understanding-Conditional-Rendering-in-React.md) 57 | 14. [React Hooks for State Management!(useContext, useEffect, useReducer).md](https://github.com/xiao-T/note/blob/master/Published/React%20Hooks%20for%20State%20Management!useContext%2C%20useEffect%2C%20useReducer.md) 58 | 15. [使用 React Hooks 管理全局 State](https://github.com/xiao-T/note/blob/master/Published/Global%20state%20management%20with%20React%20Hooks.md) 59 | 16. [2020 年 React 状态管理](https://github.com/xiao-T/note/blob/master/Published/React%20State%20Management%20in%202020.md) 60 | 17. [React hooks:并不神奇,就是数组](https://github.com/xiao-T/note/blob/master/Published/React-hooks-not-magic-just-arrays.md) 61 | 18. [用 Enzyme 测试使用 Hooks 的 React 函数组件](https://github.com/xiao-T/note/blob/master/Published/Testing-React-Function-Components-with-Hooks-using-Enzyme.md) 62 | 19. [深入理解:React Hooks 是如何工作的?](https://github.com/xiao-T/note/blob/master/Published/Deep-dive-How-do-React-hooks-really-work.md) 63 | 20. [用 Jest 和 Enzyme 测试 React I](https://github.com/xiao-T/note/blob/master/Published/Testing-React-with-Jest-and-Enzyme-I.md) 64 | 21. [用 Jest 和 Enzyme 测试 React II](https://github.com/xiao-T/note/blob/master/Published/Testing-React-with-Jest-and-Enzyme-II.md) 65 | 22. [Hooks, State, 闭包和 useReducer](https://github.com/xiao-T/note/blob/master/Published/Hooks-State-Closures-and-useReducer.md) 66 | 23. [React 中渐进式加载图片](https://github.com/xiao-T/note/blob/master/Published/Progressively-Loading-Images-In-React.md) 67 | 24. [React 组件的"黄金法则"](https://github.com/xiao-T/note/blob/master/Published/react/How-the-%E2%80%9CGolden-Rule%E2%80%9D-of-React-components-can-help-you-write-better-code.md) 68 | 25. [为 REST API 创建可复用的 React Query 组件](https://github.com/xiao-T/note/blob/master/Published/react/Creating-a-reusable-React-Query-component-for-your-REST-API.md) 69 | 26. [React 组件的单元测试](https://github.com/xiao-T/note/blob/master/Published/react/Unit-Testing-React-Components.md) 70 | 27. [React 应用性能优化的 6 条建议](https://github.com/xiao-T/note/blob/master/Published/react/6-tips-for-better-React-performance.md) 71 | 28. [4 个简单又优雅的 React Hooks](https://github.com/xiao-T/note/blob/master/Published/react/4-Nice-and-Simple-React-Hooks.md) 72 | 73 | ### Test 74 | 1. [每个单元测试必须解决的 5 个问题](https://github.com/xiao-T/note/blob/master/Published/test/5-Questions-Every-Unit-Test-Must-Answer.md) 75 | 76 | ### Webpack 77 | 78 | 1. [用 webpack 实现 prefetch/preload](https://github.com/xiao-T/note/blob/master/Published/link-rel-prefetch-preload-in-webpack.md) 79 | 2. [Webpack (v4) 中用 SplitChunksPlugin 分割代码](https://github.com/xiao-T/note/blob/master/Published/Webpack%20(v4)%20Code%20Splitting%20using%20SplitChunksPlugin.md) 80 | 81 | ### Node 82 | 83 | 1. [用 KoaJS 和 MongoDB 实现 REST API - 1](https://github.com/xiao-T/note/blob/master/Published/REST%20API%20with%20KoaJS%20and%20MongoDB%20(Part%20%E2%80%93%201).md) 84 | 2. [用 KoaJS 和 MongoDB 实现 REST API - 2](https://github.com/xiao-T/note/blob/master/Published/REST%20API%20with%20KoaJS%20and%20MongoDB%20(Part%20%E2%80%93%202).md) 85 | 3. [用 KoaJS 和 MongoDB 实现 REST API - 3](https://github.com/xiao-T/note/blob/master/Published/REST%20API%20with%20KoaJS%20and%20MongoDB%20(Part%20%E2%80%93%203).md) 86 | 87 | ### Other 88 | 1. [什么是 JWT](https://github.com/xiao-T/note/blob/master/Published/Understanding%20JWT%20(JSON%20Web%20Tokens)%20.md) 89 | 2. [切角盒子](https://github.com/xiao-T/note/blob/master/Published/Notched%20Boxes.md) 90 | 3. [如何用 SVG 做占位符和其他的图片加载技术](https://github.com/xiao-T/note/blob/master/Published/How%20to%20use%20SVG%20as%20a%20Placeholder%2C%20and%20Other%20Image%20Loading%20Techniques.md) 91 | 4. [Service Workers 和客户端如何通信](https://github.com/xiao-T/note/blob/master/Published/How%20to%20Send%20Messages%20Between%20Service%20Workers%20and%20Clients.md) 92 | 93 | 94 | 95 | ## 个人总结 96 | 97 | 1.[两端对齐几种实现方案](https://github.com/xiao-T/note/blob/master/Published/%E4%B8%A4%E7%AB%AF%E5%AF%B9%E9%BD%90%E5%87%A0%E7%A7%8D%E5%AE%9E%E7%8E%B0%E6%96%B9%E6%A1%88.md) 98 | -------------------------------------------------------------------------------- /Published/React Hooks in TypeScript.md: -------------------------------------------------------------------------------- 1 | ## React Hooks in TypeScript 2 | ## TypeScript 中使用 React Hooks 3 | 4 | > 原文地址: 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | ![](https://miro.medium.com/max/600/1*7k79tcK3Qq4-qI0rGvBrdA.png) 10 | 11 | Released in React v16.8.0, [React Hooks](https://reactjs.org/docs/hooks-intro.html) address a number of issues with React, and perhaps most notably for TypeScript users, provide a first-class solution for reusing stateful logic, built with typing in mind. Due to this, a lot of the types for Hooks can be inferred, but in some cases explicit types must be set. 12 | 13 | [React Hooks](https://reactjs.org/docs/hooks-intro.html) 伴随 React v16.8.0 一起发布,它解决了一些 React 已知的问题,对 TypeScript 用户尤其重要,通过内置的 Type,对复用 state 提供了一流的解决方案。因此,Hook 的很多 Type 可以通过推断来设置,但是有些情况还是需要明确 Type。 14 | 15 | This article assumes some knowledge of the Hooks that are available. For this refer to the [React documentation](https://reactjs.org/docs/hooks-intro.html). 16 | 17 | 针对这篇文章,假设您对 Reac Hooks 的知识有所了解。可以参看[React 的文档](https://reactjs.org/docs/hooks-intro.html)。 18 | 19 | --- 20 | 21 | ## useState 22 | 23 | In most cases, the types for ```useState``` can be inferred based on the initial value, but if you need to start with ```null``` or ```undefined```, or need more control over the typing, such as specifying the types for an array or object, a generic can be used. 24 | 25 | 大多情况下,```useState``` 的 Type 可以基于初始化的值推断出,但是,如果你需要设置 ```null``` 或者 ```undefined```,或者需要更好的控制 Type,比如设置为一个数组或对象,这时,可以用泛型来解决。 26 | 27 | ```tsx 28 | // inferred as number 29 | const [value, setValue] = useState(0); 30 | 31 | // explicitly setting the types 32 | const [value, setValue] = useState(undefined); 33 | const [value, setValue] = useState>([]); 34 | 35 | interface MyObject { 36 | foo: string; 37 | bar?: number; 38 | } 39 | const [value, setValue] = useState({ foo: 'hello' }); 40 | ``` 41 | 42 | --- 43 | 44 | ## useContext 45 | 46 | ```useContext``` can infer its types based on the context object that is passed in as an argument, so has no need for explicit typing. 47 | 48 | ```useContext``` 的 Type 也可以通过传递的参数对象来推断,因此,不需要明确的设置。 49 | 50 | ```tsx 51 | type Theme = 'light' | 'dark'; 52 | const ThemeContext = createContext('dark'); 53 | 54 | const App = () => ( 55 | 56 | 57 | 58 | ) 59 | 60 | const MyComponent = () => { 61 | const theme = useContext(ThemeContext); 62 | return
The theme is {theme}
; 63 | } 64 | ``` 65 | 66 | --- 67 | 68 | ## useEffect / useLayoutEffect 69 | 70 | These two hooks are used for performing side effects and return an optional clean up function. As they do not deal with returning values, no types are necessary. 71 | 72 | 这两个 Hook 可以用来执行有副作用的操作,并返回一个可选的清理函数。它们不需要处理返回值,因此,也不需要设置 Type。 73 | 74 | ```tsx 75 | useEffect(() => { 76 | const subscriber = subscribe(options); 77 | return () => { 78 | unsubscribe(subscriber) 79 | }; 80 | }, [options]); 81 | ``` 82 | 83 | --- 84 | 85 | ## useMemo / useCallback 86 | 87 | Both ```useMemo``` and ```useCallback``` (a shorthand for memoising functions) both have their types inferred from the values that they return. 88 | 89 | ```useMemo``` 和 ```useCallback``` (memoising 方法的简称)两者的 Type 都可以根据自身返回值来推断。 90 | 91 | ```tsx 92 | const value = 10; 93 | // inferred as number 94 | const result = useMemo(() => value * 2, [value]); 95 | 96 | const multiplier = 2; 97 | // inferred as (value: number) => number 98 | const multiply = useCallback((value: number) => value * multiplier, [multiplier]); 99 | ``` 100 | 101 | *Note: you must make sure you specify the types of the parameters of the callback for* ```useCallback```, otherwise they will be set to ```any```, regardless of whether you have TypeScript’s ```noImplicitAny``` *set to true.* 102 | 103 | *注意⚠️:你必须为 ```useCallback``` 回调方法的参数设置 Type, 否则会默认为 ```any```,而不管是否有设置 TypeScript ```noImplicitAny``` 为 true。* 104 | 105 | ---- 106 | 107 | ## useRef 108 | 109 | Historically, refs have been used for referencing DOM nodes or class components, with the ref object's readonly ```current``` value starting as ```null```until the ref is attached. For this case ```null``` can be used as the initial value and a generic can be used for the ref type: 110 | 111 | 历史上,refs 可以用来引用 DOM 节点或者类组件,ref 对象中只读属性 ```current``` 的值在有引用前默认是 ```null```。对此,```null``` 可以用来做为初始化值,然后用泛型来设置 Type。 112 | 113 | ```tsx 114 | const MyInput = () => { 115 | const inputRef = useRef(null); 116 | return 117 | } 118 | ``` 119 | 120 | Since the introduction of Hooks, ```useRef``` can also be used as a replacement for [instance properties on classes](https://reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables), in which case the type can be inferred and ```current``` becomes mutable: 121 | 122 | 根据 Hooks 文档介绍,```useRef``` 也可以用来做为一个[classes 上的实例属性](https://reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables),在这种情况下 Type 也可以被推断,并且 ```current``` 变得可变。 123 | 124 | ```tsx 125 | const myNumberRef = useRef(0); 126 | myNumberRef.current += 1; 127 | ``` 128 | 129 | --- 130 | 131 | ## useReducer 132 | 133 | Reducers, the pattern introduced by Redux, can be typed in a similar fashion, with the types for the actions and state inferred from the reducer when supplied to ```useReducer```: 134 | 135 | Reducers 是 Redux 中提出的一种模式,它在处理 Type 也比较类似,可以通过 ```useReducer``` 提供的 actions 和 state 来推断: 136 | 137 | ```tsx 138 | interface State { 139 | value: number; 140 | } 141 | 142 | type Action = 143 | | { type: 'increment' } 144 | | { type: 'decrement' } 145 | | { type: 'incrementAmount'; amount: number }; 146 | 147 | const counterReducer = (state: State, action: Action) => { 148 | switch (action.type) { 149 | case 'increment': 150 | return { value: state.value + 1 }; 151 | case 'decrement': 152 | return { value: state.value - 1 }; 153 | case 'incrementAmount': 154 | return { value: state.value + action.amount }; 155 | default: 156 | throw new Error(); 157 | } 158 | }; 159 | 160 | const [state, dispatch] = useReducer(counterReducer, { value: 0 }); 161 | 162 | dispatch({ type: 'increment' }); 163 | dispatch({ type: 'decrement' }); 164 | dispatch({ type: 'incrementAmount', amount: 10 }); 165 | 166 | // TypeScript compilation error 167 | dispatch({ type: 'invalidActionType' }); 168 | ``` 169 | 170 | --- 171 | 172 | ## useImperativeHandle 173 | 174 | ```useImperativeHandle``` is by far the most involved Hook to set types for, but also likely the least used as it is not a common (or recommended) practice to expose imperative functions (handles) on components. 175 | 176 | ```useImperativeHandle``` 是目前最需要设置 Type 的 Hook,但是,在组件上暴露一个 imperative 方法也是最不常用的(或者不推荐)实践。 177 | 178 | ```tsx 179 | // useImperativeHandle.tsx 180 | export interface MyInputHandles { 181 | focus(): void; 182 | } 183 | 184 | const MyInput: RefForwardingComponent = ( 185 | props, 186 | ref 187 | ) => { 188 | const inputRef = useRef(null); 189 | 190 | useImperativeHandle(ref, () => ({ 191 | focus: () => { 192 | if (inputRef.current) { 193 | inputRef.current.focus(); 194 | } 195 | }, 196 | })); 197 | 198 | return ; 199 | }; 200 | 201 | export default forwardRef(MyInput); 202 | ``` 203 | 204 | The above example wraps an HTML input component and exposes a ```focus```function in order to allow the input to be focussed. Firstly, an interface ```MyInputHandles``` is declared to specify the functions that will be exposed through the ref. This interface is then passed to ```RefForwardingComponent``` to set it up as a component that can have a ref passed to it, which is implemented using [```forwardRef```](https://reactjs.org/docs/forwarding-refs.html). From this, ```useImperativeHandle``` can infer the types, so you will receive a compilation error if you do not implement the interface as the return value of the factory function in second argument. 205 | 206 | 上面的示例中我们通过包装 HMTL Input 实现了一个组件,并暴露了一个方法 ```focus``` 可以让 input 获取焦点。首先,定义了接口 ```MyInputHandles``` 并指定暴露的方法。然后把接口传递给 ```RefForwardingComponent``` ,这样就可以传递 ref 给组件,组件由 [```forwardRef```](https://reactjs.org/docs/forwarding-refs.html) 来实现。因此,```useImperativeHandle``` 也可以推断 Type,如果,你不在传递的工厂函数第二个参数中指定正确的类型,那么你就会收到编译报错。 207 | 208 | The ref can then be used by using ```MyInputHandles``` in the generic passed to ```useRef```: 209 | 210 | 这时,```MyInputHandles``` 可以以泛型的方式传递给 ```useRef```: 211 | 212 | ```tsx 213 | //useImperativeHandle-usage.tsx 214 | import MyInput, { MyInputHandles } from './MyInput'; 215 | 216 | const Autofocus = () => { 217 | const myInputRef = useRef(null); 218 | 219 | useEffect(() => { 220 | if (myInputRef.current) { 221 | myInputRef.current.focus(); 222 | } 223 | }); 224 | 225 | return 226 | } 227 | ``` 228 | 229 | --- 230 | 231 | ## useDebugValue 232 | 233 | ```useDebugValue``` is used for displaying values in React Developer Tools and takes a value and an optional formatting function, for which the types can be inferred based on the value passed in. 234 | 235 | ```useDebugValue``` 可以在 React 开发者工具中显示信息,并且可以提供一个可选方法来格式化信息,它的 Type 也可以根据传递的参数来推断。 236 | 237 | ```tsx 238 | const date = new Date(); 239 | useDebugValue(date, date => date.toISOString()); 240 | ``` 241 | 242 | -------------------------------------------------------------------------------- /Published/Flexbox- space-between, Flexbox's Unsung Hero.md: -------------------------------------------------------------------------------- 1 | 2 | ## Flexbox: space-between, Flexbox's Unsung Hero 3 | ## Flexbox 的幕后英雄:space-between 4 | 5 | > 原文地址: [https://codepen.io/noahblon/post/a-practical-guide-to-flexbox-understanding-space-between-the-unsung-hero](https://codepen.io/noahblon/post/a-practical-guide-to-flexbox-understanding-space-between-the-unsung-hero) 6 | **本文版权归原作者所有,翻译仅用于学习。** 7 | 8 | ----- 9 | 10 | > The more I use ```flexbox```, the more one rule comes up over and over again: ```justify-content: space-between```. In this post, I'll demonstrate how I approach a layout problem with ```flexbox``` and how useful the ```space-between``` pattern is for tackling tricky layouts very efficiently. 11 | 12 | 随着使用 ```flexbox``` 的次数增加,其中一个规则 ```justify-content: space-between```,也频繁的出现。在这篇文章中,我将演示如何有效的利用 ```space-between``` 解决 ```flexbox``` 中棘手的问题。 13 | 14 | > ### space-between 15 | 16 | ### space-between 17 | 18 | > ```space-between``` is a value for the ```justify-content``` property. It places all flex items equally along the main axis. Any leftover space that the flex items don't take up is equally distributed between the items. It's like floating items to the left and right, but you don't have to clear anything AND you can do it horizontally OR vertically. That's a pattern that comes up basically always. 19 | 20 | ```space-between``` 是属性 ```justify-content``` 其中的一个值。它可以让所有的 ```flex``` 子元素沿着主轴的方向平均分布。所有为被暂用的剩余空间,也会在子元素之间平均分布。看起来就像子元素浮动在左边和右边,但是这并不需要清除浮动,并且你可以控制子元素水平和垂直排列。这是一个很基本的布局。 21 | 22 | > The coolest thing about ```space-between``` is the items you are spacing out maintain their intrinsic size. This makes for some very efficient markup because you really don't need many wrapping elements - many times you can just let flex position items and you're good. 23 | 24 | 更神奇的是:```space-between``` 可以让子元素保持原有大小。实现起来非常方便,并需要多余的元素去包裹它们,你只需要在父级设置 ```display: flex``` 即可。 25 | 26 | > As with most things, IMO it's best explained with a demo. Let's imagine we have an awesome project to build a Super Smash Bros. tournament app and a designer hands us this: 27 | 28 | 很多情况下,IMO 是一个很好的示例。我们想象一下,我通过一个很棒的项目创建了一个比赛App: Super Smash Bros,设计 UI 如下: 29 | 30 | ![](https://s3-us-west-2.amazonaws.com/s.cdpn.io/18515/example.png) 31 | 32 | > Here's how I'd approach building the header section - the part with the images of the fighters, the icons, their names, the score, etc. - with flexbox and space-between. 33 | 34 | 现在让我们先利用 ```space-between``` 处理 App 头部的,它包括了图片、icons、名字、比分等等。 35 | 36 | > ### Figure 1 - Breaking down the layout problem 37 | 38 | ### 图1:分拆布局 39 | 40 | ![](https://s3-us-west-2.amazonaws.com/s.cdpn.io/18515/figure1.jpg) 41 | 42 | > The first thing I like to do when approaching a layout problem is to break it into its components. There is the background image, which we can handle with absolutely positioning and taking it out of the flow. 43 | 44 | 首先,在开始前,我会考虑把布局拆分成组件形式。例如:上面这个列子中有一个背景图,我会用绝对定位处理,让它脱离文档流。 45 | 46 | > That leaves the top content to position on top of the images. There are two regions: 47 | 48 | 让其他内容覆盖在背景图的上面。这有两个区域: 49 | 50 | > 1. A top section with some icon buttons, one of the left and two on the right. 51 | > 2. A bottom section with the fighter's name, the final score, icons and so on. 52 | 53 | 1. 顶部:包含了一些 icon 按钮,一个在左边,两个在右边。 54 | 2. 底部:包含了参赛者名字、比分、icons 等等。 55 | 56 | > For these two sections, the main axis is vertical. Setting display: flex and flex-direction: column with justify-content: space-between fixes the flex items to the top and bottom of the header. 57 | 58 | 对于这两个区域来说,它们的主轴是垂直的。通过设置 ```display: flex; flex-direction: column; justify-content: space-between``` 让它们分别固定在顶部和底部。 59 | 60 | > To illustrate how this works, I've given the sections a set height, but normally we can just let the size of the content within a flex item determine it's size. As I move through the following examples, I will remove these set heights. Here's a demo. 61 | 62 | 为了演示它是如何工作的,我在外层上设置了高度,但是通常下我们让内容来决定大小。当我通过以下示例后,我会删除它们的高度。这是示例。 63 | 64 | [**Demo1**](https://codepen.io/noahblon/pen/EjVjJV) 65 | [https://codepen.io/noahblon/pen/EjVjJV](https://codepen.io/noahblon/pen/EjVjJV) 66 | 67 | > Note: We need to actually keep the background outside of the flex context because of [a bug in Firefox](https://github.com/philipwalton/flexbugs/issues/18) with space-between erroneously applying space to absolutely positioned elements. To do this I've wrapped the content in an absolutely positioned element - .header-content - as well and set the flex context there. 68 | 69 | ⚠️:事实上我需要包一层 ```.header-content``` 用来放背景图,然后,我们在 ```.header-content``` 设置 ```flex``` 上下文。这是因为 [Firefox 的一个 bug](https://github.com/philipwalton/flexbugs/issues/18):```space-between``` 错误的导致绝对定位的元素并没有脱离文档流。 70 | 71 | > ### Figure 2 - Flexing and grouping items 72 | 73 | ### 图2:Flex 分组。 74 | 75 | ![](https://s3-us-west-2.amazonaws.com/s.cdpn.io/18515/figure2.jpg) 76 | 77 | > Now let's tackle the top section. This time the items are fixed to the sides of the header, but in the horizontal direction. Set ```display:flex``` on the section sets up our flex context. We don't need to explicitly set the ```flex-direction``` because the value is row, or horizontal, by default. ```justify-content: space-between``` is used again to fix the items to the sides of the flexbox. The two icons on the right are wrapped in an element to fix them on the right side together. Using a wrapper like this is an easy and efficient way to group flex items together. In the right wrapper we can use another cool flexbox trick and give it ```display: inline-flex```. This is similar to setting ```display: inline-block``` on each of the items to allow them to sit next to each other. But, unlike ```inline-block```, we don't need to set each item, and we're not left with an annoying space between the items that needs to be killed. 78 | 79 | 现在让我们解决顶部 ```section``` 的问题。这次子元素是水平排列在 ```header``` 的两边的。通过给 ```section``` 设置 ```display: flex``` 生成一个 ```flex``` 上下文环境。默认情况下子元素是水平排列的,我们并不需要明确的指明 ```flex-direction```。```justify-content: space-between``` 再一次被用来让子元素分布在父级的两边。在右边有两个 ```icons``` 被一个元素包裹起来是为了更好彼此贴近。在这我们可以使用另外一个很酷的技巧: ```display: inline-flex```。它看起来很像 ```display: inline-block``` 让子元素水平排列。但是,不像 ```inline-block``` 我们不用在每个子元素上设置,也不用担心元素之间的空格问题。 80 | 81 | [**Demo2**](https://codepen.io/noahblon/pen/YXyXbQ) 82 | [https://codepen.io/noahblon/pen/YXyXbQ](https://codepen.io/noahblon/pen/YXyXbQ) 83 | 84 | > ### Figure 3 - The efficiency of space-between 85 | 86 | 图3:```space-between``` 的效率 87 | 88 | ![](https://s3-us-west-2.amazonaws.com/s.cdpn.io/18515/figure3.jpg) 89 | 90 | > Now for the bottom section. This is just two boxes stacked on top of each other. Similar to the wrapper used to group the icons in the top section, we don't need to do anything to these items. Again, I've given these items a set ```height``` for illustration, but really I can just let this section ```shrink-wrap``` to it's content. 91 | 92 | 现在我们来解决底部的布局问题。它包括上下两部分。这有点类似顶部右边的分组,我暂时不对子元素做任何处理。为了演示效果,我给子元素设置了 ```height```,但是实际应用中是不需要设置的,只需要弹性适应。 93 | 94 | [**Demo3**](https://codepen.io/noahblon/pen/doYoxW) 95 | [https://codepen.io/noahblon/pen/doYoxW](https://codepen.io/noahblon/pen/doYoxW) 96 | 97 | ### Figure 4 98 | 99 | ### 图4 100 | 101 | ![](https://s3-us-west-2.amazonaws.com/s.cdpn.io/18515/figure4.jpg) 102 | 103 | > The top part of the bottom section is similar to the header. The items are fixed to both sides on the horizontal axis. Simple enough! ```justify-content: space-between```. Is this starting to get repetitive? I hope so. 104 | 105 | 底部的上半部分有点类似 ```haader```。它的子元素是水平排列在两边的。用 ```justify-content: space-between``` 很容易实现。看起来有点重复了。 106 | 107 | [**Demo4**](https://codepen.io/noahblon/pen/bdVVbm) 108 | [https://codepen.io/noahblon/pen/bdVVbm](https://codepen.io/noahblon/pen/bdVVbm) 109 | 110 | ### Figure 5 111 | 112 | ### 图5 113 | 114 | ![](https://s3-us-west-2.amazonaws.com/s.cdpn.io/18515/figure5.jpg) 115 | 116 | > The bottom part of the bottom section has items fixed to each side, and an item in the middle. Again, ```space-between``` has us covered - a third item in a ```space-between``` flex context is placed in the center. So powerful! 117 | 118 | 底部的下半部分,其中两个元素分布在两边,另外一个在中间。```space-between``` 再次出现了,第三个元素完美的居中,就是它的功劳。太棒了! 119 | 120 | [**Demo5**](https://codepen.io/noahblon/pen/waKKBY) 121 | [https://codepen.io/noahblon/pen/waKKBY](https://codepen.io/noahblon/pen/waKKBY) 122 | 123 | ### Figure 6 - All together now! 124 | 125 | ### 图6:整合 126 | 127 | > Here it all is with the real content plugged in and styled. 128 | 129 | 以下的示例都是真实的内容和样式。 130 | 131 | [**Demo6**](https://codepen.io/noahblon/pen/GJppMX) 132 | [https://codepen.io/noahblon/pen/GJppMX](https://codepen.io/noahblon/pen/GJppMX) 133 | 134 | > And here it is with the background, an ```SVG``` I created to make the images blend into one another and be dynamically colored. Stay tuned for a post about that! 135 | 136 | 背景我是通过 ```SVG``` 混合图片实现的。敬请关注这个帖子。 137 | 138 | [**Demo7**](https://codepen.io/noahblon/pen/MwabGx) 139 | [https://codepen.io/noahblon/pen/MwabGx](https://codepen.io/noahblon/pen/MwabGx) 140 | 141 | > For more practical tips about flexbox, you can check out [my blog](https://codepen.io/noahblon/posts/popular/) or [subscribe to my feed](https://codepen.io/noahblon/public/feed/). You can also [follow me on Codepen](https://codepen.io/noahblon/). 142 | 143 | 更多有关 ```flexbox``` 的资讯,你可以[关注](https://codepen.io/noahblon/posts/popular/)或者[订阅](https://codepen.io/noahblon/public/feed/)我的博客,或者在 [Codepen](https://codepen.io/noahblon/) 上关注我。 144 | 145 | -------------------------------------------------------------------------------- /Published/CSS Grid Layout- Using Grid Areas.md: -------------------------------------------------------------------------------- 1 | ## CSS Grid Layout: Using Grid Areas 2 | ## CSS 网格布局:使用网格区间 3 | 4 | > 原文地址: 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | One thing we’ve mentioned, but have yet to cover properly in this series is *grid areas*. So far our grid items have each been contained within a single grid cell, but we can achieve more useful layouts by breaking beyond those boundaries. Let’s take a look! 10 | 11 | *网格区间*我们已经提起过,但是一直还没有真正的去介绍过它。目前为止,每一个网格元素都是一个单独的网格单元,但是我们可以打破元素之间的边界实现更有用的布局。让我们来看一下! 12 | 13 | ### Defining Grid Areas 14 | 15 | ### 定义网格区间 16 | 17 | Here’s the grid we’ve been working on: nine grid items automatically placed within three equal columns, three equal rows, split by gutters of 20px. 18 | 19 | 我们一直研究的网格布局:9 个元格自动的拍成 3 行,3 列,元素之间有 20px 的留白。 20 | 21 | [DEMO](https://codepen.io/tutsplus/pen/zKKRdN) 22 | 23 | Currently our items only have color styles, but let’s return to what we learned in the first tutorial and add some ```grid-column``` and ```grid-row``` rules, this time with something extra: 24 | 25 | 当前每个网格元素只是有些颜色,这次会添加一些额外的东西,我们回到第一篇教程的示例中,然后添加一些 ```grid-column``` 和 ```grid-row```: 26 | 27 | ```css 28 | .item-1 { 29 | background: #b03532; 30 | grid-column: 1 / 3; 31 | grid-row: 1; 32 | } 33 | ``` 34 | 35 | In this shorthand ```grid-column``` statement we’re effectively using ```grid-column-start``` and ```grid-column-end```, telling the item to start at grid line 1 and end at grid line 3. 36 | 37 | ```grid-column``` 是 ```grid-column-start``` 和 ```grid-column-end``` 的简写,代表着当前网格区域从第一列开始到第三列结束。 38 | 39 | ![](https://cms-assets.tutsplus.com/uploads/users/30/posts/27264/image/grid-lines.svg) 40 | 41 | Here’s what that gives us; the first item now spreads across two cells, pushing the other items right and down according to Grid’s auto-placement algorithm. 42 | 43 | 我们去看看具体的实现;第一个元素占了两个网格单元格,导致其它元素向右、向下的自动排列。 44 | 45 | [DEMO](https://codepen.io/tutsplus/pen/RGoPbL) 46 | 47 | The same can be done with rows, which would give us a much larger area in the top left of our grid. 48 | 49 | 对于行我也可以同样的处理,这样右上角的区域就会更大。 50 | 51 | ```css 52 | .item-1 { 53 | background: #b03532; 54 | grid-column: 1 / 3; 55 | grid-row: 1 / 3; 56 | } 57 | ``` 58 | 59 | #### Spanning Cells 60 | 61 | #### 横跨单元格 62 | 63 | Using what is perhaps an easier syntax we can switch ```grid-column-end``` for the ```span``` keyword. With ```span``` we aren’t tied to specifying where the area ends, instead defining how many tracks the item should spread across: 64 | 65 | ```grid-column-end``` 还有一种更简单的语法就是使用关键字:```span```。使用 ```span``` 我们不需要指定区域的结束位置,只需定义好跨越几个网格轨道: 66 | 67 | ```css 68 | .item-1 { 69 | background: #b03532; 70 | grid-column: 1 / span 2; 71 | grid-row: 1 / span 2; 72 | } 73 | ``` 74 | 75 | This gives us the same end result, but if we were to change where we want the item to start we would no longer be obliged to change the end. 76 | 77 | 这么处理我们也会得到同样的效果,但是,如果我们想改变网格元素开始的位置时,结束位置这种情况下就不需要跟着改变了。 78 | 79 | In the following demo you can see we’ve emptied the layout by removing four of the items. We’ve declared positioning on two of our items: the first spans two columns and two rows, whilst the fourth starts on column 3, row 2, and spans downward across two tracks: 80 | 81 | 看下面的 demo 你会发现我们清除了 4 个元素。我们也为其中的两个元素重新定义了位置:第一元素,占据两行两列,同时,第四个元素从第三列、第二行开始向下占用两行: 82 | 83 | [DEMO](https://codepen.io/tutsplus/pen/gwLpEE) 84 | 85 | The remaining items fill the available space automatically. This highlights perfectly how a grid layout doesn’t have to reflect the source order of the elements. 86 | 87 | 剩余的元素在可用空间里自动分布。这完美的展示了网格布局是不必按照元素原来顺序排列布局的。 88 | 89 | **Note**: there are many situations where the source order absolutely *should* reflect the presentation–don’t forget about accessibility. 90 | 91 | **注意**:大多情况下元素的原顺序*应该*和具体显示顺序保持一致 - 不要忘记可访问性。 92 | 93 | ### Named Areas 94 | 95 | ### 命名空间 96 | 97 | Using the numbering methods we’ve described so far works just fine, but [Grid Template Areas](https://www.w3.org/TR/css-grid-1/#grid-template-areas-property) can make defining layouts even more intuitive. 98 | 99 | 目前为止,使用数字编号的方式可以很好的工作,但是,[网格模版区域](https://www.w3.org/TR/css-grid-1/#grid-template-areas-property)可以让定义网格更加直观。 100 | 101 | Specifically, they allow us to name areas on the grid. With those areas named, we can reference them (instead of line numbers) to position our items. Let’s stick to our current demo for the moment and use it to make ourselves a rough page layout comprising: 102 | 103 | - header 104 | - main content 105 | - sidebar 106 | - footer 107 | 108 | 尤其是,我们可以给网格区域命名。使用区域名称,我们可以引用定位元素(代替行号)。继续来看我们的 demo,用它来实现一个粗糙的页面布局,主要包括: 109 | 110 | - 头部 111 | - 主内容 112 | - 侧边 113 | - 底部 114 | 115 | We define these areas on our grid container, almost as though we’re drawing them out: 116 | 117 | 我们在网格容器上定义区域名称,就像我们绘制网格一样: 118 | 119 | ```css 120 | .grid-1 { 121 | /* ..existing styles */ 122 | 123 | grid-template-areas: "header header header" 124 | "main main sidebar" 125 | "footer footer footer"; 126 | } 127 | ``` 128 | 129 | #### Positioning the Items 130 | 131 | #### 定位元素 132 | 133 | Now we turn our attention to the items, ditching the ```grid-column``` and ```grid-row``` rules in favor of ```grid-area```: 134 | 135 | 现在让我们关注下各个元素,放弃 ```grid-column``` 和 ```grid-row``` 用 ```grid-area``` 代替: 136 | 137 | ```css 138 | .item-1 { 139 | background: #b03532; 140 | grid-area: header; 141 | } 142 | .item-2 { 143 | background: #33a8a5; 144 | grid-area: main; 145 | } 146 | .item-3 { 147 | background: #30997a; 148 | grid-area: sidebar; 149 | } 150 | .item-4 { 151 | background: #6a478f; 152 | grid-area: footer; 153 | } 154 | ``` 155 | 156 | Our first item is slotted into the header, spanning across all three header columns. Our second item is assigned the main content area, the third becomes our sidebar, and the fourth our footer. And these needn’t follow the source order either–```.item-4``` could just as easily be positioned in the header area. 157 | 158 | 第一个元素放置在头部,跨越 3 列。主内容区域分配给第二个元素,第三个元素就变成了侧边栏,第四个元素分配了整个底部。定位这些元素我们并不需要按照源顺序,比如:```.item-4``` 也可以被放置在头部区域。 159 | 160 | [DEMO](https://codepen.io/tutsplus/pen/bwBVYp) 161 | 162 | As you can see, this makes laying out a page much easier. In fact, while we’re in the mood for visually representing our grids, why not go even further and use emojis?! 163 | 164 | 正如你看到的,这使得实现一个页面布局很容易。事实上,虽然我们让网格布局实现了可视化,为什么不更进一步使用 emojis 呢?! 165 | 166 | [DEMO](https://codepen.io/tutsplus/pen/wzorjy) 167 | 168 | ### Nesting Grid Areas 169 | 170 | ### 网格嵌套 171 | 172 | A given web page will contain all kinds of nested components, so let’s see how that works with Grid. 173 | 174 | 一个特定的页面会包含多种嵌套组件,我们来看看网格是如何处理嵌套的。 175 | 176 | When we declare a grid container ```display: grid```; only its direct descendants become *grid items*. Content we add to those child elements will be completely unaffected by Grid unless we specifically say otherwise. 177 | 178 | 当我们声明一个网格容器 ```display: grid```;只是它的子元素会变成 *网格元素*。除非我们有特别声明,添加到这些元素中的内容将完全不受 Grid 的影响。 179 | 180 | In our example, we’re going to add ```.item-5``` , ```.item-6```, and ```.item-7``` back into the markup, nesting them in ```.item-2```. 181 | 182 | 在我们的演示中,我们会在 ```.item-2``` 中嵌套 ```.item-5``` , ```.item-6```, 和 ```.item-7``` 几个标签。 183 | 184 | ```html 185 |
186 |
1
187 | 188 |
189 |
5
190 |
6
191 |
7
192 |
193 | 194 |
3
195 |
4
196 |
197 | ``` 198 | 199 | So now we need to declare our ```.item-2``` also a grid container, setting up its grid with two columns and two rows. 200 | 201 | 现在,我需要把 ```.item-2``` 定义成一个网格容器,设置成两行两列。 202 | 203 | ```css 204 | display: grid; 205 | 206 | grid-template-columns: 1fr 30%; 207 | grid-template-rows: auto auto; 208 | grid-gap: 20px; 209 | 210 | grid-template-areas: "header header" 211 | "article sidebar"; 212 | ``` 213 | 214 | We can use the names “header”, “article”, and “sidebar” again here; there’s no confusion, because everything stays in context. These grid areas only apply to the grid within ```.item-2```. 215 | 216 | 我们再一次用 “header”, “article”, 和 “sidebar” 来命名;这不会混乱,因为上下文不同。这些只会对 ```.item-2``` 有效。 217 | 218 | [DEMO](https://codepen.io/tutsplus/pen/yaVZWA) 219 | 220 | ### Conclusion 221 | 222 | ### 总结 223 | 224 | To sum up what we’ve been talking about: 225 | 226 | 1. ```grid-column``` offers us a shorthand way of defining where an item starts and ends. 227 | 1. We can also use the ```span``` keyword to make our rules more flexible. 228 | 1. ```grid-template-areas``` give us the power to name our grid areas (even using emojis if the mood takes us). 229 | 1. We can also nest grids by declaring grid items as ```display: grid```; and following the same process. 230 | 231 | 我们来总结一下: 232 | 233 | 1. ```grid-column``` 是定义列头和列尾简写。 234 | 1. 我们可以是使用关键字 ```span``` 让 CSS 更加灵活。 235 | 1. ```grid-template-areas``` 可以给网格区域命名(emoji 也可以使用)。 236 | 1. 我们可以通过定义子元素为 ```display: grid``` 实现网格的嵌套;遵守同样的网格布局规则。 237 | 238 | Once again we’ve learned some useful aspects of the CSS Grid Layout spec, and we’re getting closer and closer to real world use cases! [In the next tutorial](https://webdesign.tutsplus.com/tutorials/css-grid-layout-going-responsive--cms-27270) we’ll look at some more complex layouts and see how responsive design fits into the equation. 239 | 240 | 我们又学到了 CSS Grid 布局中几个有用的方面,并且我们的示例越来越接近真是场景![下篇教程中](https://webdesign.tutsplus.com/tutorials/css-grid-layout-going-responsive--cms-27270),我们会看到更加复杂的布局和如何实现响应布局。 241 | 242 | #### Useful Resources 243 | 244 | #### 更多有用的资源 245 | 246 | - Have I mentioned this already? Follow [@rachelandrew](https://twitter.com/rachelandrew) 247 | 248 | - 我已经提到过了!关注 [@rachelandrew](https://twitter.com/rachelandrew) 249 | 250 | -------------------------------------------------------------------------------- /Published/10-New-JavaScript-Features-in-ES2020-That-You-Should-Know.md: -------------------------------------------------------------------------------- 1 | ## 10 New JavaScript Features in ES2020 That You Should Know 2 | ## ES2020 中 Javascript 10 个你应该知道的新功能 3 | 4 | > 原文地址: 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | ![](https://www.freecodecamp.org/news/content/images/size/w2000/2020/04/es2020logo.jpg) 10 | 11 | Good news – the new ES2020 features are now finalised! This means we now have a complete idea of the changes happening in ES2020, the new and improved specification of JavaScript. So let's see what those changes are. 12 | 13 | 好消息 - ES2020 新功能已经落地!这就意味着,现在对 ES2020 中 Javascript 的新增和改进要有一个完整的了解。让我们来看看都有哪些改变。 14 | 15 | ## #1: BigInt 16 | 17 | BigInt, one of the most anticipated features in JavaScript, is finally here. It actually allows developers to have much greater integer representation in their JS code for data processing for data handling. 18 | 19 | BigInt,Javascript 中最期待的新功能终于落地。它允许开发者在 JS 中使用更大的整数进行数据处理。 20 | 21 | At the moment the maximum number you can store as an integer in JavaScript is `pow(2, 53) - 1` . But BigInt actually allows you to go even beyond that. 22 | 23 | 之前,Javascript 中最大的整数是 `pow(2, 53) - 1`。但是,BigInt 不受此限制。 24 | 25 | ![](https://www.freecodecamp.org/news/content/images/2020/04/Screenshot-2020-04-03-at-8.21.47-PM.png) 26 | 27 | However, you need to have an `n` appended at the very end of the number, as you can see above. This `n` denotes that this is a BigInt and should be treated differently by the JavaScript engine (by the v8 engine or whatever engine it is using). 28 | 29 | 然而,就如你在上面看到,你需要在数字后面添加一个 `n`。这个 `n` 说明这是一个 BigInt,Javascript 引擎应该特殊处理(不管是 V8,还是其它引擎)。 30 | 31 | This improvement is not backwards compatible because the traditional number system is IEEE754 (which just cannot support numbers of this size). 32 | 33 | 因为传统的数字系统是 IEEE754(它不支持这种大数字),因此,这个改进并不会向后兼容。 34 | 35 | ## #2: Dynamic import 36 | 37 | ## #2:动态引入 38 | 39 | Dynamic imports in JavaScript give you the option to import JS files dynamically as modules in your application natively. This is just like how you do it with Webpack and Babel at the moment. 40 | 41 | Javascript 的动态引入,允许你把 JS 文件作为一个模块动态的引入到你的应用中。这就像你使用 webpack 和 Babel 一样。 42 | 43 | This feature will help you ship on-demand-request code, better known as code splitting, without the overhead of webpack or other module bundlers. You can also conditionally load code in an if-else block if you like. 44 | 45 | 这个功能可以帮助你处理按需加载的代码,拆分代码,而且,并不需要 webpack 或者其它模块处理器。如果,你喜欢也可以在 if-else 块中加载代码。 46 | 47 | The good thing is that you actually import a module, and so it never pollutes the global namespace. 48 | 49 | 在 if-else 块中引入一个模块,这样的好处是:不会污染全局命名空间。 50 | 51 | ![](https://www.freecodecamp.org/news/content/images/2020/04/Screenshot-2020-04-03-at-8.26.27-PM.png) 52 | 53 | ## #3: Nullish Coalescing 54 | 55 | ## #3: 空值合并 56 | 57 | Nullish coalescing adds the ability to truly check `nullish` values instead of `falsely` values. What is the difference between `nullish` and `falsely` values, you might ask? 58 | 59 | 空值合并可以真正的检查 `nullish` 值,而不是 `falsely` 值。你或许会问:`nullish` 和 `falsely` 之间有什么不同呢? 60 | 61 | In JavaScript, a lot of values are `falsely`, like empty strings, the number 0, `undefined`, `null`, `false`, `NaN`, and so on. 62 | 63 | 在 Javascript 中有很多值都是 `falsely`。比如:空字符串、数字 0、`undefined` 、`null`、 `false` 、`NaN` 等。 64 | 65 | However, a lot of times you might want to check if a variable is nullish – that is if it is either `undefined` or `null`, like when it's okay for a variable to have an empty string, or even a false value. 66 | 67 | 然而,很多情况下你只想检测一个变量是否为空值 -- `undefined` 或者 `null`,就像变量可以是一个空字符串甚至是一个假值。 68 | 69 | In that case, you'll use the new nullish coalescing operator, `??` 70 | 71 | 在这个示例中,你将会看到新的空值合并操作符:`??`。 72 | 73 | ![](https://www.freecodecamp.org/news/content/images/2020/04/Screenshot-2020-04-03-at-8.47.03-PM.png) 74 | 75 | You can clearly see how the OR operator always returns a truthy value, whereas the nullish operator returns a non-nulllish value. 76 | 77 | 你可以清楚的看到 OR 操作符总是返回一个真值,但是,空值操作符返回一个非空值。 78 | 79 | ## #4: Optional Chaining 80 | ## #4:可选链 81 | 82 | Optional chaining syntax allows you to access deeply nested object properties without worrying if the property exists or not. If it exists, great! If not, `undefined` will be returned. 83 | 84 | 可选链语法允许你访问嵌套更深的对象属性,而不用担心属性是否存在。如果,存在很好。反之,会返回 `undefined`。 85 | 86 | This not only works on object properties, but also on function calls and arrays. Super convenient! Here's an example: 87 | 88 | 它不仅仅可操作对象属性,也可以操作函数的调用或者数组。这样更加方便!以下是个演示: 89 | 90 | ![](https://www.freecodecamp.org/news/content/images/2020/04/Screenshot-2020-04-03-at-8.51.58-PM.png) 91 | 92 | ## #5: Promise.allSettled 93 | 94 | The `Promise.allSettled` method accepts an array of Promises and only resolves when all of them are settled – either resolved or rejected. 95 | 96 | `Promise.allSettled` 方法接收一组 Promise,并且会返回所有的结果 - 而不管是 resolved 还是 rejected。 97 | 98 | This was not available natively before, even though some close implementations like `race` and `all` were available. This brings "Just run all promises – I don't care about the results" natively to JavaScript. 99 | 100 | 在之前,这是不可能的,尽管有些类似的实现比如:`race` 和 `all`。它只会“运行所有的 promise - 而不关心它们的结果”。 101 | 102 | ![](https://www.freecodecamp.org/news/content/images/2020/04/Screenshot-2020-04-03-at-8.54.58-PM.png) 103 | 104 | ## #6: String#matchAll 105 | 106 | `matchAll` is a new method added to the `String` prototype which is related to Regular Expressions. This returns an iterator which returns all matched groups one after another. Let's have a look at a quick example: 107 | 108 | `matchAll` 是 `String` 原型链上的一个新增的方法,它可以关联正则表达式。它返回一个迭代器,一个接一个的返回所有匹配的组。我们来看一个演示: 109 | 110 | ![](https://www.freecodecamp.org/news/content/images/2020/04/Screenshot-2020-04-03-at-8.59.14-PM.png) 111 | 112 | ## #7: globalThis 113 | 114 | If you wrote some cross-platform JS code which could run on Node, in the browser environment, and also inside web-workers, you'd have a hard time getting hold of the global object. 115 | 116 | 如果,你写过那些可以运行在 Node、浏览器或者 web-workers 等跨平台的 JS 代码,你就会花费很多的时间去处理全局对象的问题。 117 | 118 | This is because it is `window` for browsers, `global` for Node, and `self` for web workers. If there are more runtimes, the global object will be different for them as well. 119 | 120 | 这是因为不同平台全局对象也不同,浏览器中是 `window`,Node 中是 `global`,web workers 中是 `self`。如果,还有更多的运行环境,这个对象也会有不同。 121 | 122 | So you would have had to have your own implementation of detecting runtime and then using the correct global – that is, until now. 123 | 124 | 因此,你自己必要检查运行环境来决定使用正确是全局对象。 125 | 126 | ES2020 brings us `globalThis` which always refers to the global object, no matter where you are executing your code: 127 | 128 | ES2020 给我们带来了 `globalThis` 对象,它始终会引用着全局对象,而不用关系代码在哪运行: 129 | 130 | ![](https://www.freecodecamp.org/news/content/images/2020/04/Screenshot-2020-04-03-at-9.02.27-PM.png) 131 | 132 | ## #8: Module Namespace Exports 133 | 134 | ## #8:导出模块的命名空间 135 | 136 | In JavaScript modules, it was already possible to use the following syntax: 137 | 138 | Javascript 模块中,一直都可以使用以下这种语法: 139 | 140 | ```js 141 | import * as utils from './utils.mjs' 142 | ``` 143 | 144 | However, no symmetric `export` syntax existed, until now: 145 | 146 | 然而,直到现在还不可以像以下这样使用 `export` 语法: 147 | 148 | ***译者注:目前是支持的(2020-04-24)*** 149 | 150 | ```js 151 | export * as utils from './utils.mjs' 152 | ``` 153 | 154 | This is equivalent to the following: 155 | 156 | 以上和以下结果相同: 157 | 158 | ```js 159 | import * as utils from './utils.mjs' 160 | export { utils } 161 | ``` 162 | 163 | ## #9: Well defined for-in order 164 | 165 | ## #9:明确定义 for-in 的顺序 166 | 167 | The ECMA specification did not specify in which order `for (x in y)` should run. Even though browsers implemented a consistent order on their own before now, this has been officially standardized in ES2020. 168 | 169 | ECMA 规范中并没有明确定义 `for (x in y)` 的顺序。尽管,在此之前浏览器实现了一致的顺序,但是,现在已经被纳入到 ES2020 的官方规范中了。 170 | 171 | ## #10: import.meta 172 | 173 | The `import.meta` object was created by the ECMAScript implementation, with a [`null`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null) prototype. 174 | 175 | `import.meta` 是由 ECMAScript 创建实现的,默认为 [`null`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null)。 176 | 177 | Consider a module, `module.js`: 178 | 179 | 考虑一下这个模块,`module.js` : 180 | 181 | ```html 182 | 183 | ``` 184 | 185 | You can access meta information about the module using the `import.meta` object: 186 | 187 | 你可以通过 `import.meta` 对象访问模块的相关 meta 信息: 188 | 189 | ```js 190 | console.log(import.meta); // { url: "file:///home/user/module.js" } 191 | ``` 192 | 193 | It returns an object with a `url` property indicating the base URL of the module. This will either be the URL from which the script was obtained (for external scripts), or the document base URL of the containing document (for inline scripts). 194 | 195 | 它返回一个包含 `url` 属性的对象,该属性代表着模块的 URL。它可能是获取脚本的 URL(对于外部脚本来说),或者是包含模块文档的基础URL(对于内联脚本来说)。 196 | 197 | ## Conclusion 198 | 199 | ## 总结 200 | 201 | I love the consistency and speed with which the JavaScript community has evolved and is evolving. It is amazing and truly wonderful to see how JavaScript came from a language which was booed on, 10 years go, to one of the strongest, most flexible and versatile language of all time today. 202 | 203 | 我喜欢 Javascript 社区不断发展的一致性和速度。看看 Javascript 如何从一种经过十年的嘘声演变成如今这种最强大、最灵活和最通用的语言,真的很神奇。 204 | 205 | Do you wish to learn JavaScript and other programming languages in a completely new way? Head on to a [new platform for developers](https://codedamn.com/) I'm working on to try it out today! 206 | 207 | 你是否希望用一种全新的方式学习 Javascript 和其它的编程语言?我正在开发一个[全新的开发者平台](https://codedamn.com/) ,现在可以试下! 208 | 209 | What's your favorite feature of ES2020? Tell me about it by tweeting and connecting with me on [Twitter](https://twitter.com/mehulmpt) and [Instagram](https://instagram.com/mehulmpt)! 210 | 211 | ES2020 中功能哪个是你喜欢的呢?可以在 [Twitter](https://twitter.com/mehulmpt) 和 [Instagram](https://instagram.com/mehulmpt) 上联系告诉我! 212 | 213 | This is a blog post composed from my video which is on the same topic. It would mean the world to me if you could show it some love! 214 | 215 | 我的视频也有相同专题的内容。如果您能表达爱意,那就对我来说意味着世界! 216 | 217 | 218 | 219 | -------------------------------------------------------------------------------- /Published/CSS Grid Layout- Going Responsive With auto-fill and minmax().md: -------------------------------------------------------------------------------- 1 | ## CSS Grid Layout: Going Responsive With auto-fill and minmax() 2 | ## CSS 网格布局:使用 auto-fill 和 minmax() 实现响应布局 3 | 4 | > 原文地址: 5 | **本文版权归原作者所有,翻译仅用于学习。** 6 | 7 | --------- 8 | 9 | Throughout this series we’ve become familiar with Grid syntax, learned about some efficient ways of laying out elements on a page, and said goodbye to some old habits. In this tutorial we’re going to apply all of that to some practical responsive web design. 10 | 11 | 通过这个系列的学习我们已经熟悉了 Grid 的语法,学会了处理页面布局的一些高效方法,对于一些旧习惯可以说再见了。在这篇教程中,我们会继续学习处理响应布局的方法。 12 | 13 | ### Media Queries 14 | 15 | ### 媒体查询 16 | 17 | Let’s use the demo from where we left off last time. 18 | 19 | 我们继续使用上次的 Demo。 20 | 21 | [DEMO](https://codepen.io/tutsplus/pen/XjNxbW) 22 | 23 | It comprises two declared grids; our main grid and the nested grid within one of our items. We can control when these grids come into effect using media queries, meaning we can completely redefine our layout at different viewport widths. 24 | 25 | Demo 中有两个网格; 父级网格和嵌套在其中一个元素中的网格。我们可以通过媒体查询控制网格何时生效,也就是说我们可以为不同的视窗重新定义布局。 26 | 27 | Begin by duplicating the first grid declaration, and wrapping the duplicate in a mobile-first media query (I’m using 500px as the breakpoint, but that’s completely arbitrary): 28 | 29 | 首先,复制一份第一个网格布局的声明,然后,把它放在移动优先的媒体查询规则中(我用的 500px 作为一个断点,其实,这完全可以很随意的): 30 | 31 | ```css 32 | .grid-1 { 33 | /* grid declaration styles */ 34 | } 35 | 36 | 37 | @media only screen and (min-width: 500px) { 38 | 39 | .grid-1 { 40 | /* grid declaration styles */ 41 | } 42 | 43 | } 44 | ``` 45 | 46 | Now, within the first declaration we’ll change how our grid is defined, placing the whole thing in a single column. We’ll list just one column in our ```grid-template-columns``` rule, make sure the four rows we now have are defined with ```grid-template-rows```, and arrange the layout with ```grid-template-areas```: 47 | 48 | 现在,改变第一条网格布局中的定义,让整个网格变成单列的。我们只需在 ```grid-template-columns``` 定义一条规则,为了确保有四行我们需要用到 ```grid-template-rows```,然后,用 ```grid-template-areas``` 来定义网格区域名称: 49 | 50 | ```css 51 | .grid-1 { 52 | display: grid; 53 | width: 100%; 54 | margin: 0 auto; 55 | 56 | grid-template-columns: 1fr; 57 | grid-template-rows: 80px auto auto 80px; 58 | grid-gap: 10px; 59 | 60 | grid-template-areas: "header" 61 | "main" 62 | "sidebar" 63 | "footer"; 64 | } 65 | ``` 66 | 67 | We’ve also made our ```grid-gap``` just 10px by default, to account for smaller screens. 68 | 69 | 我们还用 ```grid-gap``` 定义了 10px 的留白,为了在更小的屏幕上可以访问。 70 | 71 | [Here’s what that gives us](http://codepen.io/tutsplus/pen/NRbOGL/). You’ll notice that we’re also using our media query to change the ```padding``` and ```font-size``` on our ```.grid-1 div``` items. 72 | 73 | [可以在这看看具体的样子](http://codepen.io/tutsplus/pen/NRbOGL/)。你们应该也注意到了我们也用媒体查询改变了 ```.grid-1 div``` 的 ```padding``` 和 ```font-size```。 74 | 75 | #### Our Nested Grid 76 | 77 | #### 嵌套的网格 78 | 79 | That takes care of the main layout, but we still have the nested grid which remains stubbornly in its two column layout under all circumstances. To fix that we’ll do exactly the same as before, but using a different breakpoint to suggest a content-first approach: 80 | 81 | 这只对父级网格有效,但是,第二个嵌套的网格始终还是会保持两列。用之前同样的方式可以处理这种问题,但是,这次使用不同的断点,建议使用内容优先的规则: 82 | 83 | ```css 84 | .item-2 { 85 | /* grid declaration styles */ 86 | } 87 | 88 | 89 | @media only screen and (min-width: 600px) { 90 | 91 | .item-2 { 92 | /* grid declaration styles */ 93 | } 94 | 95 | } 96 | ``` 97 | 98 | Check out [the end result on CodePen](http://codepen.io/tutsplus/pen/mAOzVq/). 99 | 100 | [在 CodePen](http://codepen.io/tutsplus/pen/mAOzVq/) 查看最终结果。 101 | 102 | A couple of things to note here: 103 | 104 | - As we’ve said before, you can *visually* arrange grid items irrespective of the source order, and media queries mean we can have different visual orders for different screen widths. However, nesting has to remain true to the source; our nested grid items must always be visually and *actually* descendants of their parent. 105 | - CSS transitions don’t have any influence over Grid layout. When our media queries kick in, and our grid areas move to their new positions, you won’t be able to ease them into place. 106 | 107 | 注意事项: 108 | 109 | - 正如我们之前说的,你在实现*视觉*上的网格布局时可以不管元素的原顺序,然后,配合媒体查询我们可以为不同宽度的屏幕实现不同的视觉效果。然而,嵌套的元素必须保证原顺序的真实性;它们对于父级必须一直是可见的,并且*必须是*父级的子元素。(*译者注:就是说嵌套的网格单元不受父级单元的顺序影响*) 110 | - CSS transitions 对网格布局中的的属性无效。当媒体查询规则生效时,网格区域会立即生效,并不会有过度的效果。 111 | 112 | ### auto-fill and minmax() 113 | 114 | ### auto-fill 和 minmax() 115 | 116 | Another (sort of) responsive approach to Grid is well suited to masonry-type layouts; blocks which size and flow automatically, depending on the viewport. 117 | 118 | 网格的另外一种响应布局非常适合 masonry 类型的布局;根据屏幕大小,自动调整元素块的大小。 119 | 120 | #### auto-fill 121 | 122 | Our approach up until now has been to dictate how many tracks there are and watch the items fit accordingly. That’s what is happening in this demo; we have ```grid-template-columns: repeat(4, 1fr)```; which says “create four columns, and make each one a single fraction unit wide”. 123 | 124 | 目前为止,我们的布局有几行几列都是明确知道的。当前的 demo 也是这么处理的;我们定义了 ```grid-template-columns: repeat(4, 1fr)```;也就是说:创建 4 列,每一列都是相同的宽度。 125 | 126 | [DEMO](https://codepen.io/tutsplus/pen/JREEdA) 127 | 128 | With the ```auto-fill``` keyword we can dictate how *wide* our tracks are and let Grid figure out how many will fit in the available space. In this demo we’ve used ```grid-template-columns: repeat(auto-fill, 9em)```; which says “make the columns 9em wide each, and fit as many as you can into the grid container”. 129 | 130 | 我们可以定义每个网格轨道有多*宽*,然后,使用关键字 ```auto-fill``` 让网格自动计算出在有限的空间可以填充多少网格轨道。在这个 demo 中我们定义了 ```grid-template-columns: repeat(auto-fill, 9em)```;也就是说:每一列都是 9em 宽,网格容器中尽可能多的填充网格轨道。 131 | 132 | [DEMO](https://codepen.io/tutsplus/pen/rrjjpy) 133 | 134 | **Note**: this also takes our gutters, the ```grid-gap```, into account. 135 | 136 | **注意**:在计算的时候 ```grid-gap``` 也是需要考虑的。 137 | 138 | The container in these demos has a dark background to show clearly how much space is available, and you’ll see that it hasn’t been completely filled in the last example. So how do we do that? 139 | 140 | Demo 中的容器都有一个黑色背景,为了展示有多少可以用空间,在最后一个示例中,你会发现并没有完全的被填充。我们如何处理呢? 141 | 142 | #### minmax() 143 | 144 | The ```minmax()``` function allows us to set a minimum and a maximum size for a track, enabling Grid to work within them. For example we could setup three columns, the first two being 1fr wide, the last being a maximum of 1fr, but shrinking no smaller than 160px: 145 | 146 | 方法 ```minmax()``` 可以让我们为网格轨道设置一个最小和最大值,网格自动的取舍。比如,我们可以设置三列,第一、第二列为 1fr 宽,最后一列宽最大值为 1fr,可以自由伸缩,但是不能小于 160px。 147 | 148 | ```css 149 | grid-template-columns: 1fr 1fr minmax(160px, 1fr); 150 | ``` 151 | 152 | All the columns will shrink as you squish the window, but the last column will only be pushed so far. [Take a look](http://codepen.io/tutsplus/pen/rrjywv/). 153 | 154 | 所有的列将会根据窗口大小自动伸缩,但是最后一列会有个最小限制。[看一下效果](http://codepen.io/tutsplus/pen/rrjywv/)。 155 | 156 | Back to our ```auto-fill``` demo, if we were to change our column width for ```minmax(9em, 1fr)``` Grid would place as many 9em tracks as possible, but then expand them to a maximum of 1fr until the container is filled: 157 | 158 | 回去看下 ```auto-fill``` 的 demo,如果,我们把列宽设置成 ```minmax(9em, 1fr)```,容器会尽可能多展示 9em 宽的网格轨道,但是,它们会在有限的空间里扩张到最大值 1fr: 159 | 160 | [DEMO](https://codepen.io/tutsplus/pen/kkggdx) 161 | 162 | **Caveat**: Grid will recalculate the tracks upon page reload (try squishing the browser window and hitting refresh) but it won’t do so on window resize. Media queries can be used to alter the values, but they still won’t play nice with window resize. 163 | 164 | **警告**:Grid 会在页面重新加载的时候重新计算网格轨道(改变浏览器窗口后刷新页面试试),~~但是,window resize 并不会重新计算~~。利用媒体查询可以改变布局,但是还是不能配合 window resize 一起使用。 165 | > **译者注:测试发现在 window resize 的时候也会重新计算,原作者提到是 chrome 早起的 bug** 166 | > 参考资料 167 | > - 168 | > - 169 | > - 170 | 171 | ### Conclusion 172 | 173 | ### 总结 174 | 175 | Let’s wrap up with some bullets: 176 | 177 | - Media queries can help us *completely* rearrange Grid layouts by redefining ```grid-template-areas``` (and other things) for different scenarios. 178 | - CSS transitions don’t have any effect on changes made to the grid layout. 179 | - The ```auto-fill``` keyword is useful for filling up grid containers. 180 | - The ```minmax()``` function complements ```auto-fill``` nicely, making sure containers are properly filled, but doesn’t give us “responsiveness” in the true sense of the word. 181 | 182 | 我们来概括一下: 183 | 184 | - 通过媒体查询重新定义 ```grid-template-areas``` (或者其它的属性)为不同的场景实现不同的 Grid 布局 185 | - CSS transitions 对 Grid 布局中的相关属性无效 186 | - 关键字 ```auto-fill``` 处理完全填满 grid 容器的布局时非常有用 187 | - 方法 ```minmax()``` 配合 ```auto-fill``` 使用,可以确保容器正确的填充,但是,这并不是真正意义上的“响应式”。 188 | 189 | With the lessons learned in this series, you’re armed to go out and start playing with Grid! Stay tuned for more Grid tutorials, practical exercises, solutions to common layout problems, and updates. 190 | 191 | 通过这一系列的课程学习,你已经可以放心大胆的使用 Grid !敬请关注更多 Grid 教程、真实练习、常用布局的解决方案和更新。 192 | 193 | #### Useful Resources 194 | 195 | - Rachel Andrew’s [Grid by Example 29: minmax() 和 spanning columns 和 rows](http://codepen.io/rachelandrew/pen/GZQYQa) 196 | - Video: Rachel Andrew (obviously) [demonstrating minmax() on the Tuts+ homepage layout](https://www.youtube.com/watch?v=paBou8Fy25k&feature=youtu.be) 197 | - W3C Editor’s Draft: [auto-fill](https://drafts.csswg.org/css-grid/#valdef-repeat-auto-fill) 198 | - W3C Editor’s Draft: [minmax()](https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-minmax) 199 | 200 | #### 有用资源 201 | 202 | - Rachel Andrew’s [Grid 示例 29: minmax() and spanning columns and rows](http://codepen.io/rachelandrew/pen/GZQYQa) 203 | - 视频: Rachel Andrew (obviously) [minmax() 在 Tuts+ 首页的演示](https://www.youtube.com/watch?v=paBou8Fy25k&feature=youtu.be) 204 | - W3C 草案: [auto-fill](https://drafts.csswg.org/css-grid/#valdef-repeat-auto-fill) 205 | - W3C 草案: [minmax()](https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-minmax) 206 | -------------------------------------------------------------------------------- /Published/javascript/10-Super-Useful-Tricks-for-JavaScript-Developers.md: -------------------------------------------------------------------------------- 1 | # 10 Super Useful Tricks for JavaScript Developers 2 | 3 | ## JavaScript 开发者 10 个非常有用的技巧 4 | 5 | > 原文地址: 6 | **本文版权归原作者所有,翻译仅用于学习。** 7 | 8 | --------- 9 | 10 | ![](https://miro.medium.com/max/1400/1*lxVomliD0hEt7tFzApKvcw.jpeg) 11 | 12 | As we all know, JavaScript has been changing rapidly. With the new ES2020, there are many awesome features introduced that you might want to checkout. To be honest, you can write code in many different ways. They might achieve the same goal, but some are shorter and much clearer. You can use some small tricks to make your code cleaner and clearer. Here is a list of useful tricks for JavaScript developers that will definitely help you one day. 13 | 14 | 我们知道,JavaScript 正在迅速的发生改变。ES2020 中带来了很多神奇的功能。老实说,你有很多编写代码的方式。它们都可以达到相同的目的,但是,有一些就比较简单明了。你也可以使用一些技巧,让你的代码更加清晰。在这里我为 JavaScript 开发者列举一些有用的技巧,相信有一天会对你有帮助。 15 | 16 | ## Method Parameter Validation 17 | 18 | ## 函数参数校验 19 | 20 | JavaScript allows you to set default values for your parameters. Using this, we can implement a neat trick to validate your method parameters. 21 | 22 | JavaScript 允许你为函数参数设置默认的值。因此,我们可以用一个小技巧来检验函数的参数。 23 | 24 | ```js 25 | const isRequired = () => { throw new Error('param is required'); }; 26 | const print = (num = isRequired()) => { console.log(`printing ${num}`) }; 27 | print(2);//printing 2 28 | print()// error 29 | print(null)//printing null 30 | ``` 31 | 32 | Neat, isn’t it? 33 | 34 | 很整洁,是吧? 35 | 36 | ## Format JSON Code 37 | ## 格式化 JSON 代码 38 | 39 | You would be quite familiar with `JSON.stringify` by now. But are you aware that you can format your output by using `stringify` ? It is quite simple actually. 40 | 41 | 现在,你应该很熟悉 `JSON.stringify` 了。但是,你知道使用 `stringify` 可以格式化输出么?使用很简单。 42 | 43 | The `stringify` method takes three inputs. The `value` , `replacer` , and `space`. The latter two are optional parameters. That is why we did not use them before. To indent our JSON, we must use the `space` parameter. 44 | 45 | `stringify` 有三个参数。分别是 `value` , `replacer` , 和 `space`。后两个是可选的。这也是我们不常用的原因。为了格式化 JSON,我们必须使用 `space`。 46 | 47 | ```js 48 | console.log(JSON.stringify({name:"John",Age:23},null,'\t')); 49 | >>> 50 | { 51 | "name": "John", 52 | "Age": 23 53 | } 54 | ``` 55 | 56 | Here’s a React component I’ve published to [Bit](https://bit.dev/). Feel free to play with the stringify [example](https://bit.dev/eden/stringify-components/display-results). 57 | 58 | 我在 [Bit](https://bit.dev/) 发布了一个 React 组件。可以随意使用它来输出 stringify 的[结果](https://bit.dev/eden/stringify-components/display-results)。 59 | 60 | ## Get Unique Values From An Array 61 | ## 数组去重 62 | 63 | Getting unique values from an array required us to use the `filter` method to filter out the repetitive values. But with the new `Set` native object, things are really smooth and easy. 64 | 65 | 从数组中获取不重复的值我们需要使用 `filter` 来过滤那些重复的值。但是,使用 `Set` 对象,处理起来更加简单顺畅。 66 | 67 | ```js 68 | let uniqueArray = [...new Set([1, 2, 3, 3,3,"school","school",'ball',false,false,true,true])]; 69 | >>> [1, 2, 3, "school", "ball", false, true] 70 | ``` 71 | 72 | ## Removing Falsy Values From Arrays 73 | 74 | ## 移除数组中的假值 75 | 76 | There can be instances where you might want to remove falsy values from an array. Falsy values are values in JavaScript which evaluate to FALSE. There are only six falsy values in JavaScript and they are, 77 | 78 | - `undefined` 79 | - `null` 80 | - `NaN` 81 | - `0` 82 | - `“”` (empty string) 83 | - `false` 84 | 85 | 很多情况下,你希望移除数组中的假值。JavaScript 中的假值就是那些计算后是 FALSE 的值。JavaScript 中有六个假值: 86 | 87 | - `undefined` 88 | - `null` 89 | - `NaN` 90 | - `0` 91 | - `“”` (空字符串) 92 | - `false` 93 | 94 | The easiest way to filter out these falsy values is to use the below function. 95 | 96 | 过滤假值最简单的方式就是使用以下的方法。 97 | 98 | ```js 99 | myArray 100 | .filter(Boolean); 101 | ``` 102 | 103 | If you want to make some modifications to your array and then filter the new array, you can try something like this. Keep in mind that the original `myArray` remains unchanged. 104 | 105 | 如果,你想做些改变,然后过滤生成新的数组,你的代码看起来应该是这样。记住,原数组 `myArray` 会保持不变。 106 | 107 | ```js 108 | myArray 109 | .map(item => { 110 | // Do your changes and return the new item 111 | }) 112 | .filter(Boolean); 113 | ``` 114 | 115 | ## Merge Several Objects Together 116 | ## 合并对象 117 | 118 | I have had several instances where I had the need to merge two or more classes, and this was my go-to approach. 119 | 120 | 我有多个实例对象,我需要把它们合并在一起,我会使用以下的方式。 121 | 122 | ```js 123 | const user = { 124 | name: 'John Ludwig', 125 | gender: 'Male' 126 | }; 127 | const college = { 128 | primary: 'Mani Primary School', 129 | secondary: 'Lass Secondary School' 130 | }; 131 | const skills = { 132 | programming: 'Extreme', 133 | swimming: 'Average', 134 | sleeping: 'Pro' 135 | }; 136 | const summary = {...user, ...college, ...skills}; 137 | ``` 138 | 139 | The three dots are also called the spread operator in JavaScript. You can read more of their uses over [here](http://bit.ly/2s7pOm2). 140 | 141 | JavaScript 中三个连续的点也被称作为展开操作符。你可以在[这](http://bit.ly/2s7pOm2)了解更多情况。 142 | 143 | ## Sort Number Arrays 144 | 145 | ## 全数字的数组排序 146 | 147 | JavaScript arrays come with a built-in sort method. This sort method converts the array elements into strings and performs a lexicographical sort on it by default. This can cause issues when sorting number arrays. Hence here is a simple solution to overcome this problem. 148 | 149 | JavaScript 数组内置了 sort 方法。此方法会把数组中的元素转化成字符串,然后,按照默认的方式排序。如果,数组中全是数字这就会有问题。有一个简单的方式来解决这个问题。 150 | 151 | ```js 152 | [0,10,4,9,123,54,1].sort((a,b) => a-b); 153 | >>> [0, 1, 4, 9, 10, 54, 123] 154 | ``` 155 | 156 | You are providing a function to compare two elements in the number array to the sort method. This function helps us the receive the correct output. 157 | 158 | 你可以提供一个方法来对比数组中的两个元素。这个方法可以帮助我们得到正确的输出。 159 | 160 | ## Disable Right Click 161 | 162 | ## 禁用右键点击 163 | 164 | You might ever want to stop your users from right-clicking on your web page. Although this is very rare, there can be several instances where you would need this feature. 165 | 166 | 你或许希望禁止用户在你的站点页面上右击。尽管,这并不常见,但是,总会遇到这种需求。 167 | 168 | ```html 169 | 170 |
171 | 172 | ``` 173 | 174 | This simple snippet would disable right click for your users. 175 | 176 | 以上这种方式就可以禁用用户的右键点击。 177 | 178 | ## Destructuring with Aliases 179 | ## 解构中重命名 180 | 181 | The **destructuring assignment** syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables. Rather than sticking with the existing object variable, we can rename them to our own preference. 182 | 183 | **解构赋值** 是 JavaScript 中一种表达式,它可以从数组、对象中提取相应的值。相比使用对象中现有的属性命名,我可以按照自己的意愿重新为变量命名。 184 | 185 | ```js 186 | const object = { number: 10 }; 187 | // Grabbing number 188 | const { number } = object; 189 | // Grabbing number and renaming it as otherNumber 190 | const { number: otherNumber } = object; 191 | console.log(otherNumber); //10 192 | ``` 193 | 194 | ## Get the Last Items in an Array 195 | ## 获取数组中最后的元素 196 | 197 | If you want to take the elements from the end of the array, you can use the `splice` method with negative integers. 198 | 199 | 如果,你想获取数组中后面的元素,你可以使用 `splice` 方法并传递一个负整数参数。 200 | 201 | ```js 202 | let array = [0, 1, 2, 3, 4, 5, 6, 7] 203 | console.log(array.slice(-1)); 204 | >>>[7] 205 | console.log(array.slice(-2)); 206 | >>>[6, 7] 207 | console.log(array.slice(-3)); 208 | >>>[5, 6, 7] 209 | ``` 210 | 211 | ## Wait Until Promises Are Complete 212 | 213 | ## 等待 Promise 的完成 214 | 215 | There might be instances where you will need to wait for several promises to be over. We can use `Promise.all` to run our promises in parallel. 216 | 217 | 有些情况你需要等待多个 promise。我们可以使用 `Promise.all` 来并发多个 promise。 218 | 219 | *Note: Promises will run concurrently in a single-core CPU and will run in parallel in multi-core CPU. Its main task is to wait until all the promises that are passed to it are resolved.* 220 | 221 | *注意:Promise 在单核 CPU 会同时执行或者在多核 CPU 中并发。主线程将会等待所有 Promise 完成* 222 | 223 | ```js 224 | const PromiseArray = [ 225 | Promise.resolve(100), 226 | Promise.reject(null), 227 | Promise.resolve("Data release"), 228 | Promise.reject(new Error('Something went wrong'))]; 229 | Promise.all(PromiseArray) 230 | .then(data => console.log('all resolved! here are the resolve values:', data)) 231 | .catch(err => console.log('got rejected! reason:', err)) 232 | ``` 233 | 234 | One main thing to note about `Promise.all` is that the method throws an error when one of the promises reject. This would mean that your code will not wait until all your promises are complete. 235 | 236 | 需要注意的是:只要有一个 Promise reject,`Promise.all` 就会抛出一个错误。这就代表着你的代码不会等到所有的 Promise 完成。 237 | 238 | If you want to wait until all your promises are complete, regardless whether they get rejected or resolved, you can use the `Promise.allSettled` . This method is in the finalized version of ES2020. 239 | 240 | 如果,你想等待所有的 Promise 完成,而不关心它们是 rejected,还是 resolved,你可以使用 `Promise.allSettled`。这个方法是 ES2020 引入的。 241 | 242 | ```js 243 | const PromiseArray = [ 244 | Promise.resolve(100), 245 | Promise.reject(null), 246 | Promise.resolve("Data release"), 247 | Promise.reject(new Error('Something went wrong'))];Promise.allSettled(PromiseArray).then(res =>{ 248 | console.log(res); 249 | }).catch(err => console.log(err));//[ 250 | //{status: "fulfilled", value: 100}, 251 | //{status: "rejected", reason: null}, 252 | //{status: "fulfilled", value: "Data release"}, 253 | //{status: "rejected", reason: Error: Something went wrong ...} 254 | //] 255 | ``` 256 | 257 | *Even though some of the promises are rejected,* `Promise.allSettled` *returns the results from all your promises.* 258 | 259 | *尽管有些 Promise 返回了 rejected,`Promise.allSettled` 还是返回了所有的结果。* 260 | 261 | ## Publish and Reuse React Components with Bit 262 | 263 | ##用 Bit 发布和重用 React 组件 264 | 265 | [Bit](https://bit.dev/) makes it easy to publish reusable React components from any codebase to Bit’s component hub. 266 | 267 | [Bit](https://bit.dev/) 让发布可重用的 React 组件变得更加简单。 268 | 269 | **Need to update a published component?** `bit import` it into your project, change it, and push it back with a bumped version. 270 | 271 | **需要更新已发布的组件?**用 `bit import` 在你的项目中引用,改变它,然后用新的版本号推送到后台即可。 272 | 273 | [Share components](https://bit.dev/) with your team to maximize code reuse, speed up delivery, and build apps that scale. 274 | 275 | 在你的团队中[分享组件](https://bit.dev/),最大限度的复用代码,提升交付效率,然后,构建可扩展的应用。 276 | 277 | ![](https://miro.medium.com/max/1400/1*Nj2EzGOskF51B5AKuR-szw.gif) -------------------------------------------------------------------------------- /Published/Testing-React-with-Jest-and-Enzyme-II.md: -------------------------------------------------------------------------------- 1 | # Testing React with Jest and Enzyme II 2 | 3 | ## 用 Jest 和 Enzyme 测试 React II 4 | 5 | > 原文地址: 6 | **本文版权归原作者所有,翻译仅用于学习。** 7 | 8 | --------- 9 | 10 | ![](https://miro.medium.com/max/1400/1*nG8BY3_MIe8STVFBU-qJRw.png) 11 | 12 | Previously we looked at how to [setup Jest and Enzyme](https://medium.com/codeclan/testing-react-with-jest-and-enzyme-20505fec4675) with some and took a slight detour to look at[ mocking ES and CommonJS modules with Jest](https://medium.com/codeclan/mocking-es-and-commonjs-modules-with-jest-mock-37bbb552da43). 13 | 14 | 先前,我们已经知道如何[设置 Jest 和 Enzyme](https://medium.com/codeclan/testing-react-with-jest-and-enzyme-20505fec4675),并且,顺便了解了 [Jest 中如何模拟 ES 和 CommonJS 模块](https://medium.com/codeclan/mocking-es-and-commonjs-modules-with-jest-mock-37bbb552da43)。 15 | 16 | In this post we are going to look at some additional examples of how to simulate user interaction with a component via Enzyme to create specific test scenarios. 17 | 18 | 在这篇文章中,我们将会看到更多的示例:如何通过 Enzyme 创建特殊的测试场景模拟组件中用户的交互。 19 | 20 | We will be using Enzyme’s **mount** for full DOM rendering as described in the first post of this series. To summarise, from the [docs](https://airbnb.io/enzyme/docs/api/mount.html): 21 | 22 | > *Full DOM rendering is ideal for use cases where you have components that may interact with DOM APIs or need to test components that are wrapped in higher order components.* 23 | > 24 | > *If you do not want to run your tests inside of a browser, the recommended approach to using `mount` is to depend on a library called [jsdom](https://github.com/tmpvar/jsdom) which is essentially a headless browser implemented completely in JS.* 25 | 26 | 如本系列第一篇文章所述,我们将会用 Enzyme 的 **mount** 的方法来实现组件的完整的渲染。来自[文档](https://airbnb.io/enzyme/docs/api/mount.html)的总结: 27 | 28 | > *在需要组件与 DOM API 交互或者测试那些被高阶组件包含的组件时,完整的 DOM 渲染是最理想的方式* 29 | > 30 | > *如果,你不打算在浏览器中运行测试,推荐使用 `mount`,它依赖 [jsdom](https://github.com/tmpvar/jsdom) 库,这个库本质上是一个用 JS 实现的 headless 浏览器。* 31 | 32 | This is what gives us the ability to interact with our React component as if we were inside a browser. 33 | 34 | 这让我们可以与组件交互,就像在浏览器中一样。 35 | 36 | The examples given are based on the following versions: 37 | 38 | 以下是基本的版本配置: 39 | 40 | ```json 41 | "enzyme": "^3.3.0", 42 | "enzyme-adapter-react-16": "^1.1.1", 43 | "enzyme-to-json": "^3.3.3", 44 | ``` 45 | 46 | ## Simulating events 47 | 48 | ## 模拟事件 49 | 50 | Enzyme syntax for simulating user interaction is straight forward to read, at it simplest as below on a mounted component: 51 | 52 | Enzyme 中模拟用户交互的语法非常简单直接,以下就是最简单的示例: 53 | 54 | ```js 55 | component.find(selector).simulate(event); 56 | ``` 57 | 58 | ### Selectors 59 | ### 选择器 60 | 61 | [Selectors](https://airbnb.io/enzyme/docs/api/selector.html) can be one of a: 62 | 63 | - CSS Selector 64 | - Prop Attribute Selector 65 | - Prop Object Selector 66 | - React Component Constructor 67 | - React Component displayName 68 | 69 | [选择器](https://airbnb.io/enzyme/docs/api/selector.html) 是下面的其中之一: 70 | 71 | - CSS 选择器 72 | - Prop 属性选择器 73 | - Prop 对象选择器 74 | - React 组件构造函数 75 | - React 组件 `displayName` 76 | 77 | In the examples covered here we will just look at the syntax behind different ways of targeting CSS selectors. The Enzyme docs are well written and contain good examples to continue reading if a CSS selector does not fit your purpose. 78 | 79 | 在这篇文章中,我们只会查看 CSS 选择器的几种不同方式。如果,CSS 选择器不能满足你的需求,可以继续查阅文档,Enzyme 的文档写的非常好,也有很好的演示。 80 | 81 | Directly from the documentation we can see that the following are supported: 82 | 83 | - Class syntax (`.foo`, `.foo-bar`, etc.) 84 | - Element syntax (`input`, `div`, `span`, etc.) 85 | - ID syntax (`#foo`, `#foo-bar`, etc.) 86 | - Attribute syntax (`[href="foo"]`, `[type="text"]`, etc.) 87 | 88 | With combinations of the above possible (`button#id-foo`, etc). 89 | 90 | 通过文档我们知道 CSS 选择器支持以下几种: 91 | 92 | - 类选择器(`.foo` `.foo-bar` 等) 93 | - 元素选择器(`input` `div` `span` 等) 94 | - ID 选择器(`#foo` `#foo-bar` 等) 95 | - 属性选择器(`[href="foo"]` `[type="text"]` 等) 96 | 97 | 以上语法也可以组合使用(`button#id-foo`)。 98 | 99 | A common error to see is `Method "simulate" is only meant to be run on a single node. 3 found instead.` if a sub-component being interacted with is used more than once in the parent. 100 | 101 | 如果,父组件中存在多个需要交互的子组件时,一个常见的错误:`Method "simulate" is only meant to be run on a single node. 3 found instead`。 102 | 103 | This is a simple fix, as it is possible to specify the index of the node you wish to interact with: 104 | 105 | 这也很容易修复,你可以给需要交互的 node 指定索引: 106 | 107 | ```js 108 | // the initial 109 | component.find([className="checkbox__input"]).simulate(event);// becomes 110 | component.find([className="checkbox__input"]).at(1).simulate(event); 111 | ``` 112 | 113 | ### Events 114 | ### 事件 115 | 116 | Enzyme’s [simulate](https://airbnb.io/enzyme/docs/api/ReactWrapper/simulate.html) is used for simulating [DOM Events](https://developer.mozilla.org/en-US/docs/Web/Events), common ones being ‘click’, ‘change’, and ‘keydown’. After the node is selected simulate is chained on as to complete the mock interaction: 117 | 118 | Enzyme 的方法 [simulate](https://airbnb.io/enzyme/docs/api/ReactWrapper/simulate.html) 可以用来模拟 [DOM 事件](https://developer.mozilla.org/en-US/docs/Web/Events),常用的有:`click`、`change`、`keydown`。选定 node 后,可以直接链式调用 simulate 来完成模拟交互: 119 | 120 | ```js 121 | component.find(selector).simulate('click'); 122 | component.find(selector).simulate('change'); 123 | component.find(selector).simulate('keydown', { keyCode: 32 }); 124 | ``` 125 | 126 | ## Writing tests 127 | 128 | ## 编写测试用例 129 | 130 | ### Testing re-rendering 131 | 132 | ### 测试重新渲染 133 | 134 | If a DOM event causes a re-render, unmounting of a child component for example, then [Jest Snapshot testing](https://jestjs.io/docs/en/snapshot-testing) can be used to test the component renders as expected. 135 | 136 | 如果,DOM 事件引起组件重新渲染,卸载子组件,这时,[Jest 快照测试](https://jestjs.io/docs/en/snapshot-testing)就可以来验证组件是否正确的重新渲染。 137 | 138 | ```js 139 | it('should be possible to open menu with Spacebar', done => { 140 | const component = mount(); 141 | component.find('#link-id').simulate('keydown', { keyCode: 32 }); 142 | expect(component).toMatchSnapshot(); 143 | component.unmount(); 144 | }); 145 | ``` 146 | 147 | ### Testing function calls 148 | ### 测试函数调用 149 | 150 | If a function is passed to a child component you may wish to test that it is called correctly when mounting the parent. The function is first mocked and passed as the correct prop. 151 | 152 | 如果,一个函数传递了子组件,你希望在父组件挂载的时候,验证它是否被正确的调用。首先,需要模拟这个函数,然后,以 prop 的形式传递下去。 153 | 154 | ```js 155 | const mockFunction = jest.fn(); 156 | it('should call mockFunction on button click', () => { 157 | const component = mount( 158 | 159 | ); 160 | component.find('button#ok-btn').simulate('click'); 161 | expect(mockFunction).toHaveBeenCalled(); 162 | 163 | component.unmount(); 164 | }); 165 | ``` 166 | 167 | ### Testing state or prop updates 168 | 169 | ### 测试 state 或者 prop 的更新 170 | 171 | The component [state](https://airbnb.io/enzyme/docs/api/ReactWrapper/state.html) and [props](https://airbnb.io/enzyme/docs/api/ShallowWrapper/props.html) are also possible to evaluate. 172 | 173 | 组件中的 [state](https://airbnb.io/enzyme/docs/api/ReactWrapper/state.html) 和 [props](https://airbnb.io/enzyme/docs/api/ShallowWrapper/props.html) 也可以测试验证。 174 | 175 | ```js 176 | it('sets loading state to true on save press', () => { 177 | const component = mount(); 178 | component.find('[className="save-button"]').simulate('click'); 179 | expect(component.state('isLoading')).toEqual(true); 180 | component.unmount(); 181 | }); 182 | ``` 183 | 184 | ### Other interactions with the document 185 | 186 | ### 与 document 的其他交互 187 | 188 | As `mount` has access to a full DOM many other aspects can be included in tests. 189 | 190 | 因为,`mount` 可以渲染完整的 DOM,因此,可以包含其他很多方面的测试。 191 | 192 | This includes the [cookies](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie) associated with the current document. These are accessible via `document.cookie`. To prevent changes from persisting between tests you may wish to use something such as 193 | 194 | 这也包括与当前 document 关联的 [cookies](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie)。它可以通过 `document.cookie` 访问。为了防止测试之间相互影响,你或许需要用到以下方式 195 | 196 | ```js 197 | beforeEach(() => { 198 | document.cookie = ''; 199 | }); 200 | ``` 201 | 202 | to reset their values. 203 | 204 | 去重置它的值。 205 | 206 | If the component synced a cookie value to what is in state on mount then the following test could be considered: 207 | 208 | 如果,组件在挂载时想同步 cookie 的值到 state 中,可以考虑以下的测试: 209 | 210 | ```js 211 | it('syncs state with user cookie on mount', () => { 212 | document.cookie = 'cookieOne=valueOne:::false&valueTwo:::true'; 213 | 214 | const component = mount(); 215 | expect(component.state('valueOne')).toEqual(false); 216 | expect(component.state('valueTwo')).toEqual(true); 217 | component.unmount(); 218 | }); 219 | ``` 220 | 221 | ## Final thoughts 222 | ## 最后的思考 223 | 224 | Hopefully this provides an indication of the possibilities that exist when using Jest and Enzyme together, and the examples here are readable enough to use the parts that apply to your own projects. 225 | 226 | 希望这能说明在一起使用 Jest 和 Enzyme 是存在可能,这里的示例也具可读性,足以用到你自己的项目中。 227 | 228 | An additional tip is that if user interactions are not producing the results that you are expected debugging can be aided with adding the Enzyme specific 229 | 230 | 另外一个提示:如果,用户交互没有产生预期的结果,Enzyme 中的 debug 可以帮到你 231 | 232 | ```js 233 | console.log(component.debug()) 234 | ``` 235 | 236 | to see a snapshot of the mounted component at that time. 237 | 238 | 这时,需要去看看组件挂载后的快照。 239 | 240 | Thanks for reading, and if you have posts of your own that expand on this feel free to link them in the comments! 😁 241 | 242 | 多谢你们喜欢,如果,你有更多的见解,可以在评论中提出!😁 243 | 244 | Other posts I have written include: 245 | 246 | - [Mocking HTTP requests with Nock](https://codeburst.io/testing-mocking-http-requests-with-nock-480e3f164851) 247 | - [Using Pa11y CI and Drone as accessibility testing gatekeepers](https://hackernoon.com/using-pa11y-ci-and-drone-as-accessibility-testing-gatekeepers-a8b5a3415227) 248 | - [What are encryption keys and how do they work?](https://medium.com/codeclan/what-are-encryption-keys-and-how-do-they-work-cc48c3053bd6) 249 | 250 | 我还写了其他的文章: 251 | 252 | - [用 Nock 模拟 HTTP 请求](https://codeburst.io/testing-mocking-http-requests-with-nock-480e3f164851) 253 | - [使用 Pa11y CI 和 Drone 做可访问性测试](https://hackernoon.com/using-pa11y-ci-and-drone-as-accessibility-testing-gatekeepers-a8b5a3415227) 254 | - [密钥是什么,它们是如何工作的?](https://medium.com/codeclan/what-are-encryption-keys-and-how-do-they-work-cc48c3053bd6) 255 | 256 | --------------------------------------------------------------------------------