You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

314 lines
10 KiB

import classNames from './classNames'
import eventsMixin from './eventsMixin'
const DEFAULT_TRIGGER = 'onClick'
const CELL_NAME = '../cell/index'
const FIELD_NAME = '../field/index'
const defaultToolbar = {
title: '请选择',
cancelText: '取消',
confirmText: '确定',
}
const defaultEvents = {
onChange() {},
onConfirm() {},
onCancel() {},
onVisibleChange() {},
onValueChange() {},
}
const defaultPlatformProps = {
labelPropName: 'label',
format(values, props) {
return Array.isArray(values.displayValue) ? values.displayValue.join(',') : values.displayValue
},
}
const defaultFieldNames = {
label: 'label',
value: 'value',
children: 'children',
}
export default function popupMixin(selector = '#wux-picker', platformProps = defaultPlatformProps) {
return Behavior({
behaviors: [eventsMixin({ defaultEvents })],
properties: {
toolbar: {
type: Object,
value: defaultToolbar,
},
trigger: {
type: String,
value: DEFAULT_TRIGGER,
},
defaultVisible: {
type: Boolean,
value: false,
},
visible: {
type: Boolean,
value: false,
},
controlled: {
type: Boolean,
value: false,
},
disabled: {
type: Boolean,
value: false,
},
},
data: {
mounted: false,
popupVisible: false,
inputValue: [],
},
methods: {
/**
* 设置组件显示或隐藏
*/
setVisibleState(popupVisible, callback = () => {}) {
if (this.data.popupVisible !== popupVisible) {
const params = {
mounted: true,
inputValue: this.data.value, // forceUpdate
popupVisible,
}
this.setData(popupVisible ? params : { popupVisible }, () => {
// collect field component & forceUpdate
if (popupVisible && this.hasFieldDecorator) {
const field = this.getFieldElem()
if (field) {
field.changeValue(field.data.value)
}
}
callback()
})
}
},
/**
* 触发 visibleChange 事件
*/
fireVisibleChange(popupVisible) {
if (this.data.popupVisible !== popupVisible) {
if (!this.data.controlled) {
this.setVisibleState(popupVisible)
}
this.setScrollValue(undefined)
this.triggerEvent('visibleChange', { visible: popupVisible })
}
},
/**
* 打开
*/
open() {
this.fireVisibleChange(true)
},
/**
* 关闭
*/
close(callback) {
if (typeof callback === 'function') {
const values = this.getPickerValue(this.scrollValue || this.data.inputValue)
callback.call(this, this.formatPickerValue(values))
}
this.fireVisibleChange(false)
},
/**
* 组件关闭时重置其内部数据
*/
onClosed() {
this.picker = null
this.setData({ mounted: false, inputValue: null })
},
/**
* 点击确定按钮时的回调函数
*/
onConfirm() {
this.close((values) => {
this.triggerEvent('change', values) // collect field component
this.triggerEvent('confirm', values)
})
},
/**
* 点击取消按钮时的回调函数
*/
onCancel() {
this.close((values) => this.triggerEvent('cancel', values))
},
/**
* 每列数据选择变化后的回调函数
*/
onValueChange(e) {
if (!this.data.mounted) return
const { value } = e.detail
if (this.data.cascade) {
this.setCasecadeScrollValue(value)
} else {
this.setScrollValue(value)
}
this.updated(value, true)
this.triggerEvent('valueChange', this.formatPickerValue(e.detail))
},
/**
* 获取当前 picker 的值
*/
getPickerValue(value = this.data.inputValue) {
this.picker = this.picker || this.selectComponent(selector)
return this.picker && this.picker.getValue(value)
},
/**
* 格式化 picker 返回值
*/
formatPickerValue(values) {
return {
...values,
[platformProps.labelPropName]: platformProps.format(values, this.data),
}
},
/**
* 获取 field 父元素
*/
getFieldElem() {
return this.field = (this.field || this.getRelationNodes(FIELD_NAME)[0])
},
/**
* 设置子元素 props
*/
setChildProps() {
if (this.data.disabled) return
const elements = this.getRelationNodes(CELL_NAME)
const { trigger = DEFAULT_TRIGGER } = this.data
if (elements.length > 0) {
elements.forEach((inputElem) => {
const { inputEvents } = inputElem.data
const oriInputEvents = inputElem.data.oriInputEvents || { ...inputEvents }
inputEvents[trigger] = (...args) => {
if (oriInputEvents && oriInputEvents[trigger]) {
oriInputEvents[trigger](...args)
}
this.onTriggerClick()
}
inputElem.setData({ oriInputEvents, inputEvents })
})
}
},
/**
* 触发事件
*/
onTriggerClick() {
this.fireVisibleChange(!this.data.popupVisible)
},
/**
* 阻止移动触摸
*/
noop() {},
/**
* 更新值
*/
updated(inputValue, isForce) {
if (!this.hasFieldDecorator || isForce) {
if (this.data.inputValue !== inputValue) {
this.setData({ inputValue })
}
}
},
/**
* 记录每列数据的变化值
*/
setScrollValue(value) {
this.scrollValue = value
},
/**
* 记录每列数据的变化值 - 针对于级联
*/
setCasecadeScrollValue(value) {
if (value && this.scrollValue) {
const length = this.scrollValue.length
if (length === value.length && this.scrollValue[length - 1] === value[length - 1]) {
return
}
}
this.setScrollValue(value)
},
},
lifetimes: {
ready() {
const { defaultVisible, visible, controlled, value } = this.data
const popupVisible = controlled ? visible : defaultVisible
// 若 defaultFieldNames 存在,则缓存之,并传递给子组件,只生效一次
if ('defaultFieldNames' in this.data) {
this.setData({
fieldNames: Object.assign({}, defaultFieldNames, this.data.defaultFieldNames),
})
}
this.mounted = true
this.scrollValue = undefined
this.setVisibleState(popupVisible)
this.setChildProps()
},
detached() {
this.mounted = false
},
},
definitionFilter(defFields) {
// set default child
Object.assign(defFields.relations = (defFields.relations || {}), {
[CELL_NAME]: {
type: 'child',
observer() {
this.setChildProps()
},
},
[FIELD_NAME]: {
type: 'ancestor',
},
})
// set default classes
Object.assign(defFields.computed = (defFields.computed || {}), {
classes: ['prefixCls', function(prefixCls) {
const wrap = classNames(prefixCls)
const toolbar = `${prefixCls}__toolbar`
const inner = `${prefixCls}__inner`
const cancel = classNames(`${prefixCls}__button`, {
[`${prefixCls}__button--cancel`]: true,
})
const confirm = classNames(`${prefixCls}__button`, {
[`${prefixCls}__button--confirm`]: true,
})
const hover = `${prefixCls}__button--hover`
const title = `${prefixCls}__title`
return {
wrap,
toolbar,
inner,
cancel,
confirm,
hover,
title,
}
}],
})
// set default observers
Object.assign(defFields.observers = (defFields.observers || {}), {
visible(popupVisible) {
if (this.data.controlled) {
this.setVisibleState(popupVisible)
}
},
value(value) {
this.updated(value)
},
})
},
})
}