DEV Community

Chris Finnigan
Chris Finnigan

Posted on • Originally published at chrisfinnigan.com

Building Flexible Vue.js Components - Part 1

Background

Frameworks such as Vue.js are really driving the transformation of web application UI's.
The developers dream of being able to build large scale applications, using small testable components is now a reality.

When building component based UIs. We want to keep code reuse high and code duplication low. With this in mind, an important step in achieving this goal, is ensuring that your components are designed and built with flexibility in mind.

Example - Counter Component

Github Repo: https://github.com/chrisfinnigan/counter-examples

We've built a counter component. It has it's own local data within the component. It increments and decrements the local data value by 1 every time the button is pressed.

<template>
  <div class="counter">
    <button @click='decrement()'>-1</button>
    <span class="counterOutput">{{count}}</span>
    <button @click='increment()'>+1</button> 
  </div>
</template>

<script>
  export default {
    name: 'Counter',
    data: () => {
      return {
        count: 0
      }
    },
    methods: {
      increment() {
        this.count++
      },
      decrement() {
        this.count--
      }
    }
  }
</script>

<style scoped lang="scss">
  .counter{
    min-width: 33%;
    margin: auto auto;
  }

  button{
    padding: 15px;
    font-size: 16px;
    margin: 15px;
    font-weight: bold;
  }

  .counterOutput{
    font-size: 16px;
    font-weight: bold;
  }
</style>

That's a great start, we've got a counter. It does what we needed it to do.

We can be more flexible though...

The next time we want to use this component, we want to increment by 10 instead of 1.
Our component doesn't support this. It would be great if we could make the increment/decrement values configurable.
No problem! We can refactor our existing component to let us do exactly that.

<template>
  <div class="counter">
    <button @click='decrement(by)'>-{{by}}</button>
    <span class="counterOutput">{{count}}</span>
    <button @click='increment(by)'>+{{by}}</button> 
  </div>
</template>

<script>
  export default {
    name: 'CounterProps',
    data: function () {
      return {
        count: 0
      }
    },
    methods: {
      increment (by) {
        this.count = this.count + by
      },
      decrement (by) {
        this.count = this.count - by
      }
    },
    props: {
      by: {
        required: true,
        type: Number
      }
    }
  }
</script>

<style scoped lang="scss">
  .counter{
    min-width: 33%;
    margin: auto auto;
  }

  button{
    padding: 15px;
    font-size: 16px;
    margin: 15px;
    font-weight: bold;
  }

  .counterOutput{
    font-size: 16px;
    font-weight: bold;
  }
</style>

We can pass this value into our component using a prop.

  <counterProps 
    :by='10'
  />

Now we can use the same component for all our counter needs.

In the next thrilling installment...

We'll continue refactoring this example to allow further flexibility. Introducing Vuex, we will refactor our component to allow us to configure the actions and getters which we want the component to use.

Top comments (0)