Skip to content

EmirDelicR/Vue-js-all

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Vue-js-all

content

Resource
Intro
Vue Life Cycle
Vue CLI
Vue Components
Advance Component Usage
Handling User Input
Using and creating directive
Filters and Mixins
Server communication Axios
Routing
State management - Vuex
Authentication
Form Validation
Animation
Testing

resource

Documentation

Official documentation

Some unofficial docks

open source projects

vue-enterprise-boilerplate

Framework

vuebulma

element

iviewui

Animation

splash screen

examples

Tutorial

Git repo

Vue school

Vue.js Best practice

Style Guide

Component Style Guide

4 Tips

Structure Vue.js Project

Build Vue Components Like A Pro

Vue Patterns

Info

Full stack radio

Books

Design Patterns

Vuejs 2 Design Patterns

Tools

Design Systems with Vue.js

Vue Developer Tools:

E2E testing

Nightwatch

Nigthwatch setup

Official TestCafe

Better E2E testing with TestCafe

E2E test Vue with TestCafe

blog TestCafe

vue-cli-plugin-e2e-testcafe

Video example

Git repo with tests

Top

intro

Guide

el: "Connect to DOM";
data: "Store Data to be used";
methods: "Methods of this Vue Instance";
computed: "Dependent Properties";
watch: "Execute code upon data change";
{{ Always string }} - string Interpolation

<!-- Bind -->
<a v-bind:href="link">{{ title }}</a>
<!-- can be written like this: -->
<a :href="link">{{ title }}</a>

<button v-on:click="functionName">{{ title }}</button>
<!-- can be written like this: -->
<button @click="functionName">{{ title }}</button>
data: {
    title: "Some link",
    link: "http://..."
}
method: {
    functionName() {
        ...
    }
}

directive

v-once - render only one time
v-html - render html
v-on:click - [different event like: mouse leave, input]
v-model="property" - two way binding
v-if="data-property" - condition attach detach element from DOM
v-else-if="data-property"
v-else
v-show - hide a element
v-for="element in data-property [array] elements" - loop

<ul>
    <li v-for="(elem, index) in elements" :key="elem">{{elem}} {{index}}</li>
</ul>
<template v-for="(elem, index) in elements">
    <h2>elem</h2>
    <p>index</p>
</template>

Top

lifecycle

The Vue Instance

Life Cycle

new Vue({
  el: "#app",
  data: {},
  beforeCreate: function() {},
  created: function() {},
  beforeMount: function() {},
  mounted: function() {},
  beforeUpdate: function() {},
  updated: function() {},
  beforeDestroy: function() {},
  destroyed: function() {},
  methods: {
    destroy: function() {
      // This destroy instance
      this.$destroy();
    }
  }
});

Top

cli

Vue-CLI-2

Learn more about the CLI here:

webpack template

sudo npm install -g vue-cli
vue init <template like webpack-simple> <project name>
cd <project name>
npm install
npm run dev

# to build for production
npm run build

Vue-CLI-3

Docks

sudo npm install -g @vue/cli
vue create <project name>
# set preset (vue-router, vuex, sass, babel,ts, pwa, eslint, unit-test, E2E test)
cd <project name>
npm run serve
Adding plugins
vue add <plugin name example vuetify> (no vue-cli-plugin-)

vuetify plugin

Css -> sass

npm install sass-loader node-sass
add this to style tag
<style scoped lang="scss">
ENV variables

create .env file in root of project

// in .env
VUE_APP_URL = url_to_page;
// TO access in component
export default {
  data() {
    return {
      url: process.env.VUE_APP_URL
    };
  }
};
// in html template
{
  {
    url;
  }
}
// can be set
.env.development
.env.production
.env.test
Vue CLI GUI
vue ui
Vue build targets

Vue App

vue build --target app
or
vue build

Vue Library

vue build --target lib

Vue Web Component

vue build --target wc

Debugging

The Vue Developer Tools

Import component

Finally, it's important to be aware of the fact, that you can also load your App.vue File (your main Component/ Instance) via the following Way:

in .babelrc:

{
  "presets": [
    ["es2015", { "modules": false }],
    ["stage-2"]
  ]
}

in main.js

import Vue from "vue";
import App from "./App.vue";

new Vue({
  el: "#app",
  ...App
});

Top

components

Docks

Component registration

Props:

Custom Events:

Non-Parent-Child Communication:

Simple component

