<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Mateusz Rybczonek on Medium]]></title>
        <description><![CDATA[Stories by Mateusz Rybczonek on Medium]]></description>
        <link>https://medium.com/@m.rybczonek?source=rss-7a2208b53e2------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*6ZlsIVn1xvWu6xpS.</url>
            <title>Stories by Mateusz Rybczonek on Medium</title>
            <link>https://medium.com/@m.rybczonek?source=rss-7a2208b53e2------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 28 Sep 2019 17:45:15 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/@m.rybczonek" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Hi Roman!]]></title>
            <link>https://medium.com/@m.rybczonek/hi-roman-6295688cc898?source=rss-7a2208b53e2------2</link>
            <guid isPermaLink="false">https://medium.com/p/6295688cc898</guid>
            <dc:creator><![CDATA[Mateusz Rybczonek]]></dc:creator>
            <pubDate>Sat, 22 Sep 2018 13:14:20 GMT</pubDate>
            <atom:updated>2018-09-22T13:14:20.954Z</atom:updated>
            <content:encoded><![CDATA[<p>Hi Roman!</p><p>I am glad to hear that you are so into that and happy to see your draft. Feel free to publish your version.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6295688cc898" width="1" height="1">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Lazy Loading images with Vue.js directives and IntersectionObserver]]></title>
            <link>https://itnext.io/lazy-loading-images-with-vue-js-directives-and-intersectionobserver-d0eb390cad9?source=rss-7a2208b53e2------2</link>
            <guid isPermaLink="false">https://medium.com/p/d0eb390cad9</guid>
            <category><![CDATA[vuejs]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Mateusz Rybczonek]]></dc:creator>
            <pubDate>Sun, 02 Sep 2018 07:24:19 GMT</pubDate>
            <atom:updated>2018-10-08T09:21:35.802Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LKECzW4_T7X1CDAseUuL_A.jpeg" /></figure><p>This article was inspired and based on <a href="https://benjamintaylorportfolio.netlify.com/?utm_campaign=Revue%20newsletter&amp;utm_medium=Newsletter&amp;utm_source=Vue.js%20Developers#/post/lazy-loading-images-with-vue-js-directives">this great blog post</a> written by <strong>Benjamin Taylor</strong>.</p><p><strong>When I think about performance and how the websites are loaded the first thing that comes to my mind is that when the content is loaded the last elements that appear on the page are images.</strong></p><p>Today images (their size and number on a single page) can be a major issue when it comes to performance. Keeping in mind that the page load of a website has a direct impact on the conversion rate, this issue should not be ignored.</p><p>In this article I would like to describe one way of reducing that initial weight of a website. What I will demonstrate is how to load only the content visible for the user when she/he sees the initial view and lazy load all the rest of the heavy-weight elements (like images) only when required.</p><p><strong>To do that we need to solve two things:</strong></p><ol><li>How to store source of the image we want to load without loading it in the first place.</li><li>How to detect when the image becomes visible (is required) to the user and trigger the request to load the image.</li></ol><p><strong>We will solve the above mentioned issues using </strong><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes"><strong>data-attributes</strong></a><strong>, </strong><a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API"><strong>IntersectionObserver</strong></a><strong> and </strong><a href="https://vuejs.org/v2/guide/custom-directive.html"><strong>Vue.js custom directive</strong></a><strong>.</strong></p><p>To make it easier to understand I created an example, a list of random articles, each one containing a short description, image and a link to the source of the article. We will go through the creation process of a components for displaying that list of articles, displaying a single article and displaying (and lazy-loading) an image for a specific article.</p><p>Most of the things I would like to show are based in the component displaying the image, so I will show a basic example of how that component looks like. We will do a step by step explanation in the next sections so don’t get too deep in the code just yet.</p><p><strong>ImageItem.vue</strong></p><p>In the component we have an ImageSpinner component that is shown when the image is being loaded and an img tag that is responsible for keeping the image source and displaying the image when the loading is completed.</p><p>The key lazy-load logic is extracted to a LazyLoadDirective that is used on our component by adding v-lazyload attribute.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XHIl-W9xdT3zrj9jU9wC8w.png" /><figcaption>ImageItem.vue</figcaption></figure><p>Script part of that component looks like that:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SVqnZKLzWKomIHVmkFImJA.png" /><figcaption>ImageItem.vue</figcaption></figure><p>As mentioned above the lazy-load logic is kept in a directive LazyLoadDirective:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cKsdb_hiYuuWIc-Wi-MmYA.png" /><figcaption>LazyLoadDirective.js</figcaption></figure><p>This is just part of a working example, you can find the whole example in this <a href="https://codesandbox.io/s/5v17x4zr64"><strong>Codesandbox example</strong></a>. We will analyse the code piece by piece and see what is actually happening in the next section.</p><h3>Real-World Example: Creating a LazyLoadDirective and using it in ImageItem component</h3><h3>1. Create a basic ImageItem component</h3><p>Let’s start with creating a component that will show an image (no lazy-loading involved). In the template, we create a figure tag that contains our image, the image itself receives src attribute that carries the image source (url).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PKAZlBGUSkbiycuGZZXu7w.png" /><figcaption>ImageItem.vue</figcaption></figure><p>In the script part we receive the prop source that gives us source url of the image we are displaying.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Pk-MBPZoqUX0VDPtbeo7Dw.png" /><figcaption>ImageItem.vue</figcaption></figure><p>That is fine, we render the image we wanted, but if we leave it as it is, we will be loading image straight away without waiting for the component to be visible on our screen. That is not what we want so let’s go to the next step.</p><h3>2. Prevent image from being loaded when the component is created.</h3><p>To prevent the image from being loaded we need to get rid of the src attribute from the img tag. But as pointed out at the beginning we still need to keep the image source somewhere. Good place to keep that information is <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes">data-* attribute</a>.</p><p>As per its definition <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes">data-* attribute</a> allow us to store information on standard, semantic HTML elements.</p><p>Sounds like a perfect fit for our need.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5HhFe2b9by4u2kLjwkwuiA.png" /><figcaption>ImageItem.vue</figcaption></figure><p>Ok, with that done we will not load our image. But wait, we will not load our image… ever!</p><p>Obviously that is not what we wanted, we want to load our image but under specific conditions. We can request the image to be loaded by replacing the src attribute with the image source url kept in data-url. That is the easy part, the issue we encounter now is — when should we replace that src?</p><p>We would like to load the image when the component carrying it becomes visible to the user. How can we detect if the user sees our image or not? Let’s check that out in the next step.</p><h3>3. Detect when the image is visible to the user.</h3><p>If you ever encountered that challenge you probably ended up with using some crazy magical javascript that when you finished didn’t look very nice.</p><p>For example, we could use events and event handlers to detect the scroll position, offset value, element height and viewport height and calculate whether an image is in the viewport or not. It even sounds crazy, doesn’t it?</p><p>If we really needed we could probably stick to that solution (no matter how ugly that would be), but doing it that way has direct implications to our performance. Those calculations would be performed each time there is a scroll event. Even worse, imagine few dozens of images each having to recalculate if it is visible or not on each scroll event.</p><p><strong>This is madness!</strong></p><h3><strong>4. </strong><a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API"><strong>Intersection Observer</strong></a><strong> to the rescue!</strong></h3><p>This very inefficient way of detecting if an element is visible in the viewport can be solved by using <a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API"><strong>Intersection Observer API</strong></a>.</p><p>Looking at the definition it allows you to configure a <strong>callback</strong> that is called whenever one element, called the <strong>target</strong>, intersects either the device viewport or a specified element.</p><p>Firing a custom callback function when the element becomes visible in the viewport? Sounds like a magic spell for what we need.</p><p>So, what we need to do to use it?</p><p>To use the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API"><strong>Intersection Observer</strong></a> we need to do few things:</p><ul><li>Create a new intersection observer</li><li>Watch the element we wish to lazy load for visibility changes</li><li>When the element is in viewport, load the element (replace src with our data-url)</li><li>Once the element is loaded, stop watching it for visibility changes (unobserve)</li></ul><p>In <a href="https://vuejs.org/"><strong>Vue</strong></a> we can use a <a href="https://vuejs.org/v2/guide/custom-directive.html"><strong>custom directive</strong></a> to wrap all this functionality and then reuse it when we need.</p><h3>5. Create a <a href="https://vuejs.org/v2/guide/custom-directive.html">custom Vue directive</a></h3><p>What is a custom directive? As per documentation, it is a way to get the low-level DOM access on elements. For example changing an attribute of a specific DOM element, in our case changing src attribute of an img element.</p><p>Our directive looks like below. Again, we will break it into pieces in a moment, I just want to give you an overview.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cKsdb_hiYuuWIc-Wi-MmYA.png" /><figcaption>LazyLoadDirective.js</figcaption></figure><p>Let’s go step by step.</p><p><a href="https://vuejs.org/v2/guide/custom-directive.html#Hook-Functions"><strong>hookFunction</strong></a></p><ul><li>allows us to fire a custom logic at a specific moment of a bound element lifecycle.</li><li>we use inserted hook because it is called when the bound element has been inserted into its parent node (this guarantees parent node presence). Since we want to observe visibility of an element in relation to its parent (or any ancestor), we need to use that hook.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Bm2eLQ0SX9Yz0-kcUbxcnA.png" /><figcaption>LazyLoadDirective.js</figcaption></figure><p><strong>loadImage function</strong></p><ul><li>responsible for replacing the src value with data-url.</li><li>in this function we have access to our el, element on which the directive is applied. We can extract the img from that element.</li><li>we check if the image exists and if it does, we add a listener that will fire a callback function when the loading is finished. That callback will be responsible for hiding the spinner and adding the animation (fade-in effect) to the image using CSS class.</li><li>we add a second listener that will be called when the loading of the image from our src url fails.</li><li>Finally, we replace src of our img element with the source url of the image we want to request and show (that triggers the request).</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WmE8PHKjnX1h4uTDnm__vQ.png" /><figcaption>LazyLoadDirective.js</figcaption></figure><p><strong>handleIntersect function</strong></p><ul><li>IntersectionObserver callback function responsible for firing loadImage on certain conditions.</li><li>it is fired when the IntersectionObserver detects that the element entered the viewport or parent component element.</li><li>it has access to entries which is an Array of all elements that are watched by the observer and observer itself.</li><li>we iterate through entries and check if a single entry becomes visible to our user isIntersecting, if it does loadImage function is fired</li><li>after the image is requested, we unobserve the element (remove it from the observer’s watch list), that prevents the image from being loaded again.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*K9DLoXTeVVbI-xqGKD_rag.png" /><figcaption>LazyLoadDirective.js</figcaption></figure><p><a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Creating_an_intersection_observer"><strong>createObserver</strong></a> <strong>function</strong></p><ul><li>responsible for creating our <strong>IntersectionObserver</strong> and attaching it to our element.</li><li><strong>IntersectionObserver</strong> constructor accepts a <strong>callback </strong>(our <strong>handleIntersect</strong> function) that is fired when the observed element passes the specified threshold and <strong>options</strong> object that carries our observer options.</li><li>options object specify root that is our reference object on which we base the visibility of watched element (it might be any ancestor of the object or our browser viewport if we pass null). It also specifies threshold value which can vary from 0 to 1 and tells us at what percentage of the target’s visibility the observer’s callback should be executed (0 meaning as soon as even one pixel is visible, 1 meaning the whole element must be visible).</li><li>after creating the <strong>IntersectionObserver</strong> we attach it to our element using observe method.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mDzhItblUVuxW1MhR5qRlQ.png" /><figcaption>LazyLoadDirective.js</figcaption></figure><p><strong>Browser support</strong></p><p>Even though it is not supported by all browsers, the coverage of 73% of users (as of 28th August 2018) sounds good enough.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PH1DS4IAB0j1Ifrj5FvOzw.png" /></figure><p>But having in mind that we want to show images to all users (remember that using data-url prevents the image from being loaded), we need to add one more piece to our directive.</p><p>We need to check if the browser supports IntersectionObserver, fire the loadImage if it doesn’t (that will request all images at once) and createObserver if it does.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*O4s_56OxoBYof1GcoALODg.png" /><figcaption>LazyLoadDirective.js</figcaption></figure><h3>6. Registering <a href="https://vuejs.org/v2/guide/custom-directive.html">directive</a></h3><p>To use our newly created directive we need to register it first. We can do it in two ways, globally (available everywhere in the app) or locally (on a specified component level).</p><p><strong>Global registration</strong></p><p>To register a directive globally we import our directive and use Vue.directive method passing the name on which we want to register our directive and directive itself. That allows us to add v-lazyload attribute to any element in our code.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vpms19JLBuQExvpvx0Ck3w.png" /><figcaption>main.js</figcaption></figure><p><strong>Local registration</strong></p><p>If we want to use our directive only in a specific component and restrict the access to it, we can register the directive locally. To do that we need to import the directive inside the component that will use it and register it in the directives object. That will give us the ability to add v-lazyload attribute to any element in that component.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cMB33sUEKDjAbERzsTxe9w.png" /></figure><h3>7. Using directive on ImageItem component</h3><p>After registering our directive we can use it by adding the v-lazyload attribute to the parent element that carries our img (figure tag in our case).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XHIl-W9xdT3zrj9jU9wC8w.png" /><figcaption>ImageItem.vue</figcaption></figure><h3>Summary</h3><p>Lazy Loading images can <strong>significantly improve your page performance</strong>. It allows you to load the images only when the user can actually see them.</p><p>For those still not convinced if it is worth playing with it I prepared some raw numbers. Let’s take our simple articles list. At the moment I was performing that test it had 11 articles with images (meaning 11 images on the page). I don’t think that is a lot of images, you can probably find bigger number in a second by going into any news page.</p><p>Let’s stick to our 11 images and check the performance of our page on <em>fast 3G </em>with only first article visible, without lazy-loaded images.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Q551f57ZMVJrOehe_hY5JQ.png" /></figure><p>As expected 11 images, 11 requests, total page size 3.2 MB.</p><p>Now, the same page with only first article visible and lazy-loded images.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4qPOuDlYxMY8efyb0G32aw.png" /></figure><p>Result, 1 image, 1 request, total page size 1.4 MB.</p><p>By adding this directive to our articles we <strong>saved 10 requests</strong> and we <strong>reduced the page size by 56%</strong> and bear in mind this is really simple example.</p><p>No more comments, let the numbers speak for themselves.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d0eb390cad9" width="1" height="1"><hr><p><a href="https://itnext.io/lazy-loading-images-with-vue-js-directives-and-intersectionobserver-d0eb390cad9">Lazy Loading images with Vue.js directives and IntersectionObserver</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Practical use of Vue.js scoped-slots]]></title>
            <link>https://itnext.io/new-unnamed-post-8da9cdbf5df3?source=rss-7a2208b53e2------2</link>
            <guid isPermaLink="false">https://medium.com/p/8da9cdbf5df3</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[vue]]></category>
            <category><![CDATA[vuejs]]></category>
            <dc:creator><![CDATA[Mateusz Rybczonek]]></dc:creator>
            <pubDate>Sun, 19 Aug 2018 09:53:31 GMT</pubDate>
            <atom:updated>2018-08-24T12:04:53.017Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>Practical Use of Vue.js Scoped Slots</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vnIQ9skrpWSYaxKn9W70XQ.png" /></figure><p><strong>There are situations when you want the template inside the slot to be able to access data from the child component that is responsible for rendering the slot content. This is particularly useful when you need freedom in creating custom templates that use the child component’s data properties. That is a typical use case for scoped slots.</strong></p><p>Imagine a component that configures and prepares an external API to be used in another component, but is not tightly coupled with any specific template. Such a component could then be reused in multiple places rendering different templates but using the same base object with specific API.</p><p>For the purpose of this blog post, I’ve created a component (GoogleMapLoader.vue) that initialises <a href="https://developers.google.com/maps/documentation/javascript/reference/">Google Maps API</a>, creates a google and map objects and exposes those objects to the parent component in which the GoogleMapLoader is used.</p><p>See below a basic example of how this can be achieved. We will analyse the code piece by piece and see what is actually happening in the next section.</p><p>The template part will look as below</p><p>GoogleMapLoader.vue</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*LFVJKuG4BvJi-81w.png" /></figure><p>Our script will look like this, we’ll have some props passed to the component which allows us to set the <a href="https://developers.google.com/maps/documentation/javascript/reference/">Google Maps API</a> and <a href="https://developers.google.com/maps/documentation/javascript/reference/map#Map">Map</a> object:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gTiq_vOBk_p9R3OC.png" /></figure><p>This is just part of a working example, you can find the whole example in this <a href="https://codesandbox.io/s/1o45zvxk0q">Codesandbox example</a>. We will analyse the code piece by piece and see what is actually happening in the next section.</p><h3>Real-World Example: Creating a Google Map Loader component</h3><h3>1. Create a component that initialises our map</h3><p>In the template we create a container for the map which will be used to mount the <a href="https://developers.google.com/maps/documentation/javascript/reference/map#Map">Map</a> object extracted from the Google Maps API.</p><p>GoogleMapLoader.vue</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*I_JUXa-SCpwGmM8G.png" /></figure><p>Inside the script part:</p><ul><li>we receive props from the parent component which will allow us to set the Google Map:</li><li><a href="https://developers.google.com/maps/documentation/javascript/style-reference">mapConfig</a> — Google Maps config object</li><li><a href="https://developers.google.com/maps/documentation/javascript/get-api-key">apiKey</a> — our personal api key required by Google Maps</li></ul><p>GoogleMapLoader.vue</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*5s8IKltO93Nv6NpF.png" /></figure><ul><li>we set the initial values of google and map to null</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Gqbxt2Jyh37m_Vf4.png" /></figure><ul><li>on mounted hook we create an instance of GoogleMapsApi and Map object from the GoogleMapApi and we set the values of google and map to the created instances</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*uhgXw3zjKG9c7zn1.png" /></figure><p>So far so good, with that done we could continue adding the other objects to the map (Markers, Polylines, etc.) and using it as a ordinary map component. But we want to use our GoogleMapLoader component only as a loader that prepares the map, not renders anything on it.</p><p>To achieve that we need to allow parent component that will use our GoogleMapLoader to access this.google and this.map that are set inside the GoogleMapLoader component. That’s where <a href="https://vuejs.org/v2/guide/components-slots.html#Scoped-Slots">scoped slots</a> really shine. Scoped slots allow us to expose the properties set in a child component to the parent component. It may sound like an inception, but bear with me one more minute.</p><h3>2. Create component that uses our initialiser component</h3><p>In the template, we render the GoogleMapLoader component and pass props that are required to initialise the map.</p><p>TravelMap.vue</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*9nuAP0o1JQJMa6X6.png" /></figure><p>Our script tag will look like below at this stage.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*eIAr4GOyMFnVEJXW.png" /></figure><p>Still no scoped slots, let’s add one.</p><h3>3. Expose google and map properties to the parent component by adding a scoped slot</h3><p>So finally we can add a scoped slot that will do the job and allow us to access the child component props in the parent component. We do that by adding the &lt;slot&gt; tag in the child component and passing the props that we want to expose (using v-bind directive or :propName shorthand). It does not differ from passing the props down to the child component, but doing it in the &lt;slot&gt; tag reverse the direction of data flow.</p><p>GoogleMapLoader.vue</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*h88MQpuMZC7BDdQr.png" /></figure><p>Now when we have the slot in the child component we need to receive and consume the exposed props in the parent component.</p><h3>4. Receive exposed props in the parent component using slot-scope attribute</h3><p>To receive the props in the parent component we declare a template element and use slot-scope attribute. The attribute has access to the object carrying all props exposed from the child component. We can grab the whole object or we can <a href="https://vuejs.org/v2/guide/components-slots.html#Destructuring-slot-scope">destructure that object</a> and get the required props. Let’s proceed with the second option.</p><p>TravelMap.vue</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*wPkTEAdGWUyh5IqG.png" /></figure><p>After doing that even though the google and map props does not exist in the TravelMap scope, the component has access to them and we can use them in the template.</p><p>Yeah, ok, but why would I do things like that, what is the use of all that?</p><p>Scoped slots allow us to pass a template to the slot instead of passing a rendered element. It’s called a “scoped” slot because although the template is rendered in the parent component scope, it will have access to certain child component data. That gives us a freedom to fill the template with custom content from the parent component.</p><h3>5. Create factory components for Markers and Polylines</h3><p>Now when we have our map ready we will create two factory components that will be used to add elements to the TravelMap.</p><p>GoogleMapMarker.vue</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*jS03-CBXicaQpICQ.png" /></figure><p>GoogleMapLine.vue</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*OdBwnavbdRjbHlwe.png" /></figure><ul><li>both of them receive google from which we extract required object (Marker or Polyline) and map which gives as a reference to the map on which we want to place our element</li><li>each component expects also an extra prop to create a corresponding element</li><li>on mounted hook we create an element (Marker / Polyline) and attach it to our map by passing the map property to the object constructor</li></ul><p><strong>6. Add elements to map</strong></p><p>Now let’s use our factory components to add elements to our map.</p><p>To add elements to our map we render the factory component and pass the google and map objects.</p><p>We also need to provide data required by the element itself (in our case marker object with position of the marker and path object with polyline coordinates).</p><p>TravelMap.vue</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*4QApAuVJ0sSV-RBt.png" /></figure><p>In our script we need to import the required factory components and set data that will be passed to the markers and lines.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*pWVUVYxGWjaHT6tS.png" /></figure><p><strong>Summary</strong></p><p>That’s it. With all those bits and pieces created we can now re-use the GoogleMapLoader component as a base for all our maps by passing different templates to each one of them. Imagine that you need to create another map with different Markers or just Markers without Polylines. By using the above pattern it becomes very easy as we just need to pass different content to the GoogleMapLoader component.</p><p>This pattern is not strictly connected to Google Maps, it can be used with any library to set the base component and expose the library’s API that might then be used in the component that summoned the base component.</p><p>It might be tempting to create a very complex solutions based on the example, but at some point we can get to the situation where this abstraction becomes an independent part of the code living in our codebase. If we get to that point it might be worth considering extraction to an add-on.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8da9cdbf5df3" width="1" height="1"><hr><p><a href="https://itnext.io/new-unnamed-post-8da9cdbf5df3">Practical use of Vue.js scoped-slots</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>