문제 상황
프로젝트 개발 중 A 페이지에서 B 페이지로 "HTTP 링크"를 전달해야 하는 요구사항이 있었습니다. 전달된 링크 문자열에 "?", "=", "&"와 같은 특수 문자가 포함되어 있었고, 이로 인해 페이지가 전환된 후 B 페이지에서는 "?" 문자 앞의 문자열만 받을 수 있었으며, 뒤의 문자열은 전달되지 않는 문제가 발생했습니다.
원인 분석
이 문제는 전달된 파라미터에 특수 문자가 포함되어 있기 때문에 발생합니다. 특히 options 객체가 "?" 뒤의 파라미터를 분리 처리하여 전체 URL 문자열이 완전히 전달되지 않는 것입니다.
해결 방안
전달 전에 encodeURIComponent()를 사용하여 인코딩하고, 수신 시 decodeURIComponent()를 사용하여 디코딩합니다. 이 방법을 사용하면 대용량 파라미터를 전달할 수 있지만 단방향 전달만 가능하다는 제약이 있습니다.
코드 예시
// A 페이지 코드
let httpLink = "https://open.com/v3/openlive/J0dd_1_1.m3u8?code=122&name=123"
wx.navigateTo({
url: '../sxtVideo/index?url='+encodeURIComponent(httpLink)
})
// B 페이지 코드
onLoad(options) {
this.setData({
videoUrl: decodeURIComponent(options.url)
})
}
다양한 페이지 간 데이터 전달 방법
1. globalData 전역 변수 활용
설명: globalData는 app.js에 고정된 속성으로, 프로젝트 전체 어디서나 접근 가능한 데이터 저장 공간입니다.
// app.js
App({
globalData: {},
})
// sender.js
const app = getApp();
app.globalData.userName = '김개발';
// receiver.js
const app = getApp();
console.log(app.globalData.userName) // '김개발'
2. Storage 캐시 활용
설명: Storage는 각 미니프로그램에 할당된 캐시 공간으로, 단일 파라미터는 최대 1MB, 총 데이터 크기는 최대 10MB까지 저장 가능합니다.
// 저장 페이지
Page({
data: {
userName: '김개발'
},
})
// 기본 타입, Date, JSON.stringify로 직렬화 가능한 객체만 지원
wx.setStorageSync('userName', this.data.userName)
// 불러오기 페이지
console.log(wx.getStorageSync('userName')) // '김개발'
3. URL 파라미터 전달
설명: URL에 직접 파라미터를 전달할 수 있지만 길이 제한이 있고 특수 기호는 지원하지 않습니다. 인코딩/디코딩 방식으로 해결할 수 있습니다.
3.1 API를 통한 페이지 이동
// 출발 페이지
// tabBar 페이지로 이동하고 다른 모든 non-tabBar 페이지를 닫음
wx.switchTab({
url: '/targetPage?id=1',
})
// 모든 페이지를 닫고 앱 내의 특정 페이지를 엽니다
wx.reLaunch({
url: '/targetPage?id=1',
});
// 현재 페이지를 닫고 앱 내의 특정 페이지로 이동 (tabBar 페이지는 불가)
wx.redirectTo({
url: '/targetPage?id=1',
});
// 현재 페이지를 유지하고 앱 내의 특정 페이지로 이동 (tabBar 페이지는 불가)
wx.navigateTo({
url: '/targetPage?id='+ encodeURIComponent(this.data.id),
});
// 도착 페이지
Page({
onLoad: function(options) {
console.log(decodeURIComponent(options.id)) // '1', 숫자, 불리언, 객체든 모두 문자열로 수신됨
},
})
3.2 컴포넌트를 통한 페이지 이동
// 출발 페이지 (WXML)
<view>
<navigator open-type="switchTab" url="/targetPage?id=1">TabBar 페이지로 이동</navigator>
<navigator open-type="reLaunch" url="/targetPage?id=1">새로운 페이지 열기</navigator>
<navigator open-type="redirectTo" url="/targetPage?id=1">현재 페이지 닫고 이동</navigator>
<navigator open-type="navigateTo" url="/targetPage?id=1">현재 페이지 유지하고 이동</navigator>
</view>
// 도착 페이지 (JS)
Page({
onLoad: function(options) {
console.log(options.id) // '1'
},
})
4. 이벤트 채널 활용
설명: 이벤트 채널은 wx.navigateTo() 전용으로 페이지 간 양방향 데이터 전송이 가능합니다.
// 출발 페이지
wx.navigateTo({
url: '/targetPage?id=1',
events: {
// 열린 페이지로부터 데이터 수신
receiveData: function(data) {
console.log(data)
},
customEvent: function(data) {
console.log(data)
}
},
success: function(res) {
// 이벤트 채널을 통해 열린 페이지로 데이터 전송
res.eventChannel.emit('sendData', { message: '안녕하세요!' })
},
})
// 도착 페이지
Page({
onLoad: function(option) {
// 이벤트 채널 획득
const eventChannel = this.getOpenerEventChannel()
// 데이터 수신 이벤트 리스너
eventChannel.on('sendData', function(data) {
console.log(data)
})
// 데이터 전송
eventChannel.emit('receiveData', { message: '반갑습니다!' })
},
})
5. 페이지 스택 활용
설명: 현재 페이지 스택에 존재하는 페이지에만 적용 가능합니다.
// 출발 페이지
Page({
data: {
userName: '김개발',
age: 25,
},
eatFood: function(food) {
console.log(food + '을 먹고 있습니다')
},
})
// 도착 페이지
Page({
onLoad: function(options) {
// 현재 페이지 스택 획득
const pages = getCurrentPages();
// 이전 페이지 객체 획득
let prevPage = pages[pages.length - 2];
console.log(prevPage.data.userName) // '김개발'
prevPage.eatFood('사과') // '사과를 먹고 있습니다'
// 또는
prevPage.setData({age: 30})
},
})