#onmount
Explore tagged Tumblr posts
Photo

Вид на море и Крым с горы Ай-Петри • Sea and Crimea view from AI-Petri mountain Фото в высоком качестве на сайте ФотоПрироды.рф | FotoNature.ru © Сергей Коваленко | Sergey Kovalenko #виднаморе #фотосгоры #пейзажКрыма #подоблаками #видыКрыма #вгорахкрыма #нагореайпетри #черноеморе #красивыйКрым #природаКрыма | #seaview #photofromthemountain #landscapeofCrimea #undertheclouds #viewsofCrimea #inthemountainsofCrimea #onmount #blacksea #beautifulCrimea #natureofCrimea https://www.instagram.com/p/BrCECAuFVck/?utm_source=ig_tumblr_share&igshid=1ey2hpkvtdq8
#виднаморе#фотосгоры#пейзажкрыма#подоблаками#видыкрыма#вгорахкрыма#нагореайпетри#черноеморе#красивыйкрым#природакрыма#seaview#photofromthemountain#landscapeofcrimea#undertheclouds#viewsofcrimea#inthemountainsofcrimea#onmount#blacksea#beautifulcrimea#natureofcrimea
0 notes
Text
Fast transition to renewables will save the world up to $12tn (£10.2tn) by 2050
Fast transition to renewables will save the world up to $12tn (£10.2tn) by 2050
Switching from fossil fuels to renewable energy could save the world asmuch as $12tn (£10.2tn) by 2050, an Oxford University study says. Thereport said it was wrong and pessimistic to claim that moving quicklytowards cleaner energy sources was expensive. Gas prices have soared onmounting concerns over energy supplies. But the researchers say that goinggreen now makes economic sense because of the…
View On WordPress
0 notes
Link
Vue Composition API によって Vue.js にも React Hooks のようなロジックの再利用性の高い開発体験がもたらされようとしています。 しかし、まだ「Composition API の良さをわかっていない」という方や「Composition API をうまく利用した書き方がわからない」という方も多いかと思います。 本記事では Composition API 時代の便利ライブラリ VueUse を用いた実装例や、 VueUse 自体の実装がどのようなものか紹介します。 Composition API の良さや雰囲気もキャッチアップしていただければ幸いです。 VueUse とは? VueUse は Anthony Fu さん1が中心に開発しているライブラリで、Composition API を用いた便利系関数を数多く集めたライブラリです。 例えば、ブラウザ上のマウスポインタの座標をリアクティブに取得する useMouse(), ブラウザ API の localStorage を使って状態を保持できる useLocalStorage(), 負荷対策のために連続する関数呼び出しを防ぐ useDebounceFn() 2などといった関数が提供されています。 公式サイト: https://vueuse.js.org/ GitHub: antfu/vueuse npm: @vueuse/core 検証環境の構築 GitHub リポジトリの Description に記載通り、Vue 2系・3系のどちらでも利用可能です: 🧰 Collection of Composition API utils for Vue 2 and 3 https://vueuse.js.org/ 今回は Vue CLI で立ち上げた Vue 2.6 系のプロジェクトに @vue/composition-api をプラグインとして追加した環境で検証します。 動作確認した環境 macOS Catalina Node.js 12.18.1 npm 6.14.5 Vue CLI v4.4.4 Chrome 83 Vue CLI のインストール Vue CLI をグローバルインストールしたくない方は、以下の手順の vue コマンド部分を npx @vue/cli に読み替えていただいても大丈夫です。 プロジェクトの作成 vue-2-vueuse-trial というプロジェクト名で環境を構築していきます: vue create vue-2-vueuse-trial 設定は以下のようにしました: Vue CLI v4.4.4 ? Please pick a preset: Manually select features ? Check the features needed for your project: Babel, TS, Linter ? Use class-style component syntax? No ? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? No ? Pick a linter / formatter config: Basic ? Pick additional lint features: Lint on save ? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files ? Save this as a preset for future projects? No プラグインと VueUse の導入 プロジェクトディレクトリが出来上がったら、@vue/composition-api と VueUse を npm install します: cd vue-2-vueuse-trial npm i @vueuse/core@vue2 @vue/composition-api src/main.ts に Vue.use(VueCompositionApi) を追加します3: src/main.ts import Vue from 'vue' +import VueCompositionApi from '@vue/composition-api' import App from './App.vue' +Vue.use(VueCompositionApi) Vue.config.productionTip = false npm run serve で開発ビルドを開始してください。 VueUse の関数を使ってみる useMouse() リアクティブにマウスポインタの座標が取得できる useMouse() を使ってみます: src/App.vue <template {{ x }}, {{ y }} </template <script lang="ts" import { defineComponent } from '@vue/composition-api' import { useMouse } from '@vueuse/core' export default defineComponent({ setup() { // tracks mouse position const { x, y } = useMouse() return { x, y } } }) </script これだけでマウスポインタの座標がリアクティブに反映されていることがわかるかと思います。 useMouse() の実装を確認すると useEventListener() という関数を使っていて、 useEventListener() はコンポーネントのマウント時(Composition API の onMounted() を利用)にイベントリスナーを追加していることがわかります: https://github.com/antfu/vueuse/blob/master/packages/core/useMouse/index.ts https://github.com/antfu/vueuse/blob/master/packages/core/useEventListener/index.ts VueUse ではこのような関数がより抽象的な関数を参照しているパターンの実装が所々に見られます。 Composition API を用いた良い実装の例として知っておくと良いかと思います。 useLocalStorage() ブラウザ API の localStorage を使って状態を保持できる useLocalStorage() を使ってみます。 まずは useLocalStorage() を使わず、 VueUse がなくても利用できる reactive() 4 を使ってみましょう: src/App.vue <template name: <input v-model="state.name" color: <input v-model="state.color" {{ state }} </template <script lang="ts" import { defineComponent, reactive } from '@vue/composition-api' export default defineComponent({ setup() { const state = reactive({ name: 'Apple', color: 'red', }) return { state } } }) </script name, color を変更すると、下に表示されている JSON 形式の state の表示も更新される画面が表示されます: 上記の実装では name を Banana, color を yellow のように変更してページをリロードすると、元の状態(name が Apple, color が red)に戻ります。 以下のように ブロックを変更し、reactive() の代わりに useLocalStorage() を利用するように変更してみます: import { defineComponent } from '@vue/composition-api' import { useLocalStorage } from '@vueuse/core' export default defineComponent({ setup() { // persist state in localStorage const state = useLocalStorage( 'my-storage', { name: 'Apple', color: 'red', }, ) return { state } } }) state が localStorage に保存されるようになったので、ページをリロードしても状態が保持されるようになりました。 サンプルアプリとしてよくある ToDo リストの状態管理に useLocalStorage() を使うようにすると、手軽にデータを保存できる ToDo リストにできて楽しいかもしれません。 公式サイトが Storybook でできている件 公式サイトが Storybook でできていて、各関数を即座に試せるリファレンスとなっています。 各関数のページ下部には関数の "Source" へのリンクがあり、ソースを見てどのような実装になっているか追っていくと Composition API を用いた良い実装の勉強となるかと思います。 所感 VueUse は多くの便利関数を提供しているので、今後お世話になる可能性が高いライブラリだと思いました。 まだ試せていない関数が多くあるので、使ってみたりコードを読んだりしてみようかと思います。
0 notes
Photo

