diff --git a/build/bin/init.js b/build/bin/init.js
index 799258e11..1cc94dc86 100644
--- a/build/bin/init.js
+++ b/build/bin/init.js
@@ -29,4 +29,3 @@ gulp.task('copy', function(callback) {
});
runSequence('copy');
-
diff --git a/build/webpack.config.dev.js b/build/webpack.config.dev.js
index f4657d327..e38ba86e3 100644
--- a/build/webpack.config.dev.js
+++ b/build/webpack.config.dev.js
@@ -34,6 +34,7 @@ module.exports = {
chunkFilename: 'async.[name].js'
},
devServer: {
+ host: '0.0.0.0',
historyApiFallback: {
rewrites: [
{ from: /^\/zanui\/vue\/examples/, to: '/examples.html' },
@@ -114,7 +115,7 @@ module.exports = {
},
render: function(tokens, idx) {
- return tokens[idx].nesting === 1
+ return tokens[idx].nesting === 1
? ``
:`
\n`;
}
diff --git a/docs/examples-docs/deep-select.md b/docs/examples-docs/deep-select.md
new file mode 100644
index 000000000..846fdd9c5
--- /dev/null
+++ b/docs/examples-docs/deep-select.md
@@ -0,0 +1,169 @@
+
+
+## DeepSelect 分类选择组件
+
+### 使用指南
+``` javascript
+import { DeepSelect } from 'vant';
+
+Vue.component(DeepSelect.name, DeepSelect);
+```
+
+### 代码演示
+
+#### 基础用法
+
+:::demo 基础用法
+```html
+
+```
+
+```javascript
+export default {
+ data() {
+ return {
+ items: items,
+ // 左侧高亮元素的index
+ mainActiveIndex: 0,
+ // 被选中元素的id
+ activeId: 1001
+ };
+ },
+ methods: {
+ onNavClick(index) {
+ this.mainActiveIndex = index;
+ },
+ onItemClick(data) {
+ console.log(data);
+ this.activeId = data.id;
+ }
+ }
+}
+
+```
+:::
+
+### API
+
+#### 传入参数
+
+| 参数 | 说明 | 类型 | 默认值 | 必须 |
+|-----------|-----------|-----------|-------------|-------------|
+| items | 分类显示所需的数据,具体数据结构可看 数据结构 | Array | [] | |
+| mainActiveIndex | 左侧导航高亮的索引 | Number | 0 | |
+| activeId | 右侧选择项,高亮的数据id | Number | 0 | |
+
+#### 事件
+| 事件名 | 说明 | 参数 |
+|-----------|-----------|-----------|
+| navclick | 左侧导航点击时,触发的事件 | index:被点击的导航的索引 |
+| itemclick | 右侧选择项被点击时,会触发的事件 | data: 该点击项的数据 |
+
+### 数据格式
+#### items 分类显示所需数据的数据结构
+`items` 整体为一个数组,数组内包含一系列描述分类的 object。
+
+每个分类里,text表示当前分类的名称。children 表示分类里的可选项,为数组结构,id被用来唯一标识每个选项
+```javascript
+[
+ {
+ // 导航名称
+ text: '所有城市',
+ // 该导航下所有的可选项
+ children: [
+ {
+ // 可选项的名称
+ text: '温州',
+ // 可选项的id,高亮的时候是根据id是否和选中的id是否相同进行判断的
+ id: 1002
+ },
+ {
+ // 可选项的名称
+ text: '杭州',
+ // 可选项的id,高亮的时候是根据id是否和选中的id是否相同进行判断的
+ id: 1001
+ }
+ ]
+ }
+]
+```
diff --git a/docs/src/doc.config.js b/docs/src/doc.config.js
index 53912fd7d..d4cba5b4a 100644
--- a/docs/src/doc.config.js
+++ b/docs/src/doc.config.js
@@ -185,6 +185,10 @@ module.exports = {
{
"groupName": "业务组件",
"list": [
+ {
+ "path": "/deep-select",
+ "title": "DeepSelect 分类选择组件"
+ },
{
"path": "/express-way",
"title": "ExpressWay 配送方式"
diff --git a/packages/deep-select/index.vue b/packages/deep-select/index.vue
new file mode 100644
index 000000000..410b6ae86
--- /dev/null
+++ b/packages/deep-select/index.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
+ {{ item.text }}
+
+
+
+
+
+
+
diff --git a/packages/index.js b/packages/index.js
index bd8f2a69a..ac61d310f 100644
--- a/packages/index.js
+++ b/packages/index.js
@@ -10,6 +10,7 @@ import Checkbox from './checkbox';
import CheckboxGroup from './checkbox-group';
import Col from './col';
import DatetimePicker from './datetime-picker';
+import DeepSelect from './deep-select';
import Dialog from './dialog';
import ExpressWay from './express-way';
import Field from './field';
@@ -57,6 +58,7 @@ const components = [
CheckboxGroup,
Col,
DatetimePicker,
+ DeepSelect,
ExpressWay,
Field,
Icon,
@@ -114,6 +116,7 @@ export {
CheckboxGroup,
Col,
DatetimePicker,
+ DeepSelect,
Dialog,
ExpressWay,
Field,
diff --git a/packages/mixins/popup/popup-context.js b/packages/mixins/popup/popup-context.js
index 45cbae621..0e0588b7b 100644
--- a/packages/mixins/popup/popup-context.js
+++ b/packages/mixins/popup/popup-context.js
@@ -1,12 +1,7 @@
import Vue from 'vue';
-let context;
const _global = Vue.prototype.$isServer ? global : window;
-if (_global && _global.popupContext) {
- context = _global.popupContext;
-}
-
const DEFAULT_CONTEXT = {
idSeed: 1,
zIndex: 2000,
@@ -15,23 +10,24 @@ const DEFAULT_CONTEXT = {
modalStack: []
};
-context = _global.popupContext = {
- ...DEFAULT_CONTEXT,
- ...context
-};
+if (!_global.popupContext) {
+ _global.popupContext = {
+ ...DEFAULT_CONTEXT
+ };
+}
const PopupContext = {
getContext(key) {
- return context[key];
+ return _global.popupContext[key];
},
setContext(key, value) {
- context[key] = value;
+ _global.popupContext[key] = value;
},
plusKeyByOne(key) {
- const oldVal = +context[key];
- context[key] = oldVal + 1;
+ const oldVal = +_global.popupContext[key];
+ _global.popupContext[key] = oldVal + 1;
return oldVal;
}
diff --git a/packages/vant-css/src/deep-select.css b/packages/vant-css/src/deep-select.css
new file mode 100644
index 000000000..e36ce7c71
--- /dev/null
+++ b/packages/vant-css/src/deep-select.css
@@ -0,0 +1,51 @@
+@import "./mixins/ellipsis";
+@import "./mixins/clearfix";
+@import './common/var.css';
+.van-deep-select {
+ user-select: none;
+ position: relative;
+ @mixin clearfix;
+ &__nav {
+ width: 143px;
+ /*float: left;*/
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: 0;
+ overflow: scroll;
+ background-color: $c-white;
+ -webkit-overflow-scrolling: touch;
+ }
+ &__nitem {
+ line-height: 44px;
+ padding: 0 15px;
+ background-color: $c-white;
+ @mixin multi-ellipsis 1;
+ &--active {
+ background-color: $c-background;
+ }
+ }
+ &__content {
+ padding: 0 15px;
+ margin-left: 143px;
+ overflow: scroll;
+ -webkit-overflow-scrolling: touch;
+ }
+ &__item {
+ position: relative;
+ line-height: 44px;
+ padding-left: 5px;
+ padding-right: 18px;
+ @mixin multi-ellipsis 1;
+ &--active {
+ color: $button-danger-background-color;
+ }
+ }
+ &__selected {
+ float: right;
+ position: absolute;
+ right: 0px;
+ top: 0;
+ bottom: 0;
+ }
+}
diff --git a/packages/vant-css/src/index.css b/packages/vant-css/src/index.css
index 8731cbdb4..45c3ed50b 100644
--- a/packages/vant-css/src/index.css
+++ b/packages/vant-css/src/index.css
@@ -6,6 +6,7 @@
@import './cell.css';
@import './cell-swipe.css';
@import './card.css';
+@import './deep-select.css';
@import './dialog.css';
@import './field.css';
@import './icon.css';
diff --git a/test/unit/specs/deep-select.spec.js b/test/unit/specs/deep-select.spec.js
new file mode 100644
index 000000000..2fa1a85b9
--- /dev/null
+++ b/test/unit/specs/deep-select.spec.js
@@ -0,0 +1,68 @@
+import DeepSelect from 'packages/deep-select';
+import { mount } from 'avoriaz';
+
+describe('DeepSelect', () => {
+ let wrapper;
+ afterEach(() => {
+ wrapper && wrapper.destroy();
+ });
+
+ it('create an empty deep-select', () => {
+ wrapper = mount(DeepSelect);
+ expect(wrapper.hasStyle('height', '0px')).to.be.true;
+ });
+
+ it('create a deep-select correctly', () => {
+ wrapper = mount(DeepSelect, {
+ propsData: {
+ items: [{
+ text: 'A',
+ children: [{
+ text: 'Cc',
+ id: 123
+ }]
+ }],
+ maxHeight: 200
+ }
+ });
+ expect(wrapper.hasClass('van-deep-select')).to.be.true;
+ expect(wrapper.hasStyle('height', '44px')).to.be.true;
+ expect(wrapper.propsData().maxHeight).to.equal(200);
+ });
+
+ it('interact with this component', () => {
+ wrapper = mount(DeepSelect, {
+ propsData: {
+ items: [{
+ text: 'A',
+ children: [{
+ text: 'Cc',
+ id: 123
+ }, {
+ text: 'Bb',
+ id: 234
+ }]
+ }, {
+ text: 'B',
+ children: [{
+ text: 'Nmi',
+ id: 345
+ }]
+ }],
+ maxHeight: 220
+ }
+ });
+ wrapper.vm.$on('navclick', index => {
+ wrapper.vm.mainActiveIndex = index;
+ });
+ wrapper.vm.$on('itemclick', item => {
+ wrapper.vm.activeId = item.id;
+ });
+ const secondNav = wrapper.find('.van-deep-select__nitem')[1];
+ secondNav.trigger('click');
+ expect(wrapper.vm.mainActiveIndex).to.equal(1);
+ const target = wrapper.find('.van-deep-select__item')[0];
+ target.trigger('click');
+ expect(wrapper.vm.activeId).to.equal(345);
+ });
+});