GithubHelp home page GithubHelp logo

hhy5277 / vue-class-component Goto Github PK

View Code? Open in Web Editor NEW

This project forked from vuejs/vue-class-component

0.0 2.0 0.0 476 KB

ES / TypeScript decorator for class-style Vue components.

License: MIT License

JavaScript 28.29% Shell 1.45% HTML 0.65% Vue 5.98% TypeScript 63.63%

vue-class-component's Introduction

vue-class-component

ECMAScript / TypeScript decorator for class-style Vue components.

npm

Usage

Required: ECMAScript stage 1 decorators. If you use Babel, babel-plugin-transform-decorators-legacy is needed. If you use TypeScript, enable --experimentalDecorators flag.

It does not support the stage 2 decorators yet since mainstream transpilers still transpile to the old decorators.

Note:

  1. methods can be declared directly as class member methods.

  2. Computed properties can be declared as class property accessors.

  3. Initial data can be declared as class properties (babel-plugin-transform-class-properties is required if you use Babel).

  4. data, render and all Vue lifecycle hooks can be directly declared as class member methods as well, but you cannot invoke them on the instance itself. When declaring custom methods, you should avoid these reserved names.

  5. For all other options, pass them to the decorator function.

Example

Following is the example written in Babel. If you are looking for TypeScript version, it's in the example directory.

<template>
  <div>
    <input v-model="msg">
    <p>prop: {{propMessage}}</p>
    <p>msg: {{msg}}</p>
    <p>helloMsg: {{helloMsg}}</p>
    <p>computed msg: {{computedMsg}}</p>
    <button @click="greet">Greet</button>
  </div>
</template>

<script>
import Vue from 'vue'
import Component from 'vue-class-component'

@Component({
  props: {
    propMessage: String
  }
})
export default class App extends Vue {
  // initial data
  msg = 123

  // use prop values for initial data
  helloMsg = 'Hello, ' + this.propMessage

  // lifecycle hook
  mounted () {
    this.greet()
  }

  // computed
  get computedMsg () {
    return 'computed ' + this.msg
  }

  // method
  greet () {
    alert('greeting: ' + this.msg)
  }
}
</script>

You may also want to check out the @prop and @watch decorators provided by vue-property-decorators.

Using Mixins

vue-class-component provides mixins helper function to use mixins in class style manner. By using mixins helper, TypeScript can infer mixin types and inherit them on the component type.

Example of declaring a mixin:

// mixin.js
import Vue from 'vue'
import Component from 'vue-class-component'

// You can declare a mixin as the same style as components.
@Component
export default class MyMixin extends Vue {
  mixinValue = 'Hello'
}

Example of using a mixin:

import Component, { mixins } from 'vue-class-component'
import MyMixin from './mixin.js'

// Use `mixins` helper function instead of `Vue`.
// `mixins` can receive any number of arguments.
@Component
export class MyComp extends mixins(MyMixin) {
  created () {
    console.log(this.mixinValue) // -> Hello
  }
}

Create Custom Decorators

You can extend the functionality of this library by creating your own decorators. vue-class-component provides createDecorator helper to create custom decorators. createDecorator expects a callback function as the 1st argument and the callback will receive following arguments:

  • options: Vue component options object. Changes for this object will affect the provided component.
  • key: The property or method key that the decorator is applied.
  • parameterIndex: The index of a decorated argument if the custom decorator is used for an argument.

Example of creating NoCache decorator:

// decorators.js
import { createDecorator } from 'vue-class-component'

export const NoCache = createDecorator((options, key) => {
  // component options should be passed to the callback
  // and update for the options object affect the component
  options.computed[key].cache = false
})
import { NoCache } from './decorators'

@Component
class MyComp extends Vue {
  // the computed property will not be cached
  @NoCache
  get random () {
    return Math.random()
  }
}

Adding Custom Hooks

If you use some Vue plugins like Vue Router, you may want class components to resolve hooks that they provides. For that case, Component.registerHooks allows you to register such hooks:

// class-component-hooks.js
import Component from 'vue-class-component'

// Register the router hooks with their names
Component.registerHooks([
  'beforeRouteEnter',
  'beforeRouteLeave',
  'beforeRouteUpdate' // for vue-router 2.2+
])
// MyComp.js
import Vue from 'vue'
import Component from 'vue-class-component'

@Component
class MyComp extends Vue {
  // The class component now treats beforeRouteEnter
  // and beforeRouteLeave as Vue Router hooks
  beforeRouteEnter (to, from, next) {
    console.log('beforeRouteEnter')
    next() // needs to be called to confirm the navigation
  }

  beforeRouteLeave (to, from, next) {
    console.log('beforeRouteLeave')
    next() // needs to be called to confirm the navigation
  }
}

Note that you have to register the hooks before component definition.

// main.js

// Make sure to register before importing any components
import './class-component-hooks'

import Vue from 'vue'
import MyComp from './MyComp'

new Vue({
  el: '#app',
  components: {
    MyComp
  }
})

Caveats of Class Properties

vue-class-component collects class properties as Vue instance data by instantiating the original constructor under the hood. While we can define instance data like native class manner, we sometimes need to know how it works.

this value in property

If you define an arrow function as a class property and access this in it, it will not work. This is because this is just a proxy object to Vue instance when initializing class properties:

@Component
class MyComp extends Vue {
  foo = 123

  bar = () => {
    // Does not update the expected property.
    // `this` value is not a Vue instance in fact.
    this.foo = 456
  }
}

You can simply define a method instead of a class property in that case because Vue will bind the instance automatically:

@Component
class MyComp extends Vue {
  foo = 123

  bar () {
    // Correctly update the expected property.
    this.foo = 456
  }
}

undefined will not be reactive

To take consistency between the decorator behavior of Babel and TypeScript, vue-class-component does not make a property reactive if it has undefined as initial value. You should use null as initial value or use data hook to initialize undefined property instead.

@Component
class MyComp extends Vue {
  // Will not be reactive
  foo = undefined

  // Will be reactive
  bar = null

  data () {
    return {
      // Will be reactive
      baz: undefined
    }
  }
}

Build the Example

$ npm install && npm run example

Questions

For questions and support please use the the official forum or community chat. The issue list of this repo is exclusively for bug reports and feature requests.

License

MIT

vue-class-component's People

Contributors

304notmodified avatar briangonzalez avatar brooooooklyn avatar decadef20 avatar eddow avatar fachher avatar finico avatar herringtondarkholme avatar hjkcai avatar kaorun343 avatar kazupon avatar ktsn avatar kuitos avatar mikekidder avatar nargonath avatar r4zzz4k avatar rixlabs avatar sorayama avatar tomoyashibata avatar vip30 avatar wprater avatar xingoxu avatar yankeeinlondon avatar yyx990803 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.