[ Vue3 ] 다른 페이지로 데이터 전달

NaHyun_kkiimm·2023년 11월 27일

목록 보기
2/2
post-thumbnail

Vue-router4을 이용한 페이지 사이의 데이터 전달

  • Vue2 프로젝트에서 사용했던 vue-router(3.x)는 params를 이용함에도 url에 노출하지 않고 다른 페이지로 데이터를 전달 할 수 있었다.

    Ex) https://example/id/1 형태가 아닌 https://example/id 만으로도 id=1인 params를 보낼 수 있었다.

  • 하지만, 현재 프로젝트에서 사용 중인 vue-router4 부터는 url에 노출시키지 않는 방식을 지원하지 않게 되었다. - 참조

    This change will break your app. This behavior has worked in some scenarios but has been advised against for years as it's an anti-pattern in routing for many reasons, one of them being reloading the page lose the params. Fortunately, there are multiple alternatives to this anti-pattern:
    : 이 변경 사항은 앱을 손상시킬 것입니다. 이 동작은 몇 가지 시나리오에서 효과가 있었지만, 페이지를 다시 로드하는 중 params를 잃게 되는 등의 여러 이유로 라우팅에서는 안티 패턴이기 때문에 수년 동안 권장되지 않았습니다. 다행이도, 이 안티 패턴에 대응하는 여러 대안들이 있습니다.

    (1) [pinia](https://pinia.vuejs.org/)와 같은 데이터를 저장소에 저장하는 기술 사용 : 여러 페이지에 걸쳐 데이터가 사용된다면 좋을 것입니다.

    (2) 기존 정의된 방식대로 paramsquery 사용하기 : URL에 들어갈 정도로 데이터가 작다면 적합합니다. 그리고 페이지 리로딩시 데이터 손실을 예방할 수 있습니다.

    (3) History API state를 이용하여 데이터를 state로 전달하기

    <router-link :to="{ name: 'somewhere', state: { myData } }">...</router-link>
    <button
      @click="$router.push({ name: 'somewhere', state: { myData } })"
    >...</button>

    (4) 네비게이션 가드 동안 to.meta라는 새로운 property로 전달하기

    router.beforeEach(async to => {
      if (to.meta.shouldFetch) {
        // name `data` whatever you want
        to.meta.data = await fetchSomething()
      }
    })
    • This is known an transient state and since it's in a navigation guard, it will be preserved when reloading the page

데이터 형식에 따른 전달 방식

  • Object (reactive()) 등

(1) 위 3번에 명시된 history을 이용한 state 전달

// Main.vue
import { useRouter } from 'vue-router'
setup() {
	const data = ref({ value: 'A', text: '1'})
	const router = useRouter()
	const onClicked = () => {
		router.push({
			name: 'SubContainer',
			state: {
				data: { JSON.stringify(data) }
			}
		})
	}
}
// SubContainer.vue
export default {
  name: 'SubContainer',
	setup() {
		const dataObj = JSON.parse(history.state.data)
		console.log(dataObj)
		// { value: 'A', text: '1' }
	}
}

[ 주의 ]

  • Objectreactive인 데이터를 JSON.stringify()로 보내지 않으면, 오류 뜬다.
    → 어떤 글에선 state 객체에 vue 반응형 proxy 객체를 넣으면 오류가 뜬다했는데, 아마 원인은 이거일듯 싶다. (공부 더 필요)
    → 다른 분은 JSON.stringify()대신 map()을 이용하시던데 사용법을 잘 모르겠다.

(2) params로 전달

: vue-router에서 params을 통한 전달은 권장하지 않는다.

// Main.vue
import { useRouter } from 'vue-router'
setup() {
	const data = ref({ value: 'A', text: '1'})
	const router = useRouter()
	const onClicked = () => {
		router.push({
			name: 'SubContainer',
			params: {
	      objectParam: JSON.stringify({
	        data: {
	          value: location.value.value,
            text: location.value.text
          }
	      })
      }
		})
	}
}
// SubContainer.vue
import { useRoute } from 'vue-router'
export default {
  name: 'SubContainer',
  setup() {
    const route = useRoute()
    if (route.params.objectParam) {
      const dataObj= JSON.parse(route.params.objectParam)
      console.log(dataObj)
			// data: {value: 'A', text: '1'}
    }
  }
}
  • 그 외(String, Number 등) - 값 1개만 전달할 경우, 적합 :
// Main.vue
import { useRouter } from 'vue-router'
setup() {
	const router = useRouter()
	const data = ref(3)
  const onClickedNext = () => {
    router.push({
      name: 'SubContainer',
      state: { data: data.value },
    })
	}
}
// SubContainer.vue
export default {
	name: 'SubContainer',
	setup() {
    const dataObj = history.state.data;
    console.log(dataObj);
	// 3
  }
}

덕분에 이틀이나 골머리를 앓았다. Vue3와 vue-router4는 시작한지 얼마 안 돼서 미숙한 점이 많지만, 프론트엔드 개발자를 지망하는 것은 아니기에 이정도까지만 아는 것으로 넘기는게 좋을 거 같다.


[ 참고자료 ]

vue-router4 state객체로 페이지 사이 데이터 전달

profile
이 또한 지나가리라

0개의 댓글