让天下没有难学的编程 |


Auld Lang Refactoring

New Year’s is filled with resolutions to work out, diet, exercise, and get more organized. This year, I’d like to get my knee in order so I can run again, continue on my vegan endeavors, and keep our apartment decluttered now that we have an infant. Tidying up got me thinking about code and refactoring. Frameworks like React and Rails offer structures to encourage code to stay clean and tight with their uses of modules and components. But sometimes when writing JavaScript from scratch, refactoring and keeping clean code can quickly get out of hand. I wanted to create a before and after example using plain JavaScript as an exercise in refactoring. The program is simple: use an input to add an item to an array and show the results on the page. Here is the “before” starter code: HTML: <div class="container"> <h1>Add Item to Array</h1> <form id="form"> <input type="text" id="item"> <input type="submit"> </form> <pre id="output">Ouput here...</pre> </div> JS: let list = [] let form = document.getElementById('form') let output = document.getElementById('output') form.addEventListener('submit', (e) => { e.preventDefault() let item = document.getElementById('item') list.push(item.value) output.innerHTML = list item.value = '' }) First I created an empty array named list. I grabbed the form and output using getElementById() then setup an event listener on the form. When submit is detected, I grabbed the input id (item) and pushed the value onto the list array. Once the list was updated, I populated the pre tag with the array. Finally, I cleared the input. The code works! But much like the Cleveland Browns, just because they have uniforms, a team name, and a quarterback, doesn’t mean the organization is streamlined and firing on all cylinders. The problem with our code is that we have three variables floating around in the global scope, which could have implications in the future if we add new variables. All of our functionality, adding the item to the list, clearing the input, and outputting the array, is packed inside our event listener, making it confusing to understand and hard to read. And if we want to add more features in the future, we’re going to have lots of cluttered code to sift through. I learned to always write the code I wish I had, then work backwards. So in this case, I’d like to have a function to call like this to start things off: const formListener = (form) => {} formListener(form) This function nicely wraps our code so we don’t have any stray variables outside roaming around like a lost Browns receiver running the wrong route. I added our list array inside and created our event listener on our form: const formListener = (form) => { let list = [] form.addEventListener('submit', (e) => { e.preventDefault() }) } formListener(form) I wanted my event listener to only deal with grabbing the input value and clearing: const formListener = (form) => { let list = [] form.addEventListener('submit', (e) => { e.preventDefault() let item = document.getElementById(‘item') item.value = ‘' }) } formListener(form) Next, I wanted a function to add our input value to our array. Something like addItem(): const addItem = (item, list) => list.push(item) const formListener = (form) => { let list = [] form.addEventListener('submit', (e) => { e.preventDefault() let item = document.getElementById(‘item') addItem(item.value, list) item.value = ‘’ }) } formListener(form) Finally, I created another function to show the array on the page, show(), and then called our formListener() function with our form: const addItem = (item, list) => list.push(item) const show = (list) => document.getElementById('output').innerHTML = list const formListener = (form) => { let list = [] form.addEventListener('submit', (e) => { e.preventDefault() let item = document.getElementById('item') addItem(item.value, list) show(list) item.value = '' }) } formListener(document.getElementById('form')) While this may be a silly example, I hope it sheds some light on the thought process that goes into refactoring, even if the un-refactored code is simple. Refactoring is a lot like writing — you write a horrible first draft, then go back and rewrite, rewrite, and rewrite until it’s clean and streamlined. Unless you’re the Browns, of course. http://danielwarren.io/2017/12/31/auld-lang-refactoring 收起
显示全部文字 查看全文
作者/Daniel Warren
时间/2018-01-01 10:12:52

My 2017 on CodePen

I was thinking: no need to write a 2017 blog post like I did about my 2016 on CodePen since I haven't done anything. Then I looked back on the things I made and realized that I actually have created a bunch! 129 public and 121 private Pens, two blog posts and three projects! So I changed my mind, here is "My 2017 on CodePen". Pens This post contains many animated Pens, I've put some of them on pause to not hog your computer totally. Just click Run Pen to start them. Unfortunately there is no Stop Pen functionality, but you can reload the page if it becomes to heavy. I've picked my favorites, not all 129 =) There is a theme to the majority of my work: explore a concept by making many variations of it. Rotating Squares First concept was "rotating squares". I was just fooling around with an animation based on a rotating square. I liked the result so I continued with two squares and three squares and so on all the way to nine. Key ingredients: using trigonometric functions for the paths of the squares rotate each square along its own axis by not clearing the canvas, cool patterns emerge My favorite is "Seven Rotating Squares": Here is the complete collection: "Rotating Squares | p5js" which is well suited to watch as CodePen TV. Random Walk Second concept was Random Walk. I've written a blog post which you can read for all the details. Here I will just show you some of the Pens. This is the starting point, a random walker: This is "Brownian Gnats". "Wayward Walker Worms" "Portrait by Brownian Motion" Flow Field Third concept was Flow Field. It all started because I was inspired by Daniel Shiffman and his video about flow field, I wanted to make pretty patterns by tracing particles in a flow field. I've written a blog post called Particles in a Simplex Noise Flow Field about this that explains it all, including the building blocks: vectors, noise and particles. This is a flow field that is controlled by 3D simplex noise. These are particles who's motion is controlled by the flow field. This is the pattern traced by the moving particles. Here I let an image influence parts of the flow field to create a text effect. I celebrate 500 CodePen followers! =) Instead of letting an image influence the flow field, you can place the vectors of the flow field at the outline of a text and get this effect. Circle Morphing Fourth concept. Again it was time for Daniel Shiffman to inspire me, this time together with Golan Levin when they announced the circlemorphing challenge on the Coding Train: create an animation that morphs a triangle or a square to a circle. Here are three of my contributions. I was so happy when Dan in a later episode shows some of my animations and mentions me. Direct link, 16 min and 18 sec in, episode: "Live Stream #105: p5.js Workflow, Circle Morphing and Arrow Function" Explore peoples contributions on Twitter using the circlemorphing hashtag. Misc That was my four concepts that I explored. Here comes some random bits and pieces that I created in 2017. I learned to write GLSL shaders. Holy smoke, Batman, how performant they are! The best place for shaders is Shadertoy.com, here is my profile. I've ported some of my shaders to CodePen, one if them is "Liquid Rainbow". As you can read further down I organized two CodePen meetups, one was about Web Audio API. During the last part of the evening we sat down and hacked some Web Audio API together, one of the attendees came up with the idea to create a scratch pad which I completed a week later. It uses the Amen break from the track "Amen, Brother", the most sampled track in the history of music. By reading this article in The Guardian I learned how to make a Harriss Spiral. I was browsing the #lissajous hash tag on Twitter and found this tweet. I just had to make one of my own. Plotting Lissajous curves by combining different rotation speeds of x and y. Move the mouse over the canvas, "Circuit Board Warper". "Sine Perlin" "Origo Sine" "SPIKY" "Circle Fractal" "Star | p5js" "3D-ish Lissajous Knot" "Antenna Generator" click to generate a new random pattern. But, but, but ... what about Web Audio API?! Relax, of course I made some Pens using Web Audio! This one is "Stomper Tribute", a tool for making bass drum sounds mainly, but you can use it to make some fun noises too. Try it out. It is a tribute/re-make of a program that I used in the 90-ies. Projects I almost forgot this part because I haven't used this feature much at all, but I made three CodePen project: Rays and Particles Gravity of Love Puzzle Game Blogging I've already mentioned the two blog posts, here they are again: Random Walk Particles in a Simplex Noise Flow Field Meetups I had already organized a few meetups before and I like it. In 2017 I decided to start a group on Meetup.com and have recurring CodePen meetups. There was one in April and one in June. The first one was about Creative Coding and the second was about Web Audio API. Both followed the same schedule: Food and socializing, I talked for a while about the topic, live coded a bit, CodePen swag raffle, Show and tell - any one can talk for 10 min about a web project of theirs, Coding together Thanks to the awesome CodePen team for sending awesome swag! The CodePen T-shirt is soooo comfy. The Meetup group has grown so much that it requires me to upgrade to a more expensive pricing plan. Luckily my employer Enfo is sponsoring that. =) Summary I'm most proud of my CodePen meetups and my flow field experiments. I'm happy to have hit both 400 and 500 followers during the year. I'm also proud to be featured in Spark 6, Spark 15, Spark 19, Spark 20 and Spark 49. The Furure, 2018 I will continue hosting CodePen meetups, I will try and have more than two during the year =). I'm not sure at all what Pens (or Projects) I will make. But I'd like to continue picking a part a concept and explore it by making many variations of it. My goal is to write blog posts about those journeys. I hope to continue my exploration of FM synthesis with Web Audio API and make it public.收起
显示全部文字 查看全文
作者/Johan Karlsson
时间/2018-01-01 04:10:46

Re-creating Cookie Advent Calendar with CSS Grid

At the beginning of December as I started enjoying a new round of Web developer "Advent Calendars" like 24ways.org, I thought about a project that I was involved in 6 years ago. I was part of a scrum team for SAVEUR, a food, entertaining, and travel magazine. The SAVEUR team had an idea for a cookie advent calendar. I really liked working with the SAVEUR team because they always had creative ideas for layouts. I also appreciated that they valued the input of the developers to help improve the project by bringing our code creativity to the table. When we met for a scrum meeting, we were shown a mockup of what they wanted. They had hired a New York illustrator who created 5 rows of 5 cars each. The cards were slightly different sizes and had different skews. They wanted it to have an organic feel. They had some ideas for what they wanted the interaction to be like. They wanted some kind of action when the user hovered over the individual cards and then they wanted the cards to flip to reveal the cookie card that linked to a recipe. They wanted it to act as a true Advent calendar where users would return to the site to click on other recipes that became available on a daily basis. Finally, they wanted the page to remember the cards that the users had already chosen and flipped. Final solution on SAVEUR.com For the original layout, I decided to use absolute positioning for each of the different cards. I am not quite sure why I chose to do it that way. I am guessing some of it had to do with where I was at in my CSS skills at the time and some of it was influenced by browser capability at the time. The project had a quick turn-around time so I am guessing that was also a factor in my decision at the time. CSS Animations were pretty new at the time. I was looking forward to dabbling into it. My first pass at the hover animation for the cards was a type of "pulse" animation. We decided against it for a variety of reasons including it might be problematic for those with seizure disorders. After some experiementation, we decided on a "shake" type animation. It ended up being implemented in JavaScript. My skills were not advanced enough at the time to tackle the JS so that was done by the back-end developer. Re-creation As I revisited the project, I was thinking about how I could easily recreate it using CSS Grid. I started learning and implementing Grid layouts about a year ago and have continued to build my skills this year. I thought it would be fun to re-create this project with my new skills. As I looked at the screenshot I had of the original page, I determined the sizing I needed to create it in Grid. I still used some absolute positioning to offset the individual cards and allow some of them to bleed into the grid gaps. I realized as I was writing this that I did not need absolute positioning but could just use negative margins. This simplifies the code just a bit. The original layout was a fixed width layout and I decided to stick with that for this re-creation. I defined a simple 5 column grid of 181 pixels width with a vertical gap of 10 pixels and horizontal gap of 15 pixels between the columns. Thanks to a Little Snapper Web Archive, I was able to get the image sprites and CSS code I had used in the original project for background positioning of the the different card images. The original shake animation was written in JavaScript, I updated this version to use CSS animation. I wrote brand new scripting for the functionality that included: Flip the card on click Only enabling cards to be flipped if they were the current date or past date in the month Created a cookie to keep track of the cards that had already been flipped Added the functionality to reset the calendar (the cookie) so that none of the cards were flipped 收起
显示全部文字 查看全文
作者/Jeff Bridgforth
时间/2017-12-30 13:50:26

Thoughts on a Syntax for Element Queries

It's possible to think of Element Queries as a natural extension to CSS Media Queries. I would summarize the requirements for media queries like this: a media type query condition(s) a stylesheet In CSS this gets exposed as: @media screen (min-width: 500px) { html { background: lime; } } The @media wraps the stylesheet, the screen part is specifying the media type, and (min-width: 500px) specifies the query condition(s). In HTML the same functionality is exposed through the media="" attribute on <style> and <link> tags: <link rel="stylesheet" media="(min-width: 500px)" href="data:text/css,html { background: lime; }"> <style media="(min-width: 500px)"> html { background: lime; } </style> Finally, in JavaScript the media querying functionality is available to authors using the window.matchMedia: if (window.matchMedia('(min-width 500px)').matches) { css = 'html { background: lime; }' } In order to extend these syntaxes in HTML, CSS, and JavaScript to cover the functionality needed to describe element queries, let's look at the requirements for element queries: a selector (list) query condition(s) event listener(s) a stylesheet Here we have a couple new ideas: a selector to apply the stylesheet to, and event listeners. Element Queries in CSS Normally JavaScript events are abstracted away from CSS authors - you don't need to worry about window.load or window.resize when writing media queries, you don't need to worry about mouseover or mouseout when writing :hover, and you're not worried about focus or blur when using :focus, etc. For the most part I believe browser makers will be able to find a way to implement element queries in the most general sense without the need for CSS authors to specify the specific events they should listen to. In addition, enhancements may be made by listening to specific events related to the selector, and/or query conditions. If a query condition for scroll is used, the browser should be able to automatically listen to scroll events on the tags matching the selector used. However it is likely that performance improvements could be made by allowing authors to limit which events trigger a reevaluation of the query conditions using a whitelist. Proposed CSS Syntax: @element html { html { background: lime; } } Here the @element wraps the stylesheet, the html specifies the selector, and we are lacking query conditions or events. This is a simple element query that would apply to the document as long as an <html> element was found. @element textarea (min-characters: 50) { textarea { background: lime; } } This example includes a query condition that counts the number of characters of text inside the value of a <textarea> element. This brings us naturally to the question: "What happens if there is more than one <textarea> in the document?" It certainly looks like as long as any <textarea> has more than 50 characters, all <textarea> tags in the document will gain a style. Because of this, another concept is required: a scoped selector. I like the idea of using $this as a placeholder inside selectors in the element query stylesheet, to represent each element tested that passes the query conditions. @element textarea (min-characters: 50) { $this { background: lime; } } Now if we have multiple <textarea> present in our document we have a way of targeting only those specific <textarea> elements that match the query conditions. But the use of this placeholder isn't limited to just applying styles to matching elements themselves - it should be able to be used anywhere in selectors in the container stylesheet: @element .widget (max-width: 300px) { $this h2 { font-size: 10pt; } } Lastly, a way to specify limited events should be offered to the user. This has no precedent in CSS so here are some ideas. It's possible that the specific names of events could be aliased to something new, but assuming for a moment that we are using the names of events from JavaScript, we need a way to specify both window-level, and tag-level event listeners. Maybe something like: @element textarea (max-characters: 5) on blur { $this { background: red; } } I would hope that by default, based on this query applying to an input element it would naturally listen to events like blur and focus and reevaluate the query conditions when those events occur, but here we limit reevaluation only to the blur event, and it is prevented from reevaluating any other time. Element Queries in HTML How could the same element query functionality be exposed to HTML? Perhaps through the use of additional attributes on <style> and <link> tags: selector for a selector list element for query conditions event for events These could look like the following: <link rel="stylesheet" selector="textarea" element="(max-characters: 5)" event="blur" href="data:text/css,$this { background: lime; }"> <style selector="textarea" element="(max-characters: 5)" event="blur"> $this { background: lime; } </style> Element Queries in JavaScript And to expose this functionality to JavaScript, perhaps something like window.matchMedia could be useful, maybe window.matchElement. It would work similarly to this: document.querySelectorAll(<selector>).filter(<query conditions>) So for an element query of (min-width: 500px) on <div> tags you would need a test like: document.querySelectorAll('div').filter(el => el.offsetWidth > 500) This works fine, but the real power of window.matchMedia is that it's able to handle CSS units, rather than just working with pixels. Having the ability to do something like the following example would be better than what we have in JavaScript right now: window.matchElement('div', '(min-width: 50em)') References If you're looking for syntax precedents for these ideas, or plugins that use something similar, check out: @element at-rule similar to EQCSS <link> attributes similar to Slinky <style> attributes similar to reproCSS 收起
显示全部文字 查看全文
作者/Tommy Hodgins
时间/2017-12-24 12:18:52

Progressive web applications - 1/2

What are progressive web applications: If you went to google, and read their explanation.. you probably wouldn't know what progressive web applications. I read a few other articles that didn't neccesarily clarify what they were. I think this happens for two reasons: - they aren't neccesarily different to other applications - they are very simple, simple things aren't always easy to explain. What exactly are they? The best way I understand them is by this: PWA are Web applications that are built and behave like other web apps in that they rely (or not.. ) on a server and render on the browser. They however.. can look and behave like native phone applications. And thus.. the attraction to them. For a company can be hard to choose what platforms to support for several reasons. In order to natively support many platforms you need to develop on different languages and support different codebases. The beauty of web applications is that they can render in many platforms without neccesarily create different codebases. They are as powerful as any other web application when it comes to create and implement new features. Behaviour wise? Well, they behave as any other native application. This means mostly that your future users don't have to learn any new behaviour. As far as they are concerned..this application it's like any other on their phone. They also have now push notifications. Layout and structure Like any other application for web, the layout en structure will depend on the framework you use and the patterns you decide to pursue. But nothing needs to be modified in order to be used on any platform. Other than, of course, having in mind different browsers. So there it is. The definition of a progressive web application is done. Complexity The technical complexity of the parts that compone them is something that I will tackle on the next post. I believe that the definiton of them is so vague, I was happy to simply explain it in a post, to take it out of the way and set the basic idea before moving onto how they are done. 收起
显示全部文字 查看全文
时间/2017-12-23 05:35:35

NADCAST.10 с Минко Гечев и Радо Станков

Предколеден 10-ти епизод на NADCAST е с Радо Станков и Минко Гечев. Разговора започна с малко meta теми, но после си поговорихме за Angular, React и JavaScript като цяло. Приятно слушане и весели празници.收起
显示全部文字 查看全文
时间/2017-12-22 06:00:00

#366: 10 Insights from the State of JS Survey

This week's JavaScript news — Read this e-mail on the Web JavaScript Weekly Issue 366 — December 22, 2017 2017 is almost over and we're taking a week off for Christmas - we hope you have a good one! We'll be back on January 5 with a special 'best of 2017' issue. If you write or develop anything awesome for our January 12 issue, just hit reply and let us know so we can consider it :-) We also have a popular Medium publication if you use that platform.- The JavaScript Weekly team (Peter, Chris, and Za'e) Everything You Need To Know About Parcel: The Web App Bundler Parcel only came out two weeks ago, but it’s already making waves, including within the webpack project itself. Indrek Lasn 10 Insights from the State of JS Survey Over 23,000 developers responded, and Sacha Grief analyzes the results. GraphQL and TypeScript are set for a great 2018, and most developers think JS is headed the right way. Sacha Greif Wes Bos Explains Async/Await in 15 Minutes [video] This is a really accessible, well presented, and short introduction to the main principles behind using async/await vs promises, if you’re not up to speed yet. dotJS 2017 MongoDB 3.6 Sessions Explained by Percona As mentioned in our last post, we are looking deeper into new sessions in MongoDB 3.6. Many of the cornerstone features of 3.6 depend directly or indirectly on sessions - things like “retryable” writes, causal consistency, killSession (global killOp) & more. Percona   Sponsor How to Become a Better Node.js Developer in 2018 A few straightforward best practices which could help you be a better Node developer in the coming year. Gergely Nemeth The Future of State Management with Apollo GraphQL A look at using apollo-link-state to manage your local data in Apollo Client, a JavaScript GraphQL client, thus avoiding using something like Redux altogether. Peggy Rayzis Take the 2017 JavaScript Ecosystem Survey npm Inc. and the JS and Node foundations are running a 10 minute ‘JavaScript ecosystem survey’ so make your voices heard. npm Inc, JS Foundation, and Node Foundation V8 Release v6.4: Yet More Speed and Memory Savings Google’s JavaScript engine shows no sign of slowing down any time soon. The 6.4 branch also introduces support for two new regular expression features. Mathias Bynens Jobs We’re Always Looking for Exceptional Software Engineers (New York)We need passionate, experienced people that can fill hybrid roles with different emphases on the context of product development. Reaktor Work with JS at Forza Football, A Product with Millions of UsersForza Football is looking for a frontend developer to join our amazing team located in Sweden. Visa/relocation sponsorship available. Forza Football Looking for a Job at a Company That Prioritizes JavaScript?Try Vettery and we’ll connect you directly with thousands of companies looking for talented frontend devs. Vettery Can't find the right job? Want companies to apply to you? Try Hired.com.-->In Brief The Future of jQuery UI and jQuery Mobile newsjQuery UI Blog A Free 'TypeScript Fundamentals' Course course It used to cost money. Now it doesn’t.James Henry Practical Redux: Beyond the Todo App course Mark Erikson on what happens if you try to build something bigger than yet another TodoMVC app using Redux?Educative  Sponsor The 'Reflect' Object, Use Cases and Things to Watch Out for tutorial A neat look at a slice of not commonly used JavaScript.Stefan Judis Testing Angular 2 and Continuous Integration with Jest tutorialMatt Fehskens An Introduction to Weak Value Maps tutorialKris Zyp How 'Controllable' React Components Maximize Reusability tutorial A deep dive into what really makes React components reusable.Noam Elboim How to Build a Realtime Poll in 5 Steps tutorialChristian Nwamba Using OpenCV from Node to Recognize Objects in Images tutorial nodeVincent Mühler Building a Voice-Activated Movie Search App Powered by Amazon Lex, Lambda, and MongoDB Atlas (Part 2) tutorialmongodb  Sponsor WebAssembly Will Let You Run High-Perf Apps in Your Browser story A neat high level overview of WebAssembly.IEEE Spectrum Which JavaScript Frameworks Are the Fastest? opinionJohn Hannah Is jQuery Still Relevant? opinionRemy Sharp Angular Top 50: What You Should Have Read in 2017 opinionLukas Marx Webpack-CLI 2.0 Released: Webpack's Command Line Interface toolswebpack Jest 22 Released: Facebook's Popular JS Testing Tool tools A major release refining almost all parts of Jest. Babel 7 support too.Facebook Cloud-Scale Monitoring and Alerting from Datadog tools See your entire stack in one place with unified dashboards and 200+ technology integrations. Try Datadog free.Datadog  Sponsor React Content Loader: A 'Content is Loading' Component using SVG codeDanilo Woznica 11 Vue.js Component Libraries You Should Know In 2018 codeJonathan Saring Unchanged: A Fast Handler for Updating JS Objects and Arrays Immutably codeTony Quetano element-ready: Detect When an Element is Ready in the DOM codeSindre Sorhus Curated by Peter Cooper and published by Cooperpress. Like this? You may also enjoy: FrontEnd Focus : Node Weekly : React Status Stop getting JavaScript Weekly : Change email address : Read this issue on the Web © Cooperpress Ltd. Fairfield Enterprise Centre, Lincoln Way, Louth, LN11 0LS, UK 收起
显示全部文字 查看全文
时间/2017-12-22 00:00:00

The Best of CodePen for 2017

We share with you a collection of the best CodePen demos for 2017.
作者/Georgi Georgiev
时间/2017-12-19 23:47:49

6 Great Resources Every Beginning a Front-end Developer Should Bookmark

If you just get started your a front-end developer career, it might be overwhelming to learn something every day. To optimize your time, it might be useful to know solid resources, to keep up with a demanding programmers’ environment. In this brief article, you will find 6 useful resources that in my opinion I think every beginning a front-end developer career should bookmark. 1. Mozilla Developer Network: probably the strongest names in the open source world. It contains HTML, CSS, JavaScript basic and advanced articles as well as modules for server-side development, tools, and testing. 2. Stack Overflow: most trusted online community for developers to learn and share their knowledge. 3. The Front-End Checklist: is an exhaustive list of all elements you need to have / to test, before launching your site / HTML page to production. 4. Javascript.info: contains modern JavaScript tutorials from the basics to advanced topics with simple, but detailed explanations. 5. CSS Tricks: contains tips and techniques on using CSS. 6. Smashing Magazine: contains reliable, useful and practical articles and guides to web designers and developers. If you like what you read, don’t forget to clap so more people see it! Make sure to follow my Linkedin or Behance. Also, visit my website here.收起
显示全部文字 查看全文
时间/2017-12-19 12:31:27

My journey with pure CSS images

I was almost in the middle of my #100DaysOfCode challenge when I started noticing on my twitter feed several cute images with the hashtag #dailyCssImages. When I would click on them I could see the code, all the beauty of CSS/SCSS and just a few lines of HTML. I started digging on images and codes, I followed several developers on Codepen who created either simple and cute or complicated and detailed images. I was fascinated. Some days past and I found an article on Medium with the title “A Beginner’s Guide to Pure CSS Images”, written by the creator of Daily CSS Images challenge, named Michael Mangialardi. It was a tutorial on how to start creating CSS Images. I decided for my 44th day of #100DaysOfCode to give it a try. The result can be seen below. My pen’s description was: Day: 44 of 100 I am planning on taking the challenge #dailycssimages. This is my first time trying to do a "koala" using only CSS. I followed this guide here I am sure I will learn so many new things with the challenge, I love cute little things and that's what I am planning to make. I have to admit I am awful at drawing by hand but I will challenge myself to get better with code and design. After finished reading the article I was hooked. I subscribed to the 10-week challenge and the next day I received my first email. The theme was “Bear Cub”. Honestly, my first image sucked. Strange enough, although I didn’t like the result, I was happy with my creation! The next day I changed my approach to designing images. I first made a simple sketch with pen and paper. And then I tried to code it. Ok, once again the result wasn’t great, but it was better than the firsts’ day. Code | Video-tutorial On the 3rd and 4th day I tried to add more details in my images and I google for some animal-inspiration. I finally created these images: Code | Video-tutorial Code | Video-tutorial On day 5, I designed a cute creature and people seemed to really like it. Code This boosted my confidence and I was ready for the 2nd week. I won’t get into a lot of detail… but I learned a couple of new tools and I tried to apply my recent knowledge into the images. The tools were about: Gradient colors and Quick shapes. The 3rd week must be on of my favorites for two reasons: The theme was FOOD! I started animating That week I made a pizza, a hamburger, a taco, a cheesecake and a pie! Video-tutorial Video-tutorial The hamburger until today has 1019 views on codepen Video-tutorial Video-tutorial The 4th week started... with a detailed Frankenstein Video-tutorial … and ended with a monster! Well, I gave my monster a twist, and I decided to make it cute. You can clearly witness how I got better at coding but not at drawing. Code | Video-tutorial This pen has 1098 view on Codepen, and I have to admit, at this point I was quite proud of my work. The 5th week was all about superheroes As I like to be playful I combined three things: Superheroes Animation MINIONS Et voila the results: Code | Video-tutorial Code | Video-tutorial On weeks 6 and 7 I designed icons and logos This is how I found an apple app store icon on google images: And this is how I recreated it: Code | Video-tutorial As for the logos: Code | Video-tutorial Code | Video-tutorial Code | Video-tutorial Code | Video-tutorial The elm logo was a bit tricky, so I took advantage of the Clippy tool: And I ended up with this logo: Code | Video-tutorial On my 40th day, I made a Nintendo 2DS I got inspired by this image: I quickly sketched a draw: And after applying some CSS I had my own Nitendo 2DS: code | video-tutorial The 9th week I felt really inspired I created five different images based on the same color palette. The three of them were minimalistic and quite abstract. code | video-tutorial code | video-tutorial code | video-tutorial On day 44 I created a robot. First I google some images, when I found the one I liked most, I drew it, and then I code it. code | video-tutorial On day 45, I decided to do something similar, a space inspired mascot-robot! code| video-tutorial I finished the challenge with a delicious cake Here are all my pure CSS images for the #dailyCssImages challenge This pen has 2.523 views and that makes me extremely happy as I spent numerous hours searching and coding. Conclusion This challenge helped me in so many different ways: I got better at CSS/SCSS, I also learned about animations. I learned new tools about colors, shapes, and animations. I connected with people all around the world on Codepen, Twitter, and Youtube. I shared my knowledge on Codepen and Youtube and I hope I helped and inspired other developers. I learned to be more patient and focused on my image and my code rather than get distracted by little things. I got better at time management. I did NOT get better at drawing! Thank you for taking the time to read my story. If you feel inspired please share it. It would be great if you could subscribe to my youtube channel as it helps me create more content. Youtube | Codepen | Github | Twitter | Site收起
显示全部文字 查看全文
作者/Eleftheria Batsou
时间/2017-12-18 09:55:14

Using React Fragments for the first time

React v16 was a very exciting release for React, and included many new features. In the recent React 16.2 release, improved support for Fragments was announced, and it’s this feature that I want to talk about today. The problem that fragments solve Up until React 16 each component had to return a single element: // will error class Demo extends Component { render() { return <p>foo</p><p>bar</p> } } // OK! class Demo extends Component { render() { return ( <div> <p>foo</p> <p>bar</p> </div> ) } } With the release of React 16, you were able to return an array of elements that a component would render: // allowed in React 16 // but you'll get a warning about keys class Demo extends Component { render() { return [<p>foo</p>, <p>bar</p>] } } This is OK; but it has two problems: It breaks the JSX abstraction; it’s odd to now have a component returning an array containing JSX elements. Whenever I do this I always forget the commas after each array item because I’m not used to using them in JSX. You have to add a key property to each element to avoid React warnings, which can make the render function verbose and less easy to follow. Because returning arrays didn’t feel that natural in React 16, it was far more common to eschew them in favour of wrapping elements in one containing element; most normally a div or a span. On a large application with a suite of components this can very quickly lead to a set of wrapping elements that can produce a big set of HTML soup. Fragments solve this problem. Fragments in React 16.2 React 16.2 introduced the Fragment: Fragments look like empty JSX tags. They let you group a list of children without adding extra nodes to the DOM: – React 16.2 release The Fragment element is imported from the react module, and can be used just like any other JSX element. The difference is that a Fragment component doesn’t end up adding any extra markup into the DOM: Using a Fragment First, we import Fragment just like we import Component from react: import React, { Fragment } from 'react' And then we use it just like any other React component: const App = () => ( <Fragment> <p>foo</p> <p>bar</p> </Fragment> ) The key here is that the resulting DOM from the App component will look like so: <p>foo</p> <p>bar</p> A special fragment syntax React 16.2 also introduced a syntactical sugar for Fragments. For example, the code below creates the exact same result as the App component above: const App = () => ( <> <p>foo</p> <p>bar</p> </> ) I’m not sure if I’ll use this syntax over the more explicit Fragment syntax; but I think this comes down to personal preference. It’s worth noting that if you need to pass a Fragment any props (most likely a key prop if you’re iterating over a list), you can’t use this special syntax; if you have to pass props you need to use Fragment. A use case for fragments At Thread we’re building a site for finding and buying clothing and I was working on a component that allows users to select their size from a dropdown. If the item is out of stock or low on stock, we wanted to show that along side their size. So a dropdown might look like so: - S - M - Low stock - L - Out of stock So we’re looping over an array of data to generate the options for the select dropdown. The data looks like so: const sizes = [ { id: 1, size: 'S', stockDisplay: 'In stock', stockLevel: 'IN_STOCK' }, { id: 2, size: 'M', stockDisplay: 'Low stock', stockLevel: 'LOW_STOCK' }, { id: 3, size: 'L', stockDisplay: 'Out of stock', stockLevel: 'OUT_OF_STOCK', }, ] Initially the code for this looked like so: generateOptionForSize = size => ( <option key={size.id} value={size.size} disabled={size.stockLevel === 'OUT_OF_STOCK'} > {size.stockLevel === 'IN_STOCK' ? size.size : `${size.size} - ${size.stockDisplay}`} </option> ) This worked fine but I felt like it could be a little cleaner, particularly the conditional for deciding if to show the extra information or not. In addition, I wanted to replace the hyphen with an mdash, and because I was returning the contents of the option as a string, that was hard to do. If I did: { size.stockLevel === 'IN_STOCK' ? size.size : `${size.size} — ${size.stockDisplay}` } React would sanitise the string and output the literal — text into the page. However, swapping out the string interpolation using ES2015 template strings for a React Fragment suddenly made the entire code easier to follow, and allowed me to use an HTML entity: generateOptionForSize = size => ( <option key={size.id} value={size.size} disabled={size.stockLevel === 'OUT_OF_STOCK'} > {size.stockLevel === 'IN_STOCK' ? ( size.size ) : ( <Fragment> {size.size} — {size.stockDisplay} </Fragment> )} </option> ) This is now easier to follow and allows me to use HTML entities and have them work as expected. Conclusion I can already see many more places through our app which could be made more straightforward and easier to work with as a result of Fragments and I’m excited to continue using them. Not only do they clear up a lot of component code, but the fact that they have no output into the DOM should lead to fewer superfluous div and span elements that a lot of React applications are littered with.收起
显示全部文字 查看全文
时间/2017-12-18 00:00:00

Why you always should use strict mode

A short and simple answer would be: "because it makes your code much easier to debug!" Examples: Without using strict mode: x = 1; That would declare your variable in the global namespace. With using namespace it would throw an error such as 'x is not defined'. So the strict mode forces you to declare your variables correctly. The strict mode can be used globally or within a specific scope in your functions: a = 3; // no strict mode function x() { "use strict"; b = 4; // throws error because strict mode } 收起
显示全部文字 查看全文
作者/Philipp Rost
时间/2017-12-17 14:42:43

Preview Image for Input

It is really amazing all of the things I am finding out about html, javascript and css. Magical things, like execCommand to format a contenteditable element or this little jem that lets a user safely view an image or file from their web browser inside of someones web app. It is all so nifty. In the pen above I made a very simple example of this. Just for my own sake but it could maybe help someone else idk.收起
显示全部文字 查看全文
作者/Daniel Jordan Osborn
时间/2017-12-17 09:04:26

Easy Photo Vignette

Vignetting in photography is the practice of making the corners darker or lighter to highlight what is in the center of the photograph. It's possible to reproduce this effect in your website using a single CSS3 property: radial-gradient. Here's the CSS for this project: body { margin: 0; } #photo { background: radial-gradient(circle, transparent, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.9)), url(https://unsplash.it/2000?image=1070); background-size: cover; background-position: center; background-repeat: no-repeat; height: 100vh; } Here's the finished project: The thing we need to do to make this happen is to use the background property in CSS on our div. Our div has an id of #photo so that's what we're hooking into to style the background. First, let's set up our background image. I'm using a nifty service from Unsplash that allows you to use Unsplash photography right in your demo without having to download the image. Learn more at unsplash.it. Here's the background property with the image in it: #photo { background: url(https://unsplash.it/2000?image=1070); } If you want this image to be full-bleed (taking up the full height and width of the viewport with no margin) then you'll need to add some other properties to the div: #photo { background: radial-gradient(circle, transparent, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.9)), url(https://unsplash.it/2000?image=1070); background-size: cover; background-position: center; background-repeat: no-repeat; height: 100vh; } You can play around with the background-position values to get the part of the photo in the viewport that you want to highlight. This photo has a really nice centered element so I'm just using center. That centers the background photo horizontally and vertically. Now that we have the photo in place let's take a look at the vignette. This effect is achieved through adding a value to the background property. When you need to layer the background property with multiple values, remember that the first value will be the topmost layer. So whatever is first in the list will go on top. We want our gradient on top of our background image so it goes first in the declaration. You may not be familiar with the radial-gradient property. It can be used on any element that supports an image. An easy use is just to add it as a value to the background property (like we're using in this tutorial). Here is what the radial-gradient property looks like: background: radial-gradient([shape of gradient], [color stop], [color stop]); For our purposes, we're going to use three stops, but two is all you really need to create a color transition. You can try our experiment with just two and see why I chose to widen out the gradient. So when we add the radial-gradient value to the background property, this is what we come out with: background: radial-gradient(circle, transparent, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.9)), url(https://unsplash.it/2000?image=1070); Let me go over our values for radial-gradient. Circle is the shape that we want. You could also try it out using elipse to see if that shape is better for your image. Then we declare three color values. In the pen you can see that I used an actual color for the first transparent value but the SASS compiler has changed it to simply say transparent. I used this value: rgba(0, 0, 0, 0). So the first value in the radial-gradient property is the center point. Obviously, we want to see the center of the image so that's why it gets a transparent color. The second value (or stop) is a little darker and the third value is darker still. That's the very outer edge of the image. You can play with those transparencies to get the type of vignetting you want. The terms we use are "light" and "heavy" when it comes to the darkness of vignetting on the photo. So that's it. Play around with different colors and transparencies. Tip: if you change the second stop to red it has a nice effect. Here's the finished pen again: 收起
显示全部文字 查看全文
作者/Brian Haferkamp
时间/2017-12-16 04:19:06

Is jQuery still relevant?

I've been cruising the reddit listings recently and without much searching I found a staggering amount of "jQuery is outdated", "jQuery isn't relevant", "I think jQuery is dying out", "…forget about jQuery. It isn't good for anything anymore", "jQuery hasn't been relevant for years in my opinion, it's best to avoid a "career" that requires it"!Now, I think it's fair to say: poppycock. But poppycock aside, the question remains: is jQuery still in 2017 (and as we join 2018) relevant and more importantly, is it worth a newcomer learning the library today?收起
显示全部文字 查看全文
时间/2017-12-15 22:10:36

Chrome 64 Beta: stronger pop-up blocker, Resize Observer, and import.meta

Unless otherwise noted, changes described below apply to the newest Chrome Beta channel release for Android, Chrome OS, Linux, Mac, and Windows.Stronger pop-up blocker1 out of every 5 user feedback reports submitted on Chrome for desktop mention some type of unwanted content. Examples include links to third-party websites disguised as play buttons or other site controls, or transparent overlays on websites that capture all clicks and open new tabs or windows. In this release, Chrome's pop-up blocker now prevents sites with these types of abusive experiences from opening new tabs or windows. Site owners can use the Abusive Experiences Report in Google Search Console to see if any of these abusive experiences have been found on their site and improve their user experience.  Two types of abusive experiences where a deceptive site control appears to do one thing, but has a different behavior when clicked. One looks like a play button on a video but sends the user to an unwanted download when clicked (left), and the other looks like a close button but instead opens unwanted pop-up windows (right).Resize ObserverTraditionally, responsive web applications have used CSS media queries or window.onresize to build responsive components that adapt content to different viewport sizes. However, both of these are global signals and require the overall viewport to change in order for the site to respond accordingly. Chrome now supports the Resize Observer API to give web applications finer control to observe changes to sizes of elements on a page. const ro = new ResizeObserver((entries) => {  for (const entry of entries) {    const cr = entry.contentRect;    console.log('Element:', entry.target);    console.log(`Element size: ${cr.width}px × ${cr.height}px`);    console.log(`Element padding: ${cr.top}px / ${cr.left}px`);  }});// Observe one or multiple elementsro.observe(someElement);The code snippet above uses the Resize Observer API to observe changes to an element. import.metaDevelopers writing JavaScript modules often want access to host-specific metadata about the current module. To make this easier, Chrome now supports the import.meta property within modules that exposes the module URL via import.meta.url. Library authors might want to access the URL of the module being bundled into the library to more easily resolve resources relative to the module file as opposed to the current HTML document. In the future, Chrome plans to add more properties to import.meta.Other features in this releaseBlink > AnimationThe offset-path property can be used to animate an element by specifying the geometry of the path that an element moves along. Blink>FontsDevelopers can now use the text-decoration-skip-ink CSS property to control how overlines and underlines are drawn when they cross over a glyph. Blink>InputCoordinates of PointerEvent with pointerType=mouse are now fractional, resulting in more precise mouse measurements. Blink>JavaScriptTo improve developer experience, Chrome now supports named captures in regular expressions, allowing developers to assign meaningful names to portions of a string that a regular expression matches. Chrome now supports the Unicode property escapes \p{…} and \P{…} for regular expressions that have the u flag set, allowing developers to create more powerful Unicode-aware regular expressions. To assist with local-aware formatting of strings produced by internationalization formatters, developers can now use Intl.NumberFormat.prototype.formatToParts() to format a number to a list of tokens and their type. Thanks to Igalia for helping make this happen! Blink>MediaMatching other browser implementations, Chrome now sets the default preload value for <video> and <audio> elements to metadata in order to reduce bandwidth and resource usage by only loading resource metadata and not the media resource itself. Chrome now supports HDR video playback when Windows 10 is in HDR mode, enabling developers to provide users with HDR VP9 Profile 2 10-bit videos. To support compatibility with the HTML Spec, Chrome now throws a "NotSupportedError" DOMException when a media element’s playbackRate is set to a value not supported by Chrome, like negative values.  Chrome now supports the Media Capabilities API in Origin Trials, enabling developers to know whether an audio or video playback will be smooth and power-efficient based on previous performance statistics. To match the Media Capture and Streams spec, getUserMedia() returns a rejected Promise with DOMException or OverconstrainedError when there is an error. Blink>NetworkDevelopers can now use the cache option to specify the cache mode of a Request.Developers can now use Request.prototype.cache to view the cache mode of a Request and determine whether a request is a reload request.  Blink>Permissions APITo better align with the Permissions API spec, the Permissions API can now be used to query the status of the camera and microphone permissions. Blink>ScrollIn Focus Management APIs, developers can now focus an element without scrolling to it by using the preventScroll attribute. Blink>SVGTo allow developers to transform and change position of transformed SVG elements, Chrome now supports transform-box for SVG elements. Thanks to Opera for making this happen! Blink>WebAudioAudioWorklet, an API that exposes low-level audio processing capability to support custom AudioNodes, is now available in origin trials and the experimental flag.Blink>WebRTCTo align with the WebRTC 1.0 spec, RTCPeerConnection now supports addTrack() for single stream use cases, as well as removeTrack(), getSenders(), ontrack, and a minimal version of the RTCRtpSender interface.Blink>WindowDialogTo improve interoperability and end user experience, window.alert() no longer brings a backgrounded tab to the foreground but instead shows the alert when the user switches to the background tab. UI>NotificationsSimilar to macOS, Chrome notifications sent through the Notifications API or chrome.notifications on Linux are now shown directly by the Linux native notification system. Deprecations and interoperability improvementsBlink> CSSTo align with the spec, getMatchedCSSRules has been removed and developers can use the Blink polyfill instead. Blink> DOMFollowing the deprecation in Chrome 45, elements can no longer host more than one Shadow Root. Blink> Performance APIsTo encourage adoption of standardized loading metrics API such as Navigation Timing 2, nextHopProtocol, and Paint Timing API, Chrome is deprecating the non-standardized chrome.loadTimes API. For a complete list of all features (including experimental features) in this release, see the Chrome 64 milestone hotlist.  Posted by Charles Harrison, Pop-Up Popping Engineer收起
显示全部文字 查看全文
作者/Chrome Blog
时间/2017-12-15 07:02:27

CircleCI meets Create React App meets Jest

It's been some time I didn't post anything at all. I'd like to try again, but in a different format (shorter, more concise: something I've never been that good at). I'd like to talk about what I've been doing this week at work, or at home, or on a train: anything code-related, basically. Sombody will hopefully find something interesting to know and read about. We've eventually started thinking at unit testing the hell out of our new shiny React app. It's now a good time: MVP's over, and my laziness too. I've tried to keep the app at a very basic level for the time being (read: I've used what I've found, with very few additions), aka: * create-react-app * React router * Redux, with redux-thunk as async middleware * Reselect * Storybook Plus a bunch of helper libraries like the moment, lodash. I'm a data-driven person (that's just partially true: I'm more of a data/chart fetishist, to be honest), and I love being able to track progresses, find possible improvements, catch weird things happened in the past and make sure that they're not going to hit us back in the future. So we got our CI server. CircleCI has been the chosen one. We also got CodeClimate. That's a fancy tool I'm fond of, due to its cool UI, and rather simple UX. Integrating these two sweeties has been fairly easy (didn't take more than two or three pomodoros, I swear). First things first, I headed to .circleci/config.yml. Setup Code Climate test reporter This first step is a rework of CodeClimate’s integration guide with CircleCI. It's simply a new step added at the jobs > build > steps level. - run: name: Setup Code Climate test reporter command: | curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter chmod +x ./cc-test-reporter In order to run CodeClimate, you also need to provide the CC_TEST_REPORTER_ID environment variable. I've done that from CircleCI's project settings page since I prefer not committing my secrets. Run the tests with coverage enabled - run: name: Unit tests with coverage command: | ./cc-test-reporter before-build npm run coverage ./cc-test-reporter after-build --exit-code $? environment: JEST_JUNIT_OUTPUT: "coverage/junit/js-test-results.xml" Would you like showing off a fancy list of errored/failed test on CircleCI as well? - store_test_results: path: coverage/junit I suppose this can be added at any time after you've run the unit tests with coverage. I've kept it right after the run step. Would you like to export these fancy html files generated by lcov? Keep on adding: - store_artifacts: path: coverage Again, I've just followed CodeClimate's guide. Big difference is that npm run coverage between before-build and after-build scripts. Because I'm not just in love with data, and charts, but I also quite like using npm scripts. Run tests with coverage This part took some extra effort to get it right, but at the end it works amazingly well. First of all, CircleCI likes JUnit syntax a lot, although Jest doesn't have that sort of test results processor. That means we have to add a dependency to make the magic happen: npm install -D jest-junit. Then, here's the npm script I've been using at the previous step: json // ... "scripts": { // ... "coverage": "react-scripts test --env=jsdom --coverage --testResultsProcessor ./node_modules/jest-junit", // ... } // ... You can skip that --env=jsdom argument if you don't rely on browser-only global objects, like document and window (I have to have it because of some polyfills being loaded). Spoiler alert: it slows the test suite execution down relatively "a lot" (for this projects it's 10s with vs 3s without). Done Final result on GitHub: And on CircleCI: Last but not least, CodeClimate: Bye!收起
显示全部文字 查看全文
作者/Rocco Curcio
时间/2017-12-15 04:52:22

The Best JavaScript and CSS Libraries for 2017

In this article we share with you a collection of the best libraries and resources of 2017.
作者/Georgi Georgiev
时间/2017-12-14 01:06:55

My Most used git commands.

A summary of my most used git commands, since it's always good to have them in mind. Basic usage: creating new branch $ git checkout -b [name_of_your_new_branch] change working branch $ git checkout [name_of_your_new_branch] push the branch to the master/origin(in this case)/ etc $ git push origin [name_of_your_new_branch] summary of active branches $ git branch check changes on a branch $ git status adding all your changes to commit $ git add . commiting your changes $ git commit -am "specify your commit message here" No as basic usage, but still important: initiating a git repository $ git init verifying a remote repository $ git remote -v clonning repos git clone [repo url here] Obscure but useful: logging the latest activity in a branch git log -p logging all the recent activity in a branch, commits, pushes..etc git log --oneline --decorate If you have uncommitted changes in your tree (i.e. it's "dirty", in git language) that you want to temporarily undo it allows you to stash them for later. Useful if you want to check the state of your code before your changes, or if you want to merge in someone elses code but aren't yet ready to commit your code as it is. Stashed changes go into a list, or stack. You can then re-apply these changes when you want. git stash create a branch from a stash of changes git stash branch testchanges remove files from a stash git rm [file name and extension here] reset everything hard git reset --hard HEAD There are a lot of git commands. But on my day to day, these are the ones I always get my hand on.收起
显示全部文字 查看全文
时间/2017-12-13 01:33:11

Automatic Snapshot Testing With Storybook and Storyshots

If you've not yet heard of it, Storybook is an amazing tool for authoring UI components. With storybook you can develop UI components in isolation; eliminating data and environment dependencies that otherwise complicate the rendering (and testing) of components. Storyshots Storybook supports several addons, including my personal favorite; storyshots. Like magic, Storyshots takes the hard work you've already put in to create storybook stories, and turns each one into a jest snapshot. A little bit of configuration and you're done. Even if you've already written hundreds of stories. Getting Started with Storybook and Storyshots Storybook has amazing documentation to help you with nearly every topic. I recommend completing the Slow Start Guide before you continue. Storyshots has an excellent README.md that will help you get started. Follow it well. When you're done with both of those, we will focus on a few more advanced topics, such as: Collocating your stories Mocking Redux Mocking context Collocating your stories Once you have the initial storyshots implementation all set up, it's time to make sure you can collocate your stories. That way you can have your stories right next to the code you wish to implement and test. If you check the Writing Stories guide you notice that they add the following to their config.js file: import { configure } from '@storybook/react'; const req = require.context('../src/components', true, /\.stories\.js$/) function loadStories() { req.keys().forEach((filename) => req(filename)) } configure(loadStories, module); Do this, and you'll be able to keep your storybook stories in the same folder as your component. Mocking redux If you're using storybook with any component that depends on data in redux state you're going to have some extra configuration on your hands before you can render it successfully. You have a few ways you can handle this, but I prefer to abstract away the complexities of mocking the store to make day-to-day development simpler. To accomplish this, we need to do the following: Create a Context component Add Context as a global decorator Create a Context component Inside your .storybook folder, create a new file named Context.js and add the contents below. import React, { Component } from 'react' import configureStore from 'redux-mock-store' const middlewares = [] const mockStore = configureStore(middlewares) const initialState = { //... your state goes here } const store = mockStore(initialState) class Context extends Component { getChildContext() { return { store: store, } } render() { return ( {this.props.children} ) } } Context.childContextTypes = { store: PropTypes.object.isRequired, } export default Context don't forget to npm i -D redux-mock-store Add Context as a global decorator For starters, we head on over to the storybook documentation again, this time to review the section on decorators In this section they describe how you can add a decorator globally by including the following in your config.js file: addDecorator((story) => ( <My> {story()} </Context> )) Make sure you update your imports to include the Context component and the addDecorator function. import { configure, addDecorator } from '@storybook/react' import Context from './Context' Mocking context In addition to a dependency on redux state, your components may also depends on React's context from time to time. A common example would be React Router's withRouter implementation, which uses context to expose various details about the route and URL. As you can see from the section above, adding things to context is pretty much a freebie at this point. You would simply extend getChildContext() and childContextTypes in the Context component to include all of your desired fields for testing.收起
显示全部文字 查看全文
作者/Brent Clark
时间/2017-12-12 19:53:10