This is a record of some gotchas I’ve come across with Vue.js v2. I love its simplicity.
Caveat: examples are taken from real code, but I have not tested them directly. If you see a problem, please contact me.
Contents of this post:
- AJAX Request
- kebab-case for Props with HTML Components
- Force Refresh of Object
AJAX Request
Include Axios:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
Make the request, noting the self
trick to keep a reference to this
:
Vue.component('my-vue-component', {
...
data: {
widgets: null
},
methods: {
fetchData: function() {
let self = this;
axios.get("/api/widgets")
.then(function (response) {
self.widgets = response.data;
})
.catch(function (error) {
console.log(error);
});
}
}
...
});
kebab-case for Props with HTML Components
Use camelCase in the JavaScript, and kebab-case in the HTML.
This is the HTML template for your component, note how the widgetName changes to widget-name:
<template id="widget-editor">
<p>{{ widgetName }}</p>
</template>
<div id="my-app">
<widget-editor :widget-name="Weather Widget"></widget-editor>
</div>
Javascript for the component:
Vue.component('widget-editor', {
// camelCase in JavaScript
props: ['widgetName'],
template: '#widget-editor'
})
Force refresh of object
Problem: let’s say you have a component that displays a model, like a “todo list” which contains another component “todo item”. If you load new data for that todo list itme from the server, you might want the todo list item component to be recreated completely so that it goes through all its initialisation steps. If you don’t destroy the model, you component might have state from the older model. For example, you might forget to reset a boolean flag “show top priority item” when the item changes. Most of this is covered by how Vue.js watches for changes in its properties you set. This is more about overcoming programmer bugs. Maybe this really isn’t a problem, and I didn’t understand what the correct approach should have been.
Controversial approach: Vue.js documentation advises you to be “data-centric”. In other words, instead of destroying and re-creating an object, you should watch for changes in your component of that object. But I’ve found in one case it was cleaner to destroy (nullify) the object first, then assign a new object to the variable, so that no state is left over from the older object.
HTML:
<template id="todo-list">
<p>
My one thing to do:
<todo-item :item-object="topPriorityItem" v-if="topPriorityItem"></todo-item>
</template>
JavaScript:
Vue.component('todo-list', {
data: {
todoItems: ['Get kebab', 'Go for a walk'],
topPriorityItem: null
},
methods: {
setTopPriority: function(itemIndex) {
this.topPriorityItem = null;
this.$nextTick(function() {
// Trick: waits until next "tick" to ensure that item nullification destroys <todo-item>
this.topPriorityItem = this.todoItems[itemIndex];
});
}
}
}
Vue.component('todo-item', {
props: [itemObject],
mounted: function() {
// Complicated state setting here that would be hard to track
// if the item wasn't destroyed and recreated
}
});