[Improvement] Popup: support lazy render (#1138)

This commit is contained in:
neverland
2018-05-23 11:01:27 +08:00
committed by GitHub
parent 7f10d99d3d
commit cb992ce979
14 changed files with 223 additions and 49 deletions
+1
View File
@@ -47,6 +47,7 @@ Use `position` prop to set popup display position
| close-on-click-overlay | Close popup when click overlay | `Boolean` | `true` |
| transition | Transition | `String` | `popup-slide` |
| lock-scroll | Whether to lock background scroll | `Boolean` | `true` |
| lazy-render | Whether to lazy render util appeared | `Boolean` | `true` |
| get-container | Return the mount node for Popup | `() => HTMLElement` | - |
### Event
+17 -1
View File
@@ -1,6 +1,6 @@
<template>
<transition :name="currentTransition">
<div v-show="value" :class="b({ [position]: position })">
<div v-if="inited || !lazyRender" v-show="value" :class="b({ [position]: position })">
<slot />
</div>
</transition>
@@ -17,6 +17,10 @@ export default create({
props: {
transition: String,
lazyRender: {
type: Boolean,
default: true
},
overlay: {
type: Boolean,
default: true
@@ -31,10 +35,22 @@ export default create({
}
},
data() {
return {
inited: this.value
};
},
computed: {
currentTransition() {
return this.transition || (this.position === '' ? 'van-fade' : `popup-slide-${this.position}`);
}
},
watch: {
value() {
this.inited = this.inited || this.value;
}
}
});
</script>
@@ -5,50 +5,18 @@ exports[`renders demo correctly 1`] = `
<div>
<button class="van-button van-button--default van-button--normal">
<!----><span class="van-button__text">弹出 Popup</span></button>
<div class="van-popup" style="display:none;">内容</div>
<!---->
</div>
<div>
<button class="van-button van-button--default van-button--normal">
<!----><span class="van-button__text">底部弹出</span></button>
<div class="van-popup van-popup--bottom" style="display:none;">
<div class="van-picker">
<div class="van-hairline--top-bottom van-picker__toolbar">
<div class="van-picker__cancel">取消</div>
<!---->
<div class="van-picker__confirm">确认</div>
</div>
<!---->
<div class="van-picker__columns" style="height:220px;">
<div class="van-picker-column" style="height:220px;">
<ul style="transition:0ms;transform:translate3d(0, 88px, 0);line-height:44px;">
<li class="van-ellipsis van-picker-column__item van-picker-column__item--selected">杭州</li>
<li class="van-ellipsis van-picker-column__item">宁波</li>
<li class="van-ellipsis van-picker-column__item">温州</li>
<li class="van-ellipsis van-picker-column__item">嘉兴</li>
<li class="van-ellipsis van-picker-column__item">湖州</li>
</ul>
</div>
<div class="van-hairline--top-bottom van-picker__frame" style="height:44px;"></div>
</div>
</div>
</div>
<!---->
<button class="van-button van-button--default van-button--normal">
<!----><span class="van-button__text">顶部弹出</span></button>
<div class="van-popup van-popup--top" style="display:none;">
内容
</div>
<!---->
<button class="van-button van-button--default van-button--normal">
<!----><span class="van-button__text">右侧弹出</span></button>
<div class="van-popup van-popup--right" style="display:none;">
<button class="van-button van-button--default van-button--normal">
<!----><span class="van-button__text">关闭弹层</span></button>
<button class="van-button van-button--default van-button--normal">
<!----><span class="van-button__text">右侧弹出</span></button>
<div class="van-popup van-popup--right" style="display:none;">
<button class="van-button van-button--default van-button--normal">
<!----><span class="van-button__text">关闭弹层</span></button>
</div>
</div>
<!---->
</div>
</div>
`;
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`reset z-index 1`] = `<div class="van-popup" name="van-fade"></div>`;
+126
View File
@@ -0,0 +1,126 @@
import Vue from 'vue';
import Popup from '../';
import { mount, TransitionStub } from '@vue/test-utils';
import { triggerDrag } from '../../../test/touch-utils';
Vue.component('transition', TransitionStub);
let wrapper;
afterEach(() => {
wrapper.vm.$destroy();
});
test('lazy render', () => {
wrapper = mount(Popup);
expect(wrapper.vm.$el.tagName).toBeFalsy();
wrapper.vm.value = true;
expect(wrapper.vm.$el.tagName).toBeTruthy();
});
test('reset z-index', () => {
wrapper = mount(Popup, {
propsData: {
value: true,
zIndex: 10,
lockScroll: false
}
});
expect(wrapper.html()).toMatchSnapshot();
});
test('popup lock scroll', () => {
const wrapper1 = mount(Popup, {
propsData: {
value: true
}
});
expect(document.body.classList.contains('van-overflow-hidden')).toBeTruthy();
triggerDrag(document, 0, 100);
triggerDrag(document, 0, -150);
const wrapper2 = mount(Popup, {
propsData: {
value: true
}
});
wrapper1.vm.$destroy();
expect(document.body.classList.contains('van-overflow-hidden')).toBeTruthy();
wrapper2.vm.$destroy();
expect(document.body.classList.contains('van-overflow-hidden')).toBeFalsy();
});
test('get container with parent', () => {
const div1 = document.createElement('div');
const div2 = document.createElement('div');
wrapper = mount({
template: `
<div>
<popup :value="true" :get-container="getContainer" />
</div>
`,
components: {
Popup
},
data() {
return {
getContainer: () => div1
};
}
});
const popup = wrapper.find('.van-popup').element;
expect(popup.parentNode).toEqual(div1);
wrapper.vm.getContainer = () => div2;
expect(popup.parentNode).toEqual(div2);
wrapper.vm.getContainer = null;
expect(popup.parentNode).toEqual(wrapper.element);
});
test('get container without parent', () => {
const div = document.createElement('div');
wrapper = mount(Popup, {
propsData: {
getContainer: () => div
}
});
const popup = wrapper.element;
expect(popup.parentNode).toEqual(div);
wrapper.vm.getContainer = null;
expect(popup.parentNode).toEqual(div);
});
test('render overlay', () => {
const div = document.createElement('div');
wrapper = mount(Popup, {
propsData: {
value: true,
overlay: false,
getContainer: () => div
}
});
expect(div.querySelector('.van-modal')).toBeFalsy();
wrapper.vm.overlay = true;
expect(div.querySelector('.van-modal')).toBeTruthy();
});
test('close on click modal', () => {
const div = document.createElement('div');
wrapper = mount(Popup, {
propsData: {
value: true,
getContainer: () => div
}
});
wrapper.vm.$on('input', val => {
wrapper.vm.value = val;
});
const modal = div.querySelector('.van-modal');
triggerDrag(modal, 0, -30);
modal.click();
expect(wrapper.vm.value).toBeFalsy();
});
+1
View File
@@ -47,6 +47,7 @@ export default {
| overlay-style | 自定义蒙层样式 | `Object` | `` |
| close-on-click-overlay | 点击蒙层是否关闭 Popup | `Boolean` | `true` |
| transition | transition 名称 | `String` | `popup-slide` |
| lazy-render | 是否在首次显示弹层时才渲染 DOM 节点 | `Boolean` | `true` |
| get-container | 指定弹出层挂载的 HTML 节点 | `() => HTMLElement` | - |
### Event