1. 程式人生 > >iview自定義Tree元件內容

iview自定義Tree元件內容

介紹

使用iview框架進行開發的話,一般都有展示樹形結構資料的需求。那麼就用的到其中的Tree元件了。但是其基本架構是滿足不了我們的需求的,基本架構如下:

在這裡插入圖片描述

一般來說一條資料肯定不止展示它的title屬性,我們的需求是展示多個屬性,並且含有多個操作按鈕,具體如下:

在這裡插入圖片描述

這其中得用到 Render 函式來自定義節點顯示內容和互動。

下面就介紹一下Tree元件如何自定義節點內容。

自定義節點內容

先把完整的程式碼貼出來,然後在解釋一波:

<template>
  <Card class="album">
    <Tree
:data="treeData" :load-data="loadData" :render="renderContent">
</Tree> </Card> </template> <script> import { mapActions } from 'vuex' export default { name: 'Album', data () { return { treeData: [], } }, methods: { ...mapActions
([ 'albumCategoryList' ]), loadData (item, callback) { let parentId = item.id || 0 let data = [] this.albumCategoryList({ parentId: parentId }).then((res) => { if (res.status === 1) { data = this.getTree(res.fields)
callback(data) } else { this.$Notice.error({ title: '錯誤', desc: res.msg }) } }).catch(error => { this.$Notice.error({ title: '錯誤', desc: '網路連線錯誤' }) console.log(error) }) }, getTree (tree = []) { let arr = []; if (tree.length !== 0) { tree.forEach(item => { let obj = {}; obj.categoryName = item.categoryName; obj.id = item.id; // 其他你想要新增的屬性 obj.removed = item.removed; // 其他你想要新增的屬性 obj.rank = item.rank; // 其他你想要新增的屬性 obj.imageUrl = item.imageUrl; // 其他你想要新增的屬性 obj.desc = item.desc; // 其他你想要新增的屬性 obj.parentId = item.parentId; // 其他你想要新增的屬性 if(item.child === 1) { obj.children = []; obj.loading = false; } arr.push(obj); }); } return arr }, renderContent (h, { root, node, data }) { return h('span', { style: { display: 'inline-block', width: '100%' } }, [ h('span',[ h('Icon', { style: { marginRight: '8px' } }), h('span', data.categoryName) ]), h('span', { style: { display: 'inline-block', float: 'right', marginRight: '32px' } }, [ h('span', { style: { display: 'inline-block', 'text-align': 'center', width: '25px', marginRight: '40px' } }, data.rank), h('span', { style: { display: 'inline-block', width: '480px', marginRight: '20px' } }, data.imageUrl || ''), h('Button', { props: Object.assign({}, { type: 'primary', size: 'small', }), style: { marginRight: '8px' }, on: { click: () => { this.albumCategoryAdd(data) } } }, '新增'), h('Button', { props: Object.assign({}, { type: 'primary', size: 'small', }), style: { marginRight: '8px' }, on: { click: () => { this.albumCategoryEdit(data) } } }, '編輯'), h('Button', { props: Object.assign({}, { type: 'error', size: 'small', }), on: { click: () => { this.changeAlbumCategoryStatus(data.id, data.removed) } } }, data.removed === 0 ? '啟用' : '停用' ) ]) ]); }, // 頁面載入後 查詢parentID=0 的分類 queryCategoryList (parentId = 0) { console.log('執行專輯分類queryCategoryList') this.albumCategoryList({ parentId: parentId }).then((res) => { if (res.status === 1) { // 這裡給節點賦值 this.treeData = this.getTree(res.fields) } else { this.$Notice.error({ title: '錯誤', desc: res.msg }) } }).catch(error => { this.$Notice.error({ title: '錯誤', desc: '網路連線錯誤' }) console.log(error) }) }, }, mounted () { this.queryCategoryList() } }
</script> <style scoped> </style>

<Tree :data="treeData" :load-data="loadData" :render="renderContent"></Tree>

看過iview中Tree元件介紹的那就知道:data是繫結展示的資料的,:load-data是用於非同步載入子節點的,:render是用於自定義節點內容的。

先看一下我們的資料結構是啥啊:

在這裡插入圖片描述

我這是axios設定的response攔截器攔截的資料截了個圖,也應該可以看清的吧…

child屬性用來表示此節點是不是有子節點,1表示有,0表示無。別的屬性就不介紹了。

首先,我們開啟頁面的時候應該把所有的頂級父節點即parentId = 0的節點展示出來,這是需要查詢資料庫的,所以在vue生命週期mounted函式中執行了頂級父節點的查詢函式,即:

mounted () {
	this.queryCategoryList()
}
	  // 頁面載入後 查詢parentID=0 的分類
      queryCategoryList (parentId = 0) {
        console.log('執行專輯分類queryCategoryList')
        this.albumCategoryList({
          parentId: parentId
        }).then((res) => {
          if (res.status === 1) {
			// 這裡給節點賦值
            this.treeData = this.getTree(res.fields)
          } else {
            this.$Notice.error({
              title: '錯誤',
              desc: res.msg
            })
          }
        }).catch(error => {
          this.$Notice.error({
            title: '錯誤',
            desc: '網路連線錯誤'
          })
          console.log(error)
        })
      },

this.albumCategoryList是使用axios傳送請求的函式,這裡沒有展示出來,但請求得到的資料結構在上面也展示出來了,應該OK的吧!

this.getTree(res.fields) 這個函式主要是轉換一下資料結構,其中要關注一下,當資料的child屬性為1即其有子節點時,obj.children = []; obj.loading = false;這兩個屬性是必須附上的,否則不會應用非同步載入效果。具體的可看看上面的完整程式碼。

下面看一下自定義節點內容的函式:

renderContent (h, { root, node, data }) {
        return h('span', {
          style: {
            display: 'inline-block',
            width: '100%'
          }
        }, [
          h('span',[
            h('Icon', {
              style: {
                marginRight: '8px'
              }
            }),
            h('span', data.categoryName)
          ]),
          h('span', {
            style: {
              display: 'inline-block',
              float: 'right',
              marginRight: '32px'
            }
          }, [
            h('span', {
              style: {
                display: 'inline-block',
                'text-align': 'center',
                width: '25px',
                marginRight: '40px'
              }
            }, data.rank),
            h('span', {
              style: {
                display: 'inline-block',
                width: '480px',
                marginRight: '20px'
              }
            }, data.imageUrl || ''),
            h('Button', {
              props: Object.assign({},  {
                type: 'primary',
                size: 'small',
              }),
              style: {
                marginRight: '8px'
              },
              on: {
                click: () => { this.albumCategoryAdd(data) }
              }
            }, '新增'),
            h('Button', {
              props: Object.assign({},  {
                type: 'primary',
                size: 'small',
              }),
              style: {
                marginRight: '8px'
              },
              on: {
                click: () => { this.albumCategoryEdit(data) }
              }
            }, '編輯'),
            h('Button', {
              props: Object.assign({},  {
                type: 'error',
                size: 'small',
              }),
              on: {
                click: () => { this.changeAlbumCategoryStatus(data.id, data.removed) }
              }
            }, data.removed === 0 ? '啟用' : '停用' )
          ])
        ]);
      },

這個render函式就不具體解釋了吧,就是根據你定義的treeData陣列中每一條資料來編織你要的樣式。

最後就是非同步載入子節點了:

loadData (item, callback) {
        let parentId = item.id || 0
        let data = []
        this.albumCategoryList({
          parentId: parentId
        }).then((res) => {
          if (res.status === 1) {
            data = this.getTree(res.fields)
            callback(data)
          } else {
            this.$Notice.error({
              title: '錯誤',
              desc: res.msg
            })
          }
        }).catch(error => {
          this.$Notice.error({
            title: '錯誤',
            desc: '網路連線錯誤'
          })
          console.log(error)
        })
      },

可以看到這裡邏輯和queryCategoryList函式差不多,只是查詢條件變成了當前節點的id,表示查詢當前節點的子節點。

PS:上面的完整程式碼是一整個VUE頁面拷貝下來的,除了albumCategoryList這個axios函式需要自己實現以外