Should we convert mixins to the class-based component definition syntax in Vue 3? - vue.js

After reading the plan for Vue 3, I noticed that the statement mixins will still be supported. However, Should I convert all of mixins components to class-based-components in case that Vue stops supporting mixins in the future?
mixins:
export default class MyComponent extends mixins(A, B, C) {
}

The class API that was originally planned for Vue 3 has been dropped and replaced with the composition API. While mixins will still be supported, composition functions have a number of advantages, such as avoiding namespace clashing, making it clearer where properties come from, and playing friendlier with Typescript.
Once Vue 3 is released I would recommend not writing more mixins but using Composition Functions. It'll be up to you to consider whether you rewrite old mixins - it will depend on whether you think the benefits of composition functions outweigh the initial cost of rewriting old mixins.

Related

How to access vuex, vue-router, pinia etc. outside of Vue components in SSR-friendly manner?

I'm trying to write SSR-friendly code, keeping in mind a potential migration of my app from SPA to SSR. One of the principles of such code is to avoid statefull singletons which can cause cross request state pollution
The problem comes when I need to use an instance of Vuex, Vue-router, Vue-i18n etc. outside of Vue component. Because the solution in all the respective SO answers is... You guessed it. To create and export a statefull singleton in a separate js file and then import it all over the app:
Vue-router: https://stackoverflow.com/a/43562210/11208064
Vuex: https://stackoverflow.com/a/47575742/11208064
Vue-i18n: https://stackoverflow.com/a/66695008/11208064
A simple example
// store.js
export default new Vuex.Store() {} // this is a singleton
// someOtherModule.js
import { store } from './store.js'
Pinia has covered the issue in the docs. They recommend to access the pinia instance via app.$pinia. However they don't specify how do I access the app instance itself.
Also the problem is not limited to these libraries. We write our own modules which work in a similar manner.
Researching the issue I came across this article. It suggests to wipe module cache, so each time you require it all the code is executed again, making it fresh and stateless. Sounds pretty sophisticated, but maybe this is the way? And if not, what is the recommended solution?

Is there a class component library to Vue that does not use decorators?

The Vue class component library uses the #Component decorator, and must thus be transpiled to work. Is there a way to use Vue class components without this decorator? Like, either a work-around or another similar library?
Use-case: Lower commitment for a legacy project, but still possible to analyze with tsc.
Transpiled environment is the expected scenario of use for Vue. It relies on custom .vue format and may lack some features without it, as well as the support of some third-party libraries because they rely on it.
The use of classes never was a good idea in Vue because it doesn't follow OOP paradigm. A class isn't instantiated directly but used as syntactic structure that is translated to Vue.component definition. Vue class components have inherent problems, one of which is poor support for TypeScript types. If Vue classes aren't already used in the project, there are reasons for them to not be the first choice.
In case there's a necessity to use Vue class components, this can be done in vanilla ES6 because decorators proposal is syntactic sugar, decorators are functions with specific signatures that are applied to classes and members and decorate them.
#foo
#bar()
class Baz {}
is the same as
let Baz = foo(bar()(class Baz {}))
Different decorator types are applied in different ways, also there are some differences between TypeScript and Babel legacy decorators.
#Component
class Foo extends Vue {
#Provide('bar') baz = 'bar'
}
is translated to
let Foo = class Foo extends Vue {
constructor() {
this.baz = 'bar'
}
}
Provide('bar')(Foo.prototype, 'baz')
Foo = Component(Foo);
With Vue 3 typescript is well supported, you could create your component as follows :
import { defineComponent } from 'vue'
export default defineComponent({
//the component options like data,props,computed...
})
For more details check the official docs
A running example to get started

Vue. Global vs local distribution of reusable options

As far as i understand there are two main ways to reuse options in different components.
Global registration of plugin or mixin making the desired options to be available all over application.
Vue.use(VuePlugin)
Or register them locally in every component where needed.
var Component = Vue.extend({ mixins: [VueMixin] })
Obviously the first method makes your code cleaner and easier to maintain. But which one is more efficient in terms of bundle size and overall application efficiency?

Polymer use code from mixin in behavior

I have code in behaviors and in mixins. If I use both the mixin and the behavior in an element, the behavior can use functionality from the mixin and vice versa.
It seems a bit weird to write code that way though as you aren't making sure that the mixin is there from the behaviors' perspective, you are assuming the element includes both.
Is there a way to really include the mixin in the behavior or do I have to convert everything to Mixins and use the mixins in the mixins that need them to make sure they are always there?
Polymer 2 Using the Polymer.MixinBehavior concepts. The mixinBehavior function also mixes in the Legacy APIs, the same as if you extended Polymer.LegacyElement. These APIs are required since since hybrid behaviors depend on them.
Example:
class SampleElement extends Polymer.mixinBehaviors([MyBehavior, MyBehavior2, ... ], Polymer.Element) {
static get is() { return 'sample-element'}
...
}
customElements.define(SampleElement .is, sample);

Do vuex modules still require namespacing?

I have set up a rather large Vuex project with multiple modules.
https://vuex.vuejs.org/en/modules.html
To grab the example of a getter a getter from a search module could be addressed like so:
computed: {
filters() {
return this.$store.state.search.filters;
}
}
Because I need to access the state of the module by referencing the search property in my property chain do I still need to namespace my module?
The documentation states the following:
By default, actions, mutations and getters inside modules are still
registered under the global namespace - this allows multiple modules
to react to the same mutation/action type.
https://vuex.vuejs.org/en/modules.html#namespacing
But if the module is under its own property in the store isn't the only conflict that could happen between modules themselves, which can easily be prevented by a simple naming convention of the files?
What am I missing here?
But if the module is under its own property in the store isn't the only conflict that could happen between modules themselves, which can easily be prevented by a simple naming convention of the files?
No, you misunderstand. The state itself is properly namespaced, but mutations, actions and getters are still collected on a global level so you can e.g. dispatch one Action and several actions from different modules react to it.
That's the default behavior, but the good news is, that there's an option to namespace mutations, actions and getters: "namespaced: true".
it's documented here: https://vuex.vuejs.org/en/modules.html#
Scroll down to the "Namespacing" section.