This repository has been archived on 2023-08-30. You can view files and clone it, but cannot push or open issues/pull-requests.
bytedo
/
wcui
Archived
1
0
Fork 0

完成input组件

old
宇天 2019-07-25 10:54:55 +08:00
parent b6a8996c69
commit 97db6283eb
1 changed files with 109 additions and 59 deletions

View File

@ -5,7 +5,9 @@
<wc-icon class="icon"></wc-icon> <wc-icon class="icon"></wc-icon>
<slot class="append" name="append"></slot> <slot class="append" name="append"></slot>
<ul class="suggestion"></ul> <div class="suggestion">
<ul class="list"></ul>
</div>
</div> </div>
</template> </template>
@ -98,12 +100,19 @@ li {
top: 50px; top: 50px;
width: 100%; width: 100%;
height: auto; height: auto;
max-height: 200px;
min-height: 46px; min-height: 46px;
padding: 8px 0; padding: 8px 0;
border-radius: 4px; border-radius: 4px;
background: #fff; background: #fff;
box-shadow: 0 0 3px rgba(0, 0, 0, 0.2); box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
.list {
overflow: hidden;
overflow-y: auto;
width: 100%;
}
&::after { &::after {
position: absolute; position: absolute;
left: 30px; left: 30px;
@ -116,7 +125,7 @@ li {
content: ''; content: '';
} }
&.show { &.show {
display: block; display: flex;
} }
li { li {
@ -129,7 +138,8 @@ li {
white-space: nowrap; white-space: nowrap;
cursor: pointer; cursor: pointer;
&:hover { &:hover,
&[focus] {
background: nth($cp, 1); background: nth($cp, 1);
} }
} }
@ -225,6 +235,7 @@ export default class Input {
type: 'text', type: 'text',
label: '', label: '',
placeholder: '', placeholder: '',
mvidx: null, //下拉列表光标的索引ID
autofocus: false, autofocus: false,
readonly: false, readonly: false,
disabled: false disabled: false
@ -311,20 +322,43 @@ export default class Input {
} }
} }
_parseSuggestion() { // 移动光标选择下拉选项
var { list } = this.props _moveSelect(ev) {
if (list && list.length) { ev.preventDefault()
var html = list var step = ev.keyCode === 38 ? -1 : 1
.map((it, i) => `<li data-idx="${i}">${it.value}</li>`) var items = Array.from(this.__LIST__.firstElementChild.children)
.join('') if (this.props.mvidx === null) {
this.__LIST__.innerHTML = html this.props.mvidx = 0
this.__LIST__.classList.toggle('show', true)
} else { } else {
this.__LIST__.classList.toggle('show', false) this.props.mvidx += step
} }
if (this.props.mvidx < 0) {
this.props.mvidx = 0
} else if (this.props.mvidx > items.length - 1) {
this.props.mvidx = items.length - 1
}
items.forEach((it, i) => {
if (i === this.props.mvidx) {
it.setAttribute('focus', '')
} else {
it.removeAttribute('focus')
}
})
} }
_moveSelect() {} // 触发列表选择
_fetchSelect(idx, ev) {
var item = this.props.list[idx]
this.value = item.value
this.dispatchEvent(
new CustomEvent('select', {
detail: item
})
)
this._handleChange(ev)
this.__LIST__.classList.remove('show')
this.props.mvidx = null
}
mounted() { mounted() {
var prepend = this.__PREPEND__.assignedNodes() var prepend = this.__PREPEND__.assignedNodes()
@ -347,39 +381,49 @@ export default class Input {
var { type } = this.props var { type } = this.props
// 回车事件
this._handleSubmit = ev => { this._handleSubmit = ev => {
if (this.disabled || this.readonly) { if (this.disabled || this.readonly) {
ev.cancelBubble = true ev.cancelBubble = true
return return
} }
// up: 38, down: 40 // up: 38, down: 40
log(ev.keyCode)
if (ev.keyCode === 38 || ev.keyCode === 40) { if (ev.keyCode === 38 || ev.keyCode === 40) {
ev.preventDefault() // 仅普通文本表单, 密码和多行文本框不做响应
return if (this.type === 'text') {
return this._moveSelect(ev)
}
} }
// 回车触发submit事件 // 回车触发submit事件
// textarea 要按Ctrl Or Cmd键, 才会触发 // textarea 要按Ctrl Or Cmd键, 才会触发
if ( if (ev.keyCode === 13) {
ev.keyCode === 13 && // 如果是输入建议存在,则第1次回车的时候, 不触发提交
(type === 'text' || (type === 'textarea' && (ev.ctrlKey || ev.metaKey))) if (this.type === 'text' && this.props.mvidx !== null) {
) { return this._fetchSelect(this.props.mvidx, ev)
this.dispatchEvent( }
new CustomEvent('submit', {
detail: this.value //
}) if (
) type === 'text' ||
(type === 'textarea' && (ev.ctrlKey || ev.metaKey))
) {
this.dispatchEvent(
new CustomEvent('submit', {
detail: this.value
})
)
}
} }
} }
// 输入状态事件
this._handleChange = ev => { this._handleChange = ev => {
ev.preventDefault()
this.dispatchEvent( this.dispatchEvent(
new CustomEvent('fetch-suggestions', { new CustomEvent('fetch-suggestions', {
detail: { detail: {
value: this.value, value: this.value,
send: list => { send: list => {
log('----', list)
this.props.list = list this.props.list = list
this._parseSuggestion() this._parseSuggestion()
} }
@ -388,49 +432,51 @@ export default class Input {
) )
} }
// 渲染建议列表
this._parseSuggestion = ev => {
var { list } = this.props
if (list && list.length) {
var html = list
.map((it, i) => `<li data-idx="${i}">${it.value}</li>`)
.join('')
this.__LIST__.firstElementChild.innerHTML = html
this.__LIST__.classList.toggle('show', true)
} else {
this.__LIST__.classList.toggle('show', false)
}
}
// 失去焦点
this._handleBlur = ev => {
setTimeout(() => {
this.__LIST__.classList.remove('show')
}, 50)
}
// 选择建议
this._handleSelect = ev => {
if (ev.target.tagName === 'LI') {
this._fetchSelect(ev.target.dataset.idx, ev)
}
}
this.__INPUT__.addEventListener('keydown', this._handleSubmit, false) this.__INPUT__.addEventListener('keydown', this._handleSubmit, false)
// 非textarea, 可做输入建议功能 // 非textarea, 可做输入建议功能
if (type === 'text') { if (type === 'text') {
this.__INPUT__.addEventListener('input', this._handleChange, false) this.__INPUT__.addEventListener('input', this._handleChange, false)
this.__INPUT__.addEventListener( this.__INPUT__.addEventListener('focus', this._parseSuggestion, false)
'focus', // this.__INPUT__.addEventListener('blur', this._handleBlur, false)
this._parseSuggestion.bind(this), this.__LIST__.addEventListener('click', this._handleSelect, false)
false
)
this.__INPUT__.addEventListener(
'blur',
ev => {
setTimeout(() => {
this.__LIST__.classList.remove('show')
}, 50)
},
false
)
this.__LIST__.addEventListener(
'click',
ev => {
this.__LIST__.classList.remove('show')
if (ev.target.tagName === 'LI') {
var idx = ev.target.dataset.idx
var item = this.props.list[idx]
this.value = item.value
this.dispatchEvent(
new CustomEvent('select', {
detail: item
})
)
}
},
false
)
} }
} }
unmount() { unmount() {
this.__INPUT__.removeEventListener('keydown', this._handleSubmit) this.__INPUT__.removeEventListener('keydown', this._handleSubmit)
this.__INPUT__.removeEventListener('input', this._handleChange) this.__INPUT__.removeEventListener('input', this._handleChange)
this.__INPUT__.removeEventListener('focus', this._parseSuggestion)
this.__INPUT__.removeEventListener('blur', this._handleBlur)
this.__LIST__.removeEventListener('click', this._handleSelect)
} }
watch(name, old, val) { watch(name, old, val) {
@ -472,6 +518,10 @@ export default class Input {
} }
break break
case 'value':
this.value = val
break
case 'readonly': case 'readonly':
case 'disabled': case 'disabled':
if (val === '') { if (val === '') {