// This register global component
Vue.component("tag-name like my-cmp", {
  data: function() {
    return {
      status: "Critical"
    };
  },
  template:
    '<p>Server Status: {{ status }} <button @click="changeStatus">Change</button></p>',
  methods: {
    changeStatus: function() {
      this.status = "Normal";
    }
  }
});
<my-cmp></my-cmp>
// local component
let com = {
    data: ...
}
new Vue({
    el: '#app',
    components: {
        'my-com': cmp
    }
});

Communication

From parent to child

<!-- parent -->
<button @click="changeName">Change my Name</button>
<app-user-detail :myName="name"></app-user-detail>
<!--child -->
<p>User Name: {{ myName }}</p>
<p>User Name Reverse: {{ reverseName() }}</p>
// parent
data: function () {
  return {
    name: 'TestName'
  };
},
methods: {
  changeName () {
    this.name = "Emir"
  }
},
// child
props: {
    myName: {
        type: String,
        required: true
    }
},
methods: {
    reverseName () {
        return this.myName.split("").reverse().join("");
    }
}
// Notice if you passing Object or Array
props: {
    myName: {
        type: Object,
        default: function() {
          return {
            myName: ObjectName.name
          }
        }
    }
},

From child to parent

<!-- child -->
<button @click="resetName">Reset name</button>
<!--parent -->
<app-user-detail :myName="name" @nameWasReset="name = $event"></app-user-detail>
// child
methods: {
  resetName () {
      this.myName = "Reset Name";
      this.$emit('nameWasReset', this.myName);
  }
}

From child to parent using callback function

<!-- child -->
<button @click="resetFn()">Reset name with callback</button>
<!--parent -->
<app-user-detail :myName="name" :resetFn="resetName" @nameWasReset="name = $event"></app-user-detail>
// parent
methods: {
  changeName () {
    this.name = "Emir";
  },
  resetName () {
    this.name = "Reset Callback"
  }
},

From child to child using simple child -parent - child communication

<!-- child - edit-->
<p>User Age: {{ userAge }}</p>
<button @click="editAge">Edit Age</button>
<!-- child - details -->
<p>User Age: {{ userAge }}</p>
<!--parent -->
<app-user-edit :userAge="age" @ageWasEdited="age = $event"></app-user-edit>
// parent
data: function () {
  return {
    name: 'TestName',
    age: 27
  };
},
// child - edit
export default {
  name: "UserEdit",
  props: {
      userAge: {
        type: Number,
        required: true
      }
  },
  methods: {
      editAge () {
        this.userAge = 31;
        this.$emit('ageWasEdited', this.userAge);
      }
  }
}
// child - details
props: {
    myName: {
      type: String,
      required: true
    },
    resetFn: Function,
    userAge: Number
},

From child to child using Event Bus (good solution)

// main.js
export const eventBus = new Vue();

// child - edit
import { eventBus } from "../main.js";
methods: {
    editAge () {
      this.userAge = 31;
      //  this.$emit('ageWasEdited', this.userAge);
      eventBus.$emit('ageWasEdited', this.userAge);
    }
}
// child - details
import { eventBus } from '../main.js';
created () {
  eventBus.$on('ageWasEdited', (age) => {
      this.userAge = age;
  });
}

Top

componentusage

Slots:

Dynamic Components:

Misc:

Slots

<!-- in child component -->
<slot></slot>
<!-- in parent component -->
<app-quote>
  <h2>{{ quoteTitle }}</h2>
  <p>A wonderful quote!</p>
</app-quote>
// parent
data: function () {
  return {
    quoteTitle: 'The Quote'
  }
},

Multiple slots

<!-- in child component -->
<div>
  <div>
    <slot name="title"></slot>
  </div>
  <div>
    <slot name="content"></slot>
  </div>
</div>
<!-- in parent component -->
<app-quote>
  <h2 slot="title">{{ quoteTitle }}</h2>
  <p slot="content">A wonderful quote!</p>
</app-quote>
dynamic components
<button @click="sleectedComponent = 'appQuote'">Quote</button>
<button @click="sleectedComponent = 'appAuthor'">Author</button>
<button @click="sleectedComponent = 'appNew'">New</button>
<component :is="sleectedComponent">
  <h2 slot="title">{{ quoteTitle }}</h2>
  <p slot="content">A wonderful quote!</p>
</component>
data: function () {
  return {
    quoteTitle: 'The Quote',
    sleectedComponent: 'appQuote'
  }
},
components: {
  appQuote: Quote,
  appAuthor: Author,
  appNew: New
}

To not destroy component:

<keep-alive>
  <component :is="sleectedComponent">
    <h2 slot="title">{{ quoteTitle }}</h2>
    <p slot="content">A wonderful quote!</p>
  </component>
</keep-alive>

Top

input

Forms:

Use v-model="property" for binding.

Behind scene v-model work:

v-model="property"
// is the same as
:value="property"
@input="property = $event.target.value"

v-model modifiers:
v-model.lazy -> fire when click on other input
v.model.trim -> remove empty spaces
v-model.number -> convert to number

For textarea use v-model and to keep structure

<p style="white-space: pre">Message: {{ message }} </p>

For checkbox use v-model="sameProperty" to store all values in one array

For radio buttons use v-model="sameProperty" to store in same variable

For options:

<select id="priority" class="form-control" v-model="selectedProperty">
  <option v-for="(item, index) in priorities" :key="index"> {{ item }} </option>
</select>

For button:

<button class="btn btn-primary" @click.prevent="submitted">Submit!</button>
 @click.prevent -> prevent submitting to server

Top

directiveall

Custom Directives:

Hooks

bind(el, binding, vnode); // Directive is Attached
inserted(el, binding, vnode); // Inserted in Parent Node
update(el, binding, vnode, oldVnode); // Once Component is Updated (without Children)
componentUpdated(el, binding, vnode, oldVnode); // Once Component is Updated (with Children)
unbind(el, binding, vnode); // Once directive is removed

Register global

in main.js

Vue.directive("changecolor", {
  bind(el, binding, vnode) {
    // value
    // el.style.backgroundColor = "green";
    // el.style.backgroundColor = binding.value;
    // modifiers
    var delay = 0;
    if (binding.modifiers["delayed"]) {
      delay = 3000;
    }
    setTimeout(() => {
      // arguments
      if (binding.arg == "background") {
        el.style.backgroundColor = binding.value;
      } else {
        el.style.color = binding.value;
      }
    }, delay);
  }
});
<p v-changecolor:background.delayed="'red'">Color this</p>
<p v-changecolor="'blue'">Color this</p>

Register local

<h3>Local</h3>
<p v-localChangeColor:background.delayed.blink="{ mainColor : 'red', secondColor: 'green', delay: 500}">Color this</p>
<p v-localChangeColor="{ mainColor : 'blue'}">Color this</p>
export default {
  name: "app",
  directives: {
    localChangeColor: {
      bind(el, binding, vnode) {
        let delay = 0;
        if (binding.modifiers["delayed"]) {
          delay = 3000;
        }
        if (binding.modifiers["blink"]) {
          let mainColor = binding.value.mainColor;
          let secondColor = binding.value.secondColor;
          let currentColor = mainColor;

          setTimeout(() => {
            setInterval(() => {
              currentColor =
                currentColor == secondColor ? mainColor : secondColor;
              if (binding.arg == "background") {
                el.style.backgroundColor = currentColor;
              } else {
                el.style.color = currentColor;
              }
            }, binding.value.delay);
          }, delay);
        } else {
          setTimeout(() => {
            // arguments
            if (binding.arg == "background") {
              el.style.backgroundColor = binding.value.mainColor;
            } else {
              el.style.color = binding.value.mainColor;
            }
          }, delay);
        }
      }
    }
  }
};

Top

filter

Filters:

Mixins:

Register global filter

<p> {{ text | toLowercase }} </p>
// in main.js
Vue.filter("toLowercase", value => value.toLowerCase());

Register local filter

<p> {{ text | toUppercase }} </p>
data () {
  return {
    text: 'Hello there!'
  }
},
filters: {
  toUppercase (value) {
    return value.toUpperCase();
  }
}

combine filters

<p> {{ text | toUppercase | toLowercase }} </p>

Filter using Computed property

<input v-model="filterText">
<ul>
  <li v-for="(item, index) in filterdeFruits" :key="index">{{ item }}</li>
</ul>
data () {
  return {
    text: 'Hello there!',
    fruits: ['Apple', 'Banana', 'Mango', 'Melon'],
    filterText: ''
  }
},
computed: {
  filteredFruits () {
    return this.fruits.filter(elem => elem.match(this.filterText))
  }
}

mixins

Mixin come first in component so that component can overwrite all

// see file fruitMixin.js
import { fruitMixin } from "../fruitMixin.js";

export default {
  name: "List",
  mixins: [fruitMixin]
};

Global mixin

// in main.js
Vue.mixin({
  created() {
    console.log("Global");
  }
});

Top

axios

Axios:

npm install --save axios

Post

import axios from "axios";
axios
  .post(this.dataBaseUrl + "users.json", formData)
  .then(res => console.log(res))
  .catch(err => console.log(err));

Get

axios
  .get(process.env.VUE_APP_DATA_BASE_URL + "users.json")
  .then(res => console.log(res))
  .catch(err => console.log(err));

Store data using get

axios
  .get(process.env.VUE_APP_DATA_BASE_URL + "users.json")
  .then(res => {
    const data = res.data;
    const users = [];
    for (let key in data) {
      const user = data[key];
      user.id = key;
      users.push(user);
    }
    this.email = users[1].email; // make this dynamic
  })
  .catch(err => console.log(err));

Setting baseURL using axios

// not working check because auto save add ;
// in main.js
axios.defaults.baseURL = process.env.VUE_APP_DATA_BASE_URL;
// add headers
axios.defaults.headers.common["Authorization"] = "test";
axios.defaults.headers.get["Accepts"] = "application/json";
// in components
axios.get("/users.json");

Interceptors

// in main.js
axios.interceptors.request.use(config => {
  console.log(config);
  return config;
});

axios.interceptors.response.use(res => {
  console.log(res);
  return res;
});

Custom axios instance

// crate file name.js
import axios from 'axios';
const instance = axios.create({
  baseURL: url
});

// set all like before
instance.defaults.headers ....
export default instance;
// To use in different file
import axiosInstanceName from 'file';

Top

routing

Github Page:

Documentation:

vue add router
// in App.vue
<router-view></router-view>
// this render '/' route
// make a router link
<router-link to="/user">User</router-link>
// To apply class active and also not apply if match /
<router-link to="/" tag="li" active-class="active" exact>
    <a>Home</a>
</router-link>

Navigation using button and function

<button @click="navigateToHome" class="btn btn-primary">Go to Home</button>
export default {
  name: "User",
  methods: {
    navigateToHome() {
      this.$router.push("/");
    }
  }
};

Passing attribute to route

// In router.js
path: "/user/:id",

// In header.vue
<router-link to="/user/1" tag="li" active-class="active">
  <a>User</a>
</router-link>
// In user.vue

data () {
  return {
      id: this.$route.params.id
  }
},
watch: {
  '$route' (to, from) {
      this.id = to.params.id;
  }
},

Child Routes

// In router.js
{
  path: "/user",
  name: "User",
  // route level code-splitting
  // this generates a separate chunk (about.[hash].js) for this route
  // which is lazy-loaded when the route is visited.
  component: () =>
    import(/* webpackChunkName: "about" */ "./components/user/User.vue"),
  children: [
    {
      path: "",
      component: () =>
        import(/* webpackChunkName: "about" */ "./components/user/UserStart.vue")
    },
    {
      path: ":id",
      component: () =>
        import(/* webpackChunkName: "about" */ "./components/user/UserDetails.vue")
    },
    {
      path: ":id/edit",
      component: () =>
        import(/* webpackChunkName: "about" */ "./components/user/UserEdit.vue")
    }
  ]
}
// In user.vue
<router-view></router-view>

Passing data route

<!-- in component -->
<router-link tag="button" :to="{ name: 'userEdit', params: {id: $route.params.id }}" class="btn btn-primary">Edit User</router-link>
// in router.js
path: ":id/edit",
component: () =>
  import(/* webpackChunkName: "about" */ "./components/user/UserEdit.vue"),
name: "userEdit"

Query parameters

<router-link tag="button" :to="{ name: 'userEdit', params: {id: $route.params.id }, query: { locale: 'en', q: 100 }}" class="btn btn-primary">Edit User</router-link>

<!--To extract data -->
<p>Locale: {{ $route.query.locale }}</p>
<p>Number: {{ $route.query.q }}</p>

Router views names

<router-view name="header-top"></router-view>
<router-view></router-view>
<router-view name="header-bottom"></router-view>
// In router.js
components: {
  default: () =>
    import(/* webpackChunkName: "about" */ "./components/user/User.vue"),
  "header-bottom": Header
},

Redirecting - catch all

{
  path: "*",
  redirect: "/"
}

Passing the Hash Fragment

<p id="data">Some Data</p>
<!-- in Router -->
<router-link tag="button" :to="link" class="btn btn-primary">Edit User</router-link>
 // In component
 data () {
  return {
    link: {
      name: 'userEdit',
      params: {
        id: this.$route.params.id
      },
      query: {
        locale: 'en',
        q: 100
      },
      hash: '#data'

    }
  }
}
// in router.js
scrollBehavior(to, from, savedPosition) {
  if (savedPosition) {
    return savedPosition;
  }
  if (to.hash) {
    return { selector: to.hash };
  }
  return {x: 0, y:0};
},

Protecting routes with guard

// beforeEnter
path: ":id",
component: () =>
  import(/* webpackChunkName: "about" */ "./components/user/UserDetails.vue"),
beforeEnter: (to, from, next) => {
  console.log("Inside Guard");
  next();
}
// or in component
beforeRouteEnter (to, from, next) {
    next(vm => {
        vm.link;
    });
}
// check auth
if(auth)
  next();
else
next(false)

// beforeLeave only put in component
beforeRouteLeave (to, from, next) {
  if (this.edited) {
      next();
  } else {
      if (confirm("Are you sure?")) {
          next();
      } else {
          next(false);
      }
  }
}

Top

vuex

Vuex Github Page:

Vuex Documentation:

vue add vuex

Getters

Use getters when you have a lot of duplicated code.

// In store.js
export default new Vuex.Store({
  state: {
    counter: 1
  },
  mutations: {},
  actions: {},
  getters: {
    doubleCounter: state => {
      return state.counter * 2;
    },
    stringCounter: state => {
      return state.counter + " Clicks";
    }
  }
});

// in component
import { mapGetters } from 'vuex';
export default {
    name: 'Counter',
    computed: mapGetters({
        counter: 'doubleCounter',
        clicks: 'stringCounter'
    })

}
<!-- in component -->
<div>
  <p>Counter is {{ counter }}</p>
  <p>Clicks: {{ clicks }}</p>
</div>

Adding more computed properties:

import { mapGetters } from 'vuex';
export default {
    name: 'Counter',
    computed: {
      ...mapGetters({
        counter: 'doubleCounter',
        clicks: 'stringCounter'
    }),
    ourOwnProperty() {

    }

}

Mutations

Mutation always must be synchronies (use action for asynchronous)

// in store.js
mutations: {
  increment: state => {
    state.counter++;
  },
  decrement: state => {
    state.counter--;
  }
},
// in component
import { mapMutations } from "vuex";
export default {
  name: "Counter",
  methods: {
    ...mapMutations({
      inc: "increment",
      dec: "decrement"
    }),
    myMethods() {}
  }
};

Actions

Best practice is to always use actions for mutating state. Functions already are builtin to receive an argument

// in store.js
actions: {
  increment: (context) => {
    context.commit("increment");
  },
  // passing argument
  decrement: ({ commit }, payload) => {
    commit("decrement", payload);
  },
  // passing multi arguments
  asyncIncrement: ({ commit }, obj) => {
    setTimeout(() => {
      commit("increment", obj.by);
    }, obj.duration);
  }
},
// in component
import { mapActions } from 'vuex';
export default {
  name: 'Counter',
  methods: {
    ...mapActions({
      inc: 'increment',
      dec: 'decrement',
      asyncInc: 'asyncIncrement'
    }),
    myMethods () {

    }
  }
}
<button @click="inc">Increment</button>
<button @click="dec(100)">Decrement</button>
<button @click="asyncInc({by:50, duration:2000})">Async Increment</button>

Two-way-binding(v-model) and Vuex

// in store.js
state: {
  value: 0
},
mutations: {
  updateValue: (state, payload) => {
    state.value = payload;
  }
},
actions: {
  updateValue: ({ commit }, payload) => {
    commit("updateValue", payload);
  }
},
getters: {
  value: state => {
    return state.value;
  }
}
// In component (Home.vue)
computed: {
  value: {
    get () {
      return this.$store.getters.value;
    },
    // This is setter for computed property
    set (value) {
      this.$store.dispatch('updateValue', value);
    }
  }
  }
<input type="text" v-model="value">
<p>{{ value }}</p>

Structure of Folders

// outsource all to folder modules/name.js and import that to store

//in store.js
import counters from "./modules/counter";
modules: {
  counters;
}

Using namespaces

Namespace

in store crate file types.js

export const NAME = "fileName/NAME";

// in fileName (counters example)
import * as types from "../types";
const getters = {
  [types.DOUBLE_COUNTER]: state => {
    return state.counter * 2;
  }
};
// in component (Result example)
import * as types from "../store/types.js";
export default {
  computed: {
    ...mapGetters({
      counter: [types.DOUBLE_COUNTER],
      clicks: "stringCounter"
    })
  }
};

Top

auth

Firebase auth API

Authenticating Requests - Firebase

JSON Web Token

Top

form

Vuelidate Docs:

Install Vuelidate

npm install --save vuelidate
// in main js
import Vuelidate from "vuelidate";
Vue.use(Vuelidate);
// in component
import { required, email } from "vuelidate/lib/validators";
validations: {
  email: {
    required, email;
  }
}
<input type="email" id="email" @input="$v.email.$touch()" v-model="email">
<div>{{ $v }}</div>
<!-- OR -->
<input type="email" id="email" @blur="$v.email.$touch()" v-model="email">
<p v-if="!$v.email.email">Please provide valide email address</p>
<p v-if="!$v.email.required">Must not be empty</p>
<!-- To output value -->
<p v-if="!$v.age.minVal">Must be at lest: {{ $v.age.$params.minVal.min }} </p>

Password validation

password: {
    required,
    minLen: minLength(6)
},
confirmPassword: {
    sameAs: sameAs(vm => {
        return vm.password
    })
}
<div class="input" :class="{invalide: $v.password.$error}">
    <label for="password">Password</label>
    <input type="password" id="password" @blur="$v.password.$touch()" v-model="password">
</div>
<div class="input" :class="{invalide: $v.confirmPassword.$error}">
    <label for="confirm-password">Confirm Password</label>
    <input type="password" id="confirm-password" @blur="$v.confirmPassword.$touch()" v-model="confirmPassword">
</div>

Validate arrays

hobbyInputs: {
  minLen: minLength(1),
  $each: {
    // this is value from hobbyInputs
    value: {
      required,
      minLen: minLength(5)
  }
}
 <div class="hobby-list">
    <div class="input" v-for="(hobbyInput, index) in hobbyInputs" :class="{invalide: $v.hobbyInputs.$each[index].$invalid}" :key="hobbyInput.id">
        <label :for="hobbyInput.id">Hobby #{{ index }}</label>
        <input type="text" :id="hobbyInput.id" @blue="$v.hobbyInputs.$each[index].value.$touch()" v-model="hobbyInput.value">
        <button @click="onDeleteHobby(hobbyInput.id)" type="button">X</button>
    </div>
</div>

Control of submit

<button type="submit" :disabled="$v.$invalid">Submit</button>

Custom validator

uniqueValidator: val => {
  if (val === "") return true;
  return axios
    .get(
      process.env.VUE_APP_DATA_BASE_URL +
        'users.json?orderBy="email"&equalTo="' +
        val +
        '"'
    )
    .then(res => {
      return Object.keys(res.data).length === 0;
    })
    .catch(err => {
      console.log(err);
    });
};
<!-- not need automatic apply -->

Top

anime

<transition>{{ element }}</transition>

Use it with v-if and v-show

To element is added:

class:

  1. *-enter
  2. *-enter-active
  3. *-leave
  4. *-leave-active

Example:

<transition name="fade">
  <div v-if="show">Info</div>
</transition>

will create:

  1. fade-enter
  2. fade-enter-active
  3. fade-leave
  4. fade-leave-active

Use type to set priority if you have transition and animation in same class for example

.slide-enter-active {
  animation: anime 1s;
  transition: opacity 2s;
}

This means that when animation is finis ali is finish in vue.js

<transition name="slide" type="animation">
  <div v-if="show">Info</div>
</transition>

Use appear to set init animation during page load

<transition name="slide" appear>
  <div v-if="show">Info</div>
</transition>

To overwrite default class *-enter ... use this:

<transition
  enter-class="Some class"
  enter-active-class="Some class"
  leave-class="Some class"
  leave-active-class="Some class"
>
  <div v-if="show">Info</div>
</transition>

Note do not leave : enter-class="" < this will throw an error>

Animation with two div-s

<transition :name="alertAnimation" mode="out-in">
  <div v-if="show" key="info">Info</div>
  <div v-else key="warning">Info-else</div>
</transition>

Top

testing

Test-doc

More-doc

Advance-test

Jest-doc

Mocking in jest

Top

About

Vue.js how to guide.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published