Angular实现双向折叠列表组件的示例代码
最近在做一个双向折叠组件,如下图所示,页面是分为两组,左边页面是Summary Panel,主要是一组列表,右边页面是Detail Panel,展示左边列表中某一项的具体信息,我们把它记作“Middle State”。
我们还看到有“<”和“>”两组按钮,这就是我们要做的“双向折叠组件”。点击左边的“<”,Summary Panel折叠起来,Detail Panel铺满整个页面,我们把它记作“Left State”,如下图
在Summary Panel折叠状态下,点击“>”,又回到“Middle State”。点击“>”,Detail Panel折叠起来,Summary Panel铺满整个页面,我们把它记作“Right State”,如下图
我们通过以上的需求分析可知,
1.页面的总体布局是一个Summary的div,两个箭头buttons,一个Detail的div。
2.页面总共有三种state“Middle”、“Left”、“Right”,有两个button“<”和“>”,也就是两个button去控制三个state。
我们需要定义一个枚举来记录页面的三种状态(注意,定义枚举要用export导出,否则后面会出错)
export enum CollapseExpandState { Middle = 1, Left, Right }
页面的结构如下,并且通过一个变量_collapseExpandState去控制“left”和“right”两个button,具体为“<”会在页面状态为“Middle”和“Right”的情况下出现,“>”会在页面状态为“Middle”和“Left”状态下出现,从需求图中即可得知
<div id="container"> <div id="summary"></div> <div id="buttons"> <div id="left" ngIf="_collapseExpandState === CollapseExpandState.Middle || CollapseExpandState.Right" (click)="_onHandleLeft($event)">《</div> <div id="right"> ngIf="_collapseExpandState === CollapseExpandState.Middle || CollapseExpandState.Left" (click)="_onHandleLeft($event)">》</div> </div> <div id="detail"></div> </div>
这里在angular的template中用到了枚举,遭遇了一些麻烦,如果我们按上述定义了枚举,并且在Angular Component的template中用了枚举,我们会得到以下的错误提示
TypeError: Cannot read property 'Middle' of undefined
也就是说,在Angular2的template中无法识别定义的枚举类型CollapseExpandState,这是因为你写的Angular Component的template模板的执行环境是你定义的ponent class,在class中并没有关于CollapseExpandState枚举的任何引用,所以Angular在为你的ponent生成模板的时候认为CollapseExpandState是undefined的。知道了原因,解决方案就很容易了,只需要在ponent class中加入这个枚举的引用即可
@ponent(...) export class ContainerWidget { public CollpaseExpandState: any = CollapseExpandState; }
我们通过枚举状态来控制了两个buttons是否在恰当的页面状态显示与否,即使是同一个buttons,在不同的页面状态下所用到的样式也会不同,这里的样式其实最主要的就是位置了。我们先来考虑如何去控制button的样式,再来考虑如何去正确定位不同页面状态下button的位置。
对于控制button的样式,我们需要控制三个样式"left button"、"right button"还有“buttons”。能够想到有三种方案
I、用ng-class
ng-class一般的用法如下
<some-element [ngClass]="{'first': true, 'second': true, 'third': false}">...</some-element>
它需要用boolean去控制,每一种样式需要一个boolean去控制,left和right各有两种样式,buttons有三种样式,这样就需要用5个boolean去控制,略显麻烦。
II、 用ElementRef.nativeElement.className
分别在buttons、left和right上用模板变量,然后在class中定义
@ViewChild("buttons") buttons: ElementRef; @ViewChild("left") left: ElementRef; @ViewChild("right") right: ElementRef;
在处理函数中这样去给class赋值从而改变样式
this.left.nativeElement.className = "XXXXX";
这样的话,我们需要从元素的角度出发,只需要3个元素变量,从而改变元素上的className即可。这样做有个隐患,注意到我们是用的ngIf来控制left和right在不同状态下是否存在,因为每一次事件处理都需要对三个元素的样式进行赋值,如果某个页面状态下ngIf为false从而元素不存在,那么就会报“Null Pointer”的错误,所以如果所引用的元素受到了ngIf的控制,不确定是否一定存在的情况下,要慎用该方法为元素赋予样式。
III、 用class="{{}}"
为了II中的尴尬,我们采用在HTML元素上对class进行直接赋值的方式,需要借用插值表达式{{}}。我们在css中用class的形式定义好样式,并且在poennt class中定义三个字符串变量记录className,然后在事件处理函数中把相应的className赋予变量即可。这样我们就不用担心元素是否存在而导致的空指针了。
考虑完如何控制样式,狼蚁网站SEO优化我们进入CSS样式的讨论,这里其实主要考虑的就是位置。
我们采用flex布局,从左到右依次排列Summary Panel, buttons和Detail Panel。我们希望Buttons向左移,空出的位置被Detail Panel来填充。来看一下不设样式的效果图
显然buttons是占据了文档流的位置的,如果这时候我们用relative定位buttpms,并且设置left的值为-74px(注意到left为负数就会把元素往左推)
.buttons{ display: flex; position: relative; margin-: 23px; left: -74px; }
效果图为
发现如果用left的话,buttons原来的文档流位置依然存在,只是buttons相对于原来的位置移动了一定的位移。
如果我们用margin-left来设置呢
.buttons{ display: flex; position: relative; margin-: 23px; margin-left: -74px; }
效果图为
它和left不同之处在于,left会留住原来的文档流位置,用margin-left原来的文档流位置会消失,而由后面的元素补充过来,而我们想要的效果,正好是用margin-left来实现的。
所以用CSS定位的时候,要明白left和margin-left的区别,从而选择正确的方式来定位。
一下,从这个案例中我们学习到了
- 双向折叠可以用“3种页面状态去控制2个按钮”来实现
- enum在Angular Component的template中用到时,需要在pnent class中添加它的引用
- 控制元素样式有很多方法,要选择合适的方法
- CSS定位中left和margin-left虽然都能把元素推向左边,left保留原来文档流位置,margin-left不保留原来文档流位置。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持狼蚁SEO。
编程语言
- 如何快速学会编程 如何快速学会ug编程
- 免费学编程的app 推荐12个免费学编程的好网站
- 电脑怎么编程:电脑怎么编程网咯游戏菜单图标
- 如何写代码新手教学 如何写代码新手教学手机
- 基础编程入门教程视频 基础编程入门教程视频华
- 编程演示:编程演示浦丰投针过程
- 乐高编程加盟 乐高积木编程加盟
- 跟我学plc编程 plc编程自学入门视频教程
- ug编程成航林总 ug编程实战视频
- 孩子学编程的好处和坏处
- 初学者学编程该从哪里开始 新手学编程从哪里入
- 慢走丝编程 慢走丝编程难学吗
- 国内十强少儿编程机构 中国少儿编程机构十强有
- 成人计算机速成培训班 成人计算机速成培训班办
- 孩子学编程网上课程哪家好 儿童学编程比较好的
- 代码编程教学入门软件 代码编程教程