赞
踩
目录
基于Element UI内置的Select下拉和Tree树形组件,组合封装的树状下拉选择器。
先看效果:
下拉状态:
选择后状态:
选择的数据:
1、加载树结构,实现树状下拉选择器;
2、可通过关键词实现本地和远程过滤;
3、高亮选择行;
4、设置默认选择行;
5、可直接应用在form表单;
树状下拉组件代码:
- <!--
- 树状下拉选择框:
- 1、加载树结构,实现树状下拉选择组件;
- 2、可通过关键词实现本地和远程过滤;
- 3、高亮选择行;
- 4、设置默认选择行;
- 5、可直接应用在form表单;
- -->
- <template>
- <el-select
- ref="selectRef"
- clearable
- :filterable="filterableFor || remoteFor"
- :remote="filterableFor || remoteFor"
- :remote-method="selectRemoteMethod"
- v-model="currentLabel"
- @visible-change="handleVisibleChange"
- @clear="handleClear"
- >
- <el-option
- style="height: 100%; padding: 0"
- value=""
- v-loading="loading"
- element-loading-text="加载中..."
- element-loading-spinner="el-icon-loading"
- >
- <el-tree
- ref="treeRef"
- :data="dataOfTree"
- :node-key="defaultProps.value"
- :props="defaultProps"
- highlight-current
- default-expand-all
- :current-node-key="selectedNode.value"
- :expand-on-click-node="false"
- @node-click="handleNodeClicked"
- :filter-node-method="filterNode"
- >
- </el-tree>
- </el-option>
-
- </el-select>
- </template>
- <script>
-
- export default {
- name: 'SelectTree',
- components: {},
- model: {
- prop: 'inputValue',
- event: 'myInputEvent'
- },
- props: {
- // 默认选中值
- defaultValue: {
- type: Number
- },
- // 是否支持搜索,本地搜索,与远程搜索配置互斥。
- filterable: {
- type: Boolean,
- default: false
- },
- // 是否远程搜索,要设置远程搜索方法
- remote: {
- type: Boolean,
- default: false
- },
- // 远程方法
- remoteMethod: {
- type: Function
- },
- treeOptions: {
- type: Array,
- default: () => {
- return []
- }
- },
- defaultProps: {
- type: Object,
- default: () => {
- return {
- children: 'children',
- label: 'label',
- value: 'value'
- }
- }
- }
- },
- watch: {
- treeOptions: {
- handler(newValue) {
- this.loading = false
- this.dataOfTree = JSON.parse(JSON.stringify(newValue))
- // 保留源数据;
- this.dataSource = JSON.parse(JSON.stringify(newValue))
- },
- deep: true,
- immediate: false
- },
- defaultValue: {
- handler(newValue) {
- this.selectedNode = {}
- this.currentLabel = undefined
- this.currentValue = newValue
- this.$nextTick(() => {
- // 过滤方式是通过value还是label;
- this.isFilterWithValue = true
- if (this.dataOfTree) {
- this.$refs.treeRef.filter(newValue)
- }
- })
- },
- deep: true,
- immediate: true
- }
- },
- computed: {
- // 是否支持搜索,本地搜索,与远程搜索配置互斥。
- filterableFor() {
- return this.remote ? false : this.filterable
- },
- remoteFor() {
- return this.filterable ? false : this.remote
- }
- },
- data() {
- return {
- selectedNode: {},
- loading: false,
- currentValue: undefined,
- currentLabel: undefined,
- dataOfTree: []
- }
- },
- created() {
- this.dataOfTree = JSON.parse(JSON.stringify(this.treeOptions))
- // 保留源数据;
- this.dataSource = JSON.parse(JSON.stringify(this.treeOptions))
- },
- mounted() {
- },
- methods: {
- selectRemoteMethod(val) {
- this.isFilterWithValue = false
- if (this.filterableFor) {
- // 本地过滤
- this.$refs.treeRef.filter(val)
- } else if (this.remoteFor) {
- // 远程搜索
- this.loading = true
- this.remoteMethod(val)
- }
- },
- handleClear() {
- // 如果内容被清空
- this.selectedNode = {}
- this.currentLabel = undefined
- this.currentValue = undefined
- const result = this.buildEmptyResult()
- this.$emit('myInputEvent', result)
- this.$emit('onNodeSelectEvent', result)
- },
- handleVisibleChange(visible) {
- if (!visible) {
- // 先移除所有数据;
- this.dataOfTree.splice(0)
- // 恢复原来的所有数据;
- this.dataOfTree.splice(0, 0, ...this.dataSource)
- // 本地过滤
- this.$refs.treeRef.filter('')
- }
- },
- filterNode(value, data) {
- if (!value) {
- return data
- }
- if (this.isFilterWithValue) {
- if (data[this.defaultProps.value] === value) {
- this.selectedNode = data
- this.currentLabel = data[this.defaultProps.label]
- this.$refs.treeRef.setCurrentKey(this.selectedNode[this.defaultProps.value])
- const result = this.buildResultByNodeData(data)
- this.$emit('myInputEvent', result)
- }
- } else {
- return data[this.defaultProps.label].indexOf(value) !== -1
- }
- return data
- },
- closeSelect() {
- this.$refs.selectRef.blur()
- },
- /**
- * @param data
- * @param node
- * @param comp
- */
- handleNodeClicked(data, node, comp) {
- this.selectedNode = data
- this.currentLabel = data[this.defaultProps.label]
- this.currentValue = data[this.defaultProps.value]
- const result = this.buildResultByNodeData(data)
- this.$emit('myInputEvent', result)
- this.$emit('onNodeSelectEvent', result)
- this.closeSelect()
- },
- buildResultByNodeData(data) {
- return {
- node: data[this.defaultProps.value],
- data: {
- label: data[this.defaultProps.label],
- value: data[this.defaultProps.value]
- },
- meta: data
- }
- },
- buildEmptyResult() {
- return {
- node: undefined,
- data: {
- label: undefined,
- value: undefined
- },
- meta: undefined
- }
- }
- }
- }
- </script>
-
- <style lang='scss' scoped>
- </style>
应用示例1:
- <template>
- <div>
- <div>测试表单</div>
- <el-form
- ref="demandFormRef"
- :model="form"
- label-suffix=":"
- status-icon
- label-position="left"
- >
- <el-form-item label="树" label-width="85px" prop="tree">
- <select-tree
- v-model="form.tree"
- filterable
- :tree-options="treeOptions"
- :default-value="form.tree.node"
- @onNodeSelectEvent="handleNodeSelectEvent($event)"
- />
- </el-form-item>
- </el-form>
- <div>
- <el-button @click="reset">重置</el-button>
- <el-button @click="submit">提交</el-button>
- </div>
- </div>
- </template>
- <script>
- import {Message} from 'element-ui'
- import SelectTree from '@/views/select-tree/SelectTree.vue'
-
- export default {
- name: 'SelectTreeExample',
- components: {
- SelectTree
- },
- props: {},
- data() {
- return {
- form: {
- tree: {node: undefined, data: {}}
- },
- treeOptions: [{
- value: 1,
- label: '一级 1',
- children: [{
- value: 11,
- label: '二级 1-1',
- children: [{
- value: 111,
- label: '三级 1-1-1'
- }]
- }]
- }, {
- value: 2,
- label: '一级 2',
- children: [{
- value: 21,
- label: '二级 2-1'
- }]
- }, {
- value: 3,
- label: '一级 3',
- children: [{
- value: 31,
- label: '二级 3-1',
- children: [{
- value: 311,
- label: '三级 3-1-1'
- }]
- }, {
- value: 32,
- label: '二级 3-2',
- children: [{
- value: 321,
- label: '三级 3-2-1'
- }]
- }]
- }]
- }
- },
- mounted() {
- // 模拟接口请求,反显选择数据
- setTimeout(() => {
- this.form.tree.node = 2
- }, 1000)
- },
- methods: {
- reset() {
- this.form.tree = {node: undefined, data: {}}
- },
- submit() {
- const data = this.form.tree.data
- Message.info(`选中节点名称是${data.label},值是${data.value}`)
- },
- handleNodeSelectEvent(dataSelected) {
- }
- }
- }
- </script>
-
- <style lang='scss' scoped>
- </style>
应用示例2:
- <template>
- <div>
- <div>测试表单</div>
- <el-form
- ref="demandFormRef"
- :model="form"
- label-suffix=":"
- status-icon
- label-position="left"
- >
- <el-form-item label="树" label-width="85px" prop="tree">
- <select-tree
- v-model="form.tree"
- remote
- :remote-method="handleRemote"
- :tree-options="treeOptions"
- :default-value="form.tree.node"
- @onNodeSelectEvent="handleNodeSelectEvent($event)"
- />
- </el-form-item>
- </el-form>
- <div>
- <el-button @click="reset">重置</el-button>
- <el-button @click="submit">提交</el-button>
- </div>
- </div>
- </template>
- <script>
- import {Message} from 'element-ui'
- import SelectTree from '@/views/components/SelectTree.vue'
-
- export default {
- name: 'SelectTreeExample',
- components: {
- SelectTree
- },
- props: {},
- data() {
- return {
- form: {
- tree: {node: undefined, data: {}}
- },
- treeOptions: [{
- value: 1,
- label: '一级 1',
- children: [{
- value: 11,
- label: '二级 1-1',
- children: [{
- value: 111,
- label: '三级 1-1-1'
- }]
- }]
- }, {
- value: 2,
- label: '一级 2',
- children: [{
- value: 21,
- label: '二级 2-1'
- }]
- }, {
- value: 3,
- label: '一级 3',
- children: [{
- value: 31,
- label: '二级 3-1',
- children: [{
- value: 311,
- label: '三级 3-1-1'
- }]
- }, {
- value: 32,
- label: '二级 3-2',
- children: [{
- value: 321,
- label: '三级 3-2-1'
- }]
- }]
- }]
- }
- },
- mounted() {
- // 模拟接口请求,反显选择数据
- setTimeout(() => {
- this.form.tree.node = 2
- }, 1000)
- },
- methods: {
- reset() {
- this.form.tree = {node: undefined, data: {}}
- },
- submit() {
- const data = this.form.tree.data
- Message.info(`选中节点名称是${data.label},值是${data.value}`)
- },
- handleRemote() {
- setTimeout(() => {
- this.treeOptions = [{
- value: 1,
- label: '一级 1',
- children: [{
- value: 11,
- label: '二级 1-1',
- children: [{
- value: 111,
- label: '三级 1-1-1'
- }]
- }]
- }]
- }, 3000)
- },
- handleNodeSelectEvent(dataSelected) {
- }
- }
- }
- </script>
-
- <style lang='scss' scoped>
- </style>
本示例中,部分实现细节或者写法,可根据实际需要调整,树状下拉的实现方式有多种,这只是其中一种,只要符合实际需求就可以。
如果发现问题,欢迎随时提出,共同改进。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。