Menu.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import _extends from 'babel-runtime/helpers/extends';
  2. import PropTypes from '../_util/vue-types';
  3. import { Provider, create } from '../_util/store';
  4. import { default as SubPopupMenu, getActiveKey } from './SubPopupMenu';
  5. import BaseMixin from '../_util/BaseMixin';
  6. import hasProp, { getOptionProps, getComponentFromProp, filterEmpty, getListeners } from '../_util/props-util';
  7. import commonPropsType from './commonPropsType';
  8. var Menu = {
  9. name: 'Menu',
  10. props: _extends({}, commonPropsType, {
  11. selectable: PropTypes.bool.def(true)
  12. }),
  13. mixins: [BaseMixin],
  14. data: function data() {
  15. var props = getOptionProps(this);
  16. var selectedKeys = props.defaultSelectedKeys;
  17. var openKeys = props.defaultOpenKeys;
  18. if ('selectedKeys' in props) {
  19. selectedKeys = props.selectedKeys || [];
  20. }
  21. if ('openKeys' in props) {
  22. openKeys = props.openKeys || [];
  23. }
  24. this.store = create({
  25. selectedKeys: selectedKeys,
  26. openKeys: openKeys,
  27. activeKey: {
  28. '0-menu-': getActiveKey(_extends({}, props, { children: this.$slots['default'] || [] }), props.activeKey)
  29. }
  30. });
  31. // this.isRootMenu = true // 声明在props上
  32. return {};
  33. },
  34. mounted: function mounted() {
  35. this.updateMiniStore();
  36. },
  37. updated: function updated() {
  38. this.updateMiniStore();
  39. },
  40. methods: {
  41. onSelect: function onSelect(selectInfo) {
  42. var props = this.$props;
  43. if (props.selectable) {
  44. // root menu
  45. var selectedKeys = this.store.getState().selectedKeys;
  46. var selectedKey = selectInfo.key;
  47. if (props.multiple) {
  48. selectedKeys = selectedKeys.concat([selectedKey]);
  49. } else {
  50. selectedKeys = [selectedKey];
  51. }
  52. if (!hasProp(this, 'selectedKeys')) {
  53. this.store.setState({
  54. selectedKeys: selectedKeys
  55. });
  56. }
  57. this.__emit('select', _extends({}, selectInfo, {
  58. selectedKeys: selectedKeys
  59. }));
  60. }
  61. },
  62. onClick: function onClick(e) {
  63. this.__emit('click', e);
  64. },
  65. // onKeyDown needs to be exposed as a instance method
  66. // e.g., in rc-select, we need to navigate menu item while
  67. // current active item is rc-select input box rather than the menu itself
  68. onKeyDown: function onKeyDown(e, callback) {
  69. this.$refs.innerMenu.getWrappedInstance().onKeyDown(e, callback);
  70. },
  71. onOpenChange: function onOpenChange(event) {
  72. var openKeys = this.store.getState().openKeys.concat();
  73. var changed = false;
  74. var processSingle = function processSingle(e) {
  75. var oneChanged = false;
  76. if (e.open) {
  77. oneChanged = openKeys.indexOf(e.key) === -1;
  78. if (oneChanged) {
  79. openKeys.push(e.key);
  80. }
  81. } else {
  82. var index = openKeys.indexOf(e.key);
  83. oneChanged = index !== -1;
  84. if (oneChanged) {
  85. openKeys.splice(index, 1);
  86. }
  87. }
  88. changed = changed || oneChanged;
  89. };
  90. if (Array.isArray(event)) {
  91. // batch change call
  92. event.forEach(processSingle);
  93. } else {
  94. processSingle(event);
  95. }
  96. if (changed) {
  97. if (!hasProp(this, 'openKeys')) {
  98. this.store.setState({ openKeys: openKeys });
  99. }
  100. this.__emit('openChange', openKeys);
  101. }
  102. },
  103. onDeselect: function onDeselect(selectInfo) {
  104. var props = this.$props;
  105. if (props.selectable) {
  106. var selectedKeys = this.store.getState().selectedKeys.concat();
  107. var selectedKey = selectInfo.key;
  108. var index = selectedKeys.indexOf(selectedKey);
  109. if (index !== -1) {
  110. selectedKeys.splice(index, 1);
  111. }
  112. if (!hasProp(this, 'selectedKeys')) {
  113. this.store.setState({
  114. selectedKeys: selectedKeys
  115. });
  116. }
  117. this.__emit('deselect', _extends({}, selectInfo, {
  118. selectedKeys: selectedKeys
  119. }));
  120. }
  121. },
  122. getOpenTransitionName: function getOpenTransitionName() {
  123. var props = this.$props;
  124. var transitionName = props.openTransitionName;
  125. var animationName = props.openAnimation;
  126. if (!transitionName && typeof animationName === 'string') {
  127. transitionName = props.prefixCls + '-open-' + animationName;
  128. }
  129. return transitionName;
  130. },
  131. updateMiniStore: function updateMiniStore() {
  132. var props = getOptionProps(this);
  133. if ('selectedKeys' in props) {
  134. this.store.setState({
  135. selectedKeys: props.selectedKeys || []
  136. });
  137. }
  138. if ('openKeys' in props) {
  139. this.store.setState({
  140. openKeys: props.openKeys || []
  141. });
  142. }
  143. }
  144. },
  145. render: function render() {
  146. var h = arguments[0];
  147. var props = getOptionProps(this);
  148. var subPopupMenuProps = {
  149. props: _extends({}, props, {
  150. itemIcon: getComponentFromProp(this, 'itemIcon', props),
  151. expandIcon: getComponentFromProp(this, 'expandIcon', props),
  152. overflowedIndicator: getComponentFromProp(this, 'overflowedIndicator', props) || h('span', ['\xB7\xB7\xB7']),
  153. openTransitionName: this.getOpenTransitionName(),
  154. parentMenu: this,
  155. children: filterEmpty(this.$slots['default'] || [])
  156. }),
  157. 'class': props.prefixCls + '-root',
  158. on: _extends({}, getListeners(this), {
  159. click: this.onClick,
  160. openChange: this.onOpenChange,
  161. deselect: this.onDeselect,
  162. select: this.onSelect
  163. }),
  164. ref: 'innerMenu'
  165. };
  166. return h(
  167. Provider,
  168. {
  169. attrs: { store: this.store }
  170. },
  171. [h(SubPopupMenu, subPopupMenuProps)]
  172. );
  173. }
  174. };
  175. export default Menu;