diff --git a/packages/dropdown-item/index.ts b/packages/dropdown-item/index.ts
index ea7be13e..fe08bdcf 100644
--- a/packages/dropdown-item/index.ts
+++ b/packages/dropdown-item/index.ts
@@ -9,6 +9,7 @@ VantComponent({
type: 'ancestor',
linked(target) {
this.parent = target;
+ this.updateDataFromParent();
},
unlinked() {
this.parent = null;
@@ -16,13 +17,23 @@ VantComponent({
},
props: {
- value: null,
- title: String,
+ value: {
+ type: null,
+ observer: 'rerender'
+ },
+ title: {
+ type: String,
+ observer: 'rerender'
+ },
disabled: Boolean,
- titleClass: String,
+ titleClass: {
+ type: String,
+ observer: 'rerender'
+ },
options: {
type: Array,
- value: []
+ value: [],
+ observer: 'rerender'
}
},
@@ -33,21 +44,30 @@ VantComponent({
displayTitle: ''
},
- created() {
- this.setData({ displayTitle: this.computedDisplayTitle(this.data.value) });
- },
-
methods: {
- computedDisplayTitle(curValue) {
- const { title, options } = this.data;
+ rerender() {
+ wx.nextTick(() => {
+ this.parent && this.parent.updateItemListData();
+ });
+ },
- if (title) {
- return title;
+ updateDataFromParent() {
+ if (this.parent) {
+ const {
+ overlay,
+ duration,
+ activeColor,
+ closeOnClickOverlay,
+ direction
+ } = this.parent.data;
+ this.setData({
+ overlay,
+ duration,
+ activeColor,
+ closeOnClickOverlay,
+ direction
+ });
}
-
- const match = options.filter(option => option.value === curValue);
- const displayTitle = match.length ? match[0].text : '';
- return displayTitle;
},
onClickOverlay() {
@@ -56,30 +76,55 @@ VantComponent({
},
onOptionTap(event: Weapp.Event) {
- let { value, displayTitle } = this.data;
const { option } = event.currentTarget.dataset;
- const { value: optionValue } = option;
+ const { value } = option;
- if (optionValue !== value) {
- value = optionValue;
- displayTitle = this.computedDisplayTitle(optionValue);
- this.$emit('change', optionValue);
- }
- this.setData({ showPopup: false, value, displayTitle });
+ const shouldEmitChange = this.data.value !== value;
+ this.setData({ showPopup: false, value });
- const time = this.data.duration || 0;
setTimeout(() => {
this.setData({ showWrapper: false });
- }, time);
+ }, this.data.duration || 0);
- // parent 中的 itemListData 是 children 上的数据的集合
- // 数据的更新由 children 各自维护,但是模板的更新需要额外触发 parent 的 setData
- this.parent.setData({ itemListData: this.parent.data.itemListData });
+ this.rerender();
+
+ if (shouldEmitChange) {
+ this.$emit('change', value);
+ }
},
- toggle() {
- const { childIndex } = this.data;
- this.parent.toggleItem(childIndex);
+ toggle(show, options = {}) {
+ const { showPopup, duration } = this.data;
+
+ if (show == null) {
+ show = !showPopup;
+ }
+
+ if (show === showPopup) {
+ return;
+ }
+
+ if (!show) {
+ const time = options.immediate ? 0 : duration;
+ this.setData({ transition: !options.immediate, showPopup: show });
+
+ setTimeout(() => {
+ this.setData({ showWrapper: false });
+ }, time);
+
+ this.rerender();
+ return;
+ }
+
+ this.parent.getChildWrapperStyle().then((wrapperStyle: String = '') => {
+ this.setData({
+ transition: !options.immediate,
+ showPopup: show,
+ wrapperStyle,
+ showWrapper: true
+ });
+ this.rerender();
+ });
}
}
});
diff --git a/packages/dropdown-menu/index.ts b/packages/dropdown-menu/index.ts
index 6e8cda6d..7f8cf7a6 100644
--- a/packages/dropdown-menu/index.ts
+++ b/packages/dropdown-menu/index.ts
@@ -2,11 +2,8 @@ import { VantComponent } from '../common/component';
import { Weapp } from 'definitions/weapp';
import { addUnit } from '../common/utils';
-interface ToggleOptions {
- immediate?: Boolean;
-}
-
-let ARRAY: WechatMiniprogram.Component.TrivialInstance[] = [];
+type TrivialInstance = WechatMiniprogram.Component.TrivialInstance;
+let ARRAY: TrivialInstance[] = [];
VantComponent({
field: true,
@@ -15,35 +12,26 @@ VantComponent({
name: 'dropdown-item',
type: 'descendant',
linked(target) {
- this.children = this.children || [];
- // 透传 props 给 dropdown-item
- const { overlay, duration, activeColor, closeOnClickOverlay, direction } = this.data;
- this.updateChildData(target, {
- overlay,
- duration,
- activeColor,
- closeOnClickOverlay,
- direction,
- childIndex: this.children.length
- });
-
this.children.push(target);
- // 收集 dorpdown-item 的 data 挂在 data 上
- target &&
- this.setData({
- itemListData: this.data.itemListData.concat([target.data])
- });
+ this.updateItemListData();
},
unlinked(target) {
- this.children = this.children.filter((child: WechatMiniprogram.Component.TrivialInstance) => child !== target);
+ this.children = this.children.filter(
+ (child: TrivialInstance) => child !== target
+ );
+ this.updateItemListData();
}
},
props: {
- activeColor: String,
+ activeColor: {
+ type: String,
+ observer: 'updateChildrenData'
+ },
overlay: {
type: Boolean,
- value: true
+ value: true,
+ observer: 'updateChildrenData'
},
zIndex: {
type: Number,
@@ -51,15 +39,18 @@ VantComponent({
},
duration: {
type: Number,
- value: 200
+ value: 200,
+ observer: 'updateChildrenData'
},
direction: {
type: String,
- value: 'down'
+ value: 'down',
+ observer: 'updateChildrenData'
},
closeOnClickOverlay: {
type: Boolean,
- value: true
+ value: true,
+ observer: 'updateChildrenData'
},
closeOnClickOutside: {
type: Boolean,
@@ -71,7 +62,10 @@ VantComponent({
itemListData: []
},
- created() {
+ beforeCreate() {
+ const { windowHeight } = wx.getSystemInfoSync();
+ this.windowHeight = windowHeight;
+ this.children = [];
ARRAY.push(this);
},
@@ -80,99 +74,67 @@ VantComponent({
},
methods: {
- updateChildData(childItem: WechatMiniprogram.Component.TrivialInstance, newData, needRefreshList: Boolean = false) {
- childItem.setData(newData);
-
- if (needRefreshList) {
- // dropdown-item data 更新,涉及到 title 的展示,触发模板更新
- this.setData({ itemListData: this.data.itemListData });
- }
- },
-
- toggleItem(active: Number) {
- this.children.forEach((item: WechatMiniprogram.Component.TrivialInstance, index: Number) => {
- const { showPopup } = item.data;
- if (index === active) {
- this.toggleChildItem(item);
- } else if (showPopup) {
- this.toggleChildItem(item, false, { immediate: true });
- }
+ updateItemListData() {
+ this.setData({
+ itemListData: this.children.map((child: TrivialInstance) => child.data)
});
},
- toggleChildItem(childItem: WechatMiniprogram.Component.TrivialInstance, show: boolean, options: ToggleOptions = {}) {
- const { showPopup, duration } = childItem.data;
+ updateChildrenData() {
+ this.children.forEach((child: TrivialInstance) => {
+ child.updateDataFromParent();
+ });
+ },
- if (show === undefined) show = !showPopup;
-
- if (show === showPopup) {
- return;
- }
-
- const newChildData = { transition: !options.immediate, showPopup: show };
-
- if (!show) {
- const time = options.immediate ? 0 : duration;
- this.updateChildData(childItem, { ...newChildData }, true);
-
- setTimeout(() => {
- this.updateChildData(childItem, { showWrapper: false }, true);
- }, time);
- return;
- }
-
- this.getChildWrapperStyle().then((wrapperStyle: String = '') => {
- this.updateChildData(
- childItem,
- {
- ...newChildData,
- wrapperStyle,
- showWrapper: true
- },
- true
- );
+ toggleItem(active: number) {
+ this.children.forEach((item: TrivialInstance, index: number) => {
+ const { showPopup } = item.data;
+ if (index === active) {
+ item.toggle();
+ } else if (showPopup) {
+ item.toggle(false, { immediate: true });
+ }
});
},
close() {
- this.children.forEach((item: WechatMiniprogram.Component.TrivialInstance) => {
- this.toggleChildItem(item, false, { immediate: true });
+ this.children.forEach((child: TrivialInstance) => {
+ child.toggle(false, { immediate: true });
});
},
getChildWrapperStyle() {
- const { windowHeight } = wx.getSystemInfoSync();
const { zIndex, direction } = this.data;
- let offset = 0;
- return this.getRect('.van-dropdown-menu').then(rect => {
- const { top = 0, bottom = 0 } = rect;
- if (direction === 'down') {
- offset = bottom;
- } else {
- offset = windowHeight - top;
+ return this.getRect('.van-dropdown-menu').then(
+ (rect: WechatMiniprogram.BoundingClientRectCallbackResult) => {
+ const { top = 0, bottom = 0 } = rect;
+ const offset = direction === 'down' ? bottom : this.windowHeight - top;
+
+ let wrapperStyle = `z-index: ${zIndex};`;
+
+ if (direction === 'down') {
+ wrapperStyle += `top: ${addUnit(offset)};`;
+ } else {
+ wrapperStyle += `bottom: ${addUnit(offset)};`;
+ }
+
+ return wrapperStyle;
}
-
- let wrapperStyle = `z-index: ${zIndex};`;
-
- if (direction === 'down') {
- wrapperStyle += `top: ${addUnit(offset)};`;
- } else {
- wrapperStyle += `bottom: ${addUnit(offset)};`;
- }
-
- return Promise.resolve(wrapperStyle);
- });
+ );
},
onTitleTap(event: Weapp.Event) {
- // item ---> dropdown-item
- const { item, index } = event.currentTarget.dataset;
+ const { index } = event.currentTarget.dataset;
+ const child = this.children[index];
- if (!item.disabled) {
- // menuItem ---> dropdown-menu
+ if (!child.data.disabled) {
ARRAY.forEach(menuItem => {
- if (menuItem && menuItem.data.closeOnClickOutside && menuItem !== this) {
+ if (
+ menuItem &&
+ menuItem.data.closeOnClickOutside &&
+ menuItem !== this
+ ) {
menuItem.close();
}
});
diff --git a/packages/dropdown-menu/index.wxml b/packages/dropdown-menu/index.wxml
index 22933b57..037ac3b6 100644
--- a/packages/dropdown-menu/index.wxml
+++ b/packages/dropdown-menu/index.wxml
@@ -1,10 +1,10 @@
+
diff --git a/packages/dropdown-menu/index.wxs b/packages/dropdown-menu/index.wxs
new file mode 100644
index 00000000..65388549
--- /dev/null
+++ b/packages/dropdown-menu/index.wxs
@@ -0,0 +1,16 @@
+/* eslint-disable */
+function displayTitle(item) {
+ if (item.title) {
+ return item.title;
+ }
+
+ var match = item.options.filter(function(option) {
+ return option.value === item.value;
+ });
+ var displayTitle = match.length ? match[0].text : '';
+ return displayTitle;
+}
+
+module.exports = {
+ displayTitle: displayTitle
+};