AngularJS/Vue/React 都是通过JS利用H5自定义标签和属性的能力,提供一些指令和逻辑控制,实现界面逻辑。所以他们在很多设计方面都有相似点。
1、典型用法
I、基本架构
HTML5 部分 -- 引入应用和控制器,并指定其作用域
<script src="angular.js"/>
<script src="my.js"/>
<div ng-app="myApp" ng-controller="myCtrl">
</div>
JS部分
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.firstName= "John";
$scope.lastName= "Doe";
});
使用模块定义应用app,并创建controller控制器
如果有依赖模块,angular.moduel('myApp',['依赖的模块']);
II、作用域 $scope 控制器controller和 HTML5元素 交互的中介
可以在 $scope 中定义数据/函数,然后在 HTML5 元素中使用;反过来,也可以通过 $scope 引用HTML5 中的因素
a、每个controller 都有一个 $scope
b、全局有一个 $rootScope,各个控制器直接如果想共享数据则通过 $rootScope
app.controller('myCtrl', ['$scope','$rootScope',function($scope,$rootScope) {
$scope.firstName= "John";
$scope.lastName= "Doe";
$scope.inc = function(){
}
}]);
2、概念
I、参数 - 数据存取
{{ 变量名 }}
支持表达式操作
{{ Number + 1}}
{{ firstName + '-' + lastName }}
{{ i > 0 ? 1 : 0}}
II、逻辑控制
a、迭代
<ng-repeat>
<ul>
<li ng-repeat="x in names">
<p id="x{{$index}}" class="x.name">
{{ x.name + ', ' + x.country }}</p></li>
</ul>
b、条件判断
<ng-if> 可以控制当前的元素是否出现
经典的表格处理
<table>
<tr ng-repeat="x in names">
<td ng-if="$odd" style="background-color:#f1f1f1">{{ x.Name }}</td>
<td ng-if="$even">{{ x.Name }}</td>
<td ng-if="$odd" style="background-color:#f1f1f1">{{ x.Country }}</td>
<td ng-if="$even">{{ x.Country }}</td>
</tr>
</table>
从基本页面逻辑处理看,angularJS和Vue的用法是一致的。
3、绑定
I、模型ng-model - 表单数据绑定 (双向绑定)
其实,双向绑定非常类似 Java中的 JavaBean ,JavaBean的变化影响到具体的展示,同样具体的展示也会影响JavaBean的值,典型的应用比如在ORM中,或者JSP中
<form ng-app="" name="myForm">
输入你的名字:
<input name="myAddress" ng-model="text" required>
</form>
$scope.text = [];
II、数据绑定/元素绑定 ng-bind
<p>剩余字数: <span ng-bind="left()"></span></p>
-- 这个例子是两者使用区别最直观的,ng-model 绑定一个参数,然后在js中使用(也可以反向影响),这里的HTML的value是 主动触发的,ng-bind 从 js提供一个方法/值, HTML 的值是被动使用的
ng-bind是从$scope -> view的单向绑定
ng-modle是$scope <-> view的双向绑定
从绑定数据来看,angularJS和Vue也是一致的。
4、逻辑-事件-控制
前面没有展开来说,从这里详细描述一下
a、从作用域来说,Vue并没有做明确说明,可以认为是一个Vue对象就是一个作用域;而angularJS 则定义了scope作用域和普通js数据区分开来
b、显式的在 模块基础上 定义了 控制器,这是Vue没有的
c、把 方法 分为 控制器和服务,做了区分, 控制器需要 DI 依赖注入(这是Spring的设计理念也用在这里)服务才能使用,这点 Vue 也没有做特殊处理
从这些来看,angularJS 要比 Vue 复杂的多
更多依赖注入的问题,后面再详细描述
I、ng-xxx指令+ 控制器方法
<div ng-app="myApp" ng-controller="personCtrl">
<button ng-click="toggle()">隐藏/显示</button>
<p ng-hide="myVar">
名: <input type=text ng-model="firstName"><br>
姓: <input type=text ng-model="lastName"><br><br>
姓名: {{firstName + " " + lastName}}
</p>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('personCtrl', function($scope) {
$scope.firstName = "John";
$scope.lastName = "Doe";
$scope.myVar = false;
$scope.toggle = function() {
$scope.myVar = !$scope.myVar;
}
});
</script>
II、其他方法
过滤器
AngularJS 使用了 管道符 | 用来过滤数据 -- 和Linux类似,Vue也类似
filter -- 选择子集
lowerCase/uppercase -- 大小写转换
orderBy -- 排序
currency -- 转换为货币形式
<li ng-repeat="x in names | filter:test | orderBy:'country'">
{{ (x.name | uppercase) + ', ' + x.country }}
</li>
5、表单元素
同Vue一样,通过 ng-model 绑定数据
比如文本输入框:<input type="text" ng-model="user.firstName"><br>
Last Name:<br>
6、组件化
angularJS通过自定义指令来实现组件化的功能,和Vue的自定义指令不是一个概念。
I、典型例子
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
<script>
var app = angular.module("myApp", []);
app.directive("caption", function() {
return {
template : '<span>{{x.name}}</span>'
};
});
</script>
</head>
<body>
<div ng-app="myApp" ng-init="names=[{name:'Jani',country:'Norway'}]">
<p>循环对象:</p>
<ul>
<li ng-repeat="x in names">
<p caption></p>
{{ x.name + ', ' + x.country }}
</li>
</ul>
II、组件化的步骤
一、注册一个组件
a、定义组件 通过模块的指令 app.directive("caption", function(){});
b、定义组件类型 restrict: 'E', 指定是 属性还是标签
c、定义控制器,里面定义一些逻辑
d、编译 complie 方法,在模版替换的各个生命周期阶段,可以有回调函数
二、使用 template 进行替换 标签元素
三、父控件(外层) 传递数据给 子控件(内层),通过 在 scope中定义的 属性,可以直接把数据传给内层
四、子控件(内层) 传递数据给父控件(外层),通过事件来传递
使用 scope.$broadcast 把事件广播出去, scope.$on 监听事件
使用 scope.$watch 触发事件
其中,二、三、四步,angularJS和Vue极其相似,只是在第一步,angularJS 明显复杂很多
define(['angular','bootstrap','css!test.style.control'], function() {
var showpane = angular.module('test.app.control',[])
showpane.directive('testShowpane', function() {
return {
restrict: 'E',
transclude: true,
scope: {
data : '=',
},
controller: [ "$scope", function(scope) {
var scrolls = scope.scrolls = scope.data;
console.log(scrolls);
}],
compile: function(tEle, tAttrs) {
console.log(tEle.html());
return {
pre: function(scope, iElem, iAttrs){
console.log('pre link => ' + iElem.html());
},
post: function(scope, iElem, iAttrs){
console.log('post link => ' + iElem.html());
_link(scope, iElem, iAttrs);
}
}
},
template:
'<div class="showpane container">\
<div ng-repeat="scroll in data" class="pane " style="{{heightStyle}}">\
<div class="row"><div class="kpititle col-xs-12 col-sm-12 col-md-12 col-lg-12">{{scroll.title}}</div></div>\
<div class="row">\
<div class="progress col-xs-8 col-sm-8 col-md-8 col-lg-8 ">\
<div class="progress-bar" ng-class="{\'progress-bar-success\':{{scroll.type == 0}},\'progress-bar-warning\':{{scroll.type == 1}},\'progress-bar-danger\':{{scroll.type == 2}}}" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: {{scroll.percent}}%;">\
</div>\
</div>\
<div><div class="kpivalue col-xs-4 col-sm-4 col-md-4 col-lg-4">{{scroll.valuedisp}}</div></div>\
</div>\
</div>\
</div>',
replace: true
};
function _link(scope, iElem, iAttrs){
function percentHeight(num){
return (Math.round(1 / num * 10000) / 100.00 + "%");
}
scope.$watch('data', function(newValue,oldValue) {
if (scope.data) {
scope.heightStyle = "height:" + percentHeight(newValue.length) +";";
scope.$broadcast("datachange", newValue);
}
}, true);
scope.$on('datachange',function (event, msg) {
console.log(msg);
});
}
});
return showpane;
});
7、其他
I、ng-option 下拉框
II、表单验证
所有表单都有 这几个属性,以及对应的方法验证 $dirty/$invalid/$error
III、全局API
比较 isArray/ isDate/ isNumber ...
转换 formJSON /toJSON 可以把Json序列化成字符串,也可以把字符串反序列化成 Json
迭代 foreach
系统 bootstrap 启动/ element 获取 HTML DOM
其他常见指令
IV、控制元素可视化 ng-disabled/ng-show/ng-hidd
V、包含文件
<div ng-include="'myUsers_List.htm'"></div>
--模块话的一种方式,把重复的代码在这里模块化
完整的angular 组件化 例子可以见参见《完整的客户端组件化案例 angularJS + requireJS》