效果如下
<uni-popup ref="bankListAll" type="dialog"> <ty-mutiple-select :multiple="false" v-model="selectedBank" :selectData="bankListAll" :duration="2000" :before-close="true" @change="mutiple_select_change" @close="close_bank_list" @confirm="selectedBankConfirm" title="请选择题库" type="input" mode="input" > </ty-mutiple-select> </uni-popup>
<listBar :list="bankList" :select_item="selectedBank" @click_item="click_bar" :is_more="isBankListMore" />
click_bar(item) { if(item === 'more') { uni.showLoading({ title:'正在加载...' }); getBankList({type: 'all'}) .then(({data}) => { this.$refs.bankListAll.open() this.bankListAll = [] data.map(item => { this.bankListAll.push({ value: item.id, label: item.name }) }) }) .finally(() => { uni.hideLoading(); }); }else{ this.selectedBank = item } }, mutiple_select_change: function({detail}) { this.selectedBank = detail.data },
//组件一 <template> <view class="list-container"> <view class="list-bar"> <text v-for="(item, index) in list" :key="index" class="item" :class="{active: select_item.value === item.value}" @click="click_item(item)">{{item.label}}</text> <text v-if="is_more" @click="click_item('more')" class="item" style="text-decoration: underline;">更多</text> </view> </view> </template> <script> export default { name: 'listBar', props: { list: { type: Array, default: [] }, select_item: { type: Object, default: {} }, is_more: { type: Boolean, default: false } }, methods: { click_item(item) { this.$emit('click_item', item) } } } </script> <style lang="scss" scoped> .list-container { 100%; height: 100rpx; overflow-x: scroll; &::-webkit-scrollbar { /*隐藏滚轮*/ display: none; } &::scrollbar { /*隐藏滚轮*/ display: none; } .list-bar{ display: block; auto; white-space: nowrap; vertical-align: middle; line-height: 100rpx; padding: 0 10rpx; .item { height: 32rpx; font-size: 32rpx; font-weight: 400; color: #666666; line-height: 32rpx; white-space: nowrap; display: inline-block; margin: 30rpx 20rpx; } .active{ color: #4A80FF; font-weight: 600; } } } </style>
//组件二 <template> <view class="uni-popup-dialog"> <view class="uni-dialog-title"> <text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{title}}</text> </view> <view class="uni-dialog-content"> <checkbox-group v-if="multiple" class="checklist-group" :class="{'is-list': true,'is-wrap':true}" @change="chagne"> <label class="checklist-box" :class="item.labelClass" :style="[item.styleBackgroud]" v-for="(item,index) in dataList" :key="index"> <checkbox class="hidden" hidden :value="item.value+''" :checked="item.selected" /> <view class="checkbox__inner" :class="item.checkboxBgClass" :style="[item.styleIcon]"> <view class="checkbox__inner-icon" :class="item.checkboxClass"></view> </view> <view class="checklist-content list-content"> <text class="checklist-text" :class="item.textClass" :style="[item.styleIconText]">{{item.label}}</text> <view v-if="icon === 'right'" class="checkobx__list" :class="item.listClass" :style="[item.styleBackgroud]"></view> </view> </label> </checkbox-group> <radio-group v-else class="checklist-group is-list is-wrap" @change="chagne"> <label v-for="(item,index) in dataList" :key="index" class="checklist-box" :class="item.labelClass" :style="[item.styleBackgroud]"> <radio hidden :disabled="item.disabled" :value="item.value+''" :checked="item.selected" /> <view v-if="(mode !=='tag' && mode !== 'list') || ( mode === 'list' && icon === 'left')" class="radio__inner" :class="item.checkboxBgClass" :style="[item.styleBackgroud]"> <view class="radio__inner-icon" :class="item.checkboxClass" :style="[item.styleIcon]"></view> </view> <view class="checklist-content" :class="{'list-content':mode === 'list' && icon ==='left'}"> <text class="checklist-text" :class="item.textClass" :style="[item.styleIconText]">{{item.label}}</text> <view v-if="mode === 'list' && icon === 'right'" class="checkobx__list" :class="item.listClass" :style="[item.styleRightIcon]"></view> </view> </label> </radio-group> </view> <view class="uni-dialog-button-group"> <view class="uni-dialog-button" @click="close"> <text class="uni-dialog-button-text">取消</text> </view> <view class="uni-dialog-button uni-border-left" @click="onOk"> <text class="uni-dialog-button-text uni-button-color">确定</text> </view> </view> </view> </template> <script> /** * PopUp 弹出层-对话框样式 * @description 弹出层-对话框样式 * @tutorial https://ext.dcloud.net.cn/plugin?id=329 * @property {String} value input 模式下的默认值 * @property {String} placeholder input 模式下输入提示 * @property {String} type = [success|warning|info|error] 主题样式 * @value success 成功 * @value warning 提示 * @value info 消息 * @value error 错误 * @property {String} mode = [base|input] 模式、 * @value base 基础对话框 * @value input 可输入对话框 * @property {String} content 对话框内容 * @property {Boolean} beforeClose 是否拦截取消事件 * @event {Function} confirm 点击确认按钮触发 * @event {Function} close 点击取消按钮触发 */ import clientdb from './clientdb.js' export default { name: "uniPopupDialog", props: { selectData: { type: Array, default () { return [] } }, placeholder: { type: [String, Number], default: '请输入内容' }, /** * 对话框主题 success/warning/info/error 默认 success */ type: { type: String, default: 'error' }, /** * 对话框模式 base/input */ mode: { type: String, default: 'base' }, /** * 对话框标题 */ title: { type: String, default: '提示' }, /** * 对话框内容 */ content: { type: String, default: '' }, /** * 拦截取消事件 ,如果拦截取消事件,必须监听close事件,执行 done() */ beforeClose: { type: Boolean, default: false }, //select multiple: { type: Boolean, default: false }, value: { type: [Object,Array, String, Number], default () { return '' } }, min: { type: [Number, String], default: '' }, max: { type: [Number, String], default: '' }, wrap: { type: Boolean, default: false }, icon: { type: String, default: 'left' }, selectedColor:{ type: String, default: '' }, selectedTextColor:{ type: String, default: '' }, // clientDB 相关 options: { type: [Object, Array], default () { return {} } }, collection: { type: String, default: '' }, action: { type: String, default: '' }, field: { type: String, default: '' }, pageData: { type: String, default: 'add' }, pageCurrent: { type: Number, default: 1 }, pageSize: { type: Number, default: 20 }, getcount: { type: [Boolean, String], default: false }, orderby: { type: String, default: '' }, where: { type: [String, Object], default: '' }, getone: { type: [Boolean, String], default: false }, manual: { type: Boolean, default: false } }, data() { return { dialogType: 'error', focus: false, val: "", //select dataList: [], range: [], contentText: { contentdown: '查看更多', contentrefresh: '加载中', contentnomore: '没有更多' }, styles: { selectedColor: '#007aff', selectedTextColor: '#333', } } }, inject: ['popup'], watch: { type(val) { this.dialogType = val }, mode(val) { if (val === 'input') { this.dialogType = 'info' } }, value(val) { this.val = val }, selectData: { handler(newVal) { this.range = newVal this.dataList = this.getDataList(this.getSelectedValue(newVal)) }, deep: true }, listData(newVal) { this.range = newVal this.dataList = this.getDataList(this.getSelectedValue(newVal)) } }, created() { // 对话框遮罩不可点击 this.popup.mkclick = false if (this.mode === 'input') { this.dialogType = 'info' this.val = this.value } else { this.dialogType = this.type } //select this.form = this.getForm('uniForms') this.formItem = this.getForm('uniFormsItem') this.formItem && this.formItem.setValue(this.value) this.styles = { selectedColor: this.selectedColor, selectedTextColor: this.selectedTextColor } if (this.formItem) { if (this.formitem.label) { this.rename = this.formitem.label this.form.inputChildrens.push(this) } } if (this.selectData && this.selectData.length !== 0) { this.range = this.selectData this.dataList = this.getDataList(this.getSelectedValue(this.range)) } else { if (this.collection) { this.loadData() } } }, mounted() { this.focus = true }, methods: { /** * 点击确认按钮 */ onOk() { this.$emit('confirm', () => { this.popup.close() }, this.val) }, /** * 点击取消按钮 */ close() { if (this.beforeClose) { this.$emit('close', () => { this.popup.close() }) return } this.popup.close() }, //select````````` init(range) {}, /** * 获取父元素实例 */ getForm(name = 'uniForms') { let parent = this.$parent; let parentName = parent.$options.name; while (parentName !== name) { parent = parent.$parent; if (!parent) return false parentName = parent.$options.name; } return parent; }, chagne(e) { const values = e.detail.value let detail = { value: [], data: [] } if (this.multiple) { this.range.forEach(item => { if (values.includes(item.value + '')) { detail.value.push(item.value) detail.data.push(item) } }) } else { const range = this.range.find(item => item.value == values) if (range) { detail = { value: range.value, data: range } } } this.formItem && this.formItem.setValue(detail.value) this.$emit('input', detail.value) this.$emit('change', { detail }) if (this.multiple) { // 如果 v-model 没有绑定 ,则走内部逻辑 // if (this.value.length === 0) { this.dataList = this.getDataList(detail.value, true) // } } else { this.dataList = this.getDataList(detail.data) } }, getLabelClass(item, index) { let classes = [] if (this.multiple) { classes.push('is-list-multiple-box') } else { classes.push('is-list-box') } item.disabled && classes.push('is-list-disabled') index !== 0 && classes.push('is-list-border') classes = classes.join(' ') return classes }, getCheckboxClass(item, type = '') { let classes = [] if (this.multiple) { classes.push(...this.getClasses(item, 'default-multiple', type)) } else { classes.push(...this.getClasses(item, 'default', type)) } classes = classes.join(' ') return classes }, getTextClass(item) { let classes = [] classes.push(...this.getClasses(item, 'list')) classes = classes.join(' ') return classes }, /** * 获取渲染的新数组 * @param {Object} value 选中内容 */ getDataList(value) { // 解除引用关系,破坏原引用关系,避免污染源数据 let dataList = JSON.parse(JSON.stringify(this.range)) let list = [] if (this.multiple) { if (!Array.isArray(value)) { value = [] // console.error('props 类型错误'); } } dataList.forEach((item, index) => { item.disabled = item.disable || item.disabled || false if (this.multiple) { if (value.length > 0) { let have = value.find(val => val === item.value) item.selected = have !== undefined } else { item.selected = false } } else { item.selected = value.value === item.value } list.push(item) }) return this.setRange(list) }, /** * 处理最大最小值 * @param {Object} list */ setRange(list) { let selectList = list.filter(item => item.selected) let min = Number(this.min) || 0 let max = Number(this.max) || '' list.forEach((item, index) => { if (this.multiple) { if (selectList.length <= min) { let have = selectList.find(val => val.value === item.value) if (have !== undefined) { item.disabled = true } } if (selectList.length >= max && max !== '') { let have = selectList.find(val => val.value === item.value) if (have === undefined) { item.disabled = true } } } this.setClass(item, index) list[index] = item }) return list }, /** * 设置 class * @param {Object} item * @param {Object} index */ setClass(item, index) { // 设置 label 的 class item.labelClass = this.getLabelClass(item, index) // 设置 checkbox外层样式 item.checkboxBgClass = this.getCheckboxClass(item, '-bg') // 设置 checkbox 内层样式 item.checkboxClass = this.getCheckboxClass(item) // 设置文本样式 item.textClass = this.getTextClass(item) // 设置 list 对勾右侧样式 item.listClass = this.getCheckboxClass(item, '-list') // 设置自定义样式 item.styleBackgroud = this.setStyleBackgroud(item) item.styleIcon = this.setStyleIcon(item) item.styleIconText = this.setStyleIconText(item) item.styleRightIcon = this.setStyleRightIcon(item) }, /** * 获取 class */ getClasses(item, name, type = '') { let classes = [] item.disabled && classes.push('is-' + name + '-disabled' + type) item.selected && classes.push('is-' + name + '-checked' + type) if (this.mode !== 'button' || name === 'button') { item.selected && item.disabled && classes.push('is-' + name + '-disabled-checked' + type) } return classes }, /** * 获取选中值 * @param {Object} range */ getSelectedValue(range) { if (!this.multiple) return this.value let selectedArr = [] range.forEach((item) => { if (item.selected) { selectedArr.push(item.value) } }) return this.value.length > 0 ? this.value : selectedArr }, /** * 设置背景样式 */ setStyleBackgroud(item) { let styles = {} if (item.selected) { styles.borderColor = this.styles.selectedColor } return styles }, setStyleIcon(item) { let styles = {} if (item.selected) { styles.backgroundColor = this.styles.selectedColor styles.borderColor = this.styles.selectedColor } return styles }, setStyleIconText(item) { let styles = {} if (item.selected) { if (this.styles.selectedTextColor) { styles.color = this.styles.selectedTextColor } else { if(this.mode === 'tag'){ styles.color = '#fff' }else{ styles.color = this.styles.selectedColor } } } return styles }, setStyleRightIcon(item){ let styles = {} if (item.selected) { styles.borderColor = this.styles.selectedColor } return styles } } } </script> <style lang="scss" scoped> .uni-popup-dialog { 300px; border-radius: 15px; background-color: #fff; } .uni-dialog-title { /* #ifndef APP-NVUE */ display: flex; /* #endif */ flex-direction: row; justify-content: center; padding-top: 15px; padding-bottom: 5px; } .uni-dialog-title-text { font-size: 16px; font-weight: 500; } .uni-dialog-content { /* #ifndef APP-NVUE */ display: flex; /* #endif */ flex-direction: row; justify-content: center; align-items: center; padding: 5px 15px 15px 15px; } .uni-dialog-content-text { font-size: 14px; color: #6e6e6e; } .uni-dialog-button-group { /* #ifndef APP-NVUE */ display: flex; /* #endif */ flex-direction: row; border-top-color: #f5f5f5; border-top-style: solid; border-top- 1px; } .uni-dialog-button { /* #ifndef APP-NVUE */ display: flex; /* #endif */ flex: 1; flex-direction: row; justify-content: center; align-items: center; height: 45px; } .uni-border-left { border-left-color: #f0f0f0; border-left-style: solid; border-left- 1px; } .uni-dialog-button-text { font-size: 14px; } .uni-button-color { color: $uni-color-primary; } .uni-dialog-input { flex: 1; font-size: 14px; } .uni-popup__success { color: $uni-color-success; } .uni-popup__warn { color: $uni-color-warning; } .uni-popup__error { color: $uni-color-error; } .uni-popup__info { color: #909399; } .uni-data-checklist { position: relative; z-index: 0; /* min-height: 36px; */ } .uni-data-loading { display: flex; align-items: center; /* justify-content: center; */ height: 36px; padding-left: 10px; } .checklist-group { /* #ifndef APP-NVUE */ display: flex; /* #endif */ flex-direction: row; flex-wrap: wrap; } .checklist-box { /* #ifndef APP-NVUE */ display: flex; /* #endif */ flex-direction: row; align-items: center; margin: 5px 0; margin-right: 25px; } .checklist-text { font-size: 14px; color: #333; margin-left: 5px; transition: color 0.2s; } .is-button { margin-right: 10px; padding: 3px 15px; border: 1px #DCDFE6 solid; border-radius: 3px; transition: border-color 0.2s; } .is-list { flex-direction: column; } .is-list-box { /* #ifndef APP-NVUE */ display: flex; /* #endif */ padding: 10px 15px; padding-left: 0; margin: 0; } .checklist-content { /* #ifndef APP-NVUE */ display: flex; /* #endif */ flex: 1; flex-direction: row; align-items: center; justify-content: space-between; } .list-content { margin-left: 5px; } .is-list-multiple-box { /* #ifndef APP-NVUE */ display: flex; /* #endif */ padding: 10px 15px; padding-left: 0; margin: 0; } .is-list-border { border-top: 1px #eee solid; } .is-tag { margin-right: 10px; padding: 3px 10px; border: 1px #eee solid; border-radius: 3px; background-color: #f5f5f5; /* transition: border-color 0.1s; */ } .is-tag-text { margin: 0; color: #666; } .checkbox__inner { flex-shrink: 0; position: relative; border: 1px solid #DCDFE6; border-radius: 2px; box-sizing: border-box; 16px; height: 16px; background-color: #fff; z-index: 1; transition: border-color 0.1s; } .checkbox__inner-icon { border: 1px solid #fff; border-left: 0; border-top: 0; height: 8px; left: 5px; position: absolute; top: 1px; 3px; opacity: 0; transition: transform .2s; transform-origin: center; transform: rotate(40deg) scaleY(0.4); } .radio__inner { flex-shrink: 0; /* #ifndef APP-NVUE */ display: flex; /* #endif */ justify-content: center; align-items: center; position: relative; border: 1px solid #DCDFE6; border-radius: 2px; box-sizing: border-box; 16px; height: 16px; border-radius: 16px; background-color: #fff; z-index: 1; transition: border-color .3s; } .radio__inner-icon { 8px; height: 8px; border-radius: 10px; opacity: 0; transition: transform .3s; } .checkobx__list { border: 1px solid #fff; border-left: 0; border-top: 0; height: 12px; 6px; transform-origin: center; opacity: 0; transition: all 0.3s; transform: rotate(45deg); } /* 禁用样式 */ .is-default-disabled-bg { background-color: #F2F6FC; border-color: #DCDFE6; /* #ifdef H5 */ cursor: not-allowed; /* #endif */ } .is-default-multiple-disabled-bg { background-color: #F2F6FC; border-color: #DCDFE6; /* #ifdef H5 */ cursor: not-allowed; /* #endif */ } .is-default-disabled { border-color: #F2F6FC; } .is-default-multiple-disabled { border-color: #F2F6FC; } .is-list-disabled { /* #ifdef H5 */ cursor: not-allowed; /* #endif */ color: #999; } .is-list-disabled-checked { color: #a1dcc1; } .is-button-disabled { /* #ifdef H5 */ cursor: not-allowed; /* #endif */ border-color: #EBEEF5; } .is-button-text-disabled { color: #C0C4CC; } .is-button-disabled-checked { border-color: #a1dcc1; } .is-tag-disabled { /* #ifdef H5 */ cursor: not-allowed; /* #endif */ border-color: #e9e9eb; background-color: #f4f4f5; } .is-tag-text-disabled { color: #bcbec2; } /* 选中样式 */ .is-default-checked-bg { border-color: #007aff; } .is-default-multiple-checked-bg { border-color: #007aff; background-color: #007aff; } .is-default-checked { opacity: 1; background-color: #007aff; transform: rotate(45deg) scaleY(1); } .is-default-multiple-checked { opacity: 1; transform: rotate(45deg) scaleY(1); } .is-default-disabled-checked-bg { opacity: 0.4; } .is-default-multiple-disabled-checked-bg { opacity: 0.4; } .is-default-checked-list { border-color: #007aff; opacity: 1; transform: rotate(45deg) scaleY(1); } .is-default-multiple-checked-list { border-color: #007aff; opacity: 1; transform: rotate(45deg) scaleY(1); } .is-list-disabled-checked { opacity: 0.4; } .is-default-disabled-checked-list { opacity: 0.4; } .is-default-multiple-disabled-checked-list { opacity: 0.4; } .is-button-checked { border-color: #007aff; } .is-button-disabled-checked { opacity: 0.4; } .is-list-checked { color: #007aff; } .is-tag-checked { border-color: #007aff; background-color: #007aff; } .is-tag-text-checked { color: #fff; } .is-tag-disabled-checked { opacity: 0.4; } .disabled-cursor { /* #ifdef H5 */ cursor: not-allowed; /* #endif */ } .is-wrap { flex-direction: column; } .hidden { /* #ifdef MP-ALIPAY */ display: none; /* #endif */ } </style>
//cilentDb const events = { load: 'load', error: 'error' } const pageMode = { add: 'add', replace: 'replace' } const attrs = [ 'pageCurrent', 'pageSize', 'collection', 'action', 'field', 'getcount', 'orderby', 'where' ] export default { data() { return { loading: false, listData: this.getone ? {} : [], paginationInternal: { current: this.pageCurrent, size: this.pageSize, count: 0 }, errorMessage: '' } }, created() { let db = null; let dbCmd = null; if(this.collection){ this.db = uniCloud.database(); this.dbCmd = this.db.command; } this._isEnded = false this.$watch(() => { var al = [] attrs.forEach(key => { al.push(this[key]) }) return al }, (newValue, oldValue) => { this.paginationInternal.pageSize = this.pageSize let needReset = false for (let i = 2; i < newValue.length; i++) { if (newValue[i] != oldValue[i]) { needReset = true break } } if (needReset) { this.clear() this.reset() } if (newValue[0] != oldValue[0]) { this.paginationInternal.current = this.pageCurrent } this._execLoadData() }) // #ifdef H5 if (process.env.NODE_ENV === 'development') { this._debugDataList = [] if (!window.unidev) { window.unidev = { clientDB: { data: [] } } } unidev.clientDB.data.push(this._debugDataList) } // #endif // #ifdef MP-TOUTIAO let changeName let events = this.$scope.dataset.eventOpts for (var i = 0; i < events.length; i++) { let event = events[i] if (event[0].includes('^load')) { changeName = event[1][0][0] } } if (changeName) { let parent = this.$parent let maxDepth = 16 this._changeDataFunction = null while (parent && maxDepth > 0) { let fun = parent[changeName] if (fun && typeof fun === 'function') { this._changeDataFunction = fun maxDepth = 0 break } parent = parent.$parent maxDepth--; } } // #endif // if (!this.manual) { // this.loadData() // } }, // #ifdef H5 beforeDestroy() { if (process.env.NODE_ENV === 'development' && window.unidev) { var cd = this._debugDataList var dl = unidev.clientDB.data for (var i = dl.length - 1; i >= 0; i--) { if (dl[i] === cd) { dl.splice(i, 1) break } } } }, // #endif methods: { loadData(args1, args2) { let callback = null if (typeof args1 === 'object') { if (args1.clear) { this.clear() this.reset() } if (args1.current !== undefined) { this.paginationInternal.current = args1.current } if (typeof args2 === 'function') { callback = args2 } } else if (typeof args1 === 'function') { callback = args1 } this._execLoadData(callback) }, loadMore() { if (this._isEnded) { return } this._execLoadData() }, refresh() { this.clear() this._execLoadData() }, clear() { this._isEnded = false this.listData = [] }, reset() { this.paginationInternal.current = 1 }, remove(id, { action, callback, confirmTitle, confirmContent } = {}) { if (!id || !id.length) { return } uni.showModal({ title: confirmTitle || '提示', content: confirmContent || '是否删除该数据', showCancel: true, success: (res) => { if (!res.confirm) { return } this._execRemove(id, action, callback) } }) }, _execLoadData(callback) { if (this.loading) { return } this.loading = true this.errorMessage = '' this._getExec().then((res) => { this.loading = false const { data, count } = res.result this._isEnded = data.length < this.pageSize callback && callback(data, this._isEnded) this._dispatchEvent(events.load, data) if (this.getone) { this.listData = data.length ? data[0] : undefined } else if (this.pageData === pageMode.add) { this.listData.push(...data) if (this.listData.length) { this.paginationInternal.current++ } } else if (this.pageData === pageMode.replace) { this.listData = data this.paginationInternal.count = count } // #ifdef H5 if (process.env.NODE_ENV === 'development') { this._debugDataList.length = 0 this._debugDataList.push(...JSON.parse(JSON.stringify(this.listData))) } // #endif }).catch((err) => { this.loading = false this.errorMessage = err callback && callback() this.$emit(events.error, err) }) }, _getExec() { let exec = this.db if (this.action) { exec = exec.action(this.action) } exec = exec.collection(this.collection) if (!(!this.where || !Object.keys(this.where).length)) { exec = exec.where(this.where) } if (this.field) { exec = exec.field(this.field) } if (this.orderby) { exec = exec.orderBy(this.orderby) } const { current, size } = this.paginationInternal exec = exec.skip(size * (current - 1)).limit(size).get({ getCount: this.getcount }) return exec }, _execRemove(id, action, callback) { if (!this.collection || !id) { return } const ids = Array.isArray(id) ? id : [id] if (!ids.length) { return } uni.showLoading({ mask: true }) let exec = this.db if (action) { exec = exec.action(action) } exec.collection(this.collection).where({ _id: dbCmd.in(ids) }).remove().then((res) => { callback && callback(res.result) if (this.pageData === pageMode.replace) { this.refresh() } else { this.removeData(ids) } }).catch((err) => { uni.showModal({ content: err.message, showCancel: false }) }).finally(() => { uni.hideLoading() }) }, removeData(ids) { let il = ids.slice(0) let dl = this.listData for (let i = dl.length - 1; i >= 0; i--) { let index = il.indexOf(dl[i]._id) if (index >= 0) { dl.splice(i, 1) il.splice(index, 1) } } }, _dispatchEvent(type, data) { if (this._changeDataFunction) { this._changeDataFunction(data, this._isEnded) } else { this.$emit(type, data, this._isEnded) } } } }