<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # picker的三級聯動 ## 序言 uView2的picker和平常其他的picker不同,因為它接收的數據源是三列數組,需要開發者自己根據需求調整列索引來滿足多列聯動的需求,但后端給的數據格式通常是一個帶children的樹形結構,無法直接適用于uView2的picker。 ? 本文主要講解對于不同數據格式實現多列聯動的示例,開發者可以根據實際需求更加定制化的開發。 ## 實際應用場景 **全國省市區的三級聯動**。 ? 這種組件因為應用場景廣泛,DCloud的插件市場也有很多的示例,但是有一個缺陷:對于需要保證數據統一性的場景下無法滿足需求,因為這樣的插件都是直接把省市區數據源放前端源碼里(如city,json, area.js),而中國區縣行政規劃又年年在變動,一旦前后端使用的數據源不一致,就有可能出現用戶選擇的位置在服務端查不到的情況。 ## 應該如何做 ? 我們來考慮用戶點開省市區的picker時候所看到的現象和交互邏輯:首先,用戶不會一下子看到全國3500多個區縣的數據,一開始只會看到【全國的省(包括直轄市在內),北京市,北京市的區】,等用戶滾動省的時候,才需要展示對應的市,滾動市的時候,才需要展示對應的區縣,發現沒有,這個渲染實際上是類似于**懶加載**的。 ? 所以我們只需要一個**能夠根據父id區列出所有子id**的方法就可以了,并不需要糾結如何動態設置滾動索引列。當然樹形格式不好做查詢,所以我們先把數據格式化成扁平的數組,如果后端本來返回的就是平鋪的數組,則我們可以省略此步驟。 ```JS function parseTree(tree) { const res = [] array.forEach(item => { // 如果item中有children,則遞歸調用 item.parentId = item.parentId || 0; let id = item.id let children = item.children if (children) { children.forEach(child => child.parentId = id) res.push(...parseTree(children)) } res.push(item) }) return res } ``` 通過上述步驟,我們就把帶children樹形嵌套的樹形結構格式化成了帶parentId的扁平數組。 然后我們還需要根據parentId去篩選數據的函數 ```js let data = parseTree(cities) // 先保存好數據 function findByParentId(id) { return data.filter(item => item.parentId === id) } ``` 完成了上述步驟后,我們就可以設計picker的交互流程了: 1. 先設計用戶一開始點擊picker時候出現的場景 ```js let col1 = findByParentId(0) // 這個主要取決于數據格式,如果說返回的有一個唯一的祖先節點(例如中國,id是100000),則直接傳入100000即可,如果沒有這個,而是直接就給34個省級行政區,則需要傳0 let col2 = findByParentId(col1[0].id) // 因為默認時候肯定停留在第一個選項,所以查出它的直接子節點放到第二列就可以。 let col3 = findByParentId(col2[0].id) // 同理設置第三列 let columns = [col1, col2, col3] ``` 這個columns就可以直接作為picker的columns屬性去設置picker的默認值了。 2. 用戶滾動列的時候出現的場景 ? 在picker的change回調中我們可以獲得用戶當前滾動的列和三列的值,通過它,我們可以設置它子列的值(使用setColumnValues)以達到聯動的效果。 ```vue <template> <u-picker ref="uPicker" @change="handlePickerChange" :columns="columns" /> </template> <script> let areas; export default { data() { return { columns: [], } }, // 見上方說明 async mounted() { let res = await api.getAreas() areas = parseTree(res) let col1 = findByParentId(0) // 這個主要取決于數據格式,如果說返回的有一個唯一的祖先節點(例如中國,id是100000),則直接傳入100000即可,如果沒有這個,而是直接就給34個省級行政區,則需要傳0 let col2 = findByParentId(col1[0].id) let col3 = findByParentId(col2[0].id) this.columns = [col1, col2, col3] }, methods: { handlePickerChange({columnIndex, value]}) { const { uPicker } = this.$refs; // 獲取組件實例 if(columnIndex == 0) { // 用戶滾動的是第一列,要同時設置第二列和第三列的值 let currentVal= value[0] let col2 = findByParentId(currentVal.id) let col3 = findByParentId(col2[0].id) uPicker.setColumValues(1, col2) uPicker.setColumValues(2, col3) } else if (columnIndex == 1) { // 用戶滾動的是第二列,只需要設置第三列的值就可以 let currentVal= value[1] let col3 = findByParentId(currentVal.id) uPicker.setColumValues(col3) } }, findByParentId(id) { return areas.filter(item => item.parentId === id) } } } </script> ``` ## 源碼示例 下面給出完整的TreeSelect類的實現供大家參考,僅通過基礎方式構建,可自己擴展。 ```js class TreeSelect { constructor(data, {key,props,root}) { this._key = key || 'id'; this._childrenProps = props || 'children'; this._root = root || '0'; this._arr = this.parseTreeToArray(data); this._len = this._arr.length || 1; } // 把樹形結構變成帶parentID的二維數組 parseTreeToArray = (array) => { const res = [] array.forEach(item => { // 如果item中有children,則遞歸調用 item.parentId = item.parentId || this._root; let id = item[this._key] let children = item[this._childrenProps] if (children) { children.forEach(child => child.parentId = id) res.push(...this.parseTreeToArray(children)) } res.push(item) }) return res } // 根據父id獲取直接子節點 findChildrenPyParentID = (id) => this._arr.filter(item => item.parentId === id) init = () => { const arr = new Array(this._len) let cols = [[],[],[]] cols[1] = this.findChildrenPyParentID(this._root) cols[2] = cols[1] ? this.findChildrenPyParentID(cols[1][0][this._key]) : [] cols[3] = cols[2] ? this.findChildrenPyParentID(cols[2][0][this._key]) : [] for (let i = 0; i < this._len; i++) { arr[i] = cols[i] } return arr } } ``` > 本文作者:不愛喝橙子汁
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看