iview自定义Tree组件内容

版权声明:本文为博主原创文章,未经博主允许不得转载 https://blog.csdn.net/liujun03/article/details/84307344

介绍

使用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函数需要自己实现以外

猜你喜欢

转载自blog.csdn.net/liujun03/article/details/84307344
今日推荐