How to Build a News App with Svelte
Svelte is a new JavaScript UI library that's similar in many ways to modern UI libraries like React. One important difference is that it doesn't use the concept of a virtual DOM.
In this tutorial, we'll be introducing Svelte by building a news application inspired by the Daily Planet, a fictional newspaper from the Superman world.
About Svelte
Svelte makes use of a new approach to building users interfaces. Instead of doing the necessary work in the browser, Svelte shifts that work to a compile-time phase that happens on the development machine when you're building your app.
In a nutshell, this is how Svelte works (as stated in the official blog):
Svelte runs at build time, converting your components into highly efficient imperative code that surgically updates the DOM. As a result, you're able to write ambitious applications with excellent performance characteristics.
Svelte is faster than the most powerful frameworks (React, Vue and Angular) because it doesn't use a virtual DOM and surgically updates only the parts that change.
We'll be learning about the basic concepts like Svelte components and how to fetch and iterate over arrays of data. We'll also learn how to initialize a Svelte project, run a local development server and build the final bundle.
Prerequisites
You need to have a few prerequisites, so you can follow this tutorial comfortably, such as:
Familiarity with HTML, CSS, and JavaScript (ES6+),
Node.js and npm installed on your development machine.
Node.js can be easily installed from the official website or you can also use NVM for easily installing and managing multiple versions of Node in your system.
We'll be using a JSON API as a source of the news for our app, so you need to get an API key by simply creating an account for free and taking note of your API key.
Getting Started
Now, let's start building our Daily Planet news application by using the degit tool for generating Svelte projects.
You can either install degit globally on your system or use the npx tool to execute it from npm. Open a new terminal and run the following command:
npx degit sveltejs/template dailyplanetnews
Next, navigate inside your project's folder and run the development server using the following commands:
cd dailyplanetnews npm run dev
Your dev server will be listening from the http://localhost:5000 address. If you do any changes, they'll be rebuilt and live-reloaded into your running app.
Open the main.js file of your project, and you should find the following code:
import App from './App.svelte'; const app = new App({ target: document.body, props: { name: 'world' } }); export default app;
This is where the Svelte app is bootstrapped by creating and exporting an instance of the root component, conventionally called App. The component takes an object with a target and props attributes.
The target contains the DOM element where the component will be mounted, and props contains the properties that we want to pass to the App component. In this case, it's just a name with the world value.
Open the App.svelte file, and you should find the following code:
<script> export let name; </script> <style> h1 { color: purple; } </style> <h1>Hello {name}!</h1>
This is the root component of our application. All the other components will be children of App.
Components in Svelte use the .svelte extension for source files, which contain all the JavaScript, styles and markup for a component.
The export let name; syntax creates a component prop called name. We use variable interpolation—{...}—to display the value passed via the name prop.
You can simply use plain old JavaScript, CSS, and HTML that you are familiar with to create Svelte components. Svelte also adds some template syntax to HTML for variable interpolation and looping through lists of data, etc.
Since this is a small app, we can simply implement the required functionality in the App component.
In the <script> tag, import the onMount() method from "svelte" and define the API_KEY, articles, and URL variables which will hold the news API key, the fetched news articles and the endpoint that provides data:
<script> export let name; import { onMount } from "svelte"; const API_KEY = "<YOUR_API_KEY_HERE>"; const URL = `https://newsapi.org/v2/everything?q=comics&sortBy=publishedAt&apiKey=${API_KEY}`; let articles = []; </script>
onMount is a lifecycle method. Here’s what the official tutorial says about that:
Every component has a lifecycle that starts when it is created and ends when it is destroyed. There are a handful of functions that allow you to run code at key moments during that lifecycle. The one you'll use most frequently is onMount, which runs after the component is first rendered to the DOM.
Next, let's use the fetch API to fetch data from the news endpoint and store the articles in the articles variable when the component is mounted in the DOM:
<script> // [...] onMount(async function() { const response = await fetch(URL); const json = await response.json(); articles = json["articles"]; }); </script>
Since the fetch() method returns a JavaScript Promise, we can use the async/await syntax to make the code look synchronous and eliminate callbacks.
The post How to Build a News App with Svelte appeared first on SitePoint.
by Ahmed Bouchefra via SitePoint https://ift.tt/2nlTHvT
0 notes
Link
What are those names?
In case you are wondering what is Snowpack and/or Svelte, let me give you some context...
Snowpack is a build tool that allows you to create your application and see the ongoing changes faster in the development process while also providing all the excellent features you may be used to with bundling applications for the deployment process.
The already known bundlers like Webpack and Parcel have to rebundle & rebuild parts of your application every time you make a change in a file and save it.
This rebundling process takes some time depending on the framework of your choice (takes more time for Angular than it does for Vue, for instance).
The difference with Snowpack is that it serves your whole application unbundled during development. As in, every file gets built just once, and then it's cached after that.
So now that you are making changes and putting features, Snowpack rebuilds only the file that has changed and serves it instantly in the browser plus, you can also use Hot-Module Replacement (HMR) to go with it.
Once you're done making the app and want to create a production build, you can plugin your preferred bundler via a plugin (lol) and have an optimized production build ready to be deployed to the hosting service of your choice.
Here's a beautiful little image that shows what this 'Unbundled Development' thing is, taken directly from the Snowpack docs.

