| <script> | 
| import ElScrollbar from 'element-ui/packages/scrollbar'; | 
| import CascaderNode from './cascader-node.vue'; | 
| import Locale from 'element-ui/src/mixins/locale'; | 
| import { generateId } from 'element-ui/src/utils/util'; | 
|   | 
| export default { | 
|   name: 'ElCascaderMenu', | 
|   | 
|   mixins: [Locale], | 
|   | 
|   inject: ['panel'], | 
|   | 
|   components: { | 
|     ElScrollbar, | 
|     CascaderNode | 
|   }, | 
|   | 
|   props: { | 
|     nodes: { | 
|       type: Array, | 
|       required: true | 
|     }, | 
|     index: Number | 
|   }, | 
|   | 
|   data() { | 
|     return { | 
|       activeNode: null, | 
|       hoverTimer: null, | 
|       id: generateId() | 
|     }; | 
|   }, | 
|   | 
|   computed: { | 
|     isEmpty() { | 
|       return !this.nodes.length; | 
|     }, | 
|     menuId() { | 
|       return `cascader-menu-${this.id}-${this.index}`; | 
|     } | 
|   }, | 
|   | 
|   methods: { | 
|     handleExpand(e) { | 
|       this.activeNode = e.target; | 
|     }, | 
|     handleMouseMove(e) { | 
|       const { activeNode, hoverTimer } = this; | 
|       const { hoverZone } = this.$refs; | 
|   | 
|       if (!activeNode || !hoverZone) return; | 
|   | 
|       if (activeNode.contains(e.target)) { | 
|         clearTimeout(hoverTimer); | 
|   | 
|         const { left } = this.$el.getBoundingClientRect(); | 
|         const startX = e.clientX - left; | 
|         const { offsetWidth, offsetHeight } = this.$el; | 
|         const top = activeNode.offsetTop; | 
|         const bottom = top + activeNode.offsetHeight; | 
|   | 
|         hoverZone.innerHTML = ` | 
|           <path style="pointer-events: auto;" fill="transparent" d="M${startX} ${top} L${offsetWidth} 0 V${top} Z" /> | 
|           <path style="pointer-events: auto;" fill="transparent" d="M${startX} ${bottom} L${offsetWidth} ${offsetHeight} V${bottom} Z" /> | 
|         `; | 
|       } else if (!hoverTimer) { | 
|         this.hoverTimer = setTimeout(this.clearHoverZone, this.panel.config.hoverThreshold); | 
|       } | 
|     }, | 
|     clearHoverZone() { | 
|       const { hoverZone } = this.$refs; | 
|       if (!hoverZone) return; | 
|       hoverZone.innerHTML = ''; | 
|     }, | 
|   | 
|     renderEmptyText(h) { | 
|       return ( | 
|         <div class="el-cascader-menu__empty-text">{ this.t('el.cascader.noData') }</div> | 
|       ); | 
|     }, | 
|     renderNodeList(h) { | 
|       const { menuId } = this; | 
|       const { isHoverMenu } = this.panel; | 
|       const events = { on: {} }; | 
|   | 
|       if (isHoverMenu) { | 
|         events.on.expand = this.handleExpand; | 
|       } | 
|   | 
|       const nodes = this.nodes.map((node, index) => { | 
|         const { hasChildren } = node; | 
|         return ( | 
|           <cascader-node | 
|             key={ node.uid } | 
|             node={ node } | 
|             node-id={ `${menuId}-${index}` } | 
|             aria-haspopup={ hasChildren } | 
|             aria-owns = { hasChildren ? menuId : null } | 
|             { ...events }></cascader-node> | 
|         ); | 
|       }); | 
|   | 
|       return [ | 
|         ...nodes, | 
|         isHoverMenu ? <svg ref='hoverZone' class='el-cascader-menu__hover-zone'></svg> : null | 
|       ]; | 
|     } | 
|   }, | 
|   | 
|   render(h) { | 
|     const { isEmpty, menuId } = this; | 
|     const events = { nativeOn: {} }; | 
|   | 
|     // optimize hover to expand experience (#8010) | 
|     if (this.panel.isHoverMenu) { | 
|       events.nativeOn.mousemove = this.handleMouseMove; | 
|       // events.nativeOn.mouseleave = this.clearHoverZone; | 
|     } | 
|   | 
|     return ( | 
|       <el-scrollbar | 
|         tag="ul" | 
|         role="menu" | 
|         id={ menuId } | 
|         class="el-cascader-menu" | 
|         wrap-class="el-cascader-menu__wrap" | 
|         view-class={{ | 
|           'el-cascader-menu__list': true, | 
|           'is-empty': isEmpty | 
|         }} | 
|         { ...events }> | 
|         { isEmpty ? this.renderEmptyText(h) : this.renderNodeList(h) } | 
|       </el-scrollbar> | 
|     ); | 
|   } | 
| }; | 
| </script> |