Vue

Komponenter, props, emits, slots


	npm create vue@latest

Setup med Create Vue (använder Vite)

Finns även Vue CLI som använder Web pack, men vi kör Create Vue

Användbara extensions & dev tool

Syntax highlightning m.m

Components & Props

Det fundamentala konceptet kring komponenter och props är samma som i React.

  • Vue-komponenter defineras i en .vue-fil med en template, script och style del (SFC - single file component)
  • Props definieras som en property till en kompent och i Vue skickas de som en v-bind directive eller shorthand :
<template>
  <child-component :some-prop="value" />
</template>

Components & Props

  • One-directional dataflow
  • Props är immutable ur ett child-komponent perspektiv
  • En skillnad är sättet hur komponenter kommunicerar tillbaka till en parent-komponent. I stället för callback funktioner i React så tillämpar Vue att children kan emitta event till en parent. Sådana emits skickas med props till parent.
  • Vue kommer "out of the box" med propvalidering och default värden. D.v.s funktionalitet som annars appliceras med Typescript i React.

Vidare tillämpar Vue:

Greeting.vue

<template>
  <div class="greeting">
    <h1>Welcome, {{ name }}!</h1>
    <p>Message to you ...</p>
  </div>
</template>

<script>
export default {
  name: 'Greeting',
  props: {
    name: {
      type: String,
      required: true
    }
  }
}
</script>

<style scoped>
.greeting h1 {
  color: #42b983;
  font-family: Verdana, sans-serif;
}

.greeting p {
  color: #333;
  font-size: 1em;
}
</style>

App.vue

<template>
  <div id="app">
    <Greeting :name="userName" />
  </div>
</template>

<script>
import Greeting from './components/Greeting.vue'

export default {
  name: 'App',
  components: {
    Greeting
  },
  data() {
    return {
      userName: 'Sandra'
    }
  }
}
</script>

Emits

Hur händelser kommunicerar uppåt 👍

Motsvarande koncept i React är att skicka callbackfunktioner men när man i Vue använder $emit så triggar man en händelse som fortplantar till dess parent.

Emits


<template>
  <button @click="emitEvent">Click me</button>
</template>

<script>
export default {
  methods: {
    emitEvent() {
      this.$emit('custom-event', payload);
    }
  }
};
</script>

ChildComponent.vue


<template>
  <Child @custom-event="handleCustomEvent" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  methods: {
    handleCustomEvent(data) {
      console.log('Event received:', payload);
    }
  }
};
</script>

ParentComponent.vue

Slots


<template>
  <ChildComponent>
    <p>Content to childcomponent</p>
  </ChildComponent>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent,
  },
};
</script>

ParentComponent.vue


<template>
  <div>
    <slot></slot> 
  </div>
</template>

<script>
export default {
  name: 'ChildComponent',
};
</script>

ChildComponent.vue

Liknar children i React

Named Slots


<template>
  <ChildComponent>
    <template v-slot:header>
      <h1>This is the header content.</h1>
    </template>
    <template v-slot:main>
      <p>This is the main content.</p>
    </template>
    <template v-slot:footer>
      <p>This is the footer content.</p>
    </template>
  </ChildComponent>
</template>

<script>
import BaseLayout from './BaseLayout.vue';

export default {
  components: {
    BaseLayout,
  },
};
</script>

Parent.vue


<template>
  <div class="base-layout">
    <header>
      <slot name="header">Default Header Content</slot>
    </header>
    <main>
      <slot>Default Main Content</slot>
    </main>
    <footer>
      <slot name="footer">Default Footer Content</slot>
    </footer>
  </div>
</template>

<script>
export default {
  name: 'BaseLayout',
};
</script>

BaseLayout.vue

Flera slots kan användas om man använder named slots. Shorthand v-slot är #.

Sätta upp Typescript i en Vue-komponent

<template>
  <div>
    <h1>{{ title }}</h1>
    <p>{{ message }}</p>
  </div>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue';

export default defineComponent({
  name: 'ExampleComponent',
  props: {
    title: {
      type: String as PropType<string>,
      required: true,
    },
    message: {
      type: String as PropType<string>,
      default: 'Default message',
    },
  },
});
</script>

Förutsatt att du valt Typescrpt i din create vue setup. Här kan du även använda dig av type eller interface.

I så fall "type : Object as PropType<CustomType>"

Vue

By sandra-larsson

Vue

  • 34