preface

Original intention: a few days ago, I found that the Vue project is developed with Decorator mode, it looks like the overall code is good, so I made a note to share with you, if you don’t like it, don’t use it.

For whom: Primary front-end development, big guy detour.

This project is built using JS and decorators. If your project is using TS, then the method of using decorators is different from that described in this article. Please refer to TS to use decorators. Note that variables are contaminated with this pattern, so you should not have variables with the same name

What is a Decorator

Decorator Decorator is a class related syntax, so Decorator decorators can only be used in class classes. They cannot be used in normal syntax or expressions. Decorators provide us with a layer of interception, first executing what’s inside the decorator, then executing our actions. See ruan Yifeng’s “Decorators” for details.

The installation

component

npm install --save vue-class-component
npm install --save vue-property-decorator
Copy the code

configuration

Do the following configuration in the project root directory babel.config.js

module.exports = {
  presets: [
    '@vue/app'].plugins: [['@babel/plugin-proposal-decorators', { legacy: true }],
    ['@babel/plugin-proposal-class-properties', { loose: true}}]]Copy the code

In the root directory of the project, jsconfig.json, do the configuration as follows

{
    "compilerOptions": {
      "experimentalDecorators": true}}Copy the code

Method of use

Here are a few common methods used in Vue. For details, see vue-property-decorator

Life cycle, methods, data

These methods are the same as the original, directly write on the line, see the following case comparison

The original writing

<script>
export default {
    data() {
        return {
            msg: "Hello frogman"}},created(){},methods: {
        test() {
        
        }
    }
}
</script>
Copy the code

Decorator writing

<script>
import { Vue } from 'vue-property-decorator'
class App extends Vue {
    msg = "Hello frogman"
    created(){}test(){}}export default App
</script>
Copy the code

Emit

The original writing

<script>
export default {
  methods: {
    send() {
      this.$emit("custom".123)
    }
  }
}
</script>
Copy the code

Decorator writing

<script>
import { Vue, Emit } from 'vue-property-decorator'
class Hello extends Vue {
  created() {
    this.send()
  }

  @Emit("custom")
  send() {
    return 123}}export default Hello
</script>
Copy the code

Provide

The original writing

<script>
export default {
  provide() {
    return {
      msg: this.msg
    }
  }
}
</script>
Copy the code

Decorator writing

<script>
class App extends Vue {
  @Provide() msg = this.msg
  msg = "Hello frogman"
}
export default App
</script>
Copy the code

Inject

The original writing

export default {
  inject: {
    msg: {
      default: () = > "".required: true
    } 
  }
}
</script>
Copy the code

Decorator writing

import { Vue, Component,Inject } from 'vue-property-decorator'
@Component
class Hello extends Vue {
  @Inject({ required: true.default: () = > "" }) msg
}
export default Hello
Copy the code

Prop

The original writing

<script>
export default {
  props: {
    msg: {
      type: () = > String.required: true
    }
  }
}
</script>
Copy the code

Decorator writing

<script>
import { Vue, Prop } from 'vue-property-decorator'
class Hello extends Vue {
  @Prop({ required: true.type: String }) msg
}
export default Hello
</script>
Copy the code

PropSync

The original writing

/ / the parent component
<HelloWorld :msg.sync="msg" v-show="msg"/>

/ / child component
<script>
export default {
  props: {
    msg: {
      require: true}},created() {
    setTimeout(() = > {
      this.test()
    }, 5000)},methods: {
    test() {
      this.$emit("update:msg".false)}}}</script>
Copy the code

Decorator writing

$emit(“update: MSG “) is the MSG in this.$emit(“update: MSG “), followed by variables

<script>
import { Vue, Component, PropSync } from 'vue-property-decorator'
@Component
class Hello extends Vue {
  @PropSync("msg", { required: true }) variable
  created() {
    setTimeout(() = > {
      this.variable = false
    }, 5000)}}export default Hello
</script>
Copy the code

Watch

The original writing

export default {
  data() {
    return {
      str: 123}},created() {
    setTimeout(() = > {
      this.str = 12
    }, 5000)},watch: {
    str: function(newVal, oldVal) {
      console.log(newVal, oldVal)
    }
  }
}
</script>
Copy the code

Decorator writing

