mirror of
https://gitee.com/xuliangzhan_admin/vxe-table.git
synced 2026-01-21 05:27:57 +08:00
优化重构
This commit is contained in:
@@ -8,5 +8,5 @@ VxeSelect.install = function (Vue) {
|
||||
Vue.component(VxeOptgroup.name, VxeOptgroup)
|
||||
}
|
||||
|
||||
export const Select = VxeSelect
|
||||
export const Select111 = VxeSelect
|
||||
export default VxeSelect
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import VxeSelect from './src/select'
|
||||
import VxeOption from './src/option'
|
||||
import VxeOptgroup from './src/optgroup'
|
||||
|
||||
VxeSelect.install = function (Vue) {
|
||||
Vue.component(VxeSelect.name, VxeSelect)
|
||||
Vue.component(VxeOption.name, VxeOption)
|
||||
Vue.component(VxeOptgroup.name, VxeOptgroup)
|
||||
}
|
||||
|
||||
export const Select = VxeSelect
|
||||
export default VxeSelect
|
||||
@@ -1,43 +0,0 @@
|
||||
import { UtilTools } from '../../tools'
|
||||
|
||||
export default {
|
||||
name: 'VxeOptgroup',
|
||||
props: {
|
||||
label: [String, Number],
|
||||
disabled: Boolean,
|
||||
size: String
|
||||
},
|
||||
provide () {
|
||||
return {
|
||||
$xeoptgroup: this
|
||||
}
|
||||
},
|
||||
inject: {
|
||||
$xeselect: {
|
||||
default: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
vSize () {
|
||||
return this.size || this.$parent.size || this.$parent.vSize
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.$xeselect.updateStatus()
|
||||
},
|
||||
destroyed () {
|
||||
this.$xeselect.updateStatus()
|
||||
},
|
||||
render (h) {
|
||||
return h('div', {
|
||||
class: 'vxe-optgroup'
|
||||
}, [
|
||||
h('div', {
|
||||
class: 'vxe-optgroup--title'
|
||||
}, UtilTools.getFuncText(this.label)),
|
||||
h('div', {
|
||||
class: 'vxe-optgroup--wrapper'
|
||||
}, this.$slots.default)
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
import { UtilTools } from '../../tools'
|
||||
|
||||
let optionUniqueId = 0
|
||||
|
||||
export default {
|
||||
name: 'VxeOption',
|
||||
props: {
|
||||
value: [String, Number],
|
||||
label: [String, Number],
|
||||
disabled: Boolean,
|
||||
size: String
|
||||
},
|
||||
inject: {
|
||||
$xeselect: {
|
||||
default: null
|
||||
},
|
||||
$xeoptgroup: {
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
id: `option_${++optionUniqueId}`
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
vSize () {
|
||||
return this.size || this.$parent.size || this.$parent.vSize
|
||||
},
|
||||
isDisabled () {
|
||||
const { $xeoptgroup, disabled } = this
|
||||
return ($xeoptgroup && $xeoptgroup.disabled) || disabled
|
||||
}
|
||||
},
|
||||
warch: {
|
||||
value () {
|
||||
this.updateView()
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.updateView()
|
||||
},
|
||||
destroyed () {
|
||||
this.updateView()
|
||||
},
|
||||
render (h) {
|
||||
const { $xeselect, id, isDisabled, value } = this
|
||||
return h('div', {
|
||||
class: ['vxe-select-option', {
|
||||
'is--disabled': isDisabled,
|
||||
'is--checked': $xeselect.value === value,
|
||||
'is--hover': $xeselect.currentValue === value
|
||||
}],
|
||||
attrs: {
|
||||
'data-option-id': id
|
||||
},
|
||||
on: {
|
||||
click: this.optionEvent,
|
||||
mouseenter: this.mouseenterEvent
|
||||
}
|
||||
}, UtilTools.getFuncText(this.label))
|
||||
},
|
||||
methods: {
|
||||
updateView () {
|
||||
this.$xeselect.updateStatus()
|
||||
},
|
||||
optionEvent (evnt) {
|
||||
this.$xeselect.changeOptionEvent(evnt, this.value)
|
||||
},
|
||||
mouseenterEvent () {
|
||||
this.$xeselect.setCurrentOption(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,387 +0,0 @@
|
||||
import VxeInput from '../../input'
|
||||
import GlobalConfig from '../../conf'
|
||||
import { UtilTools, DomTools, GlobalEvent } from '../../tools'
|
||||
|
||||
function findOffsetOption (groupList, optionValue, isUpArrow) {
|
||||
let prevOption
|
||||
let firstOption
|
||||
let isMatchOption = false
|
||||
for (let gIndex = 0; gIndex < groupList.length; gIndex++) {
|
||||
const group = groupList[gIndex]
|
||||
if (group.children.length) {
|
||||
for (let index = 0; index < group.children.length; index++) {
|
||||
const comp = group.children[index]
|
||||
if (!firstOption) {
|
||||
firstOption = comp
|
||||
}
|
||||
if (isUpArrow) {
|
||||
if (optionValue === comp.value) {
|
||||
return { offsetOption: prevOption, firstOption }
|
||||
}
|
||||
} else {
|
||||
if (isMatchOption) {
|
||||
return { offsetOption: comp, firstOption }
|
||||
}
|
||||
if (optionValue === comp.value) {
|
||||
isMatchOption = true
|
||||
}
|
||||
}
|
||||
prevOption = comp
|
||||
}
|
||||
} else {
|
||||
const comp = group.comp
|
||||
if (!firstOption) {
|
||||
firstOption = comp
|
||||
}
|
||||
if (isUpArrow) {
|
||||
if (optionValue === comp.value) {
|
||||
return { offsetOption: prevOption, firstOption }
|
||||
}
|
||||
} else {
|
||||
if (isMatchOption) {
|
||||
return { offsetOption: comp, firstOption }
|
||||
}
|
||||
if (optionValue === comp.value) {
|
||||
isMatchOption = true
|
||||
}
|
||||
}
|
||||
prevOption = comp
|
||||
}
|
||||
}
|
||||
return { firstOption }
|
||||
}
|
||||
|
||||
function findOption (groupList, optionValue) {
|
||||
for (let gIndex = 0; gIndex < groupList.length; gIndex++) {
|
||||
const group = groupList[gIndex]
|
||||
if (group.children.length) {
|
||||
for (let index = 0; index < group.children.length; index++) {
|
||||
const comp = group.children[index]
|
||||
if (optionValue === comp.value) {
|
||||
return comp
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (optionValue === group.comp.value) {
|
||||
return group.comp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'VxeSelect',
|
||||
props: {
|
||||
value: [String, Number],
|
||||
clearable: Boolean,
|
||||
placeholder: String,
|
||||
disabled: Boolean,
|
||||
prefixIcon: String,
|
||||
placement: String,
|
||||
size: String,
|
||||
transfer: { type: Boolean, default: () => GlobalConfig.select.transfer }
|
||||
},
|
||||
components: {
|
||||
VxeInput
|
||||
},
|
||||
provide () {
|
||||
return {
|
||||
$xeselect: this
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 使用技巧去更新视图
|
||||
updateFlag: 0,
|
||||
panelIndex: 0,
|
||||
panelStyle: null,
|
||||
panelPlacement: null,
|
||||
currentValue: null,
|
||||
showPanel: false,
|
||||
animatVisible: false,
|
||||
isActivated: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
vSize () {
|
||||
return this.size || this.$parent.size || this.$parent.vSize
|
||||
},
|
||||
selectLabel () {
|
||||
if (this.updateFlag) {
|
||||
const selectOption = findOption(this.getOptions(), this.value)
|
||||
if (selectOption) {
|
||||
return selectOption.label
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.panelIndex = UtilTools.nextZIndex()
|
||||
GlobalEvent.on(this, 'mousedown', this.handleGlobalMousedownEvent)
|
||||
GlobalEvent.on(this, 'keydown', this.handleGlobalKeydownEvent)
|
||||
GlobalEvent.on(this, 'mousewheel', this.handleGlobalMousewheelEvent)
|
||||
GlobalEvent.on(this, 'blur', this.handleGlobalBlurEvent)
|
||||
},
|
||||
mounted () {
|
||||
if (this.transfer) {
|
||||
document.body.appendChild(this.$refs.panel)
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
const panelElem = this.$refs.panel
|
||||
if (panelElem && panelElem.parentNode) {
|
||||
panelElem.parentNode.removeChild(panelElem)
|
||||
}
|
||||
},
|
||||
destroyed () {
|
||||
GlobalEvent.off(this, 'mousedown')
|
||||
GlobalEvent.off(this, 'keydown')
|
||||
GlobalEvent.off(this, 'mousewheel')
|
||||
GlobalEvent.off(this, 'blur')
|
||||
},
|
||||
render (h) {
|
||||
const { vSize, transfer, isActivated, disabled, clearable, placeholder, selectLabel, animatVisible, showPanel, panelStyle, prefixIcon, panelPlacement } = this
|
||||
return h('div', {
|
||||
class: ['vxe-select', {
|
||||
[`size--${vSize}`]: vSize,
|
||||
'is--visivle': showPanel,
|
||||
'is--disabled': disabled,
|
||||
'is--active': isActivated
|
||||
}]
|
||||
}, [
|
||||
h('vxe-input', {
|
||||
ref: 'input',
|
||||
props: {
|
||||
clearable,
|
||||
placeholder,
|
||||
readonly: true,
|
||||
disabled: disabled,
|
||||
type: 'text',
|
||||
prefixIcon: prefixIcon,
|
||||
suffixIcon: `vxe-icon--caret-bottom${showPanel ? ' rotate180' : ''}`,
|
||||
value: selectLabel
|
||||
},
|
||||
on: {
|
||||
clear: this.clearEvent,
|
||||
click: this.togglePanelEvent,
|
||||
focus: this.focusEvent,
|
||||
'suffix-click': this.togglePanelEvent
|
||||
}
|
||||
}),
|
||||
h('div', {
|
||||
ref: 'panel',
|
||||
class: ['vxe-select-option--panel', {
|
||||
[`size--${vSize}`]: vSize,
|
||||
'is--transfer': transfer,
|
||||
'animat--leave': animatVisible,
|
||||
'animat--enter': showPanel
|
||||
}],
|
||||
attrs: {
|
||||
'data-placement': panelPlacement
|
||||
},
|
||||
style: panelStyle
|
||||
}, [
|
||||
h('div', {
|
||||
class: 'vxe-select-option--wrapper'
|
||||
}, this.$slots.default)
|
||||
])
|
||||
])
|
||||
},
|
||||
methods: {
|
||||
getOptions () {
|
||||
const options = []
|
||||
if (!this.disabled) {
|
||||
this.$children.forEach(option => {
|
||||
if (!option.isDisabled && option.$xeselect) {
|
||||
let children = option.$children
|
||||
if (children.length) {
|
||||
children = children.filter(option => !option.isDisabled && option.$xeselect && option.$xeoptgroup)
|
||||
if (children.length) {
|
||||
options.push({ comp: option, children })
|
||||
}
|
||||
} else {
|
||||
options.push({ comp: option, children })
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return options
|
||||
},
|
||||
updateStatus () {
|
||||
this.updateFlag++
|
||||
},
|
||||
setCurrentOption (option) {
|
||||
if (option) {
|
||||
this.currentValue = option.value
|
||||
this.$nextTick(() => {
|
||||
DomTools.toView(this.$refs.panel.querySelector(`[data-option-id='${option.id}']`))
|
||||
})
|
||||
}
|
||||
},
|
||||
clearEvent (params, evnt) {
|
||||
this.clearValueEvent(evnt, null)
|
||||
this.hideOptionPanel()
|
||||
},
|
||||
clearValueEvent (evnt, selectValue) {
|
||||
this.changeEvent(evnt, selectValue)
|
||||
this.$emit('clear', { value: selectValue }, evnt)
|
||||
},
|
||||
changeEvent (evnt, selectValue) {
|
||||
if (selectValue !== this.value) {
|
||||
this.$emit('input', selectValue)
|
||||
this.$emit('change', { value: selectValue }, evnt)
|
||||
}
|
||||
},
|
||||
changeOptionEvent (evnt, selectValue) {
|
||||
this.changeEvent(evnt, selectValue)
|
||||
this.hideOptionPanel()
|
||||
},
|
||||
handleGlobalMousedownEvent (evnt) {
|
||||
if (!this.disabled) {
|
||||
if (this.showPanel && !(DomTools.getEventTargetNode(evnt, this.$el).flag || DomTools.getEventTargetNode(evnt, this.$refs.panel).flag)) {
|
||||
this.hideOptionPanel()
|
||||
}
|
||||
this.isActivated = DomTools.getEventTargetNode(evnt, this.$el).flag || DomTools.getEventTargetNode(evnt, this.$refs.panel).flag
|
||||
}
|
||||
},
|
||||
handleGlobalKeydownEvent (evnt) {
|
||||
const { showPanel, currentValue, clearable, disabled } = this
|
||||
if (!disabled) {
|
||||
const keyCode = evnt.keyCode
|
||||
const isTab = keyCode === 9
|
||||
const isEnter = keyCode === 13
|
||||
const isUpArrow = keyCode === 38
|
||||
const isDwArrow = keyCode === 40
|
||||
const isDel = keyCode === 46
|
||||
if (isTab) {
|
||||
this.isActivated = false
|
||||
}
|
||||
if (showPanel) {
|
||||
if (isTab) {
|
||||
this.hideOptionPanel()
|
||||
} else if (isEnter) {
|
||||
this.changeOptionEvent(evnt, currentValue)
|
||||
} else if (isUpArrow || isDwArrow) {
|
||||
evnt.preventDefault()
|
||||
const groupList = this.getOptions()
|
||||
let { offsetOption, firstOption } = findOffsetOption(groupList, currentValue, isUpArrow)
|
||||
if (!offsetOption && !findOption(groupList, currentValue)) {
|
||||
offsetOption = firstOption
|
||||
}
|
||||
this.setCurrentOption(offsetOption)
|
||||
}
|
||||
} else if (isEnter && this.isActivated) {
|
||||
this.showOptionPanel()
|
||||
}
|
||||
if (isDel && clearable && this.isActivated) {
|
||||
this.clearValueEvent(evnt, null)
|
||||
}
|
||||
}
|
||||
},
|
||||
handleGlobalMousewheelEvent (evnt) {
|
||||
if (!DomTools.getEventTargetNode(evnt, this.$el).flag && !DomTools.getEventTargetNode(evnt, this.$refs.panel).flag) {
|
||||
this.hideOptionPanel()
|
||||
}
|
||||
},
|
||||
handleGlobalBlurEvent () {
|
||||
this.hideOptionPanel()
|
||||
},
|
||||
updateZindex () {
|
||||
if (this.panelIndex < UtilTools.getLastZIndex()) {
|
||||
this.panelIndex = UtilTools.nextZIndex()
|
||||
}
|
||||
},
|
||||
focusEvent () {
|
||||
if (!this.disabled) {
|
||||
this.isActivated = true
|
||||
}
|
||||
},
|
||||
togglePanelEvent (params, evnt) {
|
||||
evnt.preventDefault()
|
||||
if (this.showPanel) {
|
||||
this.hideOptionPanel()
|
||||
} else {
|
||||
this.showOptionPanel()
|
||||
}
|
||||
},
|
||||
showOptionPanel () {
|
||||
if (!this.disabled) {
|
||||
this.isActivated = true
|
||||
this.animatVisible = true
|
||||
setTimeout(() => {
|
||||
this.showPanel = true
|
||||
this.setCurrentOption(findOption(this.getOptions(), this.value))
|
||||
}, 10)
|
||||
this.updateZindex()
|
||||
this.updatePlacement()
|
||||
}
|
||||
},
|
||||
hideOptionPanel () {
|
||||
this.showPanel = false
|
||||
setTimeout(() => {
|
||||
this.animatVisible = false
|
||||
}, 200)
|
||||
},
|
||||
updatePlacement () {
|
||||
this.$nextTick(() => {
|
||||
const { $refs, transfer, placement, panelIndex } = this
|
||||
const inputElem = $refs.input.$el
|
||||
const panelElem = $refs.panel
|
||||
const inputHeight = inputElem.offsetHeight
|
||||
const inputWidth = inputElem.offsetWidth
|
||||
const panelHeight = panelElem.offsetHeight
|
||||
const panelStyle = {
|
||||
zIndex: panelIndex
|
||||
}
|
||||
const { boundingTop, boundingLeft, visibleHeight } = DomTools.getAbsolutePos(inputElem)
|
||||
let panelPlacement = 'bottom'
|
||||
if (transfer) {
|
||||
const left = boundingLeft
|
||||
let top = boundingTop + inputHeight
|
||||
if (placement === 'top') {
|
||||
panelPlacement = 'top'
|
||||
top = boundingTop - panelHeight
|
||||
} else {
|
||||
// 如果下面不够放,则向上
|
||||
if (top + panelHeight > visibleHeight) {
|
||||
panelPlacement = 'top'
|
||||
top = boundingTop - panelHeight
|
||||
}
|
||||
// 如果上面不够放,则向下(优先)
|
||||
if (top < 0) {
|
||||
panelPlacement = 'bottom'
|
||||
top = boundingTop + inputHeight
|
||||
}
|
||||
}
|
||||
Object.assign(panelStyle, {
|
||||
left: `${left}px`,
|
||||
top: `${top}px`,
|
||||
minWidth: `${inputWidth}px`
|
||||
})
|
||||
} else {
|
||||
if (placement === 'top') {
|
||||
panelPlacement = 'top'
|
||||
panelStyle.bottom = `${inputHeight}px`
|
||||
} else {
|
||||
// 如果下面不够放,则向上
|
||||
if (boundingTop + inputHeight + panelHeight > visibleHeight) {
|
||||
panelPlacement = 'top'
|
||||
panelStyle.bottom = `${inputHeight}px`
|
||||
}
|
||||
}
|
||||
}
|
||||
this.panelStyle = panelStyle
|
||||
this.panelPlacement = panelPlacement
|
||||
})
|
||||
},
|
||||
focus () {
|
||||
this.showOptionPanel()
|
||||
return this.$nextTick()
|
||||
},
|
||||
blur () {
|
||||
this.hideOptionPanel()
|
||||
return this.$nextTick()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user