jasonchee.me

Vue.js Notes

v-binding attributes have a longhand and shorthand.

<div v-bind:style="{ backgroundColor: variant.variantColor }"></div>
<div :style="{ backgroundColor: variant.variantColor }"></div>

A vue component markup structure

<template>
</template>

<script>
  data() {
    return {

    }
  },
  methods() {
  },
  mounted() {
  }
</script>

<style lang="scss" scoped>
</style>

How a parent and child component can communicate

A child component inside a parent component needs to update a scoped data which exists at the parent component level. So how do we do that?

From the child component we want to fire our event and pass that logic to the parent component.

<button @click="addToCart"></button>

<script>
methods: {
  addToCart: function () {
    this.$emit('add-to-cart')
  }
}
</script>

From the parent component we want to add an attribute to the component element which will does 2 things.

<product @add-to-cart="updateCart"></product>

<script>
  methods: {
  updateCart: function () {
    this.cart += 1
  }
}
</script>

Event Bus to communicate between Vue components

An event bus allows you to be communicate between Vue components. It's a lightweight version of managing state, but not ideal when it comes to scaling up(Vuex does that).

//can place in main.js or in component...
var eventBus = new Vue();

From a grandchild component we can send out a payload to a grandparent component

//grandchild vue component method
methods: {
  onSubmit: function () {
    eventBus.$emit("review-submitted", productReview)
  }
}

//grandparent vue component on mount lifecycle retrieve payload
mounted() {
  eventBus.$on("review-submitted", productReview => () {
    this.reviews.push(productReview) //push payload from grandchild component to scoped data on grandparent component(reviews: [])
  }
}

Vue Router tips

Setting Dynamic Routes in Vue router

  {
    path: "user/:username", // component will have access to :username
    name: "user",
    component: User
  }

Access current route in a component

<h1>This is {{ $route.params.username }}'s page</h1>

Link to a dynamic route

<router-link :to="{ name: user, params: { username: "Jason"}}">Jason</router-link>

Base components

When creating global components, Vue.js has a naming convention which make it easier to import global components into main.js automatically. Copy/past the js snippet from the Automatic Registration of Global Components documentation. So as long you start the name of your component with 'Base', those components import automatically.


Named Slots

When you are using multiple slots in a component. From the primary element, Vue.js won't know which one to designate the text to. You can name your slots to identify which text belongs to which slot.

<!-- In Base Component -->
<slot name="heading"></slot>
<slot name="paragraph"></slot>

<!-- In Parent Component-->
<UserCard>
  <h2 slot="heading">Jason</h2>
  <p slot="paragraph">Interesting text here</p>
</UserCard>

Reorganizing your axios calls

Theres no need to make multiple axios API calls throughout the application. You can create a folder + file /services/EventService.js to organize your API calls.

import axios from axios

const apiClient = axios.create({
  baseURL: 'http://localhost:3000',
  withCredentials: false,
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json'
  }
})

export default {
  getEvents() {
    return apiClient.get('/events')
  },
  getEvent(id) {
    return apiClient.get('/event/'' + id)
  }
}

// and in your component just call your event helpers like so
created() {
  getEvent(this.id)
    .then(response => {
      this.event = response.data
    }…
}

Using mapState in vuex

Use computed property to interact with global states called from vuex

Option 1

import { mapState } from 'vuex'
export default {
  computed: mapState({
    userName: state => state.user.name,
    userID: state => state.user.id,
    categories: state => state.categories
  })
}

Option 2 - for dot notation

<template>
  <h1>Hello, </h1>
</template>

<script>
  import { mapState } from 'vuex'
  export default{
    computed: mapState({
      user: 'user',
      categories: 'categories'
    })
  }
</script>

Option 3 - do not include object names

import { mapState } from 'vuex'
export default{
  computed: mapState(['user', 'categories'])
}

Object Spread Operator

What is you wanted to add local computed properties and still grab properties from vuex. We use the object spread operateor (...)

export default {
  computed: {
    localComputed(): {
      return something
    }
    mapState(['user', 'categories'])
  }
}

General flow of mutation and actions for vuex

First set the state parameter

event: {}

Second, set the mutation

SET_EVENT(state, event) {
  state.event = event
}

Third, create an action and call that mutation

fetchEvent ({commit}, id){
  EventService.getEvent(id){
    .then(response => {
      commit(‘SET_EVENT’, response.data.id)
    })…
  }
}

Last, update your component

created() {
  this.$store.dispatch([‘event’])
},
computed: mapState([‘event’])