人員選擇樹,搜索自動篩選功能 (vue+chosen+zTree)

要實現的功能截圖:
這裏寫圖片描述php

要求:
一、點擊收件人輸入框能夠根據拼音自動篩選數據,而且標記已經選擇的數據,沒有結果的時候提示,相應的更新左邊樹節點狀態
二、勾選樹右側樹的節點左側輸入框出現一一對應的節點名稱html

用到的插件
vue+chosen+ztree
vue:組件化的MVVM庫
chosen:基於jquery的單選列表和多選列表加強插件
ztree:基於jquery的樹插件vue

分析
chosen插件已經能夠實現要求1中的大部分效果,咱們只須要預先提供chosen須要的數據,經過輸入框值的變化實現左右兩側數據一 一對應,最後點擊發送獲取最終的數據集合IDnode

具體實現:
1、左側選擇數據,右側樹節點更新
chosen須要的html結構jquery

//只須要提供包含數據的select標籤便可,該select默認隱藏,chosen依據該數據構建新的html結構
<select name="dept" style="width:150px;" id="dept" class="dept_select" multiple="multiple"> 
    //loop start
    <option value="部門1">部門1</option>
    <option value="部門2">部門2</option>
    <option value="部門3">部門3</option>
    //loop end
</select>

//chosen初始化
$(function(){
    $('.dept_select').chosen({
        no_results_text:'沒有結果',
        allow_single_deselect:true
    });
});

這樣要求1中的大部分效果就實現了,option裏面的數據咱們須要經過接口從後臺獲取,這裏採用vue解析數據,相應的html結構和js爲:ajax

//基於vue解析的html結構
<select data-placeholder="選擇發件人" class="chosen-select form-control" tabindex="-1" multiple="multiple">
    <template v-for='key in zmailTree'>
            <option v-for='item in key.userList' value='{{item.id}}'>{{item.name}}</option>
    </template>
</select>

//vue實例
var zmailForm=new Vue({
    el:'#zmail-form',
    ready:function(){
        var that=this;
        var getToken=$.cookie('dcValidate');
        $.ajax({  
            type:'get',
            async:false,
            url:'後臺數據接口地址',
            dataType: "json",  
            success: function(msg){
                that.$set('zmailTree', msg);
            }
        });
    },
    data:{
        zmailTree:[]
    }
});
//總結:經過vue獲取後臺數據,將json數據賦值給zmailTree這個數組,它是含有層級結構的,咱們不須要輸出層級結構,只須要輸出裏面的人員就好了,可是實踐中發現一我的問題,數據解析了,鼠標點擊輸入框出現的下拉列表中並無出現咱們剛纔解析出來的數據,咱們須要VUE的Vue.nextTick方法,延遲迴調chosen初始化代碼:

//延遲初始化chosen
Vue.nextTick(function () {
    $('#zmail-select').chosen({
        no_results_text: '沒有找到該結果',// 當檢索時沒有找到匹配項時顯示的提示文本
        search_contains: true //從任意位置開始檢索
    });
});

而後出現了下面的效果:
這裏寫圖片描述
接下來咱們要作的就是勾選與左側選擇的數據相對應的節點。chosen提供了一個change方法,該方法當選擇的值發生改變時觸發,有這個方法咱們就很容易根據select值的變化來勾選右側樹的節點json

$('select.chosen-select').on('change', function(){
    // 用戶改變了選擇,快快處理
});

咱們一樣要寫到Vue.nextTick中,其中涉及到樹的操做請參照zTree APIapi

//延遲初始化chosen
Vue.nextTick(function () {
    $('#zmail-select').chosen({
        no_results_text: '沒有找到該結果',// 當檢索時沒有找到匹配項時顯示的提示文本
        search_contains: true //從任意位置開始檢索
    });
    $('#zmail-select').on('change', function(){
        //用戶改變了值以後做以下處理
        var treeObj = $.fn.zTree.getZTreeObj("zmail-tree");//獲取目標容器
        treeObj.expandAll(true);//展開全部樹節點
        treeObj.checkAllNodes(false);//清空全部樹節點
        $("#zmail-select option:selected").each(function(i,obj){//循環選擇出來的數據
            //根據節點數據的ID屬性搜索,獲取條件徹底匹配的節點數據,注:option中解析的是ID
            var node = treeObj.getNodeByParam("id", obj.value, null);
            //將選出的節點所有勾選
            treeObj.checkNode(node, true, true);
        });
    });
});
//總結:輸入框的值只要發生了改變option的狀態就會自動更新,咱們根據已選中的option的value(即ID),加上ztree已有的getNodeByParam方法來獲取與左側數據ID一一對應的樹中的節點,而後經過checkNode方法勾選這些節點

到這裏要求1中的效果咱們就所有實現了。數組

2、勾選樹節點,左側輸入框數據更新服務器

//樹的html結構,不要忘記寫ztree這個class,不然不顯示數據
<ul class="ztree" id="zmail-tree">
        
</ul>
//--------樹初始化代碼js-----------
//人員樹基本設置
var zmailTreeSet={
    view:{
        dblClickExpand:false
    },
    async:{
        enable:true,
        type:'get',
        url:'服務器數據地址',
    },
    data:{
        simpleData:{
            enable:true,
            idKey:'id',
            pIdKey:'parentId'
        },
        key:{
            children:'userList'
        }
    },
    check:{
        enable:true,
        chkboxType:{'Y':'s','N':'s'}
    },
    callback:{
        onCheck:zmailCheck
    }
};

//勾選節點以後要處理的回調函數
function zmailCheck(){

}

