ant vue 树形菜单横向显示_快速实现一个简单可复用可扩展的Vue树组件
一、树形数据结构
树形数据是指形如以下的数据结构:
[
{
id: '1',
title: '节点1'
children: [
{
id: '1-1',
title: '节点1-1'
},
{
id: '1-2',
title: '节点1-2'
}
]
},
{
id: '2',
title: '节点2',
children: [
{
id: '2-1',
title: '节点2-1'
},
{
id: '2-2',
title: '节点2-2'
}
]
},
{
id: '3',
title: '节点3'
}
]
这并不是《数据结构与算法》里严格意义上的树定义,严格的树定义,第一层应该是一个根节点,而此处的第一层就包含了多个节点。不过这不重要,实用为上,这样的结构或许更加通用(试想,如果第一层是只包含一个节点的树,和标准定义的树又有什么本质区别呢)。树结构是递归的,它可能有很多级,我们在渲染树结构的时候也采用递归的方式来渲染。
二、Vue树组件实现的两个重要属性
1、组件的name属性
或许我们在平常开发的过程中都很少使用这个属性(至少我是如此),不过这个属性却有两个很重要的作用,摘自Vue官网:
允许组件模板递归地调用自身。注意,组件在全局用 Vue.component() 注册时,全局 ID 自动作为组件的 name。
指定 name 选项的另一个好处是便于调试。有名字的组件有更友好的警告信息。另外,当在有 vue-devtools,未命名组件将显示成 ,这很没有语义。通过提供 name 选项,可以获得更有语义信息的组件树。
这里我们因为要递归地渲染树形结构,即渲染树节点的时候使用当前组件作为子组件,所以会用到name属性。
2、插槽
Vue插槽借鉴于Web components,是在父组件自定义实现子组件部分dom的一个方法,这大大提高了子组件的复用性和扩展性。
下面是一个简单的插槽使用例子。
子组件:
子组件
父组件:
父组件通过插槽插入的内容——具名插槽
渲染结果:父组件可以通过v-slot提供一些插槽来达到组件内容自定义的目的,只要子组件模板里预留了这些插槽的位置。插槽可以有名字作为唯一标识,如也可以不设置名字而使用默认值default;父组件中填充插槽使用v-slot:name填充对应的插槽,name表示填充的插槽名称,未指定名字的插槽填充时使用v-slot:default或v-slot,二者作用是相同的。关于Vue插槽,官网描述很清楚了,这里不再赘述。此处介绍几种插槽的特殊用法。父组件通过默认插槽插入的内容——默认插槽
1)、作用域插槽
默认情况下,父组件模板里通过插槽插入的部分只能访问父组件上下文,如果你需要访问子组件的部分属性,可以通过作用域插槽:在子组件中给slot传递一些prop,然后在父组件插入内容时使用这些prop,示例如下。
子组件:
子组件
父组件:export default {
data () {
return {
nodeData: {
title: '节点1'
}
}
}
}
子组件传到插槽的nodeData的title:{{ someProp.nodeData.title }}
someProp是可以解构的,可以把从子组件传递给插槽的prop解构出来直接使用: v-slot:default="{ nodeData }"。
2)、插槽函数
从Vue2.6.0开始,所有的插槽(包括作用域插槽和普通插槽)都会作为一个函数,并通过vm.$scopeSlots暴露出来,比如上述父组件模板中给子组件插入了一个作用域插槽(名字为默认的default),在子组件实例的$scopeSlots就会暴露对应的函数:传递相应的参数(比如nodeData)调用这个函数,就可以得到插槽对应的虚拟DOM即VNode,在render函数中非常好使。只要你能访问到这个函数,就可以生成对应的虚拟DOM(并不是非得在当前组件),接下来在树组件叶子节点的渲染中,会用到这个用法。
三、树组件渲染的实现
1、树组件调用形式
作为一个可复用的树节点,渲染出来的树结构应该是可以自定义的,同时对于传入组件的prop尽可能简单。
这里设计的prop仅传入一个树形数据treeData,对于每一个节点,使用作用域插槽提供每一个节点的数据来调用者自定义渲染。所以组件调用形式很简单:
{{ nodeData.title }}
这里的调用仅仅把节点的文本渲染出来了,通常结合具体的场景,可能我们会有更多的功能需求,比如展开折叠,删除节点,添加节点等,给组件添加一个ref属性,我们可以方便地调用组件提供的函数。
2、树组件代码实现
通常递归实现树组件会分为两个部分:
树节点渲染组件,该组件通过归调用自身渲染一个子树,一直递归到渲染完全部叶子节点。
供外部调用的树形组件,提供一些外部调用的接口
下面直接给出树组件、节点组件的简单代码实现如下:树节点组件tree-node.vue:
:style="{
paddingLeft: indent
}"
v-if="nextShow">
v-for="(child, idx) of nodeData.children"
:nodeData="child"
:indent="indent"
:key="idx">
export default {
name: 'tree-node',
props: {
nodeData: {
type: Object,
required: true
}
},
components: {
'node-content': {
render (h) {
let slot = this.$parent.tree.$scopedSlots.default
let { nodeData, parentData, level, nextShow } = this.$parent
return (slot ? slot({ parentData, data: nodeData, level, nextShow }) : '
未定义插槽内容
树组件tree.vue:')
}
}
},
data () {
return {
tree: false,
level: 0,
parentData: null,
childrenShow: true,
indent: undefined
}
},
computed: {
nextShow () {
return this.nodeData.children && this.nodeData.children.length && this.childrenShow
}
},
created () {
let parent = this.$parent
if (parent.isTree) {
this.level = 1
} else {
this.level = parent.level + 1
this.parentData = parent.nodeData
}
while (parent && !parent.isTree) {
parent = parent.$parent
}
this.tree = parent
this.indent = this.tree.indent
this.tree.registerNodeComponent(this.nodeData.id, this)
},
beforeDestroy () {
this.tree.removeNodeComponent(this.nodeData.id)
},
methods: {
showChildren (show) {
this.childrenShow = show
}
}
}
v-for="(nodeData, idx) of treeData"
:nodeData="nodeData"
:key="idx">
有几个点值得注意:import treeNode from './tree-node'
export default {
components: {
treeNode
},
props: {
treeData: {
type: Array,
requied: true
},
indent: {
type: String,
default: '20px'
}
},
data () {
return {
isTree: true,
level: 0,
componentMap: {}
}
},
methods: {
registerNodeComponent (id, component) {
this.componentMap[id] = component
},
removeNodeComponent (id) {
this.componentMap[id] = undefined
},
showChildren (id, show) {
this.componentMap[id] && this.componentMap[id].showChildren(show)
}
// 更多功能
}
}
.tree-container
text-align left
树组件的componentMap保存了所有后代组件的引用。这样好处在于:在使用tree组件的时候,我们直接访问的只有树组件,想直接调用叶子节点的相关方法,可以通过树组件做转发。比如想让id为1的节点折叠起后代元素,可以调用this.$refs.tree.showChildren(1, true),在树组件的showChildren函数内,取出对应的节点组件,调用节点组件的方法。
节点自身内容的渲染。节点组件的tree树形保存了树组件的引用,节点自身内容的渲染,使用了一个子组件node-content。而node-content的内容,来自于树组件的插槽,我们通过前面所描述函数形式访问到树组件的插槽,调用函数得到了虚拟DOM,作为组件node-content的内容。当然如果未提供插槽,node-content的内容会是一段提醒含义的html串,提醒使用者插入插槽(你也可以修改为一个默认的渲染,比如渲染出nodeData.title)。
在提供的作用域插槽中,node-content组件向该插槽传递了parentData(上级节点数据), data(本级节点数据), level(层级)等一些可能常用的属性。
上述提供的树组件比较简单,仅仅提供了渲染树形结构、展开/折叠等功能,但是作为一个示例性的树形组件,它还是具有很强地扩展性以及复用性。因为使用Vue,我们用数据控制视图,所以你在使用的过程中想给组件增加比如节点多选、增删节点等操作,其实非常简单,你只用修改你的树形数据,并且在插槽上做相应的视图处理即可(比如增加选择框、添加下级/删除节点等菜单)。具体使用代码可以在github查看,或在线体验:http://wintc.top/laboratory/#/tree。本文完~
ant vue 树形菜单横向显示_快速实现一个简单可复用可扩展的Vue树组件相关推荐
- ant vue 树形菜单横向显示_丝滑般 Vue 拖拽排序树形表格组件Vue-DragTreeTable
今天给小伙伴们分享一款纵享丝滑般体验的Vue拖拽树形表格DragTreeTable. vue-drag-tree-table 基于vue.js实现可拖拽排序的树形表格组件.支持拖拽排序.固定表头.拖拽 ...
- ant vue 树形菜单横向显示_ant design vue menu 导航菜单
ant design vue menu 导航菜单 ant design vue menu 导航菜单是一个网站或者系统的重要功能,通过导航可以对网站或者系统的功能进行分门别类. 水平导航菜单 例子 首页 ...
- ant vue 树形菜单横向显示_Vue--组件Ant- 树形结构菜单
defaultExpandAll :autoExpandParent="true" :treeData="treeData" @select="thi ...
- vue 圆形百分比进度条_快速构建一个圆形的进度条
在一些特别生的网站上,用户需要一个可视化的是示,以表明网站资源仍然在加载.从Spinner到Skeleton屏幕有不同的方法来解决这类的用户体验效果. 如果我们使用的是开箱即用的解决方案,它为我们提供 ...
- django 引入同目录下py文件_快速开发一个简单的Django网站
一.创建工程 1. 在cmd中输入:django-admin.py startproject projectname 2. 修改settings.py文件:在installedapp中增加需要创建的应 ...
- 智能机器人c语言编程,【图片】教你快速制作一个简单的人工智能机器人(懂编程的人进来看)【科幻吧】_百度贴吧...
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 教你快速制作一个简单的人工智能机器人(懂编程的人进来看) 本文我首发于"人工智能吧",叫做<机器人理解人类语言>和< ...
- 流媒体视频服务:快速搭建一个简单的流媒体视频服务(一)
快速搭建一个简单的流媒体视频服务 前言 系统组成 RTMP协议简介 Red5 概述 Red5 服务器搭建 前言 最近自己在研究有关于流媒体播放的技术,网上资料甚少.出于开源精神以及在查阅资料得到各位大 ...
- 一个html写的app首页,如何快速开发一个简单好看的APP控制页面
原标题:如何快速开发一个简单好看的APP控制页面 导读 机智云开源框架为了让开发者快速开发APP,已将用户登录,设备发现,设备配网等功能做成了各个标准模块,仅保留控制页面让开发者自行开发设计,节省了开 ...
- 使用SpringBoot一小时快速搭建一个简单后台管理(增删改查)(超详细教程)
最近也是临近期末了,各种的期末大作业,后台管理也是很多地方需要用到的,为了方便大家能快速上手,快速搭建一个简单的后台管理,我花了两天时间整理了一下 我会从0开始介绍,从数据库的设计到前端页面的引入最后 ...
最新文章
- 盘点 Github 上的高仿 app 项目
- 【项目管理】RUP内容整理
- Android adb.exe程序启动不起来,如何处理
- 【白皮书分享】2020中国硬科技创新白皮书.pdf(附下载链接)
- Awesome Go
- linux的工程管理器是,Linux工程管理器——make
- Python unittest –单元测试示例
- Excel如何从身份证号码中提取性别
- 人工智能5秒免费抠图软件将改变设计行业???
- 百度指数对网站优化有什么作用
- 互联网产品运营——什么是产品运营?
- 轰动全球,一个月7级博客大V是如何炼成的!
- 推荐几款实现内网穿透的实用工具(转载)
- can和could的用法_情态动词can和could用法详解
- dataframe如何定义列名称
- Tushare学习文档(十 电影票房)
- 2017.10.27涩会题大乱斗部分题解
- VS2017安装打包工具;以及无法加载此项目,setup(不兼容),该应用程序未安装、MFC的使用
- 【陈工笔记】# WPS中如何公式居中,公式的编号靠右?#
- 如何在iPhone或iPad上使用Safari私人浏览
热门文章
- flutter创建一个demo
- @Cotroller和@RestCotroller
- 大班线描机器人_大班美术教案机器人
- abap 创建出口历程_SAP ABAP第一,两,三代出口型BADI实现 解释的概念
- c语言学习-输出9*9乘法口诀表
- 不显示样式 引用bootstrap_Bootstrap的引用样式
- OpenShift 4 - Fedora CoreOS (3) - 定制 CoreOS ISO
- 使用.NET Core进行Linux编程3:简介和第2章
- Visual Studio Code 1.45 发布
- PostgreSQL 荣获 2019 年 O'Reilly 终身成就奖