0


uniapp 改写uni-data-picker级联选择器(带搜索和多选)新增列出选择和删除功能

效果演示

注意:视频中的数据是模拟数据,请自行定义数据才可使用,数据格式末尾有例子

uniapp 改写uni-data-picker

uni-data-picker.vue更改

<template><view class="uni-data-tree"><view class="uni-data-tree-input" @click="handleInput"><slot :options="options":data="inputSelected":error="errorMessage"><view class="input-value":class="{'input-value-border': border}"><text v-if="errorMessage"class="selected-area error-text">{{errorMessage}}</text><view v-else-if="loading && !isOpened"class="selected-area"><uni-load-more class="load-more":contentText="loadMore" status="loading"></uni-load-more></view><scroll-view v-else-if="inputSelected.length"class="selected-area" scroll-x="true"><view class="selected-list"><view class="selected-item" v-for="(item,index) in inputSelected":key="index"><text>{{item.text}}</text><text v-if="index<inputSelected.length-1"class="input-split-line">{{split}}</text></view></view></scroll-view><text v-elseclass="selected-area placeholder">{{placeholder}}</text><view v-if="clearIcon && !readonly && inputSelected.length"class="icon-clear"
                        @click.stop="clear"><uni-icons type="clear" color="#e1e1e1" size="14"></uni-icons></view><view class="arrow-area" v-if="(!clearIcon || !inputSelected.length) && !readonly "><view class="input-arrow"></view></view></view></slot></view><view class="uni-data-tree-cover" v-if="isOpened" @click="handleClose"></view><view class="uni-data-tree-dialog" v-if="isOpened"><view class="uni-popper__arrow"></view><view class="dialog-caption"><view class="title-area"><text class="dialog-title">{{popupTitle}}</text></view><view class="dialog-close" @click="handleClose"><view class="dialog-close-plus" data-id="close"></view><view class="dialog-close-plus dialog-close-rotate" data-id="close"></view></view></view><data-picker-view class="picker-view" ref="pickerView" v-model="dataValue":localdata="localdata":preload="preload":collection="collection":field="field":orderby="orderby":where="where":step-searh="stepSearh":self-field="selfField":parent-field="parentField":managed-mode="true":map="map":showSearch="showSearch":ellipsis="ellipsis" @change="onchange" @datachange="ondatachange" @nodeclick="onnodeclick"></data-picker-view></view></view></template><script>import dataPicker from"../uni-data-pickerview/uni-data-picker.js"import DataPickerView from"../uni-data-pickerview/uni-data-pickerview.vue"/**
     * DataPicker 级联选择
     * @description 支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。
     * @tutorial https://ext.dcloud.net.cn/plugin?id=3796
     * @property {String} popup-title 弹出窗口标题
     * @property {Array} localdata 本地数据,参考
     * @property {Boolean} border = [true|false] 是否有边框
     * @property {Boolean} readonly = [true|false] 是否仅读
     * @property {Boolean} preload = [true|false] 是否预加载数据
     * @value true 开启预加载数据,点击弹出窗口后显示已加载数据
     * @value false 关闭预加载数据,点击弹出窗口后开始加载数据
     * @property {Boolean} step-searh = [true|false] 是否分布查询
     * @value true 启用分布查询,仅查询当前选中节点
     * @value false 关闭分布查询,一次查询出所有数据
     * @property {String|DBFieldString} self-field 分布查询当前字段名称
     * @property {String|DBFieldString} parent-field 分布查询父字段名称
     * @property {String|DBCollectionString} collection 表名
     * @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割
     * @property {String} orderby 排序字段及正序倒叙设置
     * @property {String|JQLString} where 查询条件
     * @event {Function} popupshow 弹出的选择窗口打开时触发此事件
     * @event {Function} popuphide 弹出的选择窗口关闭时触发此事件
     */exportdefault{name:'UniDataPicker',emits:['popupopened','popupclosed','nodeclick','input','change','update:modelValue'],mixins:[dataPicker],components:{
            DataPickerView
        },props:{options:{type:[Object, Array],default(){return{}}},popupTitle:{type: String,default:'请选择'},placeholder:{type: String,default:'请选择'},heightMobile:{type: String,default:''},readonly:{type: Boolean,default:false},clearIcon:{type: Boolean,default:true},border:{type: Boolean,default:true},split:{type: String,default:'/'},ellipsis:{type: Boolean,default:true},showSearch:{type: Boolean,default:false},},data(){return{isOpened:false,inputSelected:[]}},created(){this.form =this.getForm('uniForms')this.formItem =this.getForm('uniFormsItem')if(this.formItem){if(this.formItem.name){this.rename =this.formItem.name
                    this.form.inputChildrens.push(this)}}this.$nextTick(()=>{this.load()})},methods:{clear(){this.inputSelected.splice(0)this._dispatchEvent([])},onPropsChange(){this._treeData =[]this.selectedIndex =0this.load()},load(){if(this.readonly){this._processReadonly(this.localdata,this.dataValue)return}if(this.isLocaldata){this.loadData()this.inputSelected =this.selected.slice(0)}elseif(!this.parentField &&!this.selfField &&this.hasValue){this.getNodeData(()=>{this.inputSelected =this.selected.slice(0)})}elseif(this.hasValue){this.getTreePath(()=>{this.inputSelected =this.selected.slice(0)})}},getForm(name ='uniForms'){let parent =this.$parent;let parentName = parent.$options.name;while(parentName !== name){
                    parent = parent.$parent;if(!parent)returnfalse;
                    parentName = parent.$options.name;}return parent;},show(){this.isOpened =truethis.$nextTick(()=>{this.$refs.pickerView.updateData({treeData:this._treeData,selected:this.selected,selectedIndex:this.selectedIndex
                    })})this.$emit('popupopened')},hide(){this.isOpened =falsethis.$emit('popupclosed')},handleInput(){if(this.readonly){return}this.show()},handleClose(e){this.hide()},onnodeclick(e){this.$emit('nodeclick', e)},ondatachange(e){this._treeData =this.$refs.pickerView._treeData
            },onchange(e){this.hide()this.inputSelected = e
                this._dispatchEvent(e)},_processReadonly(dataList, value){var isTree = dataList.findIndex((item)=>{return item.children
                })if(isTree >-1){let inputValue
                    if(Array.isArray(value)){
                        inputValue = value[value.length -1]if(typeof inputValue ==='object'&& inputValue.value){
                            inputValue = inputValue.value
                        }}else{
                        inputValue = value
                    }this.inputSelected =this._findNodePath(inputValue,this.localdata)return}if(!this.hasValue){this.inputSelected =[]return}let result =[]for(let i =0; i < value.length; i++){var val = value[i]var item = dataList.find((v)=>{return v.value == val
                    })if(item){
                        result.push(item)}}if(result.length){this.inputSelected = result
                }},_filterForArray(data, valueArray){var result =[]for(let i =0; i < valueArray.length; i++){var value = valueArray[i]var found = data.find((item)=>{return item.value == value
                    })if(found){
                        result.push(found)}}return result
            },_dispatchEvent(selected){let item ={}if(selected.length){var value =newArray(selected.length)for(var i =0; i < selected.length; i++){
                        value[i]= selected[i].value
                    }
                    item = selected[selected.length -1]}else{
                    item.value =''}if(this.formItem){this.formItem.setValue(item.value)}this.$emit('input', item.value)this.$emit('update:modelValue', item.value)this.$emit('change',{detail:{value: selected
                    }})}}}</script><style >.uni-data-tree {position: relative;
        font-size: 14px;
        min-width:150px;
        max-width:220px;}.error-text {color: #DD524D;}.input-value {/* #ifndef APP-NVUE */display: flex;/* #endif */
        flex-direction: row;
        align-items: center;
        flex-wrap: nowrap;
        font-size: 14px;
        line-height: 38px;padding:0 5px;overflow: hidden;/* #ifdef APP-NVUE */height: 40px;/* #endif */}.input-value-border {border: 1px solid #e5e5e5;
        border-radius: 5px;}.selected-area {flex:1;overflow: hidden;/* #ifndef APP-NVUE */display: flex;/* #endif */
        flex-direction: row;}.load-more {/* #ifndef APP-NVUE */
        margin-right: auto;/* #endif *//* #ifdef APP-NVUE */width: 40px;/* #endif */}.selected-list {/* #ifndef APP-NVUE */display: flex;/* #endif */
        flex-direction: row;
        flex-wrap: nowrap;padding:0 5px;}.selected-item {
        flex-direction: row;padding:0 1px;/* #ifndef APP-NVUE */
        white-space: nowrap;/* #endif */}.placeholder {color: grey;}.input-split-line {opacity:.5;}.arrow-area {position: relative;width: 20px;/* #ifndef APP-NVUE */
        margin-bottom: 5px;
        margin-left: auto;display: flex;/* #endif */
        justify-content: center;transform:rotate(-45deg);
        transform-origin: center;}.input-arrow {width: 7px;height: 7px;
        border-left: 1px solid #999;
        border-bottom: 1px solid #999;}.uni-data-tree-cover {position: fixed;left:0;top:0;right:0;bottom:0;
        background-color:rgba(0,0,0,.4);/* #ifndef APP-NVUE */display: flex;/* #endif */
        flex-direction: column;
        z-index:100;}.uni-data-tree-dialog {position: fixed;left:0;top:20%;right:0;bottom:0;
        background-color: #FFFFFF;
        border-top-left-radius: 10px;
        border-top-right-radius: 10px;/* #ifndef APP-NVUE */display: flex;/* #endif */
        flex-direction: column;
        z-index:102;overflow: hidden;/* #ifdef APP-NVUE */width: 750rpx;/* #endif */}.dialog-caption {position: relative;/* #ifndef APP-NVUE */display: flex;/* #endif */
        flex-direction: row;/* border-bottom: 1px solid #f0f0f0; */}.title-area {/* #ifndef APP-NVUE */display: flex;/* #endif */
        align-items: center;/* #ifndef APP-NVUE */margin: auto;/* #endif */padding:0 10px;}.dialog-title {/* font-weight: bold; */
        line-height: 44px;}.dialog-close {position: absolute;top:0;right:0;bottom:0;/* #ifndef APP-NVUE */display: flex;/* #endif */
        flex-direction: row;
        align-items: center;padding:0 15px;}.dialog-close-plus {width: 16px;height: 2px;
        background-color: #666;
        border-radius: 2px;transform:rotate(45deg);}.dialog-close-rotate {position: absolute;transform:rotate(-45deg);}.picker-view {flex:1;overflow: hidden;}/* #ifdef H5 */
    @media all and(min-width: 768px){.uni-data-tree-cover {
            background-color: transparent;}.uni-data-tree-dialog {position: absolute;top: 55px;height: auto;
            min-height: 400px;
            max-height: 50vh;
            background-color: #fff;border: 1px solid #EBEEF5;
            box-shadow:0 2px 12px 0rgba(0,0,0,0.1);
            border-radius: 4px;overflow: unset;}.dialog-caption {display: none;}.icon-clear {
            margin-right: 5px;}}/* #endif *//* picker 弹出层通用的指示小三角, todo:扩展至上下左右方向定位 *//* #ifndef APP-NVUE */.uni-popper__arrow,.uni-popper__arrow::after {position: absolute;display: block;width:0;height:0;
        border-color: transparent;
        border-style: solid;
        border-width: 6px;}.uni-popper__arrow {filter: drop-shadow(0 2px 12px rgba(0,0,0,0.03));top:-6px;left:10%;
        margin-right: 3px;
        border-top-width:0;
        border-bottom-color: #EBEEF5;}.uni-popper__arrow::after {content:" ";top: 1px;
        margin-left:-6px;
        border-top-width:0;
        border-bottom-color: #fff;}/* #endif */</style>

uni-data-pickerview.vue更改

<template><view class="uni-data-pickerview"><uni-combox v-if="showSearch":candidates="candidates" placeholder="输入搜索内容"  @input="handleInput"></uni-combox><!--<input placeholder="请输入搜索内容" style="border:1px solid #ddd;width:80%;margin:0 auto;border-radius:5px;padding:5px;" @input="handleInput"/>--><scroll-view class="selected-area" scroll-x="true" scroll-y="false":show-scrollbar="false"><view class="selected-list"><template v-for="(item,index) in selected"><view class="selected-item":class="{'selected-item-active':index==selectedIndex, 'selected-item-text-overflow': ellipsis}":key="index" v-if="item.text" @click="handleSelect(index)"><text class="">{{item.text}}</text></view></template></view></scroll-view><view class="tab-c"><template v-for="(child, i) in dataList"><scroll-view class="list":key="i" v-if="i==selectedIndex":scroll-y="true"><view class="item":class="{'is-disabled': !!item.disable}" v-for="(item, j) in child":key="j"><checkbox  @click ="handleClick(item)"  v-if="showSearch && i==0":checked=" selected.length > j && item[map.value] == selected[j].value"/><text @click="handleNodeClick(item, i, j)"class="item-text item-text-overflow">{{item[map.text]}}</text><view class="check" v-if="i == 1 && selected.length > i && item[map.value] == selected[i].value"></view></view></scroll-view></template><view class="loading-cover" v-if="loading"><uni-load-more class="load-more":contentText="loadMore" status="loading"></uni-load-more></view><view class="error-message" v-if="errorMessage"><text class="error-text">{{errorMessage}}</text></view></view></view></template><script>import dataPicker from"./uni-data-picker.js"/**
     * DataPickerview
     * @description uni-data-pickerview
     * @tutorial https://ext.dcloud.net.cn/plugin?id=3796
     * @property {Array} localdata 本地数据,参考
     * @property {Boolean} step-searh = [true|false] 是否分布查询
     * @value true 启用分布查询,仅查询当前选中节点
     * @value false 关闭分布查询,一次查询出所有数据
     * @property {String|DBFieldString} self-field 分布查询当前字段名称
     * @property {String|DBFieldString} parent-field 分布查询父字段名称
     * @property {String|DBCollectionString} collection 表名
     * @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割
     * @property {String} orderby 排序字段及正序倒叙设置
     * @property {String|JQLString} where 查询条件
     */exportdefault{name:'UniDataPickerView',emits:['nodeclick','change','datachange','update:modelValue'],mixins:[dataPicker],props:{managedMode:{type: Boolean,default:false},ellipsis:{type: Boolean,default:true},showSearch:{type: Boolean,default:false},},data(){return{candidates:[],nodeList:[],}},created(){if(this.managedMode){return}this.$nextTick(()=>{this.load()})},methods:{//搜索框选择员工handleInput(e){if(this.candidates.indexOf(e)!=-1){let index =this.candidates.indexOf(e);let node =this.nodeList[index];
                    console.log(this.candidates.indexOf(e));
                    console.log(node);this._dispatchEvent()this.$emit('nodeclick', node)}//console.log(this.loadData());},//点击选择组别handleClick(item){let text = item.text;for(let i inthis.nodeList){if(this.nodeList[i].parent_value == text){this.$emit('nodeclick',this.nodeList[i])}}this._dispatchEvent()},onPropsChange(){this._treeData =[]this.selectedIndex =0this.load()},load(){if(this.isLocaldata){this.loadData()}elseif(this.dataValue.length){this.getTreePath((res)=>{this.loadData()})}},handleSelect(index){this.selectedIndex = index
            },handleNodeClick(item, i, j){if(item.disable){return}const node =this.dataList[i][j]const text = node[this.map.text]const value = node[this.map.value]if(i <this.selected.length -1){this.selected.splice(i,this.selected.length - i)this.selected.push({
                        text,
                        value
                    })
                    console.log(this.selected);}elseif(i ===this.selected.length -1){this.selected.splice(i,1,{
                        text,
                        value
                    })
                    console.log(this.selected);}if(node.isleaf){this.onSelectedChange(node, node.isleaf)return}const{
                    isleaf,
                    hasNodes
                }=this._updateBindData()if(!this._isTreeView()&&!hasNodes){this.onSelectedChange(node,true)return}if(this.isLocaldata &&(!hasNodes || isleaf)){this.onSelectedChange(node,true)return}if(!isleaf &&!hasNodes){this._loadNodeData((data)=>{if(!data.length){
                            node.isleaf =true}else{this._treeData.push(...data)this._updateBindData(node)}this.onSelectedChange(node, node.isleaf)},this._nodeWhere())return}this.onSelectedChange(node,false)},updateData(data){//新增筛选用户功能ldlet curTreeData=data.treeData;this.candidates =[];this.nodeList =[];for(let i in curTreeData){if(curTreeData[i].parent_value){this.candidates.push(curTreeData[i].text);this.nodeList.push(curTreeData[i])}}this._treeData = data.treeData
                this.selected = data.selected
                if(!this._treeData.length){this.loadData()}else{//this.selected = data.selectedthis._updateBindData()}},onDataChange(){this.$emit('datachange')},onSelectedChange(node, isleaf){if(isleaf){this._dispatchEvent()}if(node){this.$emit('nodeclick', node)}},_dispatchEvent(){this.$emit('change',this.selected.slice(0))}}}</script><style >.uni-data-pickerview {flex:1;/* #ifndef APP-NVUE */display: flex;/* #endif */
        flex-direction: column;overflow: hidden;height:100%;}.error-text {color: #DD524D;}.loading-cover {position: absolute;left:0;top:0;right:0;bottom:0;
        background-color:rgba(255,255,255,.5);/* #ifndef APP-NVUE */display: flex;/* #endif */
        flex-direction: column;
        align-items: center;
        z-index:1001;}.load-more {/* #ifndef APP-NVUE */margin: auto;/* #endif */}.error-message {
        background-color: #fff;position: absolute;left:0;top:0;right:0;bottom:0;padding: 15px;opacity:.9;
        z-index:102;}/* #ifdef APP-NVUE */.selected-area {width: 750rpx;}/* #endif */.selected-list {/* #ifndef APP-NVUE */display: flex;/* #endif */
        flex-direction: row;
        flex-wrap: nowrap;padding:0 5px;
        border-bottom: 1px solid #f8f8f8;}.selected-item {
        margin-left: 10px;
        margin-right: 10px;padding: 12px 0;
        text-align: center;/* #ifndef APP-NVUE */
        white-space: nowrap;/* #endif */}.selected-item-text-overflow {width: 168px;/* fix nvue */overflow: hidden;/* #ifndef APP-NVUE */width: 6em;
        white-space: nowrap;
        text-overflow: ellipsis;-o-text-overflow: ellipsis;/* #endif */}.selected-item-active {
        border-bottom: 2px solid #007aff;}.selected-item-text {color: #007aff;}.tab-c {position: relative;flex:1;/* #ifndef APP-NVUE */display: flex;/* #endif */
        flex-direction: row;overflow: hidden;}.list {flex:1;}.item {padding: 12px 15px;/* border-bottom: 1px solid #f0f0f0; *//* #ifndef APP-NVUE */display: flex;/* #endif */
        flex-direction: row;
        justify-content: space-between;}.is-disabled {opacity:.5;}.item-text {/* flex: 1; */color: #333333;}.item-text-overflow {width: 280px;/* fix nvue */overflow: hidden;/* #ifndef APP-NVUE */width: 20em;
        white-space: nowrap;
        text-overflow: ellipsis;-o-text-overflow: ellipsis;/* #endif */}.check {
        margin-right: 5px;border: 2px solid #007aff;
        border-left:0;
        border-top:0;height: 12px;width: 6px;
        transform-origin: center;/* #ifndef APP-NVUE */transition: all 0.3s;/* #endif */transform:rotate(45deg);}</style>

调用页面

showSearch 是否显示搜索框和多选操作 =》 true/false

<template><view><view>{{treePickTitle}}</view><uni-section :title="treePickTitle" type="line" padding ><uni-data-picker  :showSearch="showSearch":popup-title="treePickTitleSelect":localdata="dataTree" v-model="activeDataTree"
                    @change="onchange" @nodeclick="onnodeclick"></uni-data-picker></uni-section></view></template>

dataTree 格式例子

activeDataTree:"1-1",dataTree:[{text:"一年级",value:"1-0",children:[{text:"1.1班",value:"1-1"},{text:"1.2班",value:"1-2"}]},{text:"二年级",value:"2-0"},{text:"三年级",value:"3-0"}]

bw:不想用text 和value 属性也可以修改


2022/08/19修改
由于很多小伙伴私信我说遇到问题,所以了解到大家可能需要的是不仅仅是搜索和多选的功能,也需要对应下面的标签新增,和删减功能,是我这边上传的视频造成误解啦,今天花费空余时间给大家写了个例子。复制粘贴可用:
步骤:

1,找到项目下的这两个文件 把内容替换成我文章中的内容

在这里插入图片描述
2,调用页面全部代码

<template><view class="container"><uni-card is-full :is-shadow="false"><text class="uni-h6">标签组件多用于商品分类、重点内容显示等场景。</text></uni-card><uni-section title="本地数据" type="line" padding style="height: calc(100vh - 100px);"><uni-data-picker :showSearch="showSearch"  placeholder="请选择班级" popup-title="请选择所在地区":localdata="dataTree" v-model="classes"
                @change="onchange" @nodeclick="onnodeclick" @popupopened="onpopupopened" @popupclosed="onpopupclosed"></uni-data-picker><view class="userSelectBox example-body"><view class="tag-view" v-for="(value,key) in userListSelect":key="key" @click="clearTagAdmin(value)"><uni-tag :text="userList[value]" type="primary"></uni-tag><uni-icons class="clearBtn"  type="clear" size="15" color="#ccc"/></view></view></uni-section></view></template><script>exportdefault{data(){return{showSearch:true,userListSelect:[1,3],userList:['1.1班','1.2班','2.1班','2.2班'],classes:'1-2',dataTree:[{text:"一年级",value:"1-0",children:[{text:"1.1班",value:"1-1",parent_value:"1",id:0,},{text:"1.2班",value:"1-2",parent_value:"1",id:1,}]},{text:"二年级",value:"2-0",children:[{text:"2.1班",value:"2-1",parent_value:"2",id:2,},{text:"2.2班",value:"2-2",parent_value:"2",id:3}]},]}},methods:{clearTagAdmin(value){this.userListSelect =this.userListSelect.filter(item=> item != value);},onnodeclick(data){
                console.log(data);if(data.parent_value){//存在父级let dataId = data.id;this.userListSelect.push(dataId);this.userListSelect =[...newSet(this.userListSelect)]//es6数组去重}},onpopupopened(e){
                console.log('popupopened');},onpopupclosed(e){
                console.log('popupclosed');},onchange(e){
                console.log('---------onchange:', e);}}}</script><style>.title {
        font-size: 14px;
        font-weight: bold;margin: 20px 0 5px 0;}.data-pickerview {height: 400px;border: 1px #e5e5e5 solid;}.popper__arrow {top:-6px;left:50%;
        margin-right: 3px;
        border-top-width:0;
        border-bottom-color: #EBEEF5;}.popper__arrow {top:-6px;left:50%;
        margin-right: 3px;
        border-top-width:0;
        border-bottom-color: #EBEEF5;}.userSelectBox{border: 1px solid #ddd;width:98%;
        min-height: 60px;padding: 5px 1%;
        border-radius:5px;overflow: hidden;}.tag-view{display: inline-block;float: left;
        margin-right:10px;
        margin-bottom:10px;height:24px;
        min-width:24px;
        max-width:50px;position:relative;}.clearBtn{position:absolute;right:-3px;top:-8px;}.example {padding: 15px;
        background-color: #fff;}.segmented-control {
        margin-bottom: 15px;}.button-group {
        margin-top: 15px;display: flex;
        justify-content: space-around;}.form-item {display: flex;
        align-items: center;}.button {display: flex;
        align-items: center;height: 35px;
        margin-left: 10px;}.selectBox {border: 1px solid #ddd;padding: 10px 1%;height: 14px;width:98%;
        border-radius: 5px;}</style>

3,可根据自己需求进行更改:呈现效果如下:
在这里插入图片描述

在这里插入图片描述
希望多多支持哈,点个赞再走 嘻嘻~码字不易。谢谢大家,有问题可私信


本文转载自: https://blog.csdn.net/qq_36958916/article/details/125691460
版权归原作者 anne都 所有, 如有侵权,请联系我们删除。

“uniapp 改写uni-data-picker级联选择器(带搜索和多选)新增列出选择和删除功能”的评论:

还没有评论