//初始化人員樹
$.fn.zTree.init($('#zmail-tree'),zmailTreeSet);

zmailCheck方法中實現的思路
(1)首先獲取點擊複選框的節點

var zmaObj = $.fn.zTree.getZTreeObj(treeId);//getZTreeObj插件方法,獲取目標ID
var zmaNodes = zmaObj.getCheckedNodes(true);//getCheckedNodes獲取輸入框被勾選的節點集合

(2)其次清空select中的選中狀態,將其恢復到初始狀態,

$("#zmail-select option").each(function(j,obj){
obj.selected='';
});

(3)根據勾選的節點集合使select中的相應option選中,此處判斷的關鍵是數據id

for(var i = 0;i < zmaNodes.length; i++){
    if(typeof(zmaNodes[i].userList) == 'undefined'){//若是該節點的userList屬性爲空說明不是父節點,存取它的值,若是不爲空則跳過
        $("#zmail-select option[value="+zmaNodes[i].id+"]").prop('selected','selected');
    }
}

(4)更新select option列表

//循環外更新select列表
$("#zmail-select").trigger('chosen:updated');

完整的zmailCheck()代碼爲:

function zmailCheck(){
var zmaObj = $.fn.zTree.getZTreeObj(treeId);
    var zmaNodes = zmaObj.getCheckedNodes(true);
    $("#zmail-select option").each(function(j,obj){
        obj.selected='';
    });
    for(var i = 0;i < zmaNodes.length; i++){
        if(typeof(zmaNodes[i].userList) == 'undefined'){
            $("#zmail-select option[value="+zmaNodes[i].id+"]")[0].selected='selected';
        }
    }
    $("#zmail-select").trigger('chosen:updated');
}

至此要求2的效果咱們也實現了。

總結
這個功能的完成離不開對zTree和chosen這兩個插件的熟練使用,chosen用到的API爲change方法、chosen:updated方法,ztree用到的方法爲:getNodeByParam(),checkNode(),getCheckedNodes(),checkAllNodes(),expandAll()。
實現左側=》右側功能關鍵點:選出option的selected狀態id,經過getNodeByParam()獲取含有該ID的全部節點,而後使用checkNode()使這些節點的狀態變爲選中;
右側=》左側實現的關鍵點:經過getCheckedNodes()獲取全部選中的節點,根據選中的節點ID使左側的select下的option selected狀態變爲true,循環結束後('chosen:updated')更新option列表。

這個功能還有不完美的地方,那就是獲取後臺數據那裏,我說事後臺數據是有層級的,我如今只循環了兩次,只取出了二級列表,若是層級有三級四級五級那獲取的仍是二級列表,vue我也剛開始學,不知道循環後臺數據那裏如何一勞永逸的獲取不帶層級的全部後續動態添加的子級列表。
爲了便於討論給你們看下我從後臺獲取的json數據:

[
    {
        "id": "20160912113609940493862810692577", 
        "name": "xx公司", 
        "parentId": "0", 
        "userList": [
            {
                "id": "20160912113613185306623590148664", 
                "name": "演示賬號"
            }, 
            {
                "id": "20160912113613154939672576045528", 
                "name": "成員1"
            }, 
            {
                "id": "20160919121104625924937109002003", 
                "name": "成員2"
            }
        ]
    }, 
    {
        "id": "20160912113611625082971312564873", 
        "name": "組1", 
        "parentId": "20160912113609940493862810692577", 
        "userList": [
            {
                "id": "20160912113613138161662196502779", 
                "name": "成員1"
            }, 
            {
                "id": "20160912113613044493434182821910", 
                "name": "成員2"
            }, 
            {
                "id": "20160912113613169436263538841431", 
                "name": "成員3"
            }, 
            {
                "id": "20160912113613169255388288458627", 
                "name": "成員4"
            }, 
            {
                "id": "20160912113613185135119969199907", 
                "name": "成員5"
            }
        ]
    }, 
    {
        "id": "20160912113611625563131574216031", 
        "name": "組2", 
        "parentId": "20160912113609940493862810692577", 
        "userList": [
            {
                "id": "20160912113613044536244270423866", 
                "name": "成員1"
            }, 
            {
                "id": "20160912113613044570977235101231", 
                "name": "成員2"
            }, 
            {
                "id": "20160912113613044945364721175243", 
                "name": "成員3"
            }, 
            {
                "id": "20160912113613138666099077077505", 
                "mobileNum": "00010656364", 
                "name": "成員4"
            }, 
            {
                "id": "20160912113613154114377983132349", 
                "name": "成員5"
            }, 
            {
                "id": "20160912113613169433129887352698", 
                "mobileNum": "000610919", 
                "name": "成員6"
            }, 
            {
                "id": "20160912113613169883649070173455", 
                "name": "成員7"
            }, 
            {
                "id": "20160912113613185006644025528363", 
                "name": "成員8"
            }, 
            {
                "id": "20160912113613185400355507045112", 
                "name": "成員9"
            }
        ]
    }, 
    {
        "id": "20160919115007372634170390528661", 
        "name": "組3", 
        "parentId": "20160912113609940493862810692577", 
        "userList": [
            {
                "id": "20160914151121249285889869855783", 
                "name": "成員1"
            }, 
            {
                "id": "20160912113613060689705413198400", 
                "name": "成員2"
            }, 
            {
                "id": "20160912113613060223674583460143", 
                "name": "成員3"
            }, 
            {
                "id": "20160912113613154692470389028360", 
                "mobileNum": "00093049532", 
                "name": "成員4"
            }
        ]
    }
]

文章來源:個人博客

相關文章
相關標籤/搜索