Effect
experience
web component select
web components polyfill compatible support plug-ins for older browsers
https://www.webcomponents.org...
Web Component is a series of web platform API s that allow you to create new customizable, reusable and encapsulated HTML Tags
Customized components are built based on Web Component standards and can be used in browsers today, or in conjunction with JavaScript libraries and frameworks that interact arbitrarily with HTML.
It gives you the ability to create reusable components using pure JS/HTML/CSS. If HTML does not meet the requirements, we can create a Web Component that meets the requirements.
Source code
(function () { const selectListDemo = [ {name: 'test1', value: 1}, {name: 'test2', value: 2}, {name: 'test3', value: 3} ] class MidociSelect extends HTMLElement { static get observedAttributes() { return ['acitve-title', 'active-sub-title'] } constructor() { super() this.attachShadow({mode: 'open'}) this.shadowRoot.innerHTML = ` <style> :host{ --themeColor:rgb(24,144,255); box-sizing: border-box; font-size: 14px; --borderColor:#eee; } .wrapper{ position: relative; display: inline-flex; align-items: center; padding-left: 10px; width: 95px; height: 36px; border: 1px solid var(--borderColor); color: #333; border-radius: 2px; user-select: none; transition: .3s cubic-bezier(.12, .4, .29, 1.46); outline:none } .wrapper:hover{ border: 1px solid var(--themeColor); transition: .3s cubic-bezier(.12, .4, .29, 1.46); } .title{ } .arrow-out{ position: absolute; right: 12px; top: 50%; transform: translateY(0px) rotateX(0deg); transition: .3s cubic-bezier(.12, .4, .29, 1.46); } .wrapper.flip>.arrow-out{ transform: translateY(-3px) rotateX(180deg); transition: .3s cubic-bezier(.12, .4, .29, 1.46); } .arrow{ display: flex; width: 6px; height:6px; border: none; border-left: 1px solid #333; border-bottom: 1px solid #333; transform: translateY(-50%) rotateZ(-45deg); transition: .3s cubic-bezier(.12, .4, .29, 1.46); } .wrapper:hover .arrow{ border-left: 1px solid var(--themeColor); border-bottom: 1px solid var(--themeColor); transition: .3s cubic-bezier(.12, .4, .29, 1.46); } .list{ z-index: 100; position: absolute; top: 130%; left: 0; background-color: #fff; box-shadow: 0 0 10px rgba(0,0,0,0.1); visibility: hidden; min-width: 100%; border-radius: 3px; transform: scale(0); transform-origin: top; transition: .3s cubic-bezier(.12, .4, .29, 1.46); } .wrapper.flip>.list{ visibility: visible; transform: scale(1); transition: .3s cubic-bezier(.12, .4, .29, 1.46); } .item{ display: flex; align-items: center; padding-left: 10px; width: 95px; height: 36px; color: #333; border-radius: 2px; user-select: none; background-color: #fff; transition: background-color .3s ease-in-out; } .item:hover{ background-color: rgba(24,144,255,0.1); transition: background-color .3s ease-in-out; } </style> <div class="wrapper" tabindex="1"> <span class="title">1</span> <span class="arrow-out"> <span class="arrow"></span> </span> <div class="list" > <div class="item">1</div> <div class="item">2</div> <div class="item">3</div> <div class="item">4</div> </div> </div> ` this._wrapperDom = null this._listDom = null this._titleDom = null this._list = [] this._arrowFlip = false this._value = null this._name = null } connectedCallback() { this._wrapperDom = this.shadowRoot.querySelector('.wrapper') this._listDom = this.shadowRoot.querySelector('.list') this._titleDom = this.shadowRoot.querySelector('.title') this.initEvent() this.list = selectListDemo } disconnectedCallback() { this._wrapperDom.removeEventListener('click', this.flipArrow.bind(this)) this._wrapperDom.removeEventListener('blur', this.blurWrapper.bind(this)) this.shadowRoot.querySelectorAll('.item') .forEach((item, index) => { item.removeEventListener('click', this.change.bind(this, index)) }) } attributeChangedCallback(attr, oldVal, newVal) { // const attribute = attr.toLowerCase() // if (attribute === 'descriptions') { // console.log(1) // this.render(newVal) // } } set list(list) { if (!this.shadowRoot) return this._list = list this.render(list) } get list() { return this._list } set value(value) { this._value = value } get value() { return this._value } set name(name) { this._name = name } get name() { return this._name } initEvent() { this.initArrowEvent() this.blurWrapper() } initArrowEvent() { this._wrapperDom.addEventListener('click', this.flipArrow.bind(this)) } initChangeEvent() { this.shadowRoot.querySelectorAll('.item') .forEach((item, index) => { item.addEventListener('click', this.change.bind(this, index)) }) } change(index) { this.changeTitle(this._list, index) let changeInfo = { detail: { value: this._value, name: this._name }, bubbles: true } let changeEvent = new CustomEvent('change', changeInfo) this.dispatchEvent(changeEvent) } changeTitle(list, index) { this._value = list[index].value this._name = list[index].name this._titleDom.innerText = this._name } flipArrow() { if (!this._arrowFlip) { this.showList() } else { this.hideList() } } showList() { this._arrowFlip = true this._wrapperDom.classList = 'wrapper flip' } hideList() { this._arrowFlip = false this._wrapperDom.classList = 'wrapper' } blurWrapper() { this._wrapperDom.addEventListener('blur', (event) => { event.stopPropagation() this.hideList() }) } render(list) { if (!list instanceof Array) return let listString = '' list.forEach((item) => { listString += ` <div class="item" data-value="${item.value}">${item.name}</div> ` }) this._listDom.innerHTML = listString this.changeTitle(list, 0) this.initChangeEvent() } } const FrozenMidociSelect = Object.freeze(MidociSelect); customElements.define('midoci-select', FrozenMidociSelect); })()
Note: If the parent element is too low, the overflow attribute of the parent element needs to be closed, otherwise the drop-down list will be obscured.
Use
<script type="module" async> import './MidociSelect.js' </script> <midoci-select></midoci-select> <script> const list = [ {name: 'Full Platform', value: 1}, {name: 'East coupon', value: 2}, {name: 'Beijing coupon', value: 3} ] window.onload=function(){ document.querySelector('midoci-select').list=list console.log(document.querySelector('midoci-select').value) console.log(document.querySelector('midoci-select').name) document.querySelector('midoci-select').addEventListener('change', (event) => { console.log('Selected value:', event.detail.value) console.log('Selected name:', event.detail.name) }) } </script>