출처 | https://sungchuni.tistory.com/20
[배경] 모바일에서 사용하는 바텀 고정인 내비게이션 바가 온스크린 키보드가 있으면 내려가서 컨텐츠를 가리게 된다.
[목표] 앱이 아닌 모바일 웹뷰에서 input을 focus했을 때(즉, 화면에 키보드가 열려있는 경우에) bottom nav bar가 내려가도록 하기
[문제#1] 키보드 토글에 대한 자바스크립트 내장 이벤트가 없다
[문제#2]
ios, 안드로이드 모두 focus를 할 때는 문제 없지만,
안드로이드는 blur를 할 수 있는 방법이 두 가지다.
1)blur : input이 아닌 다른 곳 클릭
2)하단 backarrow 버튼을 통해 뒤로가기
2)처럼 뒤로가기를 하면 blur가 아니기 때문에 blur로 정의한 action이 일어나지 않는다
(끝내 해결 못한 예외 케이스)
[방법#1] vue에서 v-hide-bottom-nav라는 custom directive를 사용자가 직접 설정해 bottom nav bar를 숨길 수 있도록 한다
- nuxt에서 plugins/directives.js에서 각각 파일에서 정의한 directive들을 import해서 Vue에 등록한다
import directive이름 from 파일 위치;
import Vue from 'vue'
export default function(){
Vue.directive('directive이름', directive이름)
}
- custom directive를 정의할 때 쓸 수 있는 hook인 bind, unbind에 관련 내용을 정의한다
const handler = (vnode, hidden) => { // }
const bind = (el, binding, vnode){ // }
const unbind = (el, binding, vnode) => handler(vnode, false)
export default { bind, unbind }
[방법#2]
visualViewport API를 사용해서 뷰포트의 높이 차이로 키보드의 유무를 확인해 bottom nav bar를 숨기거나 보여준다
visualViewport.addEventListener('resize', handleResize);
function handleResize(event){
const {height: visualViewportHeight} = event.target;
const eventName = Math.ceil(visualViewportHeight) < window.innerHeight ? "keyboardpen" : "keyboardclose";
emitEvent.call(event, eventName)
function emitEvent(name){
window.dispatchEvent(
new CustomEvent(name, {
detail : {
originalEvent: this
}
})
//어떤 행동을 할지
)
}
}
visualViewport의 높이가 window의 내부 높이보다 작을 때 키보드가 열린 것이라 가정
- 하지만 키보드 외에도 높이를 줄이는 요인들이 있을 수 있다
- visualViewport의 높이는 double, window의 높이이기 때문에 올림 처리해서 사용
- resize에넌 적당한 값의 debounce를 해서 불필요한 중복 트리거링을 방지한다
- 터치 디바이스일 때만 작동하도록 pointer, hover 조건 추가
const {matches} = window.matchMedia("(hover:none), (pointer:coarse)");
if (matches && "VisualViewport" in window){//}