Categories
Vue Tips

Vue Tips — CSS Frameworks and Watching Nested Data

Spread the love

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at using CSS frameworks to save us time from styling everything manually and watching nested data.

Use an Off the Shelf CSS Framework

Off the shelf CSS framework saves us time from styling things that we’ve to style manually otherwise. There’re many frameworks to choose from, including Tailwind CSS, Foundation, Bulma, and Bootstrap.

They come with classes and JavaScript code to style static components like inputs and tables and also create dynamic components like modals and popups.

Some of them have their own Vue components built for it. For instance, Buefy is a library that’s based on Bulma. BootstrapVue is a component library that’s based on Bootstrap.

If there’s a Vue component library made for it then, then we should use it since they integrate much better with other Vue components in our app. They take props and emits events like any other Vue components.

For instance, we can use Buefy to take advantage of the Bulma framework without making our own styled-components based on Bulma as follows:

index.js :

new Vue({
  el: "#app",
  data: {
    name: ""
  }
});

index.html :

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/buefy/dist/buefy.min.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/buefy/dist/buefy.min.css" />
  </head>
  <body>
    <div id="app">
      <b-field label="Name" type="is-danger" message="Name">
        <b-input type="name" v-model="name" maxlength="30"> </b-input>
      </b-field>
      <p>{{name}}</p>
    </div>
    <script src="index.js"></script>
  </body>
</html>

In the code above, we have the b-field component from Buefy, which is an input form field component. Then we have our b-input component, which is the actual input component.

The label is rendered by the b-field component so that we can see the label. In addition, there’s styling with the type prop and the message prop provides a message that’s displayed.

The input has input validation and binds to a variable of our choice with v-model .

We did all that by just using the library and referencing the provided component, so it’s the best choice for quickly using styled-components.

Watching Nested Data in Vue

We can watch data with by adding a function to the watch object in our component options.

It’s useful for watching for updates in nested objects and arrays. In these cases, Vue has no idea what’s changed unless we explicitly add watcher and set it to watch for the structural changes of the object. This is because Vue sees that the reference to the object hasn’t changed.

For instance, we can use watchers to watch for changes to an array as follows:

index.js :

new Vue({
  el: "#app",
  data: {
    nums: [1, 2, 3]
  },
  methods: {
    append() {
      this.nums.push(Math.max(...this.nums) + 1);
    }
  },
  watch: {
    nums: {
      deep: true,
      handler() {
        console.log("nums changed");
      }
    }
  }
});

index.html :

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <button @click="append">Append</button>
      <p v-for="n in nums">{{n}}</p>
    </div>
    <script src="index.js"></script>
  </body>
</html>

In the code above, we have an append method to push numbers into the nums array as it’s called. Then we have the watch object with the nums object inside to watch for changes in nums . We set deep to true so that it watches for all structural changes. The handler is then run when it’s changed.

Then when we click the Append button, the handler function will run.

There’s also an immediate option so that the watcher is run when the field is initialized. For instance, we can use it as follows:

new Vue({
  el: "#app",
  data: {
    nums: [1, 2, 3]
  },
  methods: {
    append() {
      this.nums.push(Math.max(...this.nums) + 1);
    }
  },
  watch: {
    nums: {
      deep: true,
      immediate: true,
      handler() {
        console.log("nums changed");
      }
    }
  }
});

Then we’ll see nums changed logged when we first load the app.

If we want to use the same handler function to watch more than one item, we can set it to the function in the methods object.

For instance, we can write:

index.js :

new Vue({
  el: "#app",
  data: {
    nums: [1, 2, 3],
    nums2: [4, 5, 6]
  },
  methods: {
    append() {
      this.nums.push(Math.max(...this.nums) + 1);
    },
    appendTo2() {
      this.nums2.push(Math.max(...this.nums2) + 1);
    },
    watch() {
      console.log("nums changed");
    }
  },
  watch: {
    nums: {
      deep: true,
      immediate: true,
      handler: "watch"
    },
    nums2: {
      deep: true,
      immediate: true,
      handler: "watch"
    }
  }
});

index.html :

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <button @click="append">Append</button>
      <button @click="appendTo2">Append 2</button>
      <p v-for="n in nums">{{n}}</p>
      <p v-for="n in nums2">{{n}}</p>
    </div>
    <script src="index.js"></script>
  </body>
</html>

In the code above, we have 2 buttons, which append numbers to 2 separate arrays as we click it by running append or appendTo2 functions respectively.

Then since we set handler to 'watch' , the watch method in methods is called, so we’ll see that “nums changed” is logged if we click any of the buttons.

Conclusions

Off the shelf CSS frameworks are great for reducing styling effort needed for us. Some frameworks have component libraries made from it so that we don’t have to spend time styling them ourselves.

We should use watchers for watching values changes deeply nested objects and array. It has options to start watching if the component loads and also has options to watch deeply nested objects, which computed properties can’t do.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *