Types and Props
inside components folder, create JobsList.vue
type “ts” + click on bottom option
1 |
<script> composition - ts.vue |
There should be boilerplate code. Let’s add template and style.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<template></template> <script lang = "ts"> import { defineComponent } from 'vue' <script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ setup() { }, }) </script> <style scoped></style> |
Now we declare and import in file App.vue.
then put it inside of components object to use it.
1 2 3 4 5 6 7 8 9 |
<script lang="ts"> ... import JobList from './components/JobList.vue' export default defineComponent({ ... components: { JobList }, |
get rid of our placeholder template code and replace it with our component. The jobs data that we have in setup should now be passed inside the props as well:
1 2 3 4 5 |
<template> <div class="app"> <JobList :jobs="jobs"/> </div> </template> |
Implementing JobList
We make an object for props property. Then declare jobs property. This property is the options of how jobs is declared. We say it is required, and of type Array.
1 2 3 4 5 6 7 |
export default defineComponent({ props: { jobs: { required: true, type: Array } }, |
In our template, we put the necessary html and a ul. For the li, we cycle through jobs using v-for. It needs a unique key prop. We have it in jobs data array as id.
JobsList.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<template> <div class="job-list"> <ul> <li v-for="job in jobs" :key="job.id"> {{ job.title }} </li> </ul> </div> </template> <script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ props: { jobs: { required: true, type: Array } }, setup() { }, }) </script> |
If you were to run the site, you’ll see the list of titles.
Next we declare props for the component. If you were to use say Array for prop jobs, it doesn’t know what properties are available for each job because in props jobs declaration, we only declared it
as Array.
JobsList.vue
1 2 3 4 5 6 |
props: { jobs: { // prop jobs required: true, type: Array } }, |
Hence, no code suggestions when you use it in template.
The solution is that we need to type our props better.
Using Vetur for template interpolation
JobsList.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<script lang="ts"> import { defineComponent, PropType } from 'vue' import Job from '@/types/Job' export default defineComponent({ props: { jobs: { // prop jobs required: true, type: Array as PropType<Job[]> // prop jobs type } }, setup() { }, }) </script> |
Now, you’ll be able to see different options when you try to access properties of job object.
In settings, make sure Vetur > Experimental: Template Interpolation Service is checked
JobsList.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<template> <div class="job-list"> <ul> <li v-for="job in jobs" :key="job.id"> {{ job.title }} in {{ job.location }} <div class="salary"> <p>{{ job.salary }} </p> </div> <div class="description"> <p> lorem ipsum</p> </div> </li> </ul> </div> </template> |
Functions
ref – https://www.youtube.com/watch?v=usSBsgWNUZk
We want jobs to be reordered by salary, title..etc.
1 2 3 4 5 6 |
<div class="app"> <button>order by title</button> <button>order by salary</button> <button>order by location</button> <JobList :jobs="jobs" /> </div> |
add event handler to each of them.
create file types/OrderTerm.ts
1 2 |
type OrderTerm = 'location' | 'title' | 'salary' export default OrderTerm |
first create this function
App.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import OrderTerm from './types/OrderTerm' set() { const jobs = ref<Job[]>([...]) const order = ref<OrderTerm>('title') const handleClick = (term: OrderTerm) => { order.value = term } return { jobs, handleClick, order } } |
First look at order reference. We pass it into JobList so that when a button is pressed, an event happens, and manipulates the order ref.
The change in order ref can be evaluated in JobList.
1 2 3 4 |
<button @click="handleClick('title')">order by title</button> <button @click="handleClick('salary')">order by salary</button> <button @click="handleClick('location')">order by location</button> <JobList :jobs="jobs" :order="order" /> |
Since it has been set up in App.vue, we must implement this in JobList.vue
We declare order prop.
components/JobList.vue
1 2 3 4 5 6 7 8 9 |
import OrderTerm from '@/types/OrderTerm' export default defineComponent({ props: { .. order: { required: true, type: String as PropType<OrderTerm> } |
in the template:
1 |
<p>Ordered by {{ order }} </p> |
App.vue
1 2 3 4 5 |
<header> <div class="order"> <!-- put buttons here --> </div> </header> |