您好,登錄后才能下訂單哦!
本篇內容介紹了“怎么實現vue2下拉菜單dropdown組件”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
一般后臺項目結合分頁組件用到這個dropdown組件,用來做顯示分頁條數,其他用到這個組件的地方倒不是很多,其實現思路和select組件有那么些相似,現記錄下這個組件的實現。
需要注意以下幾點:
組件分為兩部分:
供我們點擊的文字,按鈕,超鏈接等等(當成插槽供用戶提供)
下拉菜單項(支持邊框,禁用等)
使用該組件應當提供的事件應該是點擊item項,然后將對應的item的對應value暴露出來,供用戶使用。
組件菜單項的顯示隱藏需要過渡動畫。
默認菜單項方向向下,當下方可視區的高度不足以容納下拉菜單的高度的時候,自動讓菜單方向向上。
這個在之前的組件實現過程中介紹過這個文件,主要是為了解決跨多層級父子組件之前數據通信的,本質上實現原理為發布訂閱模式。
/** * @Description 由于涉及到跨組件之間通信,因此我們只有自己實現發布訂閱的模式,來實現組件之間通信,靈感主要來源于element-ui組件庫源碼中跨層級父子組件通信方案,本質上也是發布訂閱和$emit和$on * @param { String } componentName 組件名 * @param { String } eventName 事件名 * @param { argument } params 參數 **/ // 廣播通知事件 function _broadcast(componentName, eventName, params) { // 遍歷當前組件的子組件 this.$children.forEach(function (child) { // 取出componentName,組件options上面可以自己配置 var name = child.$options.componentName; // 如果找到了需要通知的組件名,觸發組件上面的$eimit方法,觸發自定義事件 if (name === componentName) { child.$emit.apply(child, [eventName].concat(params)); } else { // 沒找到,遞歸往下找 _broadcast.apply(child, [componentName, eventName].concat([params])); } }); } const emiiter = { methods: { // 派發事件(通知父組件) dispatch(componentName, eventName, params) { var parent = this.$parent || this.$root; var name = parent.$options.componentName; // 循環往上層父組件,知道知道組件名和需要觸發的組件名相同即可,然后觸發對應組件的事件 while (parent && (!name || name !== componentName)) { parent = parent.$parent; if (parent) { name = parent.$options.componentName; } } if (parent) { parent.$emit.apply(parent, [eventName].concat(params)); } }, // 廣播事件(通知子組件) broadcast(componentName, eventName, params) { _broadcast.call(this, componentName, eventName, params); }, }, }; export default emiiter;
主要暴露給用戶使用的組件
<template> <div class="my-dropdown" @click.stop="trigger == 'click' ? (showMenu = !showMenu) : ''" @mouseenter="trigger == 'hover' ? (showMenu = true) : ''" @mouseleave="trigger == 'hover' ? (showMenu = false) : ''" ref="myDropDdown" > <div class="tip-text" ref="tipText"> <slot></slot> </div> <slot name="list"></slot> </div> </template> <script> import emitter from "./emitter"; export default { name: "MyDropdown", componentName: "MyDropdown", mixins: [emitter], props: { // 觸發顯示方式 trigger: { type: String, default: "click", }, // 下來菜單的出現位置(上方,下方) placement: { type: String, default: "bottom", validator: function (value) { // 這個值必須匹配下列字符串中的一個 return ["bottom", "top"].includes(value); }, }, }, data() { return { //控制菜單是否顯示 showMenu: false, }; }, mounted() { //初始化自定義事件 this.initEvent(); }, methods: { // 初始化 initEvent() { //訂閱當item點擊的時候,發布on-click事件,告知外部 this.$on("item-click", (params) => { this.$emit("on-click", params); this.showMenu = false; }); //空白點擊要隱藏菜單,需要執行的函數需要綁定this指向 this.handleEmptyDomElementClickBindThis = this.handleEmptyDomElementClick.bind(this); window.addEventListener("click", this.handleEmptyDomElementClickBindThis); }, // 處理空白區域點擊,隱藏菜單列表 handleEmptyDomElementClick(e) { if (!Array.from(this.$refs.myDropDdown.childNodes).includes(e.target)) { this.showMenu = false; } }, }, beforeDestroy() { // 移除window上面的事件 window.removeEventListener(this.handleEmptyDomElementClickBindThis); }, watch: { //變化的時候,通知子組件隱藏菜單列表 showMenu() { this.broadcast("MyDropdownMenu", "set-menu-status", this.showMenu); }, }, }; </script> <style lang="less"> .my-dropdown { position: relative; } </style>
主要暴露給用戶使用的組件,菜單列表組件
<template> <!-- 涉及到高度,位移,過渡使用js鉤子函數的方式比較好處理些 --> <transition @before-enter="beforeEnter" @enter="enter" @leave="leave" v-bind:css="false" > <div class="my-dropdown-menu" v-if="showMeune" ref="myDroupdownMenu"> <slot></slot> </div> </transition> </template> <script> import emitter from "./emitter"; export default { name: "MyDropdownMenu", componentName: "MyDropdownMenu", mixins: [emitter], data() { return { showMeune: false, timer: null, }; }, mounted() { this.$on("set-menu-status", (status) => { this.showMeune = status; }); }, methods: { //進入前,初始化需要過渡的屬性 beforeEnter: function (el) { // 初始化 el.style.opacity = 0; el.style.transform = "scaleY(0)"; el.style.transformOrigin = "top center"; }, //dom進入 enter: function (el, done) { //獲取文檔可視區高度 const htmlClientHeight = document.documentElement.clientHeight; //菜單列表相對于父元素的top偏移量 const offsetTop = el.offsetTop; const scrollHeight = el.scrollHeight; //獲取當前元素和可視區的一些長度(top,left,bottom等) const { bottom } = el.getBoundingClientRect(); // 說明底部高度不夠顯示菜單了,這時候我們需要調整菜單朝上面顯示 if (htmlClientHeight - bottom < scrollHeight) { el.style.transformOrigin = "bottom center"; el.style.top = -(scrollHeight + 20) + "px"; } else { //查看是否placement屬性,是的話我們主動處理 if (this.$parent.placement == "top") { el.style.transformOrigin = "bottom center"; el.style.top = -(scrollHeight + 20) + "px"; } else { el.style.top = offsetTop + "px"; } } el.style.transform = "scaleY(1)"; el.style.opacity = 1; //根據官網事例,必須在enter和leave里面調用done函數,不然過渡動畫不生效(切記) done(); }, //dom元素離開 leave: function (el, done) { el.style.transform = "scaleY(0)"; el.style.opacity = 0; clearTimeout(this.timer); this.timer = setTimeout(() => { //根據官網事例,必須在enter和leave里面調用done函數,不然過渡動畫不生效(切記) done(); }, 250); }, }, }; </script> <style lang="less"> .my-dropdown-menu { min-width: 100px; max-height: 200px; overflow: auto; margin: 5px 0; padding: 5px 0; background-color: #fff; box-sizing: border-box; border-radius: 4px; box-shadow: 0 1px 6px rgb(0 0 0 / 20%); z-index: 900; transform-origin: top center; position: absolute; transition: transform 0.25s ease, opacity 0.25s ease; } </style>
主要暴露給用戶使用的組件,菜單列表項組件,組件內容很簡單,主要就是展示item數據和綁定點擊事件。
<template> <div :class="[ 'my-dropdownItem', divided ? 'my-dropdownItem-divided' : '', disabled ? 'my-dropdownItem-disabled' : '', ]" @click.stop="handleItemClick" > <slot></slot> </div> </template> <script> import emitter from "./emitter"; export default { name: "MyDropdownItem", componentName: "MyDropdownItem", mixins: [emitter], props: { divided: { type: Boolean, default: false, }, disabled: { type: Boolean, default: false, }, name: { type: String, default: "", }, }, data() { return {}; }, methods: { handleItemClick() { if (this.disabled) return; // item項點擊通知dropdown組件派發到外部的自定義事件 this.dispatch("MyDropdown", "item-click", this.name); }, }, }; </script> <style lang="less"> .my-dropdownItem { margin: 0; line-height: normal; padding: 7px 16px; clear: both; color: #515a6e; font-size: 14px !important; white-space: nowrap; list-style: none; cursor: pointer; transition: background 0.2s ease-in-out; &:hover { background: #f3f3f3; } } .my-dropdownItem-divided { border-bottom: 1px solid #eee; } .my-dropdownItem-disabled { color: #cacdd2; cursor: not-allowed; &:hover { background: #fff; } } </style>
“怎么實現vue2下拉菜單dropdown組件”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。