标签:
Angularjs是完全使用 JavaScript编写的客户端技术。同其他历史悠久的 Web技术( HTML、 CSS和JavaScript)配合使用,使Web应用开发比以往更简单、更快捷。
AngularJS主要用于构建单页面Web应用。它通过增加开发人员和常见Web应用开发任务之间 的抽象级别,使构建交互式的现代Web应用变得更加简单。
AngularJS的开发团队将其描述为一种构建动态Web应用的结构化框架。 AngularJS使开发Web应用变得非常简单,同时也降低了构建复杂应用的难度。它提供了开发 者在现代Web应用中经常要用到的一系列高级功能,例如: 解耦应用服务数据模型和视图 Ajax服务 依赖注入 浏览历史 测试
和别的东西有什么不同呢 在其他JavaScript框架中,我们被迫从自定义的JavaScript对象中进行扩展,并从外到内操作DOM。 而AngularJS则通过原生的Model-View-Controller( MVC,模型?视图?控制器)功能增强了
HTML。结果表明,这个选择可以快捷和愉悦地构建出令人印象深刻并且极富表现力的客户端应用。 利用它,开发者可将页面的一部分封装为一个应用,并且不强迫整个页面都使用AngularJS进行开发。这个特质在某些情况下非常有用,比如你的工作流程中已经包含了另外一个框架,或者你只希望页面中的某一部分是动态的,而剩下的部分是静态的或者是由其他JavaScript框架来控制的。
入门演示代码:
<!DOCTYPE HTML>
<html ng-app> //当加载该页时,标记ng-app告诉AngularJS处理整个HTML页并引导应用
<head>
<title></title>
</head>
<script type="text/javascript" src="js/angular1.2.3.js"></script> //载入脚本
<body >
hello{{"world"}} //使用双大括号标记{{}} 的内容是问候语中绑定的表达式,这个表达式是一个简单的字符串 ‘World’
</body>
</html>
案例:在输入框中输入信息并动态显示出来:展示它的功能:数据绑定 <input ng-model="name" type="text" placeholder="请输入姓名"> //$scope.name=input.val(); hello{{name}}
其实上边的例子就是我们使用 ng-model 指令将内部数据模型对象( $scope)中的name属性绑定到了文本输入字段上 数据模型对象( model object)是指 $scope 对象。 $scope 对象是一个简单的 JavaScript对象,其中的属性可以被视图访问,也可以同控制器进行交互。 双向数据绑定( bi-directional)意味着如果视图改变了某个值,数据模型会通过脏检查观察到这个变化,而如果数据模型改变了某个值,视图也会依据变化重 新渲染。 它创建实时模板来代替视图,而不是将数据合并进模板之后更新DOM。任何一个独立视图组件中的值都是动态替换的。这个功能可以说是AngularJS中最重要的功能之一 要实现这个功能,只要在HTML页面中引用angular.js ,并在某个DOM元素上明确设置ng-app属性即可。 ng-app属性声明所有被其包含的内容都属于这个AngularJS应用,这也是我们 可以在Web应用中嵌套AngularJS应用的原因。只有被具有ng-app属性的DOM元素包含的元素才会受AngularJS影响。
——--------------------------------------------------
<div ng-app> //这里没有绑定在我们的html上边去 <input ng-model="name" type="text" placeholder="请输入姓名"> hello{{name}}
Angular应用的解析---MVC模式 v---模板 模板是您用HTML和CSS编写的文件,展现应用的视图。 您可给HTML添加新的元素、属性标记,作为AngularJS编译器 的指令。 AngularJS编译器是完全可扩展的,这意味着通过AngularJS您可以在HTML中构建您自己的HTML标记!---和html css 混用 c---控制器 应用程序逻辑和行为是您用JavaScript定义的控制器。 AngularJS与标准AJAX应用程序不同,您不需要另外编写侦听 器或DOM控制器,因为它们已经内置到AngularJS中了。这些功能使您的应用程序逻辑很容易编写、测试、维护和理解。 m---模型 模型是从AngularJS作用域对象的属性的引申。模型中的数据可能是Javascript对象、数组或基本类型,这都不重要, 重要的是,他们都属于AngularJS作用域对象。 画图理解---两个种情况:两个视图公用一个控制器 这么解决?不同视图用不同控制器 自动数据绑定使我们可以将视图理解为模型状态的映射。当客户端的数据模型发生变化时,视图就能反映出这些变化,并且不需要写任何自定义的代码,它就可以工作 ng-app 声 明 所 有 被 它 包 含 的 元 素 都 属 于 AngularJS 应 用 一 样 , DOM 元 素 上 的 ng-controller声明所有被它包含的元素都属于某个控制器。
案例:我的时钟案例
<div ng-app>
<div ng-controller="MyController">
<h1>Hello {{ clock }}!</h1>
</div>
</div>
<script type="text/javascript">
function MyController($scope, $timeout) {
var updateClock = function() {
$scope.clock = new Date();
$timeout(function() {
updateClock();
}, 1000);
};
updateClock();
};
</script>
控制器案例2:
<div ng-controller=‘HelloController‘>
<p>{{test.text}}, World</p>
</div>
<script type="text/javascript">
function HelloController($scope) {
$scope.test = { text: ‘Hello world‘ };
}
</script>
其实我们早就在nodejs中就大量的使用了模块这个东西 在AngularJS中,模块是定义应用的最主要方式。模块包含了主要的应用代码。一个web应用可以包含多个模块,每一个模块都包含了定义具体功能的代码。 AngularJS允许我们使用angular.module() 方法来声明模块,这个方法能够接受两个参数,第一个是模块的名称,第二个是依赖列表,也就是可以被注入到模块中的对象列表。 ——angular.module(‘app‘, []); 如果调用这个方法只传入了一个参数,那么就不是声明而是引用模块 angular.module(‘app‘); //调用模块的方式
简单测试:
<div>
<input ng-model="test"> //注意这里声明模块---注意这里是挂在根作用域(rootscope)下边的,所以ng-app下的所有东西都能获得
<p>{{test}},hello</p>//这里调用模块
</div>
一般不用去创建数据模型new model 一般绑定在scope下边的 看运行效果
作用域: scope是整个AngularJS的核心组成部分 $scope对象是定义应用业务逻辑、控制器方法和视图属性的地方。 AngularJS启动并生成视图时,会将根ng-app元素同$rootScope进行绑定。 $rootScope是所有$scope对象的最上层。
$rootScope是AngularJS最接近于全局对象的函数,所以要是在它身上绑定了很多业务逻辑并不是很好的事情--回想一下js中全局作用域的缺点。
$scope对象就是一个普通的JavaScript对象,我们可以在其上随意修改或添加属性。
$scope对象在AngularJS中充当数据模型,但与传统的数据模型不一样, $scope并不负责处理和操作数据,它只是视图和HTML之间的桥梁,它是视图和控制器之间的传送器。
演示代码:
<h1 ng-controller="myController">{{name}}</h1>
<script type="text/javascript">
function myController($rootScope) {
$rootScope.name ="zhangsan";
}
</script>
————————————
<h1 ng-controller="myController">{{name}}</h1>
<script type="text/javascript">
function myController($scope) { //我们没有把变量设置在跟上,而是用控制器显示的创建了一个隔离的子$scope对象,并且设置在了它之上
$scope.name ="zhangsan";
}
</script>
1、提供观察者以监视数据模型的变化; 2、可以将数据模型的变化通知给整个应用,甚至是系统外的组件; 3、可以进行嵌套,隔离业务功能和数据; 4、给表达式提供运算时所需的执行环境。
开发AngularJS应用的大部分工作内容,就是构建作用域及其相关的功能
1 创建:在创建控制器或指令时, AngularJS会用$injector创建一个新的作用域,并在这个新建的控制器或指令运行时将作用域传递进去。
2链接:当Angular开始运行时,所有的$scope对象都会附加或者链接到视图中。所有创建$scope对象的函数也会将自身附加到视图中。这些作用域将会注册当Angular应用上下文中发生变化时需要运行的函数。
3 更新:当事件循环运行时,它通常执行在顶层$scope对象上(被称作$rootScope),每个子作用域都执行自己的脏值检测。每个监控函数都会检查变化。如果检测到任意变化, $scope对象就会触发指定的回调函数。
4 销毁:当一个$scope在视图中不再需要时,这个作用域将会清理和销毁自己。
当Angular关心的事件发生在浏览器中时,比如用户在通过ng-model 属性监控的输入字段中输入,或者带有ng-click属性的按钮被点击时, Angular的事件循环都会启动。这个事件将在 Angular执行上下文中处理。每当事件被处理时, $scope就会对定义的表达式求值。此时事件循环会启动,并且Angular应用会监控应用程序内的所有对象
AngularJS中的控制器是一个函数,用来向视图的作用域中添加额外的功能。我们用它来给作用域对象设置初始状态,并添加自定义行为。
当我们在页面上创建一个新的控制器时, AngularJS会生成并传递一个新的$scope给这个控制器。可以在这个控制器里初始化$scope。由于AngularJS会负责处理控制器的实例化过程,我 们只需编写控制函数即可。
function myController($scope) {
$scope.say = "hello";
}
上边创建的控制器是在全局创建的,这样并不是很合理污染了全局命名空间,更合理的做法是我们创建一个模块,并在模块中去创建一个控制器 注意点1:使用ng-controller指令可以将一个控制器对象附加到DOM元素上, 注意点2,当我们创建了模块之后我们的ng-app不需要放到全局上面去,而是放在了需要的地方
div ng-app="myApp"><h1 ng-controller="myController">{{say}}</h1></div>
<script type="text/javascript">
var app = angular.module(‘myApp‘, []);
app.controller("myController",function($scope){
$scope.say="hello world";
});
</script>
只需创建控制器作用域中的函数,就能创建可以在视图中使用的自定义操作。很幸运,AngularJS允许我们在视图中像调用普通数据一样调用$scope上的函数。
可以将按钮、链接等其他任何DOM元素同点击事件进行绑定 ng-click指令将浏览器中的mouseup事件,同设置在DOM元素上的事件处理程序绑定在一起。
演示代码:
<div ng-app="myApp">
<div ng-controller="FirstController">
<h4>点击button按钮添加值,点击a标签减少值</h4>
<button ng-click="add(1)" class="button">Add</button>
<a ng-click="subtract(1)" class="button alert">Subtract</a>
<h4>Current count: {{ counter }}</h4>
</div>
</div>
<script type="text/javascript">
var app = angular.module(‘myApp‘, []);
app.controller(‘FirstController‘, function($scope) {
$scope.counter = 0;
$scope.add = function(amount) { $scope.counter += amount; };
$scope.subtract = function(amount) { $scope.counter -= amount; };
});
</script>
他们用的是同一个scope控制器可以将与一个独立视图相关的业务逻辑封装在一个独立的容器中。尽可能地精简控制器是很好的做法。作为AngularJS开发者,使用依赖注入来访问服务可以实现这个目的。 AngularJS同其他JavaScript框架最主要的一个区别就是,控制器并不适合用来执行DOM操作、格式化或数据操作,以及除存储数据模型之外的状态维护操作。它只是视图和$scope之间的 桥梁。
AngularJS允许在$scope上设置包括对象在内的任何类型的数据,并且在视图中还可以展示对象的属性。
演示代码:
<div ng-app="myApp">
<div ng-controller="myController">
<p>{{people.name}}</p>
</div>
</div>
<script type="text/javascript">
angular.module(‘myApp‘, []).controller("myController",function($scope){ //注意这是简写形式
$scope.people={
name:"zhangsan"
};
});
</script>
在拥有ng-controller=‘MyController‘ 这个属性的元素内部的任何子元素中,都可以访问person对象, 因为 它是定义在$scope上的。 $scope对象用来从数据模型向视图传递信息。同时,它也可以用来设置事件监听器,同应用的其他部分进行交互,以及创建与应用相关的特定业务逻辑。 AngularJS通过作用域将视图、控制器和指令(本书后面会介绍)隔离开来,这样就很容易为功能的具体部分编写测试。
AngularJS应用的任何一个部分,都有父级作用域存在。对于ng-app所处的层级来讲,它的父级作用域就是$rootScope。 (这里有个孤立作用域,我们在后边再研究) 所有的作用域都通过原型继承而来,也就是说它们都可以访问父级作用域 AngularJS在当前作用域中无法找到某个属性时,便会在父级作用域中进行查找。
演示代码:
<div ng-app="myApp">
<div ng-controller="parController">
<div ng-controller="chiController">
<h1 ng-click="say()">say hello</h1>
{{people}}
</div>
</div>
</div>
<script type="text/javascript">
var app=angular.module("myApp",[])
app.controller("parController",function($scope){
$scope.people={gender:"male"}
})
app.controller("chiController",function($scope){
$scope.say=function(){
$scope.people.name="zhangsan"
}
})
</script>
回顾双向数据绑定 $scope $rootScope modual 做表单实验 对class的操作(案例为test1) ng-show的使用(案例first2)
表达式在AngularJS应用中被广泛使用,因此深入理解AngularJS如何使用并运算表达式是非常重要的。 想想我们之前有没有用过表达式呢?{{}}——这就是一个基础的表达式 它的用法是使用{{}}将一个变量绑定到了$scope对象上边,然后在视图中取出来使用当用$watch进行监听时, AngularJS会对表达式或函数进行运算。 这里涉及到一个新的是知识点:$watch——我们根据名字就知道他是做什么用的:监视——在这里它的作用是对模型中的数据进行监视,并且当数据发生改变的时候做相应的响应 AngularJS为我们提供了一个非常方便的$watch方法,它可以帮助我们在每个scope中监视其中的变量(后续详解)。
演示代码:
<div ng-app="watch" >
<input ng-model=‘name‘ type=‘text‘/>
<div>change count: {{count}}</div>
</div>
<script>
angular.module(‘watch‘,[])
.run([‘$rootScope‘,function($scope){ //run这个东西先不用管,后边会解释
$scope.count = 0;
$scope.name = ‘Alfred‘;
$scope.$watch(‘name‘,function(){
$scope.count++;
})
}]);
</script>
$watch来对$scope中的name进行监视,并在它发生变化的时候将$scope中的count属性增加1。因此,每当我们对name进行一次修改时,下面显示的change count数字就会增加1。 其实表达式和eval(javascript) 非常相似,但是由于表达式由 AngularJS来处理
eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。、 使用语法:eval(string) 返回值:通过计算 string 得到的值(如果有的话)。 注意点:该方法只接受原始字符串作为参数,如果 string 参数不是原始字符串,那么该方法将不作任何改变地返回。因此请不要为 eval() 函数传递 String 对象来作为参数。
有几点不同点: 1:所有的表达式都在其所属的作用域内部执行,并有访问本地$scope的权限; 2: 不允许使用任何流程控制功能(条件控制,例如if/eles);
$parse可以将一个表达式转换为一个函数。这个函数可以被调用,其中的参数是一个上下文对象,通常来说是作用域。
演示代码:
<div ng-app="myApp">
<div ng-controller="myController">
<p>{{val}}</p>
</div>
</div>
<script type="text/javascript">
var app=angular.module("myApp",[])
app.controller("myController",function($scope,$parse){
$scope.name="zhangsan";
var expr="name ==‘wangwu‘"
var fun=$parse(expr);
$scope.val=fun();
})
</script>
过滤器用来格式化需要展示给用户的数据。 AngularJS有很多实用的内置过滤器,同时也提供了方便的途径可以自己创建过滤器。
在HTML中的模板绑定符号{{ }} 内通过| 符号来调用过滤器 {{ expression | filter }}
演示代码(自带过滤器,将名字转为大写):
<div ng-app="myApp">
<div ng-controller="myController">
{{name | uppercase}}
</div>
</div>
<script type="text/javascript">
var app = angular.module(‘myApp‘, []);
app.controller(‘myController‘, function($scope) {
$scope.name="zhangsan"
});
</script>
那我们如何在控制器中调用过滤器呢?
演示代码:
<div ng-app="myApp">
<div ng-controller="myController">
{{name}}
</div>
</div>
<script type="text/javascript">
var app = angular.module(‘myApp‘, []);
app.controller(‘myController‘,[‘$scope‘,‘$filter‘,function($scope,$filter){ //特别注意这里
$scope.name=$filter(‘uppercase‘)("lisi") //尝试一下$filter(‘lowercase‘)(‘LISI‘);
}]);
</script>
date
{{ today | date:‘medium‘ }} <!-- Aug 09, 2013 12:09:02 PM -->
案例:
<div ng-app="myApp">
<div ng-controller="myController">
{{ today | date:‘short‘ }}
</div>
</div>
<script type="text/javascript">
var app = angular.module(‘myApp‘, []);
app.controller(‘myController‘,[‘$scope‘,function($scope){
$scope.today=new Date();
}]);
</script>
日期格式化:
{{ today | date:‘short‘ }} <!-- 8/9/1312:09PM -->
{{ today | date:‘fullDate‘ }} <!-- Thursday, August 09, 2013 -->
{{ today | date:‘longDate‘ }} <!-- August 09, 2013 -->
{{ today | date:‘mediumDate‘ }} <!-- Aug 09, 2013 -->
{{ today | date:‘shortDate‘ }} <!-- 8/9/13 -->
{{ today | date:‘mediumTime‘ }} <!-- 12:09:02 PM -->
{{ today | date:‘shortTime‘ }} <!-- 12:09 PM -->
年份格式化:
四位年份: {{ today | date:‘yyyy‘ }} <!-- 2013 -->
两位年份: {{ today | date:‘yy‘ }} <!-- 13 -->
一位年份: {{ today | date:‘y‘ }} <!-- 2013 -->
月份格式化:
英文月份: {{ today | date:‘MMMM‘ }} <!-- August -->
英文月份简写: {{ today | date:‘MMM‘ }} <!-- Aug -->
数字月份: {{ today |date:‘MM‘ }} <!-- 08 -->
一年中的第几个月份: {{ today |date:‘M‘ }} <!-- 8 -->
日期格式化:
数字日期: {{ today|date:‘dd‘ }} <!-- 09 -->
一个月中的第几天: {{ today | date:‘d‘ }} <!-- 9 -->
英文星期: {{ today | date:‘EEEE‘ }} <!-- Thursday -->
英文星期简写: {{ today | date:‘EEE‘ }} <!-- Thu -->
小时格式化:
24小时制数字小时: {{today|date:‘HH‘}} <!--00-->
一天中的第几个小时: {{today|date:‘H‘}} <!--0-->
12小时制数字小时: {{today|date:‘hh‘}} <!--12-->
上午或下午的第几个小时: {{today|date:‘h‘}} <!--12-->
分钟格式化:
数字分钟数: {{ today | date:‘mm‘ }} <!-- 09 -->
一个小时中的第几分钟: {{ today | date:‘m‘ }} <!-- 9 -->
秒数格式化:
数字秒数: {{ today | date:‘ss‘ }} <!-- 02 -->
一分钟内的第几秒: {{ today | date:‘s‘ }} <!-- 2 -->
毫秒数: {{ today | date:‘.sss‘ }} <!-- .995 -->
只要满足规则我们也可以自己去定义日期格式化出来:
{{ today | date:‘hh:mm:ss.sss‘ }} <!-- 12:09:02.995 -->
currency(快速格式化为一个货币格式)
<div ng-app="myApp">
<div ng-controller="myController">
{{ money | currency }}
</div>
</div>
<script type="text/javascript">
var app = angular.module(‘myApp‘, []);
app.controller(‘myController‘,function($scope){
$scope.money=1200;
});
</script>
filter过滤器可以从给定数组中选择一个子集,并将其生成一个新数组返回 例如,在做客户端搜索时,可以从一个数组中立刻过滤出所需的结果。 这个过滤器的第一个参数可以是字符串、对象或是一个用来从数组中选择元素的函数。
1:字符串 返回所有包含这个字符串的元素。如果我们想返回不包含该字符串的元素,在参数前加!符号。
2:对象 AngularJS会将待过滤对象的属性同这个对象中的同名属性进行比较,如果属性值是字符串就会判断是否包含该字符串。如果我们希望对全部属性都进行对比,可以将$当作键名。
3:函数 对每个元素都执行这个函数,返回非假值的元素会出现在新的数组中并返回。
案例1:返回包含数组中所有包含e的单词
<div ng-app="myApp">
<div ng-controller="myController">
{{ data | filter:‘e‘ }}
</div>
</div>
<script type="text/javascript">
var app = angular.module(‘myApp‘, []);
app.controller(‘myController‘,function($scope){
$scope.data=[‘Ari‘,‘Lerner‘,‘Likes‘,‘To‘,‘Eat‘,‘Pizza‘]
});
</script>
案例2:对对象做过滤
<div ng-app="myApp">
<div ng-controller="myController">
{{ data | filter:{‘favorite food‘:‘烤鸭北京‘} }}
</div>
</div>
<script type="text/javascript">
var app = angular.module(‘myApp‘, []);
app.controller(‘myController‘,function($scope){
$scope.data= [{
‘name‘: ‘zhangsan‘,
‘City‘: ‘chengdu‘,
‘favorite food‘: ‘火锅‘
},{
‘name‘: ‘lisi‘,
‘City‘: ‘beijing‘,
‘favorite food‘: ‘烤鸭北京‘
}]
});
</script>
案例3:
<div ng-app="myApp">
<div ng-controller="myController">
{{ name | filter:checkText }}
</div>
</div>
<script type="text/javascript">
var app = angular.module(‘myApp‘, []);
app.controller(‘myController‘,function($scope){
$scope.name=[‘zhangsan‘,‘lisi‘,‘Wangwu‘,‘Hehe‘]
$scope.checkText = function(str) {
return str[0] == str[0].toUpperCase();
};
});
</script>
json过滤器可以将一个JSON或JavaScript对象转换成字符串
演示代码:
<div ng-app="myApp">
<div ng-controller="myController">
{{ name | json }}
</div>
</div>
<script type="text/javascript">
var app = angular.module(‘myApp‘, []);
app.controller(‘myController‘,function($scope){
$scope.name={‘name‘: ‘Ari‘, ‘City‘: ‘SanFrancisco‘}
});
</script>
limitTo过滤器会根据传入的参数生成一个新的数组或字符串,新的数组或字符串的长度取决于传入的参数,通过传入参数的正负值来控制从前面还是从后面开始截取。
演示代码:
<div ng-app="myApp">
<div ng-controller="myController">
{{ data | limitTo:3 }} // {{ data | limitTo:-3 }}
</div>
</div>
<script type="text/javascript">
var app = angular.module(‘myApp‘, []);
app.controller(‘myController‘,function($scope){
$scope.data="helloworld"
});
</script>
number过滤器将数字格式化成文本。它的第二个参数是可选的,用来控制小数点后截取的位数。
演示代码:
<div ng-app="myApp">
<div ng-controller="myController">
{{ data | number }} //{{ data | number:2 }}
</div>
</div>
<script type="text/javascript">
var app = angular.module(‘myApp‘, []);
app.controller(‘myController‘,function($scope){
$scope.data="12345" // $scope.data="1.2345"
});
</script>
orderBy过滤器可以用表达式对指定的数组进行排序。 orderBy可以接受两个参数,第一个是必需的,第二个是可选的。 第一个参数: 数组 重点掌握的一个 在排序表达式中使用数组元素作为谓词。对于与表达式结果并不严格相等的每个元素,则使用第一个谓词。 第二个参数用来控制排序的方向(是否逆向)。
案例1: //对象数组中的name进行排序
<div ng-app="myApp">
<div ng-controller="myController">
{{ data | orderBy:‘name‘ }} // {{ data | orderBy:‘name‘:true }}--这样对排序的顺序反转
</div>
</div>
<script type="text/javascript">
var app = angular.module(‘myApp‘, []);
app.controller(‘myController‘,function($scope){
$scope.data= [{
‘name‘: ‘zhangsan‘,
‘City‘: ‘chengdu‘,
‘favorite food‘: ‘火锅‘
},{
‘name‘: ‘lisi‘,
‘City‘: ‘beijing‘,
‘favorite food‘: ‘烤鸭北京‘
}]
});
</script>
演示代码(这个过滤器是将你类容中的第一个字母大写):
注意:过滤器本质上是一个会把我们输入的内容当作参数传入进去的函数。
<div ng-app="myApp.filters">
{{ ‘helloworld‘ | lowercase | myFilter }}
</div>
<script type="text/javascript">
angular.module(‘myApp.filters‘, [])
.filter("myFilter",function(){
return function(input){
if(input){
return input[0].toUpperCase()+input.slice(1)
}
}
})
</script>
案例2:编写一个过滤器,过滤出比10大的数字
<div ng-app="myApp">
{{ 9 | myFilter }}
</div>
<script type="text/javascript">
var app = angular.module(‘myApp‘,[]);
app.filter(‘myFilter‘,function () {
return function(element){
if(element>10){
return element;
}
}
});
标签:
原文地址:http://www.cnblogs.com/haonantong/p/4659540.html