/ Gists / Patterns.dev

Gists - Patterns.dev

On gists

Provider->Consumer

Patterns.dev Plugin patterns Vue.js

Provider.vue #

<!-- https://learn-vuejs.github.io/vue-patterns/patterns/#dependency-injection -->

<template>
  <div>
    <slot v-bind="{ state, actions }" />
  </div>
</template>

<script>
export default {
  computed: {
    state() {
      return {
        label: 'button',
      };
    },
    actions() {
      return {
        click: this.click,
      };
    },
  },
  methods: {
    click() {
      console.log('Clicked');
    },
  },
}
</script>

On gists

Renderless with default layouts

Patterns.dev Plugin patterns Vue.js

DataProvider.vue #

<!-- DataProvider.vue -->
<template>
  <slot 
    :data="data"
    :loading="loading"
    :error="error"
  >
    <component 
      :is="layouts[variant]" 
      :data="data"
      :loading="loading"
      :error="error"
    />
  </slot>
</template>

<script setup>
import DefaultLayout from './layouts/DefaultLayout.vue'
import CompactLayout from './layouts/CompactLayout.vue'
import CardLayout from './layouts/CardLayout.vue'

const props = defineProps({
  variant: {
    type: String,
    default: 'default',
    validator: (value) => ['default', 'compact', 'card'].includes(value)
  }
})

const layouts = {
  default: DefaultLayout,
  compact: CompactLayout,
  card: CardLayout
}
</script>

On gists

Container Pattern

Patterns.dev Plugin patterns Vue.js

DogImagesContainer.vue #

<!-- DogImagesContainer.vue -->

<template>
  <DogImages :dogs="dogs" />
</template>

<script setup>
  import { ref, onMounted } from "vue";
  import DogImages from "./DogImages.vue";

  const dogs = ref([]);

  onMounted(async () => {
    const response = await fetch(
      "https://dog.ceo/api/breed/labrador/images/random/6"
    );
    const { message } = await response.json();
    dogs.value = message;
  });
</script>

On gists

Data Provider

Patterns.dev Plugin patterns Vue.js

dataprovider01.vue #

<template>
  <slot :checkbox="checkbox" :toggleCheckbox="toggleCheckbox"></slot>
</template>

<script setup>
  import { ref, reactive } from "vue";

  const API_ENDPOINT_URL = "https://official-joke-api.appspot.com/random_joke";

  const data = reactive({
    setup: null,
    punchline: null,
  });
  const loading = ref(false);

  const fetchJoke = async () => {
    loading.value = true;

    const response = await fetch(API_ENDPOINT_URL);
    const responseData = await response.json();

    data.setup = responseData.setup;
    data.punchline = responseData.punchline;
    loading.value = false;
  };

  fetchJoke();
</script>



// usage
<template>
  <DataProvider v-slot="{ data, loading }">
    <div class="joke-section">
      <p v-if="loading">Joke is loading...</p>
      <p v-if="!loading">{{ data.setup }}</p>
      <p v-if="!loading">{{ data.punchline }}</p>
    </div>
  </DataProvider>

  <DataProvider v-slot="{ data, loading }">
    <p v-if="loading">Hold on one sec...</p>
    <div v-else class="joke-section">
      <details>
        <summary>{{ data.setup }}</summary>
        <p>{{ data.punchline }}</p>
      </details>
    </div>
  </DataProvider>
</template>

<script setup>
  import DataProvider from "./components/DataProvider.vue";
</script>

On gists

Renderless

Patterns.dev Plugin patterns Vue.js

MouseTracker01.vue #

<!-- MouseTracker.vue -->
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
  
const x = ref(0)
const y = ref(0)
 
const update = e => {
  x.value = e.pageX
  y.value = e.pageY
}
 
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
</script>
 
<template>
  <slot :x="x" :y="y"/>
</template>