import { Vue, Component, Watch } from 'vue-property-decorator'
@Component
class Hello extends Vue {
  str = 123

  created() {
    setTimeout(() = > {
      this.str = 12
    }, 2000)
  }

  @Watch("str", {deep: true})
  test(newVal, oldVal) {
    console.log(newVal, oldVal)
  }
}
export default Hello
Copy the code

Computed

The original writing

<script>
export default {
  computed: {
    test: {
       get() {
         return this.msg
       },
       set(val) {
         return this.msg = val
       }
     }
   }
}
</script>
Copy the code

Decorator writing

<script>
import { Vue, Component } from 'vue-property-decorator'
@Component
class App extends Vue {
  get test() {
    return this.msg
  }
  set test(val) {
    return this.msg = val
  }

}
export default App
Copy the code

Model

Sometimes we want to write a v-Model method for a component like this

The original writing

/ / the parent component
<HelloWorld :msg="msg" v-model="msg"/>

/ / child component
<input type="text" @input="test" :value="msg">

<script>
export default {
  props: {
    msg: {
      require: true}},model: {
    prop: "msg".event: "input"
  },
  methods: {
    test(e) {
      this.$emit("input", e.target.value)
    }
  }
}
</script>
Copy the code

Decorator writing

/ / the parent component
<HelloWorld :msg="msg" v-model="msg"/>

/ / child component
<input type="text" @input="test" :value="msg">

<script>
import { Vue, Component, Model, Emit } from 'vue-property-decorator'
@Component
class Hello extends Vue {
  @Model("input", {default: () = > ""}) msg
  
  test(e) {
    this.send(e)
  }
  @Emit("input")
  send(e) {
    return e.target.value
  }
}
export default Hello
</script>
Copy the code

Ref

The original writing

<HelloWorld :msg="msg" ref="val"/>

<script>
export default {
  name: 'App'.components: {
    HelloWorld
  },
  data() {
    return {
      msg: "Hello frogman"}},mounted() {
    console.log(this.$refs.val)
  },
}
</script>
Copy the code

Decorator writing

<HelloWorld :msg="msg" ref="val"/>

<script>
import { Vue, Component, Ref } from 'vue-property-decorator'
@Component({
  components: {
    HelloWorld
  }
})
class App extends Vue {
  @Ref("val") val
  msg = "Hello frogman"
  
  mounted() {
    console.log(this.val)
  }
}
export default App
</script>
Copy the code

Component

This method is imported from the component library. If you use the use lifecycle method, remember to include this decorator, otherwise it will not take effect. This decorator receives an object that can also write native Vue methods.

<script>
import { Vue, Component } from 'vue-property-decorator'
@Component({
    components: {},watch: {
        str: function(val) {
            console.log(val)
        }
    }
})
export class App extends Vue {}
</script>
Copy the code

extension

Of course, you can extend the wrapped Decorator to your needs. The Decorator takes three parameters

  • The target object
  • Target the key
  • Describe objects

If you don’t know how to describe object properties here, you can read my article “Understanding JavaScript Objects in Depth.”

<script>
function Decorator(data) {
    return (vue, key, describe) = > {
      // vue Current execution environment object
      // key The current decorator function object test
      // Describe objects where value is a function
      let fn = describe.value
      describe.value = function () {
        let status = window.confirm(data)
        if (status) return fn()
      }
    }
}
import { Vue, Component } from 'vue-property-decorator'
@Component
class App extends Vue {
  @Decorator("Please click OK")
  test() { 
    window.confirm("Are you done?")}}export default App
</script>
Copy the code

In the example above, we can extend our own Decorator. The Decorator acts as a layer of interception, performing the operations in the Decorator before the logical operations in our function itself. I only do a case here ha, depending on your specific needs.

Thank you

Thank you in spite of your busy schedule to open this article, I hope you can be helpful, if there is a problem welcome to corrections.

I am frogman, if you think this is ok, please click like.

Interested partners can join [front end entertainment circle exchange group] welcome everyone to exchange and discuss

Past oliver

What are CommonJs and Es Modules and how they differ?

Maps to Understand Data Structures with Ease

Do you know all these JavaScript Tricks for work?

【 Suggestions 】 Share some Git commands commonly used in work and how to solve special problems

Deconstruction: Making Data Access Easier!

Do you really understand the functional features in ES6?