基于 vue 与 element-ui 封装 table 中可编辑 select 组建

环境

# 安装 vue 脚手架
npm install -g @vue/cli
# 使用脚手架初始化项目
vue create element-demo
# 添加 element-ui 框架(使用 sass 预处理器)
vue add element-ui
npm install -D sass sass-loader
# 启动项目
npm run serve

文件结构

|-src
	|-components
		|-TableEditorSelect.vue
		|-TableSelectBusse.vue
	|-App.vue

TableEditorSelect.vue 组件

只有 hover 的时候才显示的 select 组建,仅仅做了样式的封装

<template>
    <el-select
        :disabled="requesting"
        :loading="loading"
        :value="value"
        @mouseenter.native="isHide = false"
        @mouseleave.native="isHide = true"
        @input="e => { $emit('input', e) }"
        :placeholder="placeholder"
        class="component table-editor-select"
        :class="[{'hide': isHide || requesting}]">
        <el-option v-for="item in options" :key="item.value" :value="item.value">{{item.label}}</el-option>
    </el-select>
</template>

<script>
export default {
    name: 'TableEditorSelect',
    props: {
        placeholder: {
            type: String,
            default: '请选择'
        },
        options: { // 备选项
            type: Array,
            required: true
        },
        requesting: { // 提交修改请求
            type: Boolean,
            default: false
        },
        loading: { // 加载备选项
            type: Boolean,
            default: false
        },
        value: { // 选中的选项
        }
    },
    data: () => ({
        isHide: true
    })
}
</script>

<style lang="scss">
.component.table-editor-select {
    &.hide {
        :not(.is-focus) .el-input__inner, :not(.is-focus) .el-input__inner:hover {
            border-color: transparent !important;
            background-color: transparent !important;
        }
        :not(.is-focus) .el-input__suffix {
            opacity: 0;
        }
    }
}
</style>

TableSelectBusse.vue 组件

独立业务请求中间层,在这一层判断是否为第一次点击,并异步求情 select 组件的选项列表,并将更新调用借口的操作封装到这一层

<template>
    <table-editor-select
        @click.native="initOptions()"
        :value="localValue"
        :loading="loading"
        :requesting="requesting"
        :options="options"
        @input="editorSelect">
    </table-editor-select>
</template>

<script>
import TableEditorSelect from './TableEditorSelect.vue'

export default {
    name: 'TableSelectBusse',
    props: {
        value: {}
    },
    data: () => ({
        loading: false, // 加载备选项
        requesting: false, // 变更请求
        loaded: false, // 第一次请求完备选项后,如果返回的备选项为空,则接下来不再进行任何请求
        localValue: '', // 当前选中值
        oldValue: '', // 之前选中值,在请求失败后回显
        options: [] // 备选项列表
    }),
    created () {
        // 添加默认值
        this.localValue = this.value
        this.oldValue = this.value
    },
    methods: {
        initOptions () { // 请求备选项
            if (this.loading || this.loaded) {
                return
            }
            this.loading = true
            setTimeout(() => {
                this.loading = false
                this.loaded = true
                this.options = [{
                    value: 1,
                    label: '选项一'
                }, {
                    value: 2,
                    label: '选项二'
                }, {
                    value: 3,
                    label: '选项三'
                }]
            }, 2000)
        },
        editorSelect (v) { // 变更
            if (this.localValue === v ) { // 如果变更目标结果和当前选中的值相同,则不进行任何操作
                return
            }
            this.oldValue = this.localValue // 将变更前的值储存起来
            this.requesting = true
            this.localValue = v // 立即显示变更后的值
            setTimeout(() => { // 开始请求变更
                const hasError = false
                if (hasError) {
                    this.localValue = this.oldValue // 请求错误的话回显之前的数据
                    this.$message.error('更新失败...')
                } else {
                    this.$message({
                        message: '更新成功',
                        type: 'success'
                    })
                }
                this.requesting = false
            }, 2000)
        }
    },
    components: {
        TableEditorSelect
    }
}
</script>

<style lang="scss">
</style>

App.vue

使用的 table 部分

<template>
    <el-card>
        <div slot="header" class="clearfix">
            <span>测试表格</span>
        </div>
        <el-table
            :data="tableData">
            <el-table-column
                label="下拉框">
                <template slot-scope="scope">
                    <table-select-busse :value="1"></table-select-busse>
                </template>
            </el-table-column>
            <el-table-column
                label="输入框">
                <template slot-scope="scope">
                    {{scope.row}}
                </template>
            </el-table-column>
        </el-table>
    </el-card>
</template>

<script>
import TableSelectBusse from './components/TableSelectBusse.vue'

export default {
    name: 'App',
    data: () => ({
        tableData: ['一行数据']
    }),
    mounted () {},
    components: {
        TableSelectBusse
    }
}
</script>

<style>
.app {}
</style>

代码仓库

你可能感兴趣的:(基于 vue 与 element-ui 封装 table 中可编辑 select 组建)