npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vue-class-api

v0.0.5

Published

Vue 3 Class API

Downloads

2

Readme

Vue 3 Class API

While we recognize the decision by the team behind Vue 3 to drop support for Class Components we decided to give it another shot.

API Documentation

@Component

Similar to vue-class-components every component is defined as:

<template>
	<div>My Component</div>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-class-api';

@Component(options: ComponentOptions)
export default class MyComponent extends Vue {}
</script>

ComponentOptions is an object with the same pattern used in the Options API (if there's any part of the Options API implementation that hasn't been covered yet in the Class API implementation).

Computed Properties

All getter/setters are automatically transformed into computed properties.

@Prop

import { Vue, Component, Prop } from 'vue-class-api';

@Component()
export default class MyComponent extends Vue {
	@Prop({ type : Number, default : 3 })
	readonly foo: number;

	@Prop({ required : true })
	readonly bar: number;

	@Prop()
	readonly lorem: number;
}

Prop takes one argument that is identical what would normally be supplied to the props object in the Options API.

@Ref

Simplifies accessing template refs by moving them to the instance's scope.

<template>
	<div>My Component</div>
	<MyOtherComponent ref="foo"></MyOtherComponent>
</template>

<script lang="ts">
import { Vue, Component }    from 'vue-class-api';
import MyOtherComponent from './foo/MyOtherComponent.vue'

@Component({ 
	components : { MyOtherComponent }
})
export default class MyComponent extends Vue {
	@Ref()
	foo: MyOtherComponent;

	// assuming `MyOtherComponent` has exposed a method called `poke()`
	pokeFoo() {
		this.foo.poke(); // identical to this.$refs.foo.poke();
	}
}
</script>

@Expose

Once used, only the decorated fields would be available to the parent component when referenced using the ref attribute.

import { Vue, Component, Expose } from 'vue-class-api';

@Component()
export default class MyComponent extends Vue {

	@Expose()
	foo() {
		console.log('Called foo');
	}

	// Not accessible if this component is referenced by parent
	hiddenFunction() {
		console.log('Boo!');
	}

}

@Emits

Populated the emits field in the Options API which helps with better documentation of the component.

import { Vue, Component, Emits } from 'vue-class-api';

@Component()
export default class MyComponent extends Vue {

	isCool = false;

	// List out any potential emits from the method
	@Emits('bob', 'marley')
	foo() {
		if (this.isCool) {
			this.$emit('bob');
		}
		else {
			this.$emit('marley');
		}
		this.$emit('bob');
		console.log('Called foo');
	}

	@Emits('jack', 'bob')
	bar() {
		this.$emit('jack');
		this.$emit('bob');
		console.log('Boo!');
	}

}

Above will produce:

{
	emits : [ 'bob', 'marley', 'jack' ],
}

@Watch

Example:

import { Vue, Component, Watch } from 'vue-class-api';

@Component()
export default class MyComponent extends Vue {

	spaghetti = {
		delicious : true,
	}

	@Watch('spaghetti', { deep : true, immediate : false })
	foo() {
		console.log('Somebody touched my spaghetti!');
	}

	mounted() {
		this.spaghetti.delicious = false;
	}

}

@Provide/@Inject

import { Vue, Component, Provide } from 'vue-class-api';

@Component({ components : MyChildComponent })
export default class MyComponent extends Vue {
	@Provide('food')
	food: number = 123;
}
import { Vue, Component, Inject } from 'vue-class-api';

@Component()
export default class MyChildComponent extends Vue {
	@Inject('food')
	bar: number;

	mounted () {
		console.log(this.bar === 123); // true
	}
}

Objects are also supported, however they are being wrapped in a computed function provided by Composition API. The reactivity behavior is subject to change depending on how computed changes.

@Hook

Lifecycle hooks are available in two forms:

  1. Hook decorator around any method which exposes method in the methods object and also gets used as a lifecycle hook
  2. Special method names defined on the class
import { Vue, Component, Hook } from 'vue-class-api';

@Component()
export default class MyComponent extends Vue {

	@Hook('mounted')
	foo() {
		console.log('This will run second.');
	}

	// Since the name of the method is one of the lifecycle hooks it gets picked up as a life cycle hook 
	mounted() {
		console.log('This will run first.');
	}

	@Hook('beforeMount')
	bar() {
		console.log('This will run before everything else');
	}

	@Hook('mounted')
	foo2() {
		console.log('You can have more than one mounted hook so long as the method is decorated with the same hook name');
		console.log('This will run after foo()'); // While not guaranteed, in most of the cases, the order of decorator execution is top->bottom
	}

}

Mixin

In order to create nested Vue Components you can use the Mixin helper function like so:

import { Vue, Component, Mixin } from 'vue-class-api';

@Component()
export default class Mom extends Vue {
	mounted() {
		console.log('Dad');
	}
}

@Component()
export default class Dad extends Vue {
	mounted() {
		console.log('Mom');
	}
}

@Component()
export default class Child extends Mixin(Mom, Dad) {
	mounted() {
		console.log('Child');
	}
}

The order of mounted hooks running would be like so:

Mom
Dad
Child

While this is not a temporary solution and here to stay, we are working on a better solution for component inheritance with a more robust development flow.

Roadmap

  1. Extending Components: We're working on a better solution for nested components that provides full typescript support.
  2. More Quality-of-Life Decorators: We're trying to isolate component options into their own standalone decorators. The end goal is to not have a need to provide any arguments to the @Component decorator.

Contributions

If you have a proposal for a new decorator to simplify the component definition process or some new cool feature you recently stumbled upon, open up a pull-request. All ideas are welcome!

License

                GNU GENERAL PUBLIC LICENSE
                   Version 3, 29 June 2007

Copyright (C) 2007 Free Software Foundation, Inc. https://fsf.org/ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.