|
1 |
| -# Vue Router์ ์ปดํฌ์ง์
API %{#vue-router-and-the-composition-api}% |
| 1 | +# Vue Router์ ์ปดํฌ์ง์
API %{#Vue-Router-and-the-Composition-API}% |
2 | 2 |
|
3 | 3 | <VueSchoolLink
|
4 |
| -href="https://vueschool.io/lessons/router-and-the-composition-api" |
5 |
| -title="Learn how to use Vue Router with the composition API" |
| 4 | + href="https://vueschool.io/lessons/router-and-the-composition-api" |
| 5 | + title="Vue Router์ ์ปดํฌ์ง์
API ์ฌ์ฉ๋ฒ ๋ฐฐ์ฐ๊ธฐ" |
6 | 6 | />
|
7 | 7 |
|
8 |
| -Vue 3์์๋ `setup`๊ณผ [์ปดํฌ์ง์
API](https://vuejs.kr/guide/extras/composition-api-faq.html)๊ฐ ๋์
๋์์ต๋๋ค. ๋ฐ๋ผ์ ์ปดํฌ๋ํธ ๋ด๋ถ์ ํ์ ๊ฐ๋์ `this`์์ ๋ผ์ฐํฐ์ ์ ๊ทผํ๋ ๊ธฐ์กด ๋ฐฉ์์ ๋์ฒดํ ์ ์๋ ๋ช ๊ฐ์ง ์๋ก์ด ํจ์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. |
| 8 | +Vue์ [์ปดํฌ์ง์
API](https://vuejs.org/guide/extras/composition-api-faq.html) ๋์
์ ์๋ก์ด ๊ฐ๋ฅ์ฑ์ ์ด์์ง๋ง, Vue Router์ ์ ์ฒด ์ ์ฌ๋ ฅ์ ํ์ฉํ๊ธฐ ์ํด์๋ ๋ช ๊ฐ์ง ์๋ก์ด ํจ์๋ฅผ ์ฌ์ฉํ์ฌ `this`์ ๋ํ ์ ๊ทผ์ ๋์ฒดํ๊ณ ์ปดํฌ๋ํธ ๋ด ๋ค๋น๊ฒ์ด์
๊ฐ๋๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ์์ต๋๋ค. |
9 | 9 |
|
10 |
| -## `setup` ๋ด๋ถ์์ ๋ผ์ฐํฐ ๋ฐ ํ์ฌ ๋ผ์ฐํธ์ ์ ๊ทผํ๊ธฐ %{#accessing-the-router-and-current-route-inside-setup}% |
| 10 | +## `setup` ๋ด์์ ๋ผ์ฐํฐ ๋ฐ ํ์ฌ ๋ฃจํธ ์ ๊ทผ %{#Accessing-the-Router-and-current-Route-inside-setup}% |
11 | 11 |
|
12 |
| -`setup` ๋ด๋ถ์์๋ `this`์ ์ ๊ทผํ ์ ์๊ธฐ ๋๋ฌธ์, `this.$router` ๋๋ `this.$route`์ ์ ๊ทผํ ์ ์์ต๋๋ค. ์ ๊ทผํ๊ธฐ ์ํด์๋ `useRouter` ๋๋ `useRoute` ํจ์๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค. |
| 12 | +`setup` ๋ด์์ `this`์ ์ ๊ทผํ ์ ์๊ธฐ ๋๋ฌธ์ `this.$router`๋ `this.$route`์ ์ง์ ์ ๊ทผํ ์ ์์ต๋๋ค. ๋์ , `useRouter`์ `useRoute` ์ปดํฌ์ ๋ธ์ ์ฌ์ฉํฉ๋๋ค: |
13 | 13 |
|
14 |
| -```js |
| 14 | +```vue |
| 15 | +<script setup> |
15 | 16 | import { useRouter, useRoute } from 'vue-router'
|
16 | 17 |
|
17 |
| -export default { |
18 |
| - setup() { |
19 |
| - const router = useRouter() |
20 |
| - const route = useRoute() |
21 |
| - |
22 |
| - function pushWithQuery(query) { |
23 |
| - router.push({ |
24 |
| - name: 'search', |
25 |
| - query: { |
26 |
| - ...route.query, |
27 |
| - ...route, |
28 |
| - }, |
29 |
| - }) |
30 |
| - } |
31 |
| - }, |
| 18 | +const router = useRouter() |
| 19 | +const route = useRoute() |
| 20 | +
|
| 21 | +function pushWithQuery(query) { |
| 22 | + router.push({ |
| 23 | + name: 'search', |
| 24 | + query: { |
| 25 | + ...route.query, |
| 26 | + ...query, |
| 27 | + }, |
| 28 | + }) |
32 | 29 | }
|
| 30 | +</script> |
33 | 31 | ```
|
34 | 32 |
|
35 |
| -`route`๋ ๋ฐ์ํ ๊ฐ์ฒด์ด๋ฏ๋ก ํด๋น ์์ฑ์ ๋ชจ๋ ๊ฐ์ํ ์ ์์ผ๋ฏ๋ก, `route` ๊ฐ์ฒด ์ ์ฒด๋ฅผ ๊ฐ์ํ๋ ๊ฒ์ ํผํ๋๊ฒ ์ข์ต๋๋ค. ๋๋ถ๋ถ์ ๊ฒฝ์ฐ, ๋ณ๊ฒฝํ๋ ค๋ ํ๋ผ๋ฏธํฐ๋ฅผ ์ง์ ๊ฐ์ํ๋ ๊ฒ์ด ์ข์ต๋๋ค. |
| 33 | +`route` ๊ฐ์ฒด๋ ๋ฐ์ํ ๊ฐ์ฒด์
๋๋ค. ๋๋ถ๋ถ์ ๊ฒฝ์ฐ, `route` ๊ฐ์ฒด ์ ์ฒด๋ฅผ ๊ฐ์ํ๋ ๊ฒ์ **ํผํด์ผ ํฉ๋๋ค**. ๋์ , ๋ณ๊ฒฝ์ ๊ธฐ๋ํ๋ ์์ฑ๋ค์ ์ง์ ๊ฐ์ํ ์ ์์ต๋๋ค: |
36 | 34 |
|
37 |
| -```js |
| 35 | +```vue |
| 36 | +<script setup> |
38 | 37 | import { useRoute } from 'vue-router'
|
39 | 38 | import { ref, watch } from 'vue'
|
40 | 39 |
|
41 |
| -export default { |
42 |
| - setup() { |
43 |
| - const route = useRoute() |
44 |
| - const userData = ref() |
45 |
| - |
46 |
| - // ํ๋ผ๋ฏธํฐ๊ฐ ๋ณ๊ฒฝ๋ ๋ ์ ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๊ธฐ. |
47 |
| - watch( |
48 |
| - () => route.params.id, |
49 |
| - async newId => { |
50 |
| - userData.value = await fetchUser(newId) |
51 |
| - } |
52 |
| - ) |
53 |
| - }, |
54 |
| -} |
| 40 | +const route = useRoute() |
| 41 | +const userData = ref() |
| 42 | +
|
| 43 | +// ํ๋ผ๋ฏธํฐ ๋ณ๊ฒฝ ์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ต๋๋ค |
| 44 | +watch( |
| 45 | + () => route.params.id, |
| 46 | + async newId => { |
| 47 | + userData.value = await fetchUser(newId) |
| 48 | + } |
| 49 | +) |
| 50 | +</script> |
55 | 51 | ```
|
56 | 52 |
|
57 |
| -ํ
ํ๋ฆฟ ๋ด๋ถ์์๋ ์ฌ์ ํ `$router` ๋ฐ `$route`๋ก ์ ๊ทผํ ์ ์์ผ๋ฏ๋ก, `setup` ๋ด๋ถ์์ `router` ๋ฐ `route`๋ฅผ ๋ฐํํ ํ์๋ ์์ต๋๋ค. |
| 53 | +ํ
ํ๋ฆฟ์์๋ ์ฌ์ ํ `$router`์ `$route`์ ์ ๊ทผํ ์ ์์ผ๋ฏ๋ก, ํ
ํ๋ฆฟ์์๋ง ์ด ๊ฐ์ฒด๋ค์ด ํ์ํ ๊ฒฝ์ฐ `useRouter`๋ `useRoute`๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ์์ต๋๋ค. |
58 | 54 |
|
59 |
| -## ํ์ ๊ฐ๋ %{#navigation-guards}% |
| 55 | +## ๋ค๋น๊ฒ์ด์
๊ฐ๋ %{#Navigation-Guards}% |
60 | 56 |
|
61 |
| -Vue Router๋ ์
๋ฐ์ดํธ ๋ฐ ๋ฆฌ๋ธ ๊ฐ๋๋ฅผ ์ปดํฌ์ง์
API ๋ฉ์๋๋ก ๋
ธ์ถํ๋ฏ๋ก, `setup` ํจ์์์ ์ปดํฌ๋ํธ ๋ด ํ์ ๊ฐ๋๋ฅผ ๊ณ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. |
| 57 | +Vue Router๋ ์ปดํฌ์ง์
API ํจ์๋ก ์
๋ฐ์ดํธ์ ๋ ๋จ ๊ฐ๋๋ฅผ ๋
ธ์ถํฉ๋๋ค: |
62 | 58 |
|
63 |
| -```js |
| 59 | +```vue |
| 60 | +<script setup> |
64 | 61 | import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
|
65 | 62 | import { ref } from 'vue'
|
66 | 63 |
|
67 |
| -export default { |
68 |
| - setup() { |
69 |
| - // `this`์ ์ ๊ทผ ๊ถํ์ด ์์ผ๋ฉฐ, beforeRouteLeave ์ต์
๊ณผ ๋์ผ |
70 |
| - onBeforeRouteLeave((to, from) => { |
71 |
| - const answer = window.confirm( |
72 |
| - '์ ๋ง ๋ ๋์๊ฒ ์ต๋๊น? ์ ์ฅ๋์ง ์์ ๋ณ๊ฒฝ ์ฌํญ์ด ์์ต๋๋ค!' |
73 |
| - ) |
74 |
| - // ํ์์ ์ทจ์ํ๊ณ ๊ฐ์ ํ์ด์ง์ ๋จธ๋ฌผ๊ธฐ |
75 |
| - if (!answer) return false |
76 |
| - }) |
77 |
| - |
78 |
| - const userData = ref() |
79 |
| - |
80 |
| - // `this`์ ์ ๊ทผ ๊ถํ์ด ์์ผ๋ฉฐ, beforeRouteUpdate ์ต์
๊ณผ ๋์ผ |
81 |
| - onBeforeRouteUpdate(async (to, from) => { |
82 |
| - // ์ฟผ๋ฆฌ ๋๋ ํด์๊ฐ ๋ณ๊ฒฝ๋์์ ์ ์์ผ๋ฏ๋ก, ID๊ฐ ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ์๋ง ์ ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๊ธฐ. |
83 |
| - if (to.params.id !== from.params.id) { |
84 |
| - userData.value = await fetchUser(to.params.id) |
85 |
| - } |
86 |
| - }) |
87 |
| - }, |
88 |
| -} |
| 64 | +// beforeRouteLeave ์ต์
๊ณผ ๊ฐ์ง๋ง `this`์ ๋ํ ์ ๊ทผ์ด ์์ต๋๋ค |
| 65 | +onBeforeRouteLeave((to, from) => { |
| 66 | + const answer = window.confirm( |
| 67 | + '์ ๋ง ํ์ด์ง๋ฅผ ๋ ๋์๊ฒ ์ต๋๊น? ์ ์ฅ๋์ง ์์ ๋ณ๊ฒฝ์ฌํญ์ด ์์ต๋๋ค!' |
| 68 | + ) |
| 69 | + // ๋ค๋น๊ฒ์ด์
์ ์ทจ์ํ๊ณ ๊ฐ์ ํ์ด์ง์ ๋จธ๋ญ
๋๋ค |
| 70 | + if (!answer) return false |
| 71 | +}) |
| 72 | +
|
| 73 | +const userData = ref() |
| 74 | +
|
| 75 | +// beforeRouteUpdate ์ต์
๊ณผ ๊ฐ์ง๋ง `this`์ ๋ํ ์ ๊ทผ์ด ์์ต๋๋ค |
| 76 | +onBeforeRouteUpdate(async (to, from) => { |
| 77 | + // id๊ฐ ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉ์๋ฅผ ๊ฐ์ ธ์ต๋๋ค |
| 78 | + if (to.params.id !== from.params.id) { |
| 79 | + userData.value = await fetchUser(to.params.id) |
| 80 | + } |
| 81 | +}) |
| 82 | +</script> |
89 | 83 | ```
|
90 | 84 |
|
91 |
| -์ปดํฌ์ง์
API ๊ฐ๋๋ `<router-view>`๋ก ๋ ๋๋ง๋ ๋ชจ๋ ์ปดํฌ๋ํธ์์๋ ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก, ๋ผ์ฐํธ ์ปดํฌ๋ํธ ๋ด์์๋ง ์ฌ์ฉํด์ผ ํ๋ ๊ฒ์ ์๋๋๋ค. |
| 85 | +์ปดํฌ์ง์
API ๊ฐ๋๋ `<router-view>`์ ์ํด ๋ ๋๋ง๋ ๋ชจ๋ ์ปดํฌ๋ํธ์์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ์ปดํฌ๋ํธ ๋ด ๊ฐ๋์ฒ๋ผ ๋ผ์ฐํธ ์ปดํฌ๋ํธ์์ ์ง์ ์ฌ์ฉํ ํ์๋ ์์ต๋๋ค. |
92 | 86 |
|
93 |
| -## `useLink` |
| 87 | +## `useLink` %{#useLink}% |
94 | 88 |
|
95 |
| -Vue ๋ผ์ฐํฐ๋ RouterLink์ ๋ด๋ถ ๋์์ ์ปดํฌ์ ๋ธ๋ก ๋
ธ์ถํฉ๋๋ค. ์ด๋ `RouterLink`์ props์ ๊ฐ์ ๋ฐ์ ๊ฐ์ฒด๋ฅผ ํ์ฉํ๊ณ low-level ์์ฑ์ ๋
ธ์ถํ์ฌ ์์ ๋ง์ `RouterLink` ์ปดํฌ๋ํธ๋ฅผ ๊ตฌ์ถํ๊ฑฐ๋ ์ฌ์ฉ์ ์ง์ ๋งํฌ๋ฅผ ์์ฑํฉ๋๋ค: |
| 89 | +Vue Router๋ RouterLink์ ๋ด๋ถ ๋์์ ์ปดํฌ์ ๋ธ๋ก ๋
ธ์ถํฉ๋๋ค. ์ด๋ `RouterLink`์ props์ ๊ฐ์ ๋ฐ์ํ ๊ฐ์ฒด๋ฅผ ๋ฐ์๋ค์ด๋ฉฐ, ์์ ๋ง์ `RouterLink` ์ปดํฌ๋ํธ๋ฅผ ๊ตฌ์ถํ๊ฑฐ๋ ์ฌ์ฉ์ ์ ์ ๋งํฌ๋ฅผ ์์ฑํ๊ธฐ ์ํ ์ ์์ค ์์ฑ๋ค์ ๋
ธ์ถํฉ๋๋ค: |
96 | 90 |
|
97 |
| -```js |
| 91 | +```vue |
| 92 | +<script setup> |
98 | 93 | import { RouterLink, useLink } from 'vue-router'
|
99 | 94 | import { computed } from 'vue'
|
100 | 95 |
|
101 |
| -export default { |
102 |
| - name: 'AppLink', |
103 |
| - |
104 |
| - props: { |
105 |
| - // TypeScript๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, @ts-ignore ์ถ๊ฐ๊ฐ ํ์ํจ |
106 |
| - ...RouterLink.props, |
107 |
| - inactiveClass: String, |
108 |
| - }, |
109 |
| - |
110 |
| - setup(props) { |
111 |
| - const { |
112 |
| - // ํ์ฉ๋ ๋ผ์ฐํธ(route) ๊ฐ์ฒด |
113 |
| - route, |
114 |
| - // ๋งํฌ์์ ์ฌ์ฉํ href |
115 |
| - href, |
116 |
| - // ๋งํฌ๊ฐ ํ์ฑ ์ํ์ธ์ง ๋ํ๋ด๋ boolean ํ์
์ ๊ฐ ์ฐธ์กฐ |
117 |
| - isActive, |
118 |
| - // ๋งํฌ๊ฐ ์ ํํ ํ์ฑ ์ํ์ธ์ง ๋ํ๋ด๋ boolean ํ์
์ ๊ฐ ์ฐธ์กฐ |
119 |
| - isExactActive, |
120 |
| - // ๋งํฌ๋ก ์ด๋ํ๋ ํจ์ |
121 |
| - navigate |
122 |
| - } = useLink(props) |
123 |
| - |
124 |
| - const isExternalLink = computed( |
125 |
| - () => typeof props.to === 'string' && props.to.startsWith('http') |
126 |
| - ) |
127 |
| - |
128 |
| - return { isExternalLink, href, navigate, isActive } |
129 |
| - }, |
130 |
| -} |
| 96 | +const props = defineProps({ |
| 97 | + // TypeScript ์ฌ์ฉ ์ @ts-ignore ์ถ๊ฐ |
| 98 | + ...RouterLink.props, |
| 99 | + inactiveClass: String, |
| 100 | +}) |
| 101 | +
|
| 102 | +const { |
| 103 | + // ํด๊ฒฐ๋ ๋ผ์ฐํธ ๊ฐ์ฒด |
| 104 | + route, |
| 105 | + // ๋งํฌ์์ ์ฌ์ฉํ href |
| 106 | + href, |
| 107 | + // ๋งํฌ๊ฐ ํ์ฑํ๋์๋์ง ๋ํ๋ด๋ ๋ถ๋ฆฐ ref |
| 108 | + isActive, |
| 109 | + // ๋งํฌ๊ฐ ์ ํํ ํ์ฑํ๋์๋์ง ๋ํ๋ด๋ ๋ถ๋ฆฐ ref |
| 110 | + isExactActive, |
| 111 | + // ๋งํฌ๋ก ์ด๋ํ๋ ํจ์ |
| 112 | + navigate |
| 113 | +} = useLink(props) |
| 114 | +
|
| 115 | +const isExternalLink = computed( |
| 116 | + () => typeof props.to === 'string' && props.to.startsWith('http') |
| 117 | +) |
| 118 | +</script> |
131 | 119 | ```
|
132 | 120 |
|
133 |
| -RouterLink์ `v-slot`์ `useLink` ์ปดํฌ์ ๋ธ๊ณผ ๋์ผํ ์์ฑ์ ๋ํ ์ก์ธ์ค๋ฅผ ์ ๊ณตํฉ๋๋ค. |
| 121 | +RouterLink์ `v-slot`์ `useLink` ์ปดํฌ์ ๋ธ๊ณผ ๋์ผํ ์์ฑ์ ์ ๊ทผํ ์ ์์ต๋๋ค. |
0 commit comments