ionic入门教程第十八课-初识自定义指令directive oni-bar(tab-bar)
经过这么长时间的学习,我想大家都有了一定的基础了。
这节课尝试着给大家讲点更加深入的东西,能理解的就好好学学,还理解不来的朋友也不要紧,可以当做扩展阅读看看就好。
学习切忌过于急躁。
到目前为止,我教程里面提到的内容都是使用了ionic的内置指令和一些angularjs的内置指令来实现的。如ion-nva-bar、ion-list、ion-nav-view和ng-repeat、ng-bind等
其中ion是ionic的命名空间,ng是angularjs的命名空间,- 后面的是指令的名字。
如果你使用的ide是webstorm,并且安装了angularjs的插件,那你可以在文件中键入“ngdc”快速创建指令
不使用快捷方式的,可以新建一个文件。(我自己也没用过快捷创建,感觉格式跟我写的不是很一样。)
键入angular.module().directive(name,function factory(){})
这里我先不对所有的API进行讲解,我们先拿一个简单的实例来说明。
我们要完成一个这样的在bar中的tab页。
首先我们新建一个项目ionic start onibartest tabs
然后使用webstorm打开项目,关于目录结和初始化运行结果的内容这里就不说了,前面的教程里都提到过了。
然后我们分析一下,我们要的效果是在一个bar里面有一个切换页,然后左边有一个按钮,右边有一个按钮。
由于要重写这个bar,所以首先我们注释掉新建项目中的bar代码
然后自己放上一个
<ion-header-bar class="bar bar-header" align-title="center"> </ion-header-bar>运行起来会在界面上看到一个空白的bar。
然后我们处理左边的按钮。这里随口说一些这个按钮,有两种方式实现。
1、放上一个div定义class是buttons,声明这是一个按钮组,在标签内的第一个buttons,会被当做是左边的按钮,第二个就是右边的按钮了。
<div class="buttons"> <button class="button button-icon icon ion-navicon-round" > </button> </div>
2、放上ion-bav-buttons 定义side left左边 right右边
<ion-nav-buttons side="left"> <button class="button button-icon icon ion-navicon-round" > </button> </ion-nav-buttons>这里我们随意点用了第一种方法实现。同样处理了右边的按钮。
接着我们处理中间的tab。根据bar的布局,我们可以把中间的tab页,当做就是当前页面的标题。
所以,随意这么处理。这不是本节课的重点。
<div class="title"> <ion-tabs class="tabs-striped" > <div ng-repeat="item in onibaritems"> <ion-tab title="{{item.title}}" href="{{item.href}}"></ion-tab> </div> </ion-tabs> </div>定义ng-repeat是为了是中间的tab项支持配置。这里又有一个小细节,顺便提一下。这里ng-repeat的element使用了一个div作为对象。
但是我们常用的ion-tabs 和ion-tab的组合并没有这个div。用这个div的目的是如果在ion-tabs中使用ng-repeat那么出来的循环就是tabs的循环。
如果在tab中使用ng-repeat那就找不到item对象。这是因为ion-tabs和ion-tab都是ionic自带的指令,都会经过编译变成一些复杂元素的集合体。
不好控制循环对象,所以这里在加入一层div处理这个bug。说了一堆,说不清楚,看不懂的就当我没说。无关紧要的。
然后因为这个bar放的位置是在index文件,这里我简单的使用rootscope,来定义了onibaritems
最后的代码就是
html
js
运行结果
为了使这个tab好看点,在style文件中加入样式。
运行结果如效果图所示。这里就不重复上图了。
接下来我们开始讲解如何把我们上面说到的所有东西编写成指令呢。
为什么我要在前面讲这么一大堆,就是想让大家明白一个过程,指令做的事情就是把你定义好的这些属性和样式编译出来。
可以理解为最后编译出来的html和上面所写的是一样的。
首先我们在www/js文件夹下新建一个文件夹directives然后新建一个文件OniBarDirective.js
首先这里需要关注的是oniBar,这个指令的名字,使用的是驼峰式的写法。那么在模板中就可以使用oni-bar。
一、根据我们前面的定义,这个指令是要被编译成元素的。所以我们加入第一个参数restrict:'E'
restrict接受4个参数或者这4个参数的任意组合,E:元素、A:属性、C:样式表、M:注释。不理解的先不管,后续的课程会再将这个
二、然后把我们开始写的html代码拷贝进来,修改成一行字符串。如果属性是用双引号的,前后加上单引号把缩进去掉就可以了。加入第二个参数,注意以下内容是单行的
template:'<ion-header-bar class="bar bar-header" align-title="center"><div class="buttons"><button class="button button-icon icon ion-navicon-round" ></button></div><div class="title"><ion-tabs class="tabs-striped" ><div ng-repeat="item in items"><ion-tab title="{{item.title}}" href="{{item.href}}"></ion-tab></div></ion-tabs></div><div class="buttons"><button class="button button-icon icon ion-ios-search" > </button> </div> </ion-header-bar>',
上面这个字符串和最上面提到的html页面的内容是一样的,我为了做区分把ng-repeat里面onibaritems改成items。下面会提到这两个数据传输。
三、接下来加入第三个参数replace:true,
replace接受两个参数true表示会替换指令所在的元素。false指令的html会被编译到躲在元素的内部(追加)
这里可以换种概念理解,设置为true则表示它自己就是父级。父级的内容会被覆盖掉。false表示它是父级的子级,保留父级的其他兄弟子级。
四、接下来我们使用link函数:link:function postLink(scope,element,attrs){}
这里自动传入三个参数scope:作用域 element绑定数据的对象 attrs对象的所有属性。
这里我们利用attrs对象的属性来进行传值。这里需要注意的是外面的对象传进来会变成一个字符串,所以要做转换
link: function(scope, element, attrs) { scope.items = JSON.parse(attrs.items); }在html中使用<oni-baritems="{{onibatitems}}"></oni-bar>
完成的指令代码如下:
注意使用时要引用文件,然后在app.js文件中加入
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services','starter.directives'])五、细心的朋友应该已经发现了,我们还有一部分的内容---样式表是独立在这个指令之外的,也就是说要另外引用相关的样式文件才能使得这个指令达到预期的效果。
所以我们把style文件中的css样式剪切出来也加到指令里面。
最终整个指令的代码如下:
angular.module('starter.directives', []) .directive('oniBar', [function() { return { restrict: 'E', template:'<ion-header-bar class="bar bar-header" align-title="center"><div class="buttons"><button class="button button-icon icon ion-navicon-round" ></button></div><div class="title"><ion-tabs class="tabs-striped" ><div ng-repeat="item in items"><ion-tab title="{{item.title}}" href="{{item.href}}"></ion-tab></div></ion-tabs></div><div class="buttons"><button class="button button-icon icon ion-ios-search" > </button> </div> </ion-header-bar>', replace:true, controller: function(){ var style = window.document.createElement('style'); style.type = 'text/css'; style.innerHTML += '.tabs .tab-title{font-family:"微软雅黑" !important;}'; style.innerHTML += '.tabs-striped .tab-item.tab-item-active, .tabs-striped .tab-item.active, .tabs-striped .tab-item.activated {margin-top: 0px;border-style: solid;border-width: 0 0 3px 0;border-color: #FF7A01; }'; style.innerHTML += '.tabs-striped .tabs{border-bottom: 0px solid #ddd !important;}'; style.innerHTML += '.tab-item{font-size: 17px;}'; style.innerHTML += '.bar .title{margin: 1px 37px;}'; window.document.getElementsByTagName('head')[0].appendChild(style); }, link: function(scope, element, attrs) { scope.items = JSON.parse(attrs.items); } } }])这样子这个指令才是一个完整的整体。
这节课的目的只是让大家对这个自定义指令有一个基本的感知。我后续会出一节或者两节来详细讲解相关的api。
大家都知道ionic的tab在安卓和ios环境下是不同的,所以如果在安卓环境下运行这个指令,那将看不到中间切换页的文字
所以我们可以在config中加入
使得tab在两个平台上的表现一致。
Demo地址:http://pan.baidu.com/s/1o85uIng
大家还有其他的问题可以通过以下方式找到我
新浪微博:小虎Oni 微信公众号:ionic__公众号最近没时间维护,但还是希望大家关注,谢谢