Unbundled vs Bundled development
So now you might be thinking, "Okay, that sounds cool and all, but how am I supposed to use this for my web apps, and if it's a bundler, does it support my existing ones?."
Well, yes, and yes. It supports many of the things we've used working with other frameworks. It comes with support out of the box for things like Typescript, JSX, CSS Modules, and you can pick a template to have support for React or Vue or Svelte, and so on.
You can use the 'Create Snowpack App' to get started with your framework of choice, and you can also take an existing app and migrate it to Snowpack easily.
Refer to the Get started section in the official docs (which are very well-written by the way).
Now for Svelte's case, it's a library much like React that cares mainly about providing the UI layer of an application without paying attention to the rest of the application's stack.
Since it goes about the visual aspect of an app, you can start using it in any project you have already created by incrementally adding some Svelte components to it and have it work like before.
But I'm not going to go too much on why choosing Svelte or how to get started building cool things with it. There's already a great post on that matter written by @nimrodkra that you can read all about here
What are we going to build?
We'll be making a sample app to demonstrate how easy it is to get started building something from scratch.
It is a relatively simple one, but it will help illustrate some of the features we can use to make something more interesting than a usual 'to-do list.'
Here's what it will look like:
Screenshot of the end result
Starting out
To begin, open your terminal and run this command.
npx create-snowpack-app snowpack-svelte --template @snowpack/app-template-svelte
You can also pass in the --use-yarn flag if you prefer.
It will create the directory and install all the dependencies in it and then give you a message that it initialized a git repo and will show all the available commands currently in package.json.
Now you can use cd inside the folder and start the dev server either with npm start or yarn start
Once you do that, you'll already be with your new site open in your default browser, and a dev server with hot reloading enabled. Boom, that was fast.
Open the folder in VSCode and start making some changes in the App.svelte file, save it and see the changes instantly reflected there.
Now it is time to do some coding...
Fetching the data
Now go ahead and remove all the code from the template except for the first div, and we'll be putting everything that we do inside it.
We'll change the default message string to 'Random Users' and then display it inside the template within an h1 tag.
Now here comes the fun part. We'll be fetching data from an external API and render it on our page. In Angular, we use the HttpClient, and in React, we can use the Axios library.
In this case, we're going to be using the Fetch API to call the jsonplaceholder endpoint.
So we'll create a getUsers function and fetch the data there like this:
function getUsers() { fetch("http://jsonplaceholder.typicode.com/users") .then(res => res.json()) .then(data => console.log(data)); }
And to use this function, we'll put a button on the template to call it once it's clicked.
<button on:click={getUsers}>Fetch Users</button>
Here we are using the svelte syntax for the onclick event and passing it the name of the function that we created.
Now, if we open the browser console tab, we can see the array of users that gets returned once we click the 'Fetch Users' button.
Rendering the data
Let's display the data on our page. For that, remember to remove the console.log and instead assign the data to our users variable. With that done, we can now display the data on the page instead of the console.
One way we could go about doing that is to put the users variable directly into the template, and that will just spit out our array of objects.
But, it would display undefined until we click the button to fetch the data from the API.
To take care of that, we're going to use the {#if} construct in Svelte to validate if we have the data available or not to be displayed. We'll do it like this.
{#if users} {JSON.stringify(users, null, 1)} {/if}
Now you can see the array printed all over the screen. We'll want a better way to display this data separately for each of the users returned.
How are we going to go about that? Well iterating over the 'users' array. In React, we could use the map function and render all the users in a list.
Here we're going to use another Svelte construct called {#each}, and we'll render a list item for every user like this.
{#if users} <ul class="user-list"> {#each users as user} <li> <div class="user"> <h3>{user.name}</h3> <p>Username: {user.username} </p> <p>Phone: {user.phone} </p> <p>Website: https://{user.website} </p> </div> </li> {/each} </ul> {/if}
If you look into the response, we get from the API. You'll notice that each user object has several properties. Here I just chose the ones shown for the sake of simplicity. You can add additional ones if you like.
Applying basic styling
Ok, that works, now let's give it some styling so that they look nicer. You can write all the CSS rules inside the <style> tags like this.
<style> .App { text-align: center; font-family: Verdana, Geneva, Tahoma, sans-serif; } .user-list { display: flex; flex-flow: row wrap; justify-content: center; list-style: none; padding: 1rem; } .user-list li { width: 45%; padding: 0.5rem } .user { padding: 4px; border: 1px solid #ccc; border-radius: 6px; text-align: center; } </style>
Now that looks much better. Feel free to play around with the styles and give it some more color if you like.
We're almost done. There's something else I'd like to do just that it doesn't look like an empty page at the beginning.
What if we don't have to use the button to fetch data, but instead, we fetch it once the component is created.
In that case, we're going to use one of Svelte's lifecycle methods that are called onMount, and we use it like this.
import { onMount } from 'svelte'; onMount(() => { getUsers(); })
With it, we can now remove the button, and the data will be displayed on the page once it is loaded.
And that's it! We now have a fully functioning app that fetches data from an API and displays it on a page.
We could take the div with the user class and turn it into a component and then call it from App.svelte but that, as they say, is an exercise left to the reader 😛.
Also, bonus points if you take the div with the App class an turn it into a main tag.
There you have it folks, the entire application, minus the CSS styles, is very short. (About 35 lines or so)
And it didn't take too much time to get it done 'cuz we can see the result in realtime every time we save the file.
0 notes
Text
An Overview of What's Coming in Vue 3
At the time of this writing, Vue 3.0 is at its 10th alpha version. Expect a faster, smaller, more maintainable, and easier to use version of the Vue you know and love. You can still use Vue via a script tag and your Vue 2.x code will continue to work. But you can start playing with the alpha version of Vue 3.0 here and we’re going to get into some of what v3 is offering.
Among other things, there’s a new API for creating components. It doesn’t introduce new concepts to Vue, but rather exposes Vue’s core capabilities like creating and observing reactive state as standalone functions. This is ultimately useful to Vue developers of all levels.
Options API and Composition API
In Vue 2, components are created with the object-based Options API. Vue 3 adds a set of APIs, referred to as the Composition API, which is function-based. This is primarily to address two issues that Vue 2 ran into for very large projects.
In large components that encapsulate multiple logical tasks, you want to group code by feature, but the nature of the Options API is that such code gets split up (among lifecycle hooks and so on), negatively affecting readability. Secondly, you want to be able to reuse logic in large-scale projects, and in Vue 2, solutions like mixins don’t address either issue very well.
Vue 3 seeks to kill both birds with one stone by exposing a new API. This API will live alongside the Options API, not replace it. This means that you can go on building components in the way that you’re used to without encountering any problems. But, you can also start building with the Composition API, which provides more flexible code organization and logic reuse capabilities as well as other improvements.
Even if the problems it specifically addresses are not pertinent to you, the new API has clearly had a lot of thought go into it to push Vue forward as a framework, for instance, by reducing the extent to which Vue operates “magically” behind the scenes.
— Sorry to interrupt this program! 📺
If you're interested in learning Vue in a comprehensive and structured way, I highly recommend you try The Vue.js Master Class course by Vue School. Learning from a premium resource like that is a serious investment in yourself.
Plus, this is an affiliate link, so if you purchase the course you help Alligator.io continue to exist at the same time! 🙏
- Seb, ✌️+❤️
Composition API
The Composition API is available now as a plugin for Vue 2 so you can try it out. It will be shipped baked-in in Vue 3.
In Vue 2 reactivity was achieved through the getters and setters of Object.defineProperty. This caused some limitations which you’ve already probably experienced (e.g.: updating an Array by index). In Vue 3, reactivity is accomplished through proxies, a feature that was introduced in JavaScript ES6.
You need not have a Vue instance to use the new reactivity API. It offers standalone APIs which allow you to create, observe, and react to state changes.
You would first import { reactive } from 'vue'. Then, you could create an object in the following way:
const state = reactive({ count: 0 })
You’ll have access to APIs that will allow you to dynamically inject component lifecycle hooks into a Vue instance.
The lifecycle registration methods can only be used in the setup() method which is the entry point where all the composition functions are called. For instance:
import { onMounted } from 'vue' export default { setup() { onMounted(() => { console.log('component is mounted.') }) } }
Functions that use these APIs can be imported into a component, allowing the component to do multiple logical tasks with reusable and readable code.
TypeScript
The composition API also offers better TypeScript support. It’s supposed to result in better type inferences with bindings returned from setup() and props declarations used to infer types.
Component code using TypeScript and JavaScript will look largely identical and TypeScript definitions benefit JavaScript users as well, say, if they use an IDE like Visual Studio Code.
View Declaration
Vue 2 supports templates as well as render functions. You don’t need to know an awful lot here except that Vue 3 continues to support both while optimizing rendering speed (such as by speeding up diff algorithms that operate under the hood so that Vue knows what needs to be re-rendered).
Faster
Virtual DOM has been rewritten from the ground-up to make for faster mounting and patching.
Compile-time hints have been added to reduce runtime overhead. This means skipping unnecessary condition branches and avoiding re-renders. Static tree and static prop hoisting means entire trees and nodes can skip being patched. Inline functions (like in a handler for a component in a template) won’t cause unnecessary re-renders.
You’re going to get a proxy-based observation mechanism with full language coverage and better performance. Instance properties will be proxied faster using native Proxy instead of Object.defineProperty like before.
You can expect up to 100% faster component instance initialization with double the speed and half the memory usage. 🏎️🏎️🏎️
Smaller
Vue 3 is also smaller.
It is tree shaking-friendly. Tree shaking refers to shaking off unused code. The core runtime has gone from ~20kb in size, gzipped, to ~10kb, gzipped.
The size of the Vue bundle increases with each new feature but, by providing most global APIs and Vue helpers as ES module exports, Vue 3 makes more code tree shakeable, even template code.
Coherence
Libraries like Vue Router and test-utils will be updated to line up with the new Vue. Vue now has a custom renderer API (similar to React Native for those who want to use it to create renderers for mobile or other host environments.
Conclusion
There is a ton to look forward to with Vue 3 with more like Portals that couldn’t fit in this short post. The new Composition API moves us towards an all around better Vue. An exact release date is not set but it’s coming soon. Get a head start now!
via Alligator.io https://ift.tt/2RdfYbt
0 notes
Link
dhamaniasad starred rstacruz/onmount Feb 12, 2019
rstacruz/onmount
Safe, reliable, idempotent and testable behaviors for DOM nodes
JavaScript 123 Updated Feb 12
0 notes
Text
Composi/core
Functional Components
@composi/core is a JavaScrip Library for creating functional components. It accomplishes this use virtual nodes and a virtual DOM, similar to React. In fact, if you look at the function components, they will look just like React function components.
import { h, render } from '@composi/core' // Define functional component: function List(props) { return ( <ul> { props.data.map(item => <li key={item.id}>{item.value}</li>) } </ul> ) } // Render the component: render(<List data={things})/>, document.body)
As you can see in the above example, it uses the same pattern of passing values down using props, and the familar render function. One big difference is that @composi/core does not require special syntax for props--no need for camel-cased events (onClick) or special terms (className). Instead you use the normal standard HTML versions of properties.
Lifecycle Hooks
@composi/core also provides functional components with something React does not: lifecycle hooks. You put these directly on the element you want to track. @composi/core offers the following three lifecycle hooks:
onmount--gets passed a reference to the element that mounted
onupdate--gets passed a reference to the element that was updated, along with the old and new props.
onumnount--gets a reference to the component that will unmount.
Runtime Programs
Besdies these, @composi/core has a third function, run. This create a runtime environment which gives you a scaled down version of The Elm Architecture. This provides state management for functional components.
Every runtime program is an object with three methods:
const program = { init() { // Initialize the program with state and a subscription: return [state, effect] }, view(state, send) { // Render a functional component with the program's state: return render(<Component {...{state}}/>, document.body) }, update(msg, state) { // do something with state, then return it. // Returning state with get passed to view, // causing the component to re-render. return [state] } }
The init method is for setup for the program: setting default state and launching in effects, such as timers or fetching data.
The view method is for returning a presentation of the program's state. This is where we take the state and use it to render a functional component.
The update method is where all the business logic of the program resides. Like Redux, this consists of actions that can modify state according to the received messages that it receives from events in the view and then return the updated state.
Size Matters
@composi/core provies all the functionality that we discussed so far while weighing in a just under 3KB. It's really small. That means it load fast. You get virtual DOM, functional components, lifecycle hooks and Redux-style state managegment in a tiny footprint.
Install
Actually, you do want to install @composi/core. Instead you want to install the CLI for creating new projects: @composi/create-composi-app.
npm i -g @composi/create-composi-app
After installing, you can use it to create a new project:
create-composi-app 'MyProject'
This will create a new @composi/core project on your desktop. Open you terminal and cd to the new project. The run:
npm i
This will install the project's dependencies. When it's done, you can build and launch your new project:
npm start
Everything you need for developing your project you will find in its src folder:
|-src |-css |-images |-js
Any changes you make in these folder will cause the project to rebuild and reload in the browser.
Summary
@composi/core is a light-weight and powerful solution for solving many of the same problems that React addresses.
To learn more about @composi/core in greater detail, visit the website: https://composi.github.io
#javascript#virtual dom#component#reactjs#front end developer#web development#functional programming
1 note
·
View note
Text
Your aging female parent or male parent
Life assurance for seniors is specially designed to produce coverage for people that can be too previous life insurance for elderly parents to qualify for typical insurance policies.It might be laborious to observe the subject of burial insurance with associate senior loved one. However, several older folks wish to arrange for the expense of their funerals, and that they are eased that you simply facilitate them return up with a concept. Your aging female parent or male parent is also ready to pay the premiums. However, lots of seniors got to carry onmounted incomes, and that they don't have any extra cash.Of course, lots of adult kids are happy to create modest monthly premium payments for his or her folks. this is often a higher possibility for them than having to come back up.
0 notes
Quote
Some commonly used APIs have verbose names. For example, we use componentDidMount() instead of didMount() or onMount(). This is intentional. The goal is to make the points of interaction with the library highly visible.
Design Principles - React
0 notes
Text
Fast transition to renewables will save the world up to $12tn (£10.2tn) by 2050
Fast transition to renewables will save the world up to $12tn (£10.2tn) by 2050
Switching from fossil fuels to renewable energy could save the world asmuch as $12tn (£10.2tn) by 2050, an Oxford University study says. Thereport said it was wrong and pessimistic to claim that moving quicklytowards cleaner energy sources was expensive. Gas prices have soared onmounting concerns over energy supplies. But the researchers say that goinggreen now makes economic sense because of the…
View On WordPress
0 notes
Text
Lazy Loading Images in Svelte
One easy way to improve the speed of a website is to only download images only when they’re needed, which would be when they enter the viewport. This “lazy loading” technique has been around a while and there are lots of great tutorials on how to implement it.
But even with all the resources out there, implementing lazy loading can look different depending on the project you’re working in or the framework you’re using. In this article, I’ll use the Intersection Observer API alongside the onLoad event to lazy load images with the Svelte JavaScript framework.
Check out Tristram Tolliday’s introduction to Svelte if you’re new to the framework.
Let’s work with a real-life example
I put this approach together while testing the speed on a Svelte and Sapper application I work on, Shop Ireland. One of our goals is to make the thing as fast as we possible can. We hit a point where the homepage was taking a performance hit because the browser was downloading a bunch of images that weren’t even on the screen, so naturally, we turned to lazy loading them instead.
Svelte is already pretty darn fast because all of the code is compiled in advance. But once we tossed in lazy loading for images, things really started speeding up.
This is what we’re going to work on together. Feel free to grab the final code for this demo from GitHub and read along for an explanation of how it works.
This is where we’ll end up by the end:
CodePen Embed Fallback
Let’s quickly start up Svelte
You might already have a Svelte app you’d like to use, but if not, let’s start a new Svelte project and work on it locally. From the command line:
npx degit sveltejs/template my-svelte-project cd my-svelte-project npm install npm run dev
You should now have a beginner app running on http://localhost:5000.
Adding the components folder
The initial Svelte demo has an App.svelte file but no components just yet. Let’s set up the components we need for this demo. There is no components folder, so let’s create one in the src folder. Inside that folder, create an Image folder — this will hold our components for this demo.
We’re going to have our components do two things. First, they will check when an image enters the viewport. Then, when an image does enter, the components will wait until the image file has loaded before showing it.
The first component will be an <IntersectionObserver> that wraps around the second component, an <ImageLoader>. What I like about this setup is that it allows each component to be focused on doing one thing instead of trying to pack a bunch of operations in a single component.
Let’s start with the <IntersectionObserver> component.
Observing the intersection
Our first component is going to be a working implementation of the Intersection Observer API. The Intersection Observer is a pretty complex thing but the gist of it is that it watches a child element and informs us when it enters the bounding box of its parent. Hence images: they can be children of some parent element and we can get a heads up when they scroll into view.
While it’s definitely a great idea to get acquainted with the ins and outs of the Intersection Observer API — and Travis Almand has an excellent write-up of it — we’re going to make use of a handy Svelte component that Rich Harris put together for svelte.dev.
We’ll set this up first before digging into what exactly it does. Create a new IntersectionObserver.svelte file and drop it into the src/components/Image folder. This is where we’ll define the component with the following code:
<script> import { onMount } from 'svelte';
export let once = false; export let top = 0; export let bottom = 0; export let left = 0; export let right = 0;
let intersecting = false; let container;
onMount(() => { if (typeof IntersectionObserver !== 'undefined') { const rootMargin = `${bottom}px ${left}px ${top}px ${right}px`;
const observer = new IntersectionObserver(entries => { intersecting = entries[0].isIntersecting; if (intersecting && once) { observer.unobserve(container); } }, { rootMargin });
observer.observe(container); return () => observer.unobserve(container); }
function handler() { const bcr = container.getBoundingClientRect();
intersecting = ( (bcr.bottom + bottom) > 0 && (bcr.right + right) > 0 && (bcr.top - top) < window.innerHeight && (bcr.left - left) < window.innerWidth );
if (intersecting && once) { window.removeEventListener('scroll', handler); } }
window.addEventListener('scroll', handler); return () => window.removeEventListener('scroll', handler); }); </script>
<style> div { width: 100%; height: 100%; } </style>
<div bind:this={container}> <slot {intersecting}></slot> </div>
We can use this component as a wrapper around other components, and it will determine for us whether the wrapped component is intersecting with the viewport.
If you’re familiar with the structure of Svelte components, you’ll see it follows a pattern that starts with scripts, goes into styles, then ends with markup. It sets some options that we can pass in, including a once property, along with numeric values for the top, right, bottom and left distances from the edge of the screen that define the point where the intersection begins.
We’ll ignore the distances but instead make use of the once property. This will ensure the images only load once, as they enter the viewport.
The main logic of the component is within the onMount section. This sets up our observer, which is used to check our element to determine if it’s “intersecting” with the visible area of the screen. It also attaches a scroll event to check whether the element is visible as we scroll, and then it’ll remove this listener if we’ve determined that it is viable and that once is true.
Loading the images
Let’s use our <IntersectionObserver> component to conditionally load images by wrapping it around an <ImageLoader> component. Again, this is the component that receives a notification from the <IntersectionOberserver> so it knows it’s time to load an image.
That means we’ll need a new component file in components/Image. Let’s call it ImageLoader.svelte. Here’s the code we want in it:
<script> export let src export let alt
import IntersectionObserver from './IntersectionObserver.svelte' import Image from './Image.svelte' </script>
<IntersectionObserver once={true} let:intersecting={intersecting}> {#if intersecting} <Image {alt} {src} /> {/if} </IntersectionObserver>
This component takes some image-related props — src and alt — that we will use to create the actual markup for an image. Notice that we’re importing two components in the scripts section, including the <IntersectionObserver> we just created and another one called <Image> that we haven’t created yet, but will get to in a moment.
The <IntersectionObserver> is put to work by acting as a wrapping around the soon-to-be-created <Image> component. Check out those properties on it. We are setting once to true, so the image only loads the first time we see it.
Then we make use of Svelte’s slot props. What are those? Let’s cover that next.
Slotting property values
Wrapping component, like our <IntersectionObserver> are handy for passing props to the children it contains. Svelte gives us something called slot props to make that happen.
In our <IntersectionObserver> component you may have noticed this line:
<slot {intersecting}></slot>
This is passing the intersecting prop into whatever component we give it. In this case, our <ImageLoader> component receives the prop when it uses the wrapper. We access the prop using let:intersecting={intersecting} like so:
<IntersectionObserver once={true} let:intersecting={intersecting}>
We can then use the intersecting value to determine when it’s time to load an <Image> component. In this case, we’re using an if condition to check for when it’s go time:
<IntersectionObserver once={true} let:intersecting={intersecting}> {#if intersecting} <Image {alt} {src} /> {/if} </IntersectionObserver>
If the intersection is happening, the <Image> is loaded and receives the alt and src props. You can learn a bit more about slot props in this Svelte tutorial.
We now have the code in place to show an <Image> component when it is scrolled onto the screen. Let’s finally get to building the component.
Showing images on load
Yep, you guessed it: let’s add an Image.svelte file to the components/Image folder for our <Image> component. This is the component that receives our alt and src props and sets them on an <img> element.
Here’s the component code:
<script> export let src export let alt
import { onMount } from 'svelte'
let loaded = false let thisImage
onMount(() => { thisImage.onload = () => { loaded = true } })
</script>
<style> img { height: 200px; opacity: 0; transition: opacity 1200ms ease-out; } img.loaded { opacity: 1; } </style>
<img {src} {alt} class:loaded bind:this={thisImage} />
Right off the bat, we’re receiving the alt and src props before defining two new variables: loaded to store whether the image has loaded or not, and thisImage to store a reference to the img DOM element itself.
We’re also using a helpful Svelte method called onMount. This gives us a way to call functions once a component has been rendered in the DOM. In this case, we’re set a callback for thisImage.onload. In plain English, that means it’s executed when the image has finished loading, and will set the loaded variable to a true value.
We’ll use CSS to reveal the image and fade it into view. Let’s give set an opacity: 0 on images so they are initially invisible, though technically on the page. Then, as they intersect the viewport and the <ImageLoader> grants permission to load the image, we’ll set the image to full opacity. We can make it a smooth transition by setting the transition property on image. The demo sets the transition time to 1200ms but you can speed it up or slow it down as needed.
That leads us to the very last line of the file, which is the markup for an <img> element.
<img {src} {alt} class:loaded bind:this={thisImage} />
This uses class:loaded to conditionally apply a .loaded class if the loaded variable is true. It also uses the bind:this method to associate this DOM element with the thisImage variable.
Let’s hook it all up!
Alright, it’s time to actually use our component. Crack open the App.svelte file and drop in the following code to import our component and use it:
<script> import ImageLoader from './components/Image/ImageLoader.svelte'; </script>
<ImageLoader src="OUR_IMAGE_URL" alt="Our image"></ImageLoader>
Here’s the demo once again:
CodePen Embed Fallback
And remember that you’re welcome to download the complete code for this demo on GitHub. If you’d like to see this working on a production site, check out my Shop Ireland project. Lazy loading is used on the homepage, category pages and search pages to help speed things up. I hope you find it useful for your own Svelte projects!
The post Lazy Loading Images in Svelte appeared first on CSS-Tricks.
You can support CSS-Tricks by being an MVP Supporter.
Lazy Loading Images in Svelte published first on https://deskbysnafu.tumblr.com/
0 notes
Link
We're going to use a no-bundle dev server for Vue 3 called vite which allows us to develop Vue apps with Single-File Components without any bundling during development.
Create a vite app
Open up your terminal and do the following:
$ npx create-vite-app <project-name> $ cd <project-name> $ npm install $ npm run dev
Creating a hook to see if a user is web monetized
In the root of your project folder, create a file named use-web-monetization.js and paste the code below.
import { ref, onMounted } from "vue"; export const useWebMonetization = () => { const isMonetized = ref(false); const isLoading = ref(true); onMounted(() => { if (!document.monetization) { // No web monetization polyfill is installed (e.g. Coil). isLoading.value = false; isMonetized.value = false; return; } // Check the value of document.monetization.state // to see if a user is web monetized. const { state } = document.monetization; if (state === "stopped") { // Not currently sending micropayments, nor trying to. isLoading.value = false; isMonetized.value = false; } // Determine when Web Monetization has started actively paying document.monetization.addEventListener("monetizationstart", (event) => { isLoading.value = false; isMonetized.value = true; }); }); return { isMonetized, isLoading, }; }
We created a file that has a reusable hook named useWebMonetization that returns isMonetized and isLoading states.
And now we can use it inside any .vue file like below.
<template> <div> <div v-if="isLoading"> Loading... </div> <div v-else-if="isMonetized"> Some exclusive content! </div> <div v-else> Show ads here! </div> </div> </template> <script> import { useWebMonetization } from "./use-web-monetization"; export default { setup() { const { isLoading, isMonetized } = useWebMonetization(); return { isLoading, isMonetized, }; } }; </script>
Testing Web Monetization
test-web-monetization is a website that provides a bookmarklet that we can use to test our projects without signing up for a Coil account.
Good luck to everyone!
0 notes
Text
Getting Acquainted With Svelte, the New Framework on the Block
For the last six years, Vue, Angular, and React have run the world of front-end component frameworks. Google and Facebook have their own sponsored frameworks, but they might leave a bitter taste for anyone who advocates for an open and unbiased web. Vue is another popular framework that has multiple sponsors, but isn’t run by a single corporation, which may be attractive to some folks.
There’s another player in the framework space that’s gaining attention and operates very much in the same spirit as Vue as far adopting an open MIT license: Svelte.
Svelte has been covered here on CSS-Tricks before, like Ollie Williams’ excellent overview of how it can be used to write more convenient, component-based CSS. This article is going to zoom out a bit and provide a little more context about Svelt, as well as how it differentiates itself from other frameworks, and how to implement it in your own projects.
What makes Svelte different?
I can confidently say that Svelte has been the easiest JavaScript component library to learn and start putting to use in a productive way.
— Jeff Delaney, from Svelte Realtime Todo List with Firebase
OK, so Svelte is a JavaScript component library. But so is React. And Angular. And Vue. What makes Svelte stand out from the bunch?
Svelte is trying to do a few things that are different from the rest:
All the code is compiled ahead of time.
There is no virtual DOM.
CSS scoping is baked in.
Let’s break those down a bit because they significantly distinguish Svelte from other front-end frameworks.
All the code is compiled ahead of time.
Svelte is a compiler, meaning that the code in Svelte files gets converted from an easier-to-write hybrid language that mixes HTML, JavaScript, and CSS into lower-level optimized JavaScript, HTML, and CSS files.
This is very similar to the way C# gets compiled down to bytecode, or how Typescript compiles down to JavaScript. But where traditional compilers tend to go down to one language, Svelte mixes all three.
This makes writing code a lot more flexible, and benefits the client (web browser) as the computation is done when the application is built, not on every browser when the web app is visited.
There is no Virtual DOM.
A DOM (or Document Object Model) is an interface that defines the logical structure of a webpage. It takes HTML and converts it to a structure that can be manipulated and accessed. Chris has a classic post that thoroughly explains it.
The Virtual DOM extends the concept of a DOM by creating a “second” DOM in memory. Like the DOM, this is manipulated and accessed by traditional frameworks (e.g. Angular, Vue, and React). At build, this second “virtual” DOM gets consolidated with the actual DOM, allowing the UI to render.
And what about the Shadow DOM? Well, the Shadow DOM is technically part of the “real” DOM, just in the shadows. As such it is a great tool for isolating chunks of code that don’t leak into or conflict with other elements on the page — a little bit like (but at the same time almost nothing like) an iframe. The shadow DOM is sorta the crux for most component-based front-end frameworks because they leverage the siloed nature of the Shadow DOM to serve specific code to specific elements.
While that isn’t exactly a key selling point of Svelte, it is possible to work with the Shadow DOM experimentally. The Shadow DOM hasn’t really quite caught on in progressive web practices, which is a shame, and probably due to the confusion between drafts and lack of support from IE and Edge.
So, where am I going with all this? The difference between Svelte and other JavaScript frameworks is the lack of a Virtual DOM. That’s important because it contributes to faster apps — faster than frameworks using a Virtual DOM. Yes, the Virtual DOM can be super fast because it only updates parts of the DOM when needed, but as applications grow, the impact of a duplicate DOM stored in memory can have an overall negative impact on performance.
Svelte takes a different approach and does a lot of these heavy calculations at build time. All that heavy lifting in advance, which allows Svelte to surgically insert changes only where needed.
CSS scoping is baked in.
Svelte has built-in styling, which is essential in other modern frameworks. The different between CSS in Svelte and CSS in other frameworks is that Svelte takes the CSS from each component and spits it out to a separate CSS file on build.
A personal gripe I have with most CSS-in-JS approaches is that it seems like an over-engineered solution. Svelte’s approach keeps things lean, vanilla, and encapsulated — while keeping everything where it should be.
For those who love preprocessors, there are plugins, whether it for Sass, Less or Gulp. But since Svelte is still in its infancy, I would recommend using plain ol’ CSS with a minified CSS framework of your choice so you can utilize Svelte’s handy dandy component scoping.
You could just as easily keep to your usual styling preferences and completely forgo Svelte’s CSS builder. However, I’d argue that is a massive shame, as Svelte’s solution has been extremely clean and enjoyable, at lease in my experience. But anyone who has to work with IE11 (😬) and even older browsers will know that normalizing styles is a must. This is a good place to stop and check out Ollie’s post because he dives much deeper into Svelte’s styling features and advantages.
How Svelte stacks up to other frameworks
We just looked at what how Svelte has a different approach for compiling, interacting with DOM and writing CSS. You might be wondering: how does Svelte compare to other popular frameworks?
There are plenty of comparisons already out there, but suffice to say that Svelte is pretty darn fast. But speed isn’t the only basis for comparison. Instead, let’s do a side-by-side that looks at a broader overview in a format much loved by the development community: a table!
SvelteVueReact Angular (2+) What is it Compiler Framework Framework Framework First Commit Nov. 16, 2016 Jul. 29, 2013May 24, 2013Sep. 18, 2014 Backing Open source Multiple Sponsors Facebook Google Community¹Small Large Massive Large Satisfaction288% 87% 89% 38%
Svelte is in a strong position considering its late entrance and small community. Developer satisfaction is high, while the big three have been seeing recent declines. The Svelte community is small, but growing, and the code is open source which is a huge plus for the overall web community.
Let’s look at an example of using Svelte
I hope that I have convinced you that Svelte is worth at least a try. If so, let’s fire up the terminal and try a real-world examples of an everyday use case: implementing the Intersection Observer. If you’ve ever run a Lighthouse report, it may have been shouted at you for not using passive scroll events. That may be the most boring sentence I have written in my life, but it’s scores points for performance and isn’t overly complicated to do with the Intersection Observer in Svelte.
Let’s skip all the installation and setup stuff because we can avoid it with REPL, the online editor Svelte uses to demonstrate the framework on its site. The standard “Hello world” boilerplate is in there. Go ahead and download the ZIP file of the app, in the upper-right corner of the screen.
Now, unzip the file and cd into the folder from the terminal and run npm -i to initialize the project. Once that’s done, do npm run build and you’ll get a copy of your lightweight miniature Svelte “Hello, world!” app.
Now we can get into the actual task of adding the IntersectionObserver.
First, we import the code that has already kindly been written by the Svelte team. It’s in the source code of the svelte.dev git repo (the inner cogs of which make for fascinating reading).
<script> import { onMount } from 'svelte'; export let once = false; export let top = 0; export let bottom = 0; export let left = 0; export let right = 0; let intersecting = false; let container; onMount(() => { if (typeof IntersectionObserver !== 'undefined') { const rootMargin = `${bottom}px ${left}px ${top}px ${right}px`; const observer = new IntersectionObserver(entries => { intersecting = entries[0].isIntersecting; if (intersecting && once) { observer.unobserve(container); } }, { rootMargin }); observer.observe(container); return () => observer.unobserve(container); } function handler() { const bcr = container.getBoundingClientRect(); intersecting = ( (bcr.bottom + bottom) > 0 && (bcr.right + right) > 0 && (bcr.top - top) < window.innerHeight && (bcr.left - left) < window.innerWidth ); if (intersecting && once) { window.removeEventListener('scroll', handler); } } window.addEventListener('scroll', handler); return () => window.removeEventListener('scroll', handler); }); </script> <style> div { width: 100%; height: 100%; } </style> <div bind:this={container}> <slot {intersecting}></slot> </div>
Stick this in a file called IntersectionObserver.svelte in a src/components folder. Then, reference it from the main Svelte file: App.svelte.
import IntersectionObserver from "../components/IntersectionObserver.svelte";
Now that we have the Intersection Observer available as a component, we can wrap other elements with it.
<IntersectionObserver let:intersecting top={400}> {#if intersecting} <section> This message will Show if it is intersecting </section> {:else} <section> This message won't Show if it is intersecting </section> {/if} </IntersectionObserver>
That’s really it! You can see how the Intersection Observer component allows us to use <IntersectionObserver> like a wrapper and define where the intersection should trigger, which is 400 pixels from the top in this example. As a reminder, this is all being exported as vanilla JavaScript! Super performant, no funny business. We’re sandwiching JavaScript and HTML together which is cool because we can see what the Intersection Observer is directly affecting, leaving no ambiguity and without being penalized for performance.
The OnMount function is necessary to tell Svelte that this code needs to run within the browser, as the Intersection Observer can’t be figured out ahead of time.
We’ll need to add some styling so that we can experience the observer in action, and we can do that directly in your App.svelte file. This might look super familiar if you have worked with any of the other front-end frameworks:
<style> .somesection { display: flex; align-items: center; justify-content: center; width: 100%; height: 100vh; } .somesection.even{ �� background: #ccc; } .content{ text-align: center; width: 350px; } </style>
Finally, we can copy and paste our Intersection Observer element four times to create more intersections. That gives us a mini web app that reactively adds and removes content as it comes into view — perfect to use with media, like lazy-loading. Check out a demo of the final result and be sure to crack open DevTools to see the Intersection Observer
Some final thoughts
My personal recommendation is to give Svelte a try. We’ve only scratched the surface of the framework in this article, but having converted my personal website to Svelte, I can confidently say that it is a pleasure to work with. It is performant, has a brilliant VSCode linter, and best of all, is easy to use. It may be small and new on the block, but I have a keen feeling that it is the relief from bloated “Goliath” frameworks, the “David” that frontend-ers have been looking for.
So should you use Svelte in a real project? Comparing risk and reward definitely comes into play. The community is smaller than other frameworks, meaning you’re likely to find less support and fewer tutorials to guide your along. At the same time, Svelte is in its third generation, meaning most of the gremlins should have been driven away, leaving a lean and reliable framework.
As with anything new, common sense rules, try it out with something non-commercial, take it for a spin, and see how you go.
Is there anything else? Funny you should ask! There are two co-projects that live in the Svelte Ecosystem: Sapper and Native. Sapper is a framework that utilizes Svelte for building full web applications, including routing, service workers, and all the good stuff you need to get started. I have used it to rebuild my personal website, and so far, I am a fan. Svelte Native is the most experimental of the Svelte projects, a NativeScript mobile app builder that utilizes Svelte under the hood. I confess that is where my knowledge on the subject ends. Luckily, it has a website with further information.
What do you think? Have you given Svelte a try? Do you think it stacks up to other frameworks? Let’s discuss it in the comments!
Based on a mix of Github Contributions, NPM Downloads and StackOverflow topics
State of JS review 2019
The post Getting Acquainted With Svelte, the New Framework on the Block appeared first on CSS-Tricks.
Getting Acquainted With Svelte, the New Framework on the Block published first on https://deskbysnafu.tumblr.com/
0 notes
Text
An Early Look at the Vue 3 Composition API in the Wild
I recently had an opportunity to try the new Vue Composition API in a real project to check where it might be useful and how we could use it in the future.
Until now, when we were creating a new component we were using Options API. That API forced us to separate the component’s code by options, meaning that we needed to have all reactive data in one place (data), all computed properties in one place (computed), all methods in one place (methods), and so on.
As it is handy and readable for smaller components, it becomes painful when the component gets more complicated and deals with multiple functionalities. Usually, logic related to one specific functionality contains some reactive data, computed property, a method or a few of them; sometimes it also involves using component lifecycle hooks. That makes you constantly jump between different options in the code when working on a single logical concern.
The other issue that you may have encountered when working with Vue is how to extract a common logic that can be reused by multiple components. Vue already has few options to do that, but all of them have their own drawbacks (e.g. mixins, and scoped-slots).
The Composition API brings a new way of creating component, separating code and extracting reusable pieces of code.
Let’s start with code composition within a component.
Code composition
Imagine you have a main component that sets up few things for your whole Vue app (like layout in Nuxt). It deals with the following things:
setting locale
checking if the user is still authenticated and redirects them if not
preventing the user from reloading the app too many times
tracking user activity and reacting when the user is inactive for specific period of time
listening on an event using EventBus (or window object event)
Those are just a few things the component can do. You can probably imagine a more complex component, but this will serve the purpose of this example. For the sake of readability, I am just using names of the props without the actual implementation.
This is how the component would look like using Options API:
<template> <div id="app"> ... </div> </template> <script> export default { name: 'App', data() { return { userActivityTimeout: null, lastUserActivityAt: null, reloadCount: 0 } }, computed: { isAuthenticated() {...} locale() {...} }, watch: { locale(value) {...}, isAuthenticated(value) {...} }, async created() { const initialLocale = localStorage.getItem('locale') await this.loadLocaleAsync(initialLocale) }, mounted() { EventBus.$on(MY_EVENT, this.handleMyEvent) this.setReloadCount() this.blockReload() this.activateActivityTracker() this.resetActivityTimeout() }, beforeDestroy() { this.deactivateActivityTracker() clearTimeout(this.userActivityTimeout) EventBus.$off(MY_EVENT, this.handleMyEvent) }, methods: { activateActivityTracker() {...}, blockReload() {...}, deactivateActivityTracker() {...}, handleMyEvent() {...}, async loadLocaleAsync(selectedLocale) {...} redirectUser() {...} resetActivityTimeout() {...}, setI18nLocale(locale) {...}, setReloadCount() {...}, userActivityThrottler() {...}, } } </script>
As you can see, each option contains parts from all functionalities. There is no clear separation between them and that makes the code hard to read, especially if you are not the person who wrote it and you are looking at it for the first time. It is very hard to find which method is used by which functionality.
Let’s look at it again but identify the logical concerns as comments. Those would be:
Activity tracker
Reload blocker
Authentication check
Locale
Event Bus registration
<template> <div id="app"> ... </div> </template> <script> export default { name: 'App', data() { return { userActivityTimeout: null, // Activity tracker lastUserActivityAt: null, // Activity tracker reloadCount: 0 // Reload blocker } }, computed: { isAuthenticated() {...} // Authentication check locale() {...} // Locale }, watch: { locale(value) {...}, isAuthenticated(value) {...} // Authentication check }, async created() { const initialLocale = localStorage.getItem('locale') // Locale await this.loadLocaleAsync(initialLocale) // Locale }, mounted() { EventBus.$on(MY_EVENT, this.handleMyEvent) // Event Bus registration this.setReloadCount() // Reload blocker this.blockReload() // Reload blocker this.activateActivityTracker() // Activity tracker this.resetActivityTimeout() // Activity tracker }, beforeDestroy() { this.deactivateActivityTracker() // Activity tracker clearTimeout(this.userActivityTimeout) // Activity tracker EventBus.$off(MY_EVENT, this.handleMyEvent) // Event Bus registration }, methods: { activateActivityTracker() {...}, // Activity tracker blockReload() {...}, // Reload blocker deactivateActivityTracker() {...}, // Activity tracker handleMyEvent() {...}, // Event Bus registration async loadLocaleAsync(selectedLocale) {...} // Locale redirectUser() {...} // Authentication check resetActivityTimeout() {...}, // Activity tracker setI18nLocale(locale) {...}, // Locale setReloadCount() {...}, // Reload blocker userActivityThrottler() {...}, // Activity tracker } } </script>
See how hard it is to untangle all of those? 🙂
Now imagine you need to make a change in one functionality (e.g. activity tracking logic). Not only do you need to know which elements are related to that logic, but even when you know, you still need to jump up and down between different component options.
Let’s use the Composition API to separate the code by logical concerns. To do that we create a single function for each logic related to a specific functionality. This is what we call a composition function.
// Activity tracking logic function useActivityTracker() { const userActivityTimeout = ref(null) const lastUserActivityAt = ref(null) function activateActivityTracker() {...} function deactivateActivityTracker() {...} function resetActivityTimeout() {...} function userActivityThrottler() {...} onBeforeMount(() => { activateActivityTracker() resetActivityTimeout() }) onUnmounted(() => { deactivateActivityTracker() clearTimeout(userActivityTimeout.value) }) }
// Reload blocking logic function useReloadBlocker(context) { const reloadCount = ref(null) function blockReload() {...} function setReloadCount() {...} onMounted(() => { setReloadCount() blockReload() }) }
// Locale logic function useLocale(context) { async function loadLocaleAsync(selectedLocale) {...} function setI18nLocale(locale) {...} watch(() => { const locale = ... loadLocaleAsync(locale) }) // No need for a 'created' hook, all logic that runs in setup function is placed between beforeCreate and created hooks const initialLocale = localStorage.getItem('locale') loadLocaleAsync(initialLocale) }
// Event bus listener registration import EventBus from '@/event-bus' function useEventBusListener(eventName, handler) { onMounted(() => EventBus.$on(eventName, handler)) onUnmounted(() => EventBus.$off(eventName, handler)) }
As you can see, we can declare reactive data (ref / reactive), computed props, methods (plain functions), watchers (watch) and lifecycle hooks (onMounted / onUnmounted). Basically everything you normally use in a component.
We have two options when it comes to where to keep the code. We can leave it inside the component or extract it into a separate file. Since the Composition API is not officially there yet, there are no best practices or rules on how to deal with it. The way I see it, if the logic is tightly coupled to a specific component (i.e. it won’t be reused anywhere else), and it can’t live without the component itself, I suggest leaving it within the component. On the flip side, if it is general functionality that will likely be reused, I suggest extracting it to a separate file. However, if we want to keep it in a separate file, we need to remember to export the function from the file and import it in our component.
This is how our component will look like using newly created composition functions:
<template> <div id="app"> </div> </template> <script> export default { name: 'App', setup(props, context) { useEventBusListener(MY_EVENT, handleMyEvent) useActivityTracker() useReloadBlocker(context) useLocale(context) const isAuthenticated = computed(() => ...) watch(() => { if (!isAuthenticated) {...} }) function handleMyEvent() {...}, function useLocale() {...} function useActivityTracker() {...} function useEventBusListener() {...} function useReloadBlocker() {...} } } </script>
This gives us a single function for each logical concern. If we want to use any specific concern, we need to call the related composition function in the new setup function.
Imagine again that you need to make some change in activity tracking logic. Everything related to that functionality lives in the useActivityTracker function. Now you instantly know where to look and jump to the right place to see all the related pieces of code. Beautiful!
Extracting reusable pieces of code
In our case, the Event Bus listener registration looks like a piece of code we can use in any component that listens to events on Event Bus.
As mentioned before, we can keep the logic related to a specific functionality in a separate file. Let’s move our Event Bus listener setup into a separate file.
// composables/useEventBusListener.js import EventBus from '@/event-bus' export function useEventBusListener(eventName, handler) { onMounted(() => EventBus.$on(eventName, handler)) onUnmounted(() => EventBus.$off(eventName, handler)) }
To use it in a component, we need to make sure we export our function (named or default) and import it in a component.
<template> <div id="app"> ... </div> </template> <script> import { useEventBusListener } from '@/composables/useEventBusListener' export default { name: 'MyComponent', setup(props, context) { useEventBusListener(MY_EVENT, myEventHandled) useEventBusListener(ANOTHER_EVENT, myAnotherHandled) } } </script>
That’s it! We can now use that in any component we need.
Wrapping up
There is an ongoing discussion about the Composition API. This post has no intention to promote any side of the discussion. It is more about showing when it might be useful and in what cases it brings additional value.
I think it is always easier to understand the concept on a real life example like above. There are more use cases and, the more you use the new API, the more patterns you will see. This post is merely a few basic patterns to get your started.
Let’s go again through the presented use cases and see where the Composition API can be useful:
General features that can live on its own without tight coupling with any specific component
All logic related to a specific feature in one file
Keep it in @/composables/*.js and import it in components
Examples: Activity Tracker, Reload Blocker, and Locale
Reusable features that are used in multiple components
All logic related to a specific feature in one file
Keep it in @/composables/*.js and import in components
Examples: Event Bus listener registration, window event registration, common animation logic, common library usage
Code organization within component
All logic related to a specific feature in one function
Keep the code in a composition function within the component
The code related to the same logical concern is in the same place (i.e. there’s no need to jump between data, computed, methods, lifecycle hooks, etc.)
Remember: This is all a work-in-progress!
The Vue Composition API is currently at work in progress stage and is subject to future changes. Nothing mentioned in the examples above is sure, and both syntax and use cases may change. It is intended to be shipped with Vue version 3.0. In the meantime, you can check out view-use-web for a collection of composition functions that are expected to be included in Vue 3 but can be used with the Composition API in Vue 2.
If you want to experiment with the new API you can use the @vue/composition library.
The post An Early Look at the Vue 3 Composition API in the Wild appeared first on CSS-Tricks.
An Early Look at the Vue 3 Composition API in the Wild published first on https://deskbysnafu.tumblr.com/
0 notes