Solving Common Vue Problems — Loading Images, Events, and More
By: John Au-Yeung
Tags: JavaScript, Web Development, Software Development, Technology, Programming

Photo by Mike Benna on Unsplash

Vue.js makes developing front end apps easy. However, there are still chances that we’ll run into problems.

In this article, we’ll look at some common issues and see how to solve them.

Emit Event from Grandchild to Grandparent Component

We can emit events from grandchild to grandparent by calling this.$emit from the grandchild.

Then its parent can pass it off to the grandparent with the v-on="$listeners" code in its template.

Then the grandparent can listen to it with the usual v-on or @ listener code.

For example, we can write:

Vue.component('grand-child', {

template: '<button @click="emitEvent">emit value</button>',

methods: {

emitEvent() { this.$emit('event', 'value') }

}

})

We emit an event event when the button is clicked.

Then in the child component, we write:

Vue.component('child', {

template: '<grand-child v-on="$listeners"></grand-child>'

})

We reference the grand-child component in child . To pass the event emitted by grand-child to the grandparent component, we have:

v-on="$listeners"

to pass them off.

Then to create the grandparent, we write:

Vue.component('parent', {

template: '<child @event="value = $event"></child>',

data(){

return {

value: undefined

}

},

})

Then value will be assigned to 'value' since that’s what we passed in from grand-child .

$event has the value emitted with the event in the 2nd argument of $emit .

Updating Arrays

To update arrays, we can call the Vue.set method by writing:

Vue.set(object, prop, value)

object is any object, including arrays.

prop is a property value, which can also be an array index.

value is the value we want to update the object property or array entry with.

In a component, we can also use the this.$set method with the same arguments.

So we can write:

this.$set(object, prop, val)

Calling Vue.set or this.$set is required when we call the following array methods:

push()

pop()

shift()

unshift()

splice()

sort()

reverse()

Vue can’t track them changes for these methods.

If we want to delete an entry from an object or array, we use Vue.delete :

Vue.delete(obj, 'foo')

Then we remove the obj.foo property.

Passing Parameters to Computed Properties

We can pass in values to computed properties if our computed property function returns a function.

For instance, we can write:

computed: {

salutation() {

return greeting => `${greeting} ${this.firstName} ${this.lastName}`

}

}

We have the salutation computed property which returns a function.

Then we can reference it by calling it instead of just accessing the value of the property.

We can write:

this.salutation('hi');

to return the string we want.

We can also just use a method.

For instance, we can write:

methods: {

greet(greeting){

return `${greeting} ${this.firstName} ${this.lastName}`

}

}

Use an Image in a Single File Component

To use an image in a single file component, we can either import or require it.

For example, we can write:

<template>

<div id="app">

<img :src="image" />

</div>

</template> <script>

import image from "./assets/pic.png" export default {

data() {

return {

image: image

}

}

}

</script>

or:

<template>

<div id="app">

<img :src="require('./assets/pic.png')" />

</div>

</template> <script>

export default {

}

</script>

We pass in the object returned by import or require into the src prop.

Define Global Data

We cand define global data in our Vue app if we put in a data property into the object we pass into the Vue constructor.

For example, we can write:

new Vue({

data:{

shared

}

})

shared is the data we want to make global.

data is the property to expose the data.

‘Template should contain exactly one root element’ Error

Vue components can only contain one root element.

So we must wrap everything inside a root element.

404 when Reloading the App

If we have html5 mode on, then we have to make sure that all paths go to our Vue app instead of some file on the server.

This is because there’s no distinction in the URL to indicate where we want to go.

If we have a hash before the URL, then we won’t have this problem.

If we don’t want the hash in our URL, then we have to configure our server to redirect all URLs to the Vue app.

For example, we can write:

<ifModule mod_rewrite.c>

RewriteEngine On

RewriteBase /

RewriteRule ^index\.html$ - [L]

RewriteCond %{REQUEST_FILENAME} !-f

RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule . /index.html [L]

</ifModule>

We redirect all URLs to index.html with:

RewriteRule ^index\.html$ - [L]

this is the config for an Apache server. It should be part of the .htaccess file.

Photo by Marliese Streefland on Unsplash

Conclusion

We can emit from grandchild to grandparent with v-on='$listener' .

Also, we need to redirect to index.html if we use HTML5 mode for URLs.

Images can be imported or required.