在vue js中递归显示下拉列表

时间:2018-12-30 04:13:57

标签: vue.js

我有一个名为商品的表名

id   parent_id  title
1        0      Profile
2        1      About Us
3        1      Why Us?
4        0      Kbow Us

现在我想在vue laravel上创建下拉菜单,以使其在父类别下以适当的缩进或-标记深度递归地显示子类别。例如:

<select>
<option value="1">Profile</option>
<option value="2">-About Us</option>
<option value="3">--Why Us</option>
<option value="4">Kbow Us</option>
</select>

我想为vue js中子类别的任何深度递归生成动态结构,就像上面一样。

1 个答案:

答案 0 :(得分:0)

我将使用过滤器和递归函数将每个选项返回,直到未找到任何父项,从而跟踪深度并使用该深度附加缩进标记。

由于您可能会将文章传递到视图文件(在PHP数组或集合中),因此可以将数据传递到vue组件,例如:

<my-nested-select :articles='{!! json_encode($articles) !!}'></my-nested-select>

以下是使用生成的数据的示例,过滤器是重要的部分:

new Vue({
  el: '#app',
  data: () => ({ 
    items: [],
    selected: null
  }),
  created () {
    // 1. Create some dummy data where each option has an increasing chance of being nested.
    const tmp = []
  
    for (let i = 1; i <= 50; i++) {
      let isChild = !!tmp.length ? Math.random() < ((i / 50) * tmp.length || 1) : null
      
      let parent_id = isChild ? Math.ceil(Math.random() * tmp.length - 1) : null
          
      tmp.push({
        id: i,
        parent_id,
        text: `Option ${i}`
      })
    }
     
    // 2. Sort the generated data so child options are in order following their parent option.
    this.items = tmp.reduce((items, item) => {
      if (!items.length || !item.parent_id) {
        items.unshift(item)
      } else {
        const index = items.findIndex(({ id }) => id === item.parent_id)
        
        if (index) {
          items.splice(index, 0, item)
        }
      }
      
      return items
    }, []).reverse()
  },
  filters: {
    depth (option, items) {    
      let depth = 0
      
      // 3. The magic happens here with a recursive function to find the depth to which each option is nested.
      const pad = ({ parent_id }) => {        
        if (!!parent_id) {
          depth += 1
          
          let parent = items.find(({ id }) => id === parent_id)
          
          if (!parent) {
            return depth
          }
          
          return pad(parent)
        }
        
        return depth
      }
      
      // 4. Call the recursive function above, create an array of hyphens and concat them together with the option's text.
      return Array(pad(option)).fill('-').concat([' ', option.text]).join('')
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <select v-model="selected">
    <option v-for="option in items" :value="option.id" :key="option.id">{{ option | depth(items) }}</option>
  </select>
  
  <h4>Data</h4>
  
  <ul>
    <li v-for="item in items" :key="item.id"><pre><code>{{ item }}</code></pre></li>
  </ul>
</div>