The fact is that when node.js came along, JavaScript replaced Java and C#, but this led to things like classes in ES6, dependency injection in Angular.js, decorators in Ember, CSS-in-JS, ecosystem lock-in, engine-lock-in, etc, etc.
frameworks:
- name: "Hyperapp"
year: 2017
url: "https://hyperapp.dev"
description: "A minimalist framework focused on simplicity and functional programming, usable directly in the browser."
- name: "HTM"
year: 2018
url: "https://github.com/developit/htm"
description: "A lightweight library for JSX-like syntax without compilation, compatible with frameworks like Preact."
- name: "Lit"
year: 2018
url: "https://lit.dev"
description: "A library for building web components using native browser APIs, without requiring a build process."
- name: "Alpine.js"
year: 2019
url: "https://alpinejs.dev"
description: "A lightweight framework for declarative, reactive UI, easily usable without Node.js or compilation."
- name: "Petite-Vue"
year: 2021
url: "https://github.com/vuejs/petite-vue"
description: "A minimalist subset of Vue.js, focused on progressive enhancement and browser-native use."
vue_lifecycle_methods:
vue2:
beforeCreate:
description: "Called synchronously after the instance has been initialized, before data observation and event/watcher setup."
created:
description: "Called synchronously after the instance is created. At this point, the instance has finished processing options, which means the following have been set up: data observation, computed properties, methods, and watchers, though it has not yet been mounted to the DOM."
beforeMount:
description: "Called right before the mounting begins: the render function is about to be called for the first time."
mounted:
description: "Called after the instance has been mounted, where el is replaced by the newly created vm.$el. If the root instance is mounted to an in-document element, vm.$el will also be in-document when mounted is called."
beforeUpdate:
description: "Called when data changes, before the DOM is patched."
updated:
description: "Called after a data change causes the DOM to be re-rendered and patched."
activated:
description: "Called when a kept-alive component is activated."
deactivated:
description: "Called when a kept-alive component is deactivated."
beforeDestroy:
description: "Called right before a Vue instance is destroyed."
destroyed:
description: "Called after a Vue instance has been destroyed."
vue3:
beforeCreate:
description: "Called right after the instance has been initialized, before data observation and event/watcher setup."
created:
description: "Called after the instance is created. At this point, the instance has finished processing options, which means the following have been set up: reactive data, computed properties, methods, and watchers, though it has not yet been mounted."
beforeMount:
description: "Called right before the mounting begins: the render function is about to be called for the first time."
mounted:
description: "Called after the instance has been mounted. At this point, the el property is replaced by the newly created vm.$el. If the root instance is mounted on an in-document element, vm.$el will also be in-document."
beforeUpdate:
description: "Called when data changes, before the virtual DOM is patched."
updated:
description: "Called after a data change causes the virtual DOM to be re-rendered and patched."
beforeUnmount:
description: "Called right before a component instance is unmounted."
unmounted:
description: "Called after a component instance is unmounted."
activated:
description: "Called when a kept-alive component is activated."
deactivated:
description: "Called when a kept-alive component is deactivated."
errorCaptured:
description: "Called when an error from a descendant component is captured."
Vuex to Pinia
lifecycle_methods:
store_initialization:
vuex: 'store'
pinia: 'createPinia'
state_definition:
vuex: 'state'
pinia: 'state'
getters:
vuex: 'getters'
pinia: 'getters'
actions:
vuex: 'actions'
pinia: 'actions'
mutations:
vuex: 'mutations'
pinia: 'no direct equivalent (use actions or composition API)'
modules:
vuex: 'modules'
pinia: 'no direct equivalent (use multiple stores)'
plugins:
vuex: 'plugins'
pinia: 'plugins'
state_access:
vuex: 'this.$store.state'
pinia: 'useStore().$state'
commit:
vuex: 'this.$store.commit'
pinia: 'useStore().$patch'
dispatch:
vuex: 'this.$store.dispatch'
pinia: 'useStore().$patch or direct action call'
strict_mode:
vuex: 'strict'
pinia: 'no direct equivalent (use devtools or custom logic)'
hot_module_replacement:
vuex: 'store.hotUpdate'
pinia: 'not needed (store is reactive by default)'
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Vue 3 with Pinia and Axios</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/pinia@2/dist/pinia.iife.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<dropdown-component></dropdown-component>
</div>
<script>
const { createApp, ref, onMounted, defineComponent } = Vue;
const { createPinia, defineStore } = Pinia;
// Define the Pinia store
const useStore = defineStore('main', {
state: () => ({
options: [],
selectedOption: null
}),
actions: {
fetchOptions() {
const script = document.createElement('script');
const callbackName = 'foo';
// Define the callback function
window[callbackName] = (response) => {
this.options = response.query.search.map(item => item.title);
};
// Set the JSONP URL
const url = `https://en.wikipedia.org/w/api.php?action=query&format=json&list=search&srsearch=vue&origin=*&callback=${callbackName}`;
// Set the script element's src to the JSONP URL
script.src = url;
// Append the script to the document
document.body.appendChild(script);
// Clean up the script and callback after execution
script.onload = () => {
document.body.removeChild(script);
delete window[callbackName];
};
script.onerror = (error) => {
console.error('Error fetching options:', error);
document.body.removeChild(script);
delete window[callbackName];
};
}
}
});
// Define the Vue component
const DropdownComponent = defineComponent({
template: `
<div>
<label for="wiki-select">Choose an article:</label>
<select id="wiki-select" v-model="selectedOption" ref="selectDropdown">
<option v-for="option in options" :key="option" :value="option">{{ option }}</option>
</select>
<p>Selected option: {{ selectedOption }}</p>
</div>
`,
setup() {
const store = useStore();
const selectDropdown = ref(null);
// Define the foo method
const foo = (selectedOption) => {
console.log('Selected option changed:', selectedOption);
};
onMounted(() => {
store.fetchOptions();
selectDropdown.value.addEventListener('change', (event) => {
foo(event.target.value);
});
});
return {
options: store.options,
selectedOption: store.$state.selectedOption,
selectDropdown
};
}
});
// Create the Vue app and Pinia store
const app = createApp({
components: {
DropdownComponent
}
});
const pinia = createPinia();
app.use(pinia);
app.mount('#app');
</script>
</body>
</html>
Nuxt
/*
Scope:
publicRuntimeConfig: These configuration values are accessible on both the server and the client. This means any value defined here can be accessed and used in your client-side code.
privateRuntimeConfig: These configuration values are only accessible on the server side. They are not exposed to the client, making them suitable for sensitive data that should not be exposed to the client.
Security:
publicRuntimeConfig: Since values here are available on the client side, they should not contain sensitive information such as API keys or secrets.
privateRuntimeConfig: Safe to store sensitive information as these values are only accessible on the server.
Access:
publicRuntimeConfig: You can access these values using this.$config in your Vue components and context.$config in the Nuxt context.
privateRuntimeConfig: These values are accessible in server-side code, such as server middleware, API routes, and server-side Vue components.
*/
import axios from 'axios';
export default async () => {
const { data } = await axios.get('https://api.example.com/config');
return {
publicRuntimeConfig: {
apiBase: process.env.API_BASE || data.apiBase,
},
privateRuntimeConfig: {
apiSecret: process.env.API_SECRET || data.apiSecret,
},
};
};
documentation:
- name: "GitHub Issue - Extract window.__NUXT__ to <script>"
description: "Discusses how to extract `window.__NUXT__` to a `<script>` tag for SEO purposes."
url: "https://github.com/nuxt/nuxt/issues/8548"
- name: "GitHub Issue - Remove window.__NUXT__ once app initialises"
description: "Discusses the use of `window.__NUXT__` for backward compatibility and its removal in future versions."
url: "https://github.com/nuxt/nuxt/issues/25336"
- name: "Nuxt Documentation - The Context"
description: "Explains the context object, which includes `window.__NUXT__`."
url: "https://v2.nuxt.com/docs/internals-glossary/context/"
Window Object Keys
Framework Specific Object Literals:
Framework
Window Object Key(s)
Nuxt
__nuxt__
Vue 2
Vue, Vuex
Vue 3
Vue, Vuex
Angular.js
$window
Angular
$window, ng, ngCore
Ember
Em, Ember
Svelte
svelte, Svelte
Solid.js
solid
Mithril.js
m, Mithril
Backbone.js
Backbone, _, $
DOM Wrappers
event_bubbling_issues:
Ember:
- description: "Event bubbling issues with components not propagating events as expected."
url: https://stackoverflow.com/questions/19776520/bubble-up-events-from-ember-component
- description: "Stopping bubbling/propagation in Ember 2.x causing unexpected behavior."
url: https://stackoverflow.com/questions/48713114/stopping-bubbling-propagation-in-ember-2-x
- description: "Inner actions bubbling to outer link-to helpers unexpectedly."
url: https://stackoverflow.com/questions/35157428/how-to-stop-the-inner-action-from-bubbling-to-the-outer-link-to-helper
- description: "View events bubbling to actions in Ember."
url: https://github.com/emberjs/ember.js/issues/10040
Vue2:
- description: "Custom events not bubbling naturally in Vue 2."
url: https://stackoverflow.com/questions/41993508/vuejs-bubbling-custom-events
- description: "Preventing event bubbling in Vue 2 using modifiers like `.stop`."
url: https://stackoverflow.com/questions/48798216/prevent-event-bubbling-in-vue
- description: "Challenges with bubbling events on component chains."
url: https://stackoverflow.com/questions/42029150/how-to-bubble-events-on-a-component-subcomponent-chain-with-vue-js-2
Vue3:
- description: "Custom events do not propagate up the component chain by default."
url: https://stackoverflow.com/questions/64613446/do-custom-events-propagate-up-the-component-chain-in-vue-3
- description: "Issues with event bubbling in SVG elements within Vue 3 components."
url: https://www.devgem.io/posts/handling-click-events-in-vue-3-solving-svg-click-event-bubbling
- description: "Opt-in event bubbling discussion for Vue 3."
url: https://github.com/vuejs/rfcs/discussions/581
Svelte:
- description: "Event bubbling issues with wrong order of event handling."
url: https://github.com/sveltejs/svelte/issues/14787
- description: "Event bubbling not working as expected in nested components."
url: https://github.com/sveltejs/svelte/issues/149
- description: "Event bubbling order issues in Svelte 5."
url: https://github.com/sveltejs/svelte/issues/14786
Solid.js:
- description: "stopPropagation on parent elements affecting child event handling."
url: https://github.com/solidjs/solid/issues/1278
- description: "Event delegation and bubbling behavior in Solid.js."
url: https://docs.solidjs.com/reference/jsx-attributes/on_
- description: "Event handlers and bubbling behavior in Solid.js."
url: https://docs.solidjs.com/concepts/components/event-handlers
Lit.js:
- description: "LitElement prevents event bubbling on polyfilled browsers."
url: https://github.com/lit/lit-element/issues/658
- description: "Change events not bubbling outside Shadow DOM in Lit."
url: https://github.com/lit/lit-element/issues/922
- description: "Declarative event listeners and bubbling in Lit."
url: https://lit.dev/docs/components/events/
function getQueryParam(key) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get(key);
}
jQuery Usage
$(document).ready(function() {
// Store the function object
$(document).data('getQueryParam', getQueryParam);
// Retrieve and use the function
const getQueryParam = $(document).data('getQueryParam');
const value = getQueryParam('foo');
// Assert the query parameter
if (value === 'bar') {
console.log("The query parameter 'foo' has the value 'bar'");
} else {
console.log("The query parameter 'foo' does not have the value 'bar'");
}
});
JQuery QUnit Test
QUnit.test("Query string contains key 'foo' with value 'bar'", function(assert) {
const getQueryParam = $(document).data('getQueryParam');
const value = getQueryParam('foo');
assert.equal(value, 'bar', "The query parameter 'foo' should have the value 'bar'"); });