重构wc-option;优化radio和checkbox组件
parent
afd6d5715c
commit
0ae310b871
|
@ -253,7 +253,7 @@ export default class Checkbox {
|
||||||
this._checkGroup()
|
this._checkGroup()
|
||||||
|
|
||||||
this._handlClick = $.bind(this, 'click', ev => {
|
this._handlClick = $.bind(this, 'click', ev => {
|
||||||
ev.preventDefault()
|
ev.stopPropagation()
|
||||||
this._toggleCheck()
|
this._toggleCheck()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -4,19 +4,11 @@
|
||||||
<input readonly />
|
<input readonly />
|
||||||
<wc-icon is="trigon-down"></wc-icon>
|
<wc-icon is="trigon-down"></wc-icon>
|
||||||
</section>
|
</section>
|
||||||
<ul class="options-box"></ul>
|
<div class="options-box"><slot /></div>
|
||||||
<slot name="option"></slot>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
ul,
|
|
||||||
li {
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
slot {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
:host {
|
:host {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
min-width: 72px;
|
min-width: 72px;
|
||||||
|
@ -74,8 +66,6 @@ slot {
|
||||||
.options-box {
|
.options-box {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 36px;
|
top: 36px;
|
||||||
|
@ -87,19 +77,6 @@ slot {
|
||||||
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.15);
|
||||||
transition: height 0.15s linear;
|
transition: height 0.15s linear;
|
||||||
|
|
||||||
li {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
height: 32px;
|
|
||||||
padding: 0 8px;
|
|
||||||
transition: background 0.15s linear;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&.active {
|
|
||||||
background: var(--color-plain-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
@ -126,6 +103,7 @@ slot {
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import '../icon/index'
|
import '../icon/index'
|
||||||
|
import './option'
|
||||||
import $ from '../utils'
|
import $ from '../utils'
|
||||||
|
|
||||||
export default class Dropdown {
|
export default class Dropdown {
|
||||||
|
@ -136,8 +114,7 @@ export default class Dropdown {
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
optionShow: false,
|
optionShow: false
|
||||||
options: []
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__init__() {
|
__init__() {
|
||||||
|
@ -146,23 +123,30 @@ export default class Dropdown {
|
||||||
var outbox = this.root.children[1]
|
var outbox = this.root.children[1]
|
||||||
this.__PREVIEW__ = outbox.children[0]
|
this.__PREVIEW__ = outbox.children[0]
|
||||||
this.__OPTIONS__ = outbox.children[1]
|
this.__OPTIONS__ = outbox.children[1]
|
||||||
this.__SLOT__ = outbox.children[2]
|
|
||||||
this.__INPUT__ = this.__PREVIEW__.children[0]
|
this.__INPUT__ = this.__PREVIEW__.children[0]
|
||||||
this.__ICO__ = this.__PREVIEW__.children[1]
|
this.__ICO__ = this.__PREVIEW__.children[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_updateChildrenStat() {
|
||||||
|
Array.from(this.children).forEach(it => {
|
||||||
|
if (it.tagName === 'WC-OPTION' && it.root) {
|
||||||
|
if (it.value === this.props.value) {
|
||||||
|
it.setAttribute('active', '')
|
||||||
|
this.__INPUT__.value = it.label || it.textContent
|
||||||
|
} else {
|
||||||
|
it.removeAttribute('active')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
get value() {
|
get value() {
|
||||||
return this.props.value
|
return this.props.value
|
||||||
}
|
}
|
||||||
|
|
||||||
set value(val) {
|
set value(val) {
|
||||||
this.props.value = val
|
this.props.value = val
|
||||||
for (let it of this.state.options) {
|
this._updateChildrenStat()
|
||||||
if (it.opt.value === val) {
|
|
||||||
this.__INPUT__.value = it.label
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get disabled() {
|
get disabled() {
|
||||||
|
@ -187,24 +171,6 @@ export default class Dropdown {
|
||||||
}
|
}
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
let opts = this.__SLOT__.assignedNodes()
|
|
||||||
this.state.options = []
|
|
||||||
|
|
||||||
this.__OPTIONS__.innerHTML = opts
|
|
||||||
.map(it => {
|
|
||||||
let attr = ''
|
|
||||||
let tmp = { label: it.textContent, opt: { ...it.dataset } }
|
|
||||||
for (let k in tmp.opt) {
|
|
||||||
attr += `data-${k}="${tmp.opt[k]}" `
|
|
||||||
}
|
|
||||||
tmp.label = tmp.label || tmp.opt.value
|
|
||||||
tmp.opt.value = tmp.opt.value || tmp.label
|
|
||||||
|
|
||||||
this.state.options.push(tmp)
|
|
||||||
return `<li ${attr}>${tmp.label}</li>`
|
|
||||||
})
|
|
||||||
.join('')
|
|
||||||
|
|
||||||
this._activeFn = $.bind(this.__PREVIEW__, 'click', ev => {
|
this._activeFn = $.bind(this.__PREVIEW__, 'click', ev => {
|
||||||
if (this.disabled) {
|
if (this.disabled) {
|
||||||
return
|
return
|
||||||
|
@ -214,16 +180,20 @@ export default class Dropdown {
|
||||||
})
|
})
|
||||||
|
|
||||||
this._pickedFn = $.bind(this.__OPTIONS__, 'click', ev => {
|
this._pickedFn = $.bind(this.__OPTIONS__, 'click', ev => {
|
||||||
if (ev.target === ev.currentTarget) {
|
let elem = ev.target
|
||||||
|
|
||||||
|
if (elem === ev.currentTarget) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let detail = { ...ev.target.dataset }
|
while (elem.tagName !== 'WC-OPTION') {
|
||||||
this.__INPUT__.value = ev.target.textContent
|
elem = elem.parentNode
|
||||||
this.props.value = detail.value || ev.target.textContent
|
}
|
||||||
|
|
||||||
|
this.props.value = elem.value
|
||||||
|
|
||||||
|
this._updateChildrenStat()
|
||||||
this.dispatchEvent(new CustomEvent('input'))
|
this.dispatchEvent(new CustomEvent('input'))
|
||||||
this.dispatchEvent(new CustomEvent('select', { detail }))
|
|
||||||
|
|
||||||
this.state.optionShow = false
|
this.state.optionShow = false
|
||||||
this.__OPTIONS__.classList.toggle('active', false)
|
this.__OPTIONS__.classList.toggle('active', false)
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
<template>
|
||||||
|
<label><slot /></label>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
height: 32px;
|
||||||
|
transition: background 0.15s linear;
|
||||||
|
color: var(--color-dark-1);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
label {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0 8px;
|
||||||
|
cursor: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:host(:hover),
|
||||||
|
:host([active]) {
|
||||||
|
label {
|
||||||
|
background: var(--color-plain-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:host([disabled]) {
|
||||||
|
color: var(--color-grey-1);
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import $ from '../utils'
|
||||||
|
export default class Option {
|
||||||
|
props = {
|
||||||
|
value: '',
|
||||||
|
label: '',
|
||||||
|
disabled: false
|
||||||
|
}
|
||||||
|
|
||||||
|
__init__() {
|
||||||
|
/* render */
|
||||||
|
}
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return this.props.value
|
||||||
|
}
|
||||||
|
|
||||||
|
set value(val) {
|
||||||
|
if (val === this.props.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.props.value = val
|
||||||
|
}
|
||||||
|
|
||||||
|
get label() {
|
||||||
|
return this.props.label
|
||||||
|
}
|
||||||
|
|
||||||
|
set label(val) {
|
||||||
|
if (val === this.props.label) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.props.label = val
|
||||||
|
}
|
||||||
|
|
||||||
|
get disabled() {
|
||||||
|
return this.props.disabled
|
||||||
|
}
|
||||||
|
|
||||||
|
set disabled(val) {
|
||||||
|
var type = typeof val
|
||||||
|
|
||||||
|
if (val === this.props.disabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ((type === 'boolean' && val) || type !== 'boolean') {
|
||||||
|
this.props.disabled = true
|
||||||
|
this.setAttribute('disabled', '')
|
||||||
|
} else {
|
||||||
|
this.props.disabled = false
|
||||||
|
this.removeAttribute('disabled')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this._clickFn = $.bind(this, 'click', ev => {
|
||||||
|
if (this.disabled) {
|
||||||
|
ev.stopPropagation()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
unmount() {
|
||||||
|
$.unbind(this, 'click', this._clickFn)
|
||||||
|
}
|
||||||
|
|
||||||
|
watch() {
|
||||||
|
switch (name) {
|
||||||
|
case 'value':
|
||||||
|
case 'label':
|
||||||
|
this[name] = val
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'disabled':
|
||||||
|
this.disabled = val !== null
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -239,7 +239,7 @@ export default class Radio {
|
||||||
}
|
}
|
||||||
|
|
||||||
this._handleClick = $.catch(this, 'click', ev => {
|
this._handleClick = $.catch(this, 'click', ev => {
|
||||||
ev.preventDefault()
|
ev.stopPropagation()
|
||||||
this._toggleCheck()
|
this._toggleCheck()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Reference in New Issue