티스토리 뷰
components/. composables/, utils/ 하위의 파일은 모두 자동으로 임폴트 된다.
SEO최적화에 유리할 수 있게 링크 이동 할 때에는 router를 이용하는 것이 옳다.
<RouterLink v-slot="{ navigate }" :to="`/coures/${courseSlug}`">
<CourseCard
:title="title"
:subtitle="subtitle"
:thumbnail="thumbnail"
/>
</RouterLink>
하지만 nuxt에서는 nuxtlink를 이용해서 링크 이동을 한다.
<NuxtLink custom :to="`/course/${courseSlug}`">
<CourseCard
:title="title"
:subtitle="subtitle"
:thumbnail="thumbnail"
/>
</NuxtLink>
참고로 NuxtLink에 custom 속성을 넣으면 a태그로 만들어지지않고 div가 된다. (RouterLink 도 동일) 페이지 이동을 위해서 navigate를 달아준다.
>
<NuxtLink v-slot="{ navigate }" custom :to="`/course/${courseSlug}`">
<CourseCard
:title="title"
:subtitle="subtitle"
:thumbnail="thumbnail"
@click="navigate"
/>
</NuxtLink>
v-slot="navigate"를 넣어주고 하위 컴포넌트에도 클릭이벤트로 넣어준다.
Composables 의 문법은 기본적으로 이렇다.
course 상세
export const useCourse = (courseSlug: string) => {
const { courses } = useCourses();
const course = courses.find(
(course: any) => course.courseSlug === courseSlug,
);
return { course };
};
:string 부분은 타입을 명시해 준 것이다. 타입스크립트는 강력한 정적타입 언어이기 때문에 변수나 매개변수의 타입을 명시적으로 지정해주어야 한다.
course 리스트
import courses from './coursesData';
export const useCourses = () => {
return { courses };
};
router의 파라미터값을 넣을 때 오류가 났었는데, 그 이유는 파라미터의 경우 배열로 올 수도 있기 때문이다. 이렇게 as string을 붙여 타입을 지정해 주거나
컴포서블에서
export const useCourse = (courseSlug: string | string[]) => {
const { courses } = useCourses();
const course = courses.find(
(course: any) => course.courseSlug === courseSlug,
);
return { course };
};
2개의 타입을 몇시해주면 된다. 하지만 나는 string으로 받는 데이터가 필요하기 때문에 as string을 붙여 해결한다.,
3. types 만들기
루트에 types 폴더를 만들어준다.
export interface Course {
title: string;
subtitle: string;
courseSlug: string;
content: string;
thumbnail: string;
video: string;
rating: number;
reviewsCount: number;
studentCount: number;
reviewsUrl: string;
inflearnUrl: string;
gymcodingUrl: string;
}
Course 라는 인터페이스를 만들어준다.
데이터를 뿌리는 순서를 생각해보자면
1. 컴포서블은 데이터를 가져오는 역할을 한다.
+ types에서 인터페이스를 만들어(스프링의 dto 역할) 자료에 꼭 맞게 넣어준다.
3. 컴포서블에서 use~~ 를 만들어 준다. (데이터 가공 역할도 함)
4. pages에서 원하는 데이터를 프롭스 안에 use~~를 이용하여 가져온 뒤 뿌려준다.
이렇게 타입 임폴트시에 ~로 시작하는데 이것은
https://nuxt.com/docs/api/nuxt-config
공식 문서상 이렇게 잡혀있다.
위에 잡은 type에 맞게
coursesData.ts 에서 타입지정
import type { Course } from '~/types/course';
const courses: Course[] = [
{
useCourses.ts에서 타입지정
import courses from './coursesData';
import type { Course } from '~/types/course';
interface CoursesReturn {
courses: Course[];
}
export const useCourses = (): CoursesReturn => {
return { courses };
};
다음 처럼 리턴 타입은 CourseReturn으로 지정했음에도 오류가 난다면, 위의 함수에서 courses.find로 인해 찾은 값이 기에 그렇다. undefined일 수 있기 때문임.
이렇게 undefined로 타입지정을 추가하거나
types/global.d.ts 파일을 생성해서
export {};
declare global {
type Maybe<T> = T | null | undefined;
}
이렇게 정의해두면 자동으로 전역에 해당 설정이 퍼지게 된다.
T는 제네릭으로 내가 만약 위처럼 Course를 썻다면 Course가 저 자리로 가게된다.
사용방식
import type { Course } from '~/types/course';
interface CourseReturn {
course: Maybe<Course>; //Course | null | undefined
}
export const useCourse = (courseSlug: string | string[]): CourseReturn => {
const { courses } = useCourses();
const course = courses.find(
(course: any) => course.courseSlug === courseSlug,
);
return { course };
};
+ 추가로 컴포서블에서 데이터를 가공해서 다른모양으로 리턴을 하려고 하는데,
import coursesData from './coursesData';
import type { CourseWithPath } from '~/types/course';
interface CoursesReturn {
courses: CourseWithPath[];
}
export const useCourses = (): CoursesReturn => {
const courses = coursesData.map((item) => ({
...item,
rating: item.rating.toFixed(1), // 5.0
reviewsCount: item.reviewsCount.toLocaleString(), // 1000 - >1,000
studentCount: item.studentCount.toLocaleString(), // 12345 -> 12,345
path: `
/course/${item.courseSlug}`,
}));
return { courses };
};
숫자들의 형식을 바꿔준 뒤에 리턴을 해주려고 한다. 새로운 path라는 데이터도 추가해줬다. type을 바꿔줘야하는데
export interface Course {
title: string;
subtitle: string;
courseSlug: string;
content: string;
thumbnail: string;
video: string;
rating: number;
reviewsCount: number;
studentCount: number;
reviewsUrl: string;
inflearnUrl: string;
gymcodingUrl: string;
}
export interface CourseWithPath {
title: string;
subtitle: string;
courseSlug: string;
content: string;
thumbnail: string;
video: string;
rating: string;
reviewsCount: string;
studentCount: string;
reviewsUrl: string;
inflearnUrl: string;
gymcodingUrl: string;
path: string;
}
이렇게 데이터를 불러올 때와 뿌려줄 때를 각기 다르게 만들어 주었따.
혹은
type NewType = Omit<Course, 'rating' | 'reviewsCount' | 'studentCount'>;
// 3개를 제외한 새로운 타입을 만들다
export interface CourseWithPath extends NewType {
path: string;
rating: string;
reviewsCount: string;
studentCount: string;
}
이렇게 사용도 가능하다.
newType을 어차피 한곳에 쓰면
export interface CourseWithPath
extends Omit<Course, 'rating' | 'reviewsCount' | 'studentCount'> {
path: string;
rating: string;
reviewsCount: string;
studentCount: string;
}
이렇게 넣어도됌
Emit 로 바뀌었는데.
<script setup lang="ts">
// runtime
// 런타임
const emit = defineEmits(['change', 'update'])
// type-based
// 타입기반
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', value: string): void
}>()
//3.3+ :대체 더 간결한 문법
defineEmits<{
change: [id:number];
update: [value:string];
}>();
<script setup lang="ts">
interface Props {
thumbnail: string;
title: string;
subtitle: string;
}
defineProps<Props>();
// defineProps({
// thumbnail: {
// type: String,
// default: '',
// },
// title: { type: String, default: '' },
// subtitle: String,
// });
props도 이렇게 간결하게 가능하다.
'dev_공부일지 > Nuxt' 카테고리의 다른 글
NuxtPage 컴포넌트 , 파라미터 변경에도 리렌더링 시키기 (0) | 2024.05.15 |
---|---|
vue3 with TypsScript (0) | 2024.05.15 |
라우팅 기본 : 파일 기본 라우팅 (0) | 2024.05.15 |
Nuxt 컴포넌트 계층 (0) | 2024.05.13 |
Quasar Ui Framwork 설치 (0) | 2024.05.13 |
- Total
- Today
- Yesterday
- filter
- BindingResult
- 스프링부트
- jpa api
- reject
- 백엔드 개발자 역량
- 컨트
- exception
- Java
- 향해플러스백엔드
- 항해99
- 백엔드 개발자 공부
- 인터셉터
- SpringBoot
- rejectValue
- thymleaf
- react실행
- hypertexttransferprotocol
- 예외처리
- React
- ArgumentResolver
- 리터럴
- JPA
- Intercepter
- 로그인
- 향해99
- 향해플러스
- 항해플러스
- 스프링공부
- HTTP
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 26 |
27 | 28 | 29 | 30 | 31 |