Jack Huang's Blog


  • 首页

  • 标签

  • 归档

  • 搜索

C++虚函数与纯虚函数

发表于 2019-09-15 | 更新于 2024-04-20

在面向对象程序设计领域,C++、Object Pascal 等语言中有虚函数(英语:virtual function)或虚方法(英语:virtual method)的概念。这种函数或方法可以被子类继承和覆盖,通常使用动态调度实现。

纯虚函数或纯虚方法是一个需要被非抽象的派生类覆盖(override)的虚函数. 包含纯虚方法的类被称作抽象类; 抽象类不能被直接实例化。 一个抽象基类的一个子类只有在所有的纯虚函数在该类(或其父类)内给出实现时, 才能直接实例化. 纯虚方法通常只有声明(签名)而没有定义(实现),但有特例情形要求纯虚函数必须给出函数体定义.

虚函数示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# include <iostream>
# include <vector>

using namespace std;
class Animal
{
public:
virtual void eat() const { cout << "I eat like a generic Animal." << endl; }
virtual ~Animal() {}
};

class Wolf : public Animal
{
public:
void eat() const { cout << "I eat like a wolf!" << endl; }
};

class Fish : public Animal
{
public:
void eat() const { cout << "I eat like a fish!" << endl; }
};

class GoldFish : public Fish
{
public:
void eat() const { cout << "I eat like a goldfish!" << endl; }
};


class OtherAnimal : public Animal
{
};

int main()
{
std::vector<Animal*> animals;
animals.push_back( new Animal() );
animals.push_back( new Wolf() );
animals.push_back( new Fish() );
animals.push_back( new GoldFish() );
animals.push_back( new OtherAnimal() );

for( std::vector<Animal*>::const_iterator it = animals.begin();
it != animals.end(); ++it)
{
(*it)->eat();
delete *it;
}

return 0;
}

以下是虚函数 Animal::eat() 的输出:

1
2
3
4
5
I eat like a generic Animal.
I eat like a wolf!
I eat like a fish!
I eat like a goldfish!
I eat like a generic Animal.

纯虚函数示例

在C++语言中, 纯虚函数用一种特别的语法[=0]定义。

1
2
3
4
class Abstract {
public:
virtual void pure_virtual() = 0;
};

纯虚函数的定义仅提供方法的原型. 虽然在抽象类中通常不提供纯虚函数的实现, 但是抽象类中可以包含其实现, 而且可以不在声明的同时给出定义[2]. 每个非抽象子类仍然需要重载该方法, 抽象类中实现的调用可以采用以下这种形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
void Abstract::pure_virtual() {
// do something
}

class Child : public Abstract {
virtual void pure_virtual(); // no longer abstract, this class may be
// instantiated.
};

void Child::pure_virtual() {
Abstract::pure_virtual(); // the implementation in the abstract class
// is executed
}

参考链接

  1. 虚函数和纯虚函数的区别,by hackbuteer1.
  2. 虚函数,by wikipedia.
  3. C++中虚析构函数的作用,by StarLee.
  4. 开源免费的C/C++网络库(c/c++ sockets library) 七剑下天山,by 工程师WWW.
  5. VS2010中属性页中,C/C++ –>预处理器定义,by J.M.Liu.
  6. 深入理解C/C++混合编程(关于#ifdef __cplusplus extern “C” {…}的用法),by zzwdkxx.
  7. 带你玩转 Visual Studio——带你多工程开发,by luoweifu.
  8. c++中冒号(:)和双冒号(::)的用法,by 小金乌会发光-Z&M.
  9. C++ 构造函数总结,by chaibubble.
  10. 详谈C++保护成员和保护继承,by C语言中文网.
  11. c++ 内联函数(一看就懂),by 兴趣斗士.
  12. 浅析C++类的内存布局,by 冯Jungle.
  13. 图说C++对象模型:对象内存布局详解,by melonstreet.
  14. C++ 对象的内存布局,by 陈皓.
  15. C++类对象的内存布局,by 一叶知秋dong.
  16. C++中类所占的内存大小以及成员函数的存储位置,by SOC罗三炮.
  17. struct的用法和struct的对齐原则,by 马小超i.

Ubuntu16.04编译安装OSG

发表于 2019-09-14

OpenSceneGraph是一个开源高性能3D图形工具包,应用程序开发人员在视觉模拟,游戏,虚拟现实,科学可视化和建模等领域使用。 它完全使用标准C ++和OpenGL编写,可在所有Windows平台,OSX,GNU / Linux,IRIX,Solaris,HP-Ux,AIX和FreeBSD操作系统上运行。 OpenSceneGraph现已成为世界领先的场景图技术,广泛应用于视觉,空间,科学,石油天然气,游戏和虚拟现实行业。本文主要记录在Ubuntu 16.04下编译安装OpenSceneGraph的过程。

下载OSG源代码

1
2
3
# cd ~/software
# git clone https://github.com/openscenegraph/OpenSceneGraph.git
# git checkout OpenSceneGraph-3.6.4

下载安装依赖

安装OSG编译所需依赖

1
# sudo apt-get build-dep openscenegraph

下载OSG数据资源

1
2
3
# cd ~/software
# wget http://www.openscenegraph.org/downloads/stable_releases/OpenSceneGraph-3.4.0/data/OpenSceneGraph-Data-3.4.0.zip
# unzip OpenSceneGraph-Data-3.4.0.zip

编译安装

1
2
3
4
5
# cd ~/software/openscenegraph
# cmake .
# make
# sudo make install
# sudo ldconfig -v //如找不到相关osg库,可运行该命令

运行示例

编辑.bashrc文件,添加如下环境变量:

1
2
3
export PATH=${PATH}:/home/myaccount/software/OpenSceneGraph/bin
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/home/myaccount/software/OpenSceneGraph/lib
export OSG_FILE_PATH=/home/myaccount/software/OpenSceneGraph-Data:/home/myaccount/OpenSceneGraph-Data/Images

使用如下命令运行示例:

1
sh ./runexamples.bat

参考链接

  1. Getting Started,by OpenSceneGraph.
  2. ubuntu 环境 安装OSG,by qing101hua.
  3. OSG Data Resources,by OpenSceneGraph.

VSCode离线安装插件

发表于 2019-09-07 | 更新于 2023-08-18

Visual Studio Code(简称VS Code)是一个由微软开发,同时支持Windows 、 Linux和macOS等操作系统且开放源代码的代码编辑器。与Sublime相比,VSCode开源,且有强大的社区支持,各种插件层出不穷。因为工作原因,需要在离线情况下使用VSCode。为了增强VSCode的功能,需要离线情况下安装其插件。具体方法如下:

下载VSCode插件

从VSCode的官方市场Extensions for the Visual Studio family of products搜索和下载插件。官方市场下载VSCode插件可能会下载失败,可以跑到插件的github代码库,下载其最新发布版。

下载VSCode插件

图1 下载VSCode插件

离线安装VSCode插件

打开VSCode的软件,选择左侧Extension,点击“…”,选择“从VSIX安装”,选择离线下载的VSCode插件进行安装。

离线安装VSCode插件

图2 离线安装VSCode插件

下载旧版本VSCode插件

新版本VSCode插件对VSCode的版本要求也高,会导致新版本VSCode插件无法在旧版本VSCode中无法安装的问题。因此,需要下载旧版本VSCode插件,但是官网上只能下载最新的VSCode插件,因此需要一种方法来解决改问题。具体方法请参考vscode下载之前版本插件,本质上就是修改VSCode插件下载链接中的版本号参数。

参考链接

  1. Visual Studio Code,by wikipedia.
  2. Extensions for the Visual Studio family of products,by vscode.
  3. GitHub最热!码代码不得不知的所有定律法则,by Dave Kerr.
  4. vscode下载之前版本插件,by itas109.

Vue-js父子组件渲染过程简介

发表于 2019-09-03 | 更新于 2022-08-21

Vuejs组件化开发是前端工程化的一个重要里程碑。在实际开发过程中,子组件渲染得不到理想的视觉效果。导致这一问题的原因埋藏在Vuejs父子组件的渲染过程。因此简单介绍Vuejs父子组件的渲染过程。

加载渲染过程

父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

子组件更新过程

父beforeUpdate->子beforeUpdate->子updated->父updated

父组件更新过程

父beforeUpdate->父updated

销毁过程

父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

参考链接

  1. vue父子组件的渲染顺序, by rosenWang.
  2. Vue-js入门简介,by jackhuang.
  3. inheritAttrs、vm.$listeners 、vm.$attrs 详解,by 简单tao的简单.

vuejs组件间通信的方法

发表于 2019-09-02 | 更新于 2023-08-30

Vuejs一个吸引人的地方是可以进行组件化开发,避免了前端开发的无序状态。组件无法单独工作,必然会跟父子组件或兄弟组件之间进行通信,以合作实现某种功能。下面即简单介绍Vuejs组件之间的各种通信方式。

方法一、props/$emit

  • 父组件向子组件传值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 父组件中
<template>
<div class="section">
<com-article :articles="articleList" @onEmitIndex="onEmitIndex"></com-article>
<p>{{currentIndex}}</p>
</div>
</template>

<script>
import comArticle from './test/article.vue'
export default {
name: 'HelloWorld',
components: { comArticle },
data() {
return {
currentIndex: -1,
articleList: ['红楼梦', '西游记', '三国演义']
}
},
methods: {
onEmitIndex(idx) {
this.currentIndex = idx
}
}
}
</script>
  • 子组件向父组件传值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div>
<div v-for="(item, index) in articles" :key="index" @click="emitIndex(index)">{{item}}</div>
</div>
</template>

<script>
export default {
props: ['articles'],
methods: {
emitIndex(index) {
this.$emit('onEmitIndex', index)
}
}
}
</script>

方法二、$emit/$on

方法三、vuex

方法四、$attrs/$listeners

方法五、provide/inject

Vue2.2.0新增API,这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。一言而蔽之:祖先组件中通过provider来提供变量,然后在子孙组件中通过inject来注入变量。
provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。

需要注意的是:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。

虽说provide 和 inject 主要为高阶插件/组件库提供用例,但如果你能在业务中熟练运用,可以达到事半功倍的效果!

方法六、$parent / $children与 ref

参考链接

  1. Vue 组件间通信六种方式(完整版),by 浪里行舟.
  2. 逐行剖析 Vue.js 源码,by 难凉热血.
  3. Vue 组件间通信的八种方式,by ikoala.

客户端使用JS导出CSV文件及中文乱码问题解决方案

发表于 2019-08-27 | 更新于 2020-05-14

在浏览器端无需服务器端支持,直接将JS Array数据导出成CSV文件并下载,是一个常见的开发需求。具体方法如下:

1
2
3
4
5
6
7
8
9
var csvContent= this.$refs.flightInfoGrid.exportdata('csv')
var link = document.createElement('a');
// "\ufeff"是为了解决CSV中文乱码问题
var blob = new Blob(["\ufeff" +csvContent],{type: 'text/csv;charset=utf-8;'});
var url = URL.createObjectURL(blob);
link.href = url;
link.setAttribute('download', 'FlightInfo.csv');
link.click();
document.body.removeChild(link);

中文乱码问题分析

utf-8保存的csv格式要让Excel正常打开的话,必须加入在文件最前面加入BOM(Byte order mark)。

ANSI的话是可以做到正常显示和保存,但是这是有前提的,就是必须在你的电脑(区域和语言设置)把对非Unicode字符处理设置为Chinese,如果是English的话,显示照样是乱码。

Unicode的csv,Excel就根本不支持,打开虽然可以显示不乱码,但是已经不是按逗号显示在不同的单元格里面了,而是按行显示在第一个单元格里面。

BOM(byte-order mark),即字节顺序标记,它是插入到以UTF-8、UTF16或UTF-32编码Unicode文件开头的特殊标记,用来识别Unicode文件的编码类型。具体编码如下表:

BOM Encoding
EF BB BF UTF-8
FE FF UTF-16 (big-endian)
FF FE UTF-16 (little-endian)
00 00 FE FF UTF-32 (big-endian)
FF FE 00 00 UTF-32 (little-endian)

微软建议所有的 Unicode 文件应该以 ZERO WIDTH NOBREAK SPACE(U+FEFF)字符开头。这作为一个“特征符”来识别文件中使用的编码和字节顺序。BOM的本意不错,但它并不是一个通用标准,从而导致了很多不兼容的问题。

UTF-8

UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字元编码,也是一种前缀码。它可以用一至四个字节对Unicode字符集中的所有有效编码点进行编码,属于Unicode标准的一部分,最初由肯·汤普逊和罗布·派克提出。

由于较小值的编码点一般使用频率较高,直接使用Unicode编码效率低下,大量浪费内存空间。UTF-8就是为了解决向后兼容ASCII码而设计,Unicode中前128个字符(与ASCII码一一对应),使用与ASCII码相同的二进制值的单个字节进行编码,这使得原来处理ASCII字元的软体无须或只须做少部份修改,即可继续使用。因此,它逐渐成为电子邮件、网页及其他储存或传送文字优先采用的编码方式。

参考链接

  1. Excel 2007 打开 UTF-8 编码 CSV 文件的BUG,by oyi319.
  2. How to export JavaScript array info to csv (on client side)?,by stackoverflow.
  3. blob 导出csv 用execl打开出现乱码,by 黑魔法.
  4. UTF-8,by wikipedia.

如何使用图标icon

发表于 2019-08-25 | 更新于 2022-08-24

在前端网页的世界里,Icon是最基本的元素之一。使用Icon已成为前端开发者最基本的技能。下面将主要介绍利用SVG Sprites技术在前端中使用Icon的方法。

Icon的演化史

Icon最早用img实现,后为了提高效率,减少img请求,出现image sprite技术,实现将多个图片合成一个图片,然后利用 css 的 background-position 定位显示不同的 icon 图标。但该技术维护困难。

随后出现了font库实现页面图标,例如 Font Awesome。目前最常用的是iconfont,里面图标应有尽有,且开源。

iconfont的使用方法

unicode

优势:

  • 兼容性最好,支持ie6+
  • 支持按字体的方式去动态调整图标大小,颜色等等

劣势:

  • 不支持多色图标
  • 在不同的设备浏览器字体的渲染会略有差别

具体使用方法参考手摸手,带你优雅的使用 icon,不建议使用。

font-class

与unicode使用方式相比,具有如下特点:

  • 兼容性良好,支持ie8+
  • 相比于unicode语意明确,书写更直观。可以很容易分辨这个icon是什么。

symbol

随着IE浏览器逐渐淡出历史舞台,svg-icon 使用形式慢慢成为主流和推荐的方法,请参考未来必热:SVG Sprites技术介绍。其优点有:

  • 支持多色图标了,不再受单色限制。
  • 支持像字体那样通过font-size,color来调整样式。
  • 支持 ie9+
  • 可利用CSS实现动画。
  • 减少HTTP请求。
  • 矢量,缩放不失真
  • 可以很精细的控制SVG图标的每一部分

具体使用方法如下:

  • 使用SVG Sprite生成SVG雪碧图

SVG雪碧图

图1 SVG雪碧图
  • 加入通用css代码(引入一次就行)
1
2
3
4
5
6
7
8
<style type="text/css">
.icon {
width: 1em; height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
  • 挑选相应图标并获取类名,应用于页面
1
2
3
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-xxx"></use>
</svg>

使用svg-icon的好处是再也不用发送woff|eot|ttf| 这些很多个字体库请求了,所有的svg都可以内联在html内。且svg 是一个真正的矢量,不管再怎么的放缩它都不会失真模糊,而且svg可以控制的属性也更加的丰富,也能做出更加生动和复杂的图标。

生成SVG sprite的方法

推荐使用svg-sprite-loader ,它是一个Webpack loader。

1
2
import '@/src/icons/qq.svg; //引入图标
<svg><use xlink:href="#qq" /></svg> //使用图标

自动导入多个SVG

使用 webpack 的 require.context 实现自动导入多个SVG Icon,避免手动一个个引入。

require.context有三个参数:

  • directory:说明需要检索的目录
  • useSubdirectories:是否检索子目录
  • regExp: 匹配文件的正则表达式
1
2
3
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./svg', false, /\.svg$/)
requireAll(req)

参考链接

  1. 手摸手,带你优雅的使用 icon,by 花裤衩.
  2. 未来必热:SVG Sprites技术介绍,by 张鑫旭.
  3. 如何在vue项目中优雅的使用SVG,by SilentLove.
  4. 关于webpack的require.context,by yeyan1996.
  5. requireContext.keys().map(requireContext)在批量导入时的作用,by 咲奈.
  6. 使用require.context实现前端工程自动化,by 心_c2a2.
  7. webpack依赖管理,by docschina.
  8. 懒人神器:svg-sprite-loader实现自己的Icon组件,by
    Yawenina.
  9. SVG on the Web – Implementation Options,by svgontheweb.
  10. SVG Search,by uiset.
  11. SVG图标颜色文字般继承与填充,by 张鑫旭.
  12. How To Create a Beautiful Color Palette for your Website or App,by goodpalette.

USB供电能力简介

发表于 2019-08-20

最近买了个行车记录仪,它通过USB接口供电,要求电源输入为5V2A,即要求电源的输出功率要达到10W。不想直接安装到车上,想插在电脑的USB接口上,测试行车记录仪的功能。那么电脑USB接口的供电能力足够吗?

USB标准供电能力

USB有多个标准,供电能力各不相同:

  • USB1.1 传输速率最高12Mbps; 电源供应 5V 500mA
  • USB2.0 传输速率最高480Mbps; 电源供应 5V 500mA
  • USB3.0 传输速率最高5Gbps; 电源供应 5V 900mA

最新的USB3.0标准输出电压为5V,输出电流最大为900mA,如果超过可能会因发热造成线路损坏。,因此电脑上的标准USB接口无法支持行车记录仪的正常使用。

注意: 输出电压由电源输出决定,但输出电流大小由负载决定。

USB快充技术

目前的快充技术基本有三种:USB-IF组织的USB PD、高通QC、联发科PEP/PE,其他手机厂商的快充方案大多来自这三个。

  • USB PD(快充标准)目前基本绑定在USB3.0(数据传输标准)和USB Type-C(接头物理标准)上了,也得到谷歌和苹果两大巨头的支持,非常有希望成为未来的统一标准。

  • 高通Quick Charge技术则是实际上被中高端智能手机采用最多的,小米、华硕、LG、乐视、中兴、HTC等最近两年的旗舰都是这个标准,三星FastCharge是QC的马甲,索尼也用QC。 由于硬件端和软件端都被强硬规定, 高通最新的QC 4.0已经使用了USB PD协议,成为了USB PD的一个分支。

  • 联发科PEP技术推广成本最低,广泛用于中低端手机,魅族mCharge也是基于PEP。 不过联发科的PE3.0有可能被苹果采用。

参考链接

  1. 关于USB快充你不得不知的几点问题,by EDN.
  2. 手机充电是用电脑 USB 快还是用插座快?,by zhihu.
  3. 瓦特,by wikipedia.
  4. 手机快充是跟数据线有关还是跟充电器有关?,by zhihu.

MSSQL2008中分页查询的实现

发表于 2019-08-17

在后台管理中,涉及分页操作,需要数据库支持limit和offset选项,但在MSSQL2008中这两个选项不支持,不过可以用ROW_NUMBER函数在SQL语句中实现数据分页效果。SQL代码示例如下:

1
2
3
4
5
6
SELECT * FROM  
(SELECT Users.id as id,name,sign,account,audit,roleName,RoleId, Users.deleteFlag as deleteFlag,
ROW_NUMBER() OVER (ORDER BY Users.createdAt) AS Seq
FROM Users LEFT JOIN Roles ON Users.RoleId=Roles.id)Users
Where deleteFlag=0 and
Seq > :offset_num and Seq<= :offset_num+:limit_num

参考链接

  1. How to use Offset . . .Fetch Next in SQL SERVER 2008 R2,by microsoft msdn.

关系数据库中存储树结构及前端还原的方法

发表于 2019-08-17

树形结构很常见,例如组织结构图、线性化讨论等。树形结构中,实例被称为节点(node),每个节点有多个子节点和一个父节点。最上层的节点叫根(root)节点,它没有父节点。最底层的节点叫叶(leaf)节点,它没有子节点。本文主要介绍如何在关系数据库中存储树结构,以及如何从关系数据库中恢复树结构。

关系数据库中存储树结构的方法

层级数据设计方案

在关系数据库中存储树结构主要有以下几种方案:

  • 邻接表模型

最常见的解决方案,在数据库表中添加parent_id字段,再引用同一张表中的其他记录的id。可通过一个外键约束维护这种关系。

优点:增加叶节点、修改节点或子树位置很方便。

缺点:查询节点的所有后代、删除子树很困难。

  • 路径枚举

路径枚举是一个由连续的直接层级关系组成的完整路径。例如/usr/local/lib。

优点:查询节点所有后代、插入新节点很方便。
缺点:依赖应用程序逻辑代码维护路径字符串,验证字符串正确性开销大。受限于字符串长度,树结构无法无限扩展。

  • 嵌套集

嵌套集解决方案是存储子孙节点的相关信息,而不是节点的直接祖先。通常使用两个数字nsleft和nsright编码每个节点,以表示子孙节点信息。

nsleft的数值小于该节点所有后代的ID,同时nsright的值大于该节点所有后代的ID。

确定这三个值(nsleft,ID,nsright)的简单方法是对树进行一次深度优先遍历,在逐层深入过程中依次递增地分配nsleft的值,并在返回时依次递增地分配nsright的值。

优点:查询给定节点祖先和后代很容易,删除非叶子节点,其后代会自动代替被删除节点成为其祖先节点的直接后代。

缺点:不易理解,插入和移动节点复杂。

  • 闭包表

闭包表通过额外的数据库表记录树中节点间父子的关系,包括直接的父子关系、间接的父子关系和指向自己的关系。

层级数据设计比较

层级数据设计比较
设计 表 查询子 查询树 插入 删除 引用完整性
邻接表 1 简单 困难 简单 简单 是
邻接表+递归查询 1 简单 简单 简单 简单 否
路径枚举 1 简单 简单 简单 简单 否
嵌套集 1 困难 简单 困难 困难 否
闭包集 2 简单 简单 简单 简单 是
  • 邻接表设计最简单,如果使用的数据库支持WITH或CONNECT BY PRIOR的递归查询,将使得邻接表查询更为高效。

前端从关系数据库中还原树结构

表结构,使用sequelize的对象表示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
'use strict';
module.exports = (sequelize, DataTypes) => {
const Role = sequelize.define('Role', {
id: {
type: DataTypes.STRING(50),
primaryKey: true
},
roleName: {
type: DataTypes.STRING(128),
allowNull: false
},
path: {
type: DataTypes.STRING(512),
allowNull: false,
unique: true,
comment: '角色路径唯一!'
},
deleteFlag:{
type: DataTypes.BOOLEAN,
defaultValue: false
}
}, {});
Role.associate = function(models) {
// associations can be defined here
Role.hasMany(models.User)
};
return Role;
};

递归生成角色树:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 获取第一层节点
function getFirstLevel(recordList){
var firstLevelList=[];
for(let i=0;i< recordList.length;i++){
let record=recordList[i]
if (record.path.length === 2 && record.path.split('')[1] === '/' && parseInt(record.path.split('')[0])>=0){
record.label=record.roleName
firstLevelList.push(record)
}
}
return firstLevelList
}

// 指定根节点,递归生成角色树
function recursiveTree(parentRecord,recordList){
for (let i = 0; i < recordList.length; i++){
let record = recordList[i]
if(parentRecord.path==record.path.slice(0,-2)){
record=recursiveTree(record,recordList)
if (parentRecord.children==undefined){
parentRecord.children=[]
}
parentRecord.children.push(record)
}
}
parentRecord.label = parentRecord.roleName
return parentRecord
}

// 生成角色树
export function parseRoleTree(recordList){
var result = getFirstLevel(recordList);

for (let i=0;i<result.length;i++){
parent = result[i]
parent = recursiveTree(parent, recordList)
}

return result;
}

参考链接

  1. java递归生成树形结构菜单,by 伊宇紫.
  2. Bill Karwin著,谭振林,Push Chen译. SQL反模式[M].人民邮电出版社.
上一页1…363738…54下一页

Jack Huang

535 日志
69 标签
© 2026 Jack Huang
由 Hexo 强力驱动
|
主题 — NexT.Muse