/ Gists / Vue.js

Gists - Vue.js

On gists

My Modal with v-model

Vue.js

app.js #

<script setup>
import { ref } from 'vue'
import Modal from './Modal.vue'

const openByRef = ref(false)

setTimeout(() => {
  openByRef.value = true
}, 2000)
</script>

<template>
  <Modal v-model="openByRef">

    <template #buttons="slotProps">
      inner state: {{ slotProps.opened }} <br />
      outer state: {{ openByRef }} <br /><br />
      <button @click="slotProps.open()">open</button> | 
      <button @click="slotProps.close()">close</button>
  
      <br /><br />
    </template>

    <template #default="slotProps">
      OBSAH MODALU
    </template>

  </Modal>
</template>

On gists

Vue.js: Inline composables

Popular ⭐ Vue.js

readme.md #



On gists

Modal - composable (toRaw ...)

Vue.js

useModal.js #

import { ref } from 'vue'

// keep track of component to render
const component = ref();
// keep track of whether to show modal
const show = ref(false);

export function useModal() {
    return {
        component,
        show,
        // methods to show/hide modal
        showModal: () => show.value = true,
        hideModal: () => show.value = false,
    }
}

On gists

Composable: RecipeCalculator (dynamic method call)

Vue.js

useRecipeCalculator.js #

/* eslint-disable no-unused-vars */
import { ref, readonly } from 'vue'

const stepsMax = {
  parts: 16,
  weight: 7
}
const selected = {
  type: null,
  amount: null
}

const amount = ref(0)
let step = 0

const calcMethods = {
  increaseWeight: () => {
    if (step >= stepsMax[selected.type]) {
      return
    }
    amount.value *= 2
    step++
  },
  decreaseWeight: () => {
    if (amount.value <= selected.amount) {
      return
    }
    amount.value /= 2
    step--
  },
  increaseParts: () => {
    if (step >= stepsMax[selected.type]) {
      return
    }
    amount.value++
    step++
  },
  decreaseParts: () => {
    if (amount.value <= 1) {
      return
    }
    amount.value--
    step--
  }
}

const increase = () => {
  const fn = `increase${selected.type.charAt(0).toUpperCase() + selected.type.slice(1)}`
  calcMethods[fn]()
}

const decrease = () => {
  const fn = `decrease${selected.type.charAt(0).toUpperCase() + selected.type.slice(1)}`
  calcMethods[fn]()
}

/**
 * @param {string} type - The type of ratio, must be 'parts' or 'weight'.
 * @param {number} recipeAmount - The amount of ratio.
 * @returns {{ amount: Readonly<number>, increase: () => void, decrease: () => void }}
 */
export const useRecipeCalculator = (type, recipeAmount) => {
  selected.type = type
  selected.amount = recipeAmount
  amount.value = recipeAmount

  return {
    amount: readonly(amount),
    increase,
    decrease
  }
}

On gists

Vue.js - Suspense

Vue.js

Suspense.vue #

<template>
  <div>
    <h1>Async Component Example</h1>
    <suspense>
      <template #default>
        <AsyncComponent />
      </template>
      <template #fallback>
        <LoadingSpinner />
      </template>
    </suspense>
  </div>
</template>

<script setup>
import { defineAsyncComponent } from 'vue';

const AsyncComponent = defineAsyncComponent(() =>
  import('./AsyncComponent.vue')
);
</script>

On gists

Convert Vue component to Web component

Web components Vue.js

HelloWorld.ce.vue #

<!-- ce je jen interni oznaceni ze to bude custom element = web component -->
<script setup>
defineProps({
  msg: {
    type: String,
    required: true,
    default: 'AAA'
  }
})
</script>

<template>
  <div>{{ msg }}</div>
</template>

<style scoped>
h1 {
  font-weight: 500;
  font-size: 2.6rem;
  position: relative;
  top: -10px;
}

h3 {
  font-size: 1.2rem;
}

.greetings h1,
.greetings h3 {
  text-align: center;
}

@media (min-width: 1024px) {
  .greetings h1,
  .greetings h3 {
    text-align: left;
  }
}
</style>

On gists

Composable return values - destruct - keep reactivity

Vue.js

Example.js #

// Composable
const useBurger = () => {
  const lettuce = ref(true);
  const ketchup = ref(true);
return {
  lettuce,
  ketchup,
}


// Component
setup() {
  // We can destructure but still keep our reactivity
  const { ketchup } = useBurger();
  watchEffect(() => console.log(ketchup.value));
  return {
    ketchup,
    removeKetchup: () => ketchup.value = false
  };
}



// If you don't want to destructure the values, you can always wrap it in reactive and it
// will be converted to a reactive object

// Component
setup() {
    // Wrap in `reactive` to make it a reactive object
    const burger = reactive(useBurger());
    watchEffect(() => console.log(burger.ketchup));
        return {
        burger,
        removeKetchup: () => burger.ketchup = false
    }
}



// destruct needs toRefs
const refBurger = ref({ lettuce: true });
const reactiveBurger = reactive({ lettuce: true });

const { lettuce } = toRefs(refBurger.value);
const { lettuce } = toRefs(reactiveBurger);

On gists

Dynamic Vue.js component in runtime

Vue.js

Dynamic.vue #

<template>
  <h1>test</h1>
  <component :is="dynamicComponent" />
</template>


<script setup>
import { computed} from 'vue'

const dynamicComponent = computed(() => {

  let template = `
    <h3>Toto je dynamic component</h3>
    <p>Nejaky text</p>
  `

  return { template }

})
</script>

<!--/* musi to byt jako bundle vue .. build, ne runtime vue   */-->

On gists

Pinia - defineStore with argument (each components has its own)

Vue.js

store.js #

// One storage for all ...
export const useCounterStore = defineStore('counter', () => {
    const count = ref(0);
    function increment() {
        count.value++;
    }

    return { count, increment };
});


// Dynamic storage = each components get its own
export function useCounterStore(key) {
    return defineStore(key, () => {
        const count = ref(0);
        function increment() {
            count.value++;
        }

        return { count, increment };
    })();
}


//And more ES6 style
export const useCounterStore = key => defineStore(key, () => {
    const count = ref(0);
    const increment = () => {
        count.value++;
    };

    return { count, increment };
})();