简介可以自动完成UI的AngularJS工具angular-smarty


Posted in Javascript onJune 23, 2015

简介可以自动完成UI的AngularJS工具angular-smarty

我们最近为我们的论坛增加了一个自动完成功能(称为Smarty),在要求专业人员简介的主页上。这是一个超有用的功能,因为它有助于我们将用户导航到他们真正想去的地方。它很有意思,也是用AngularJS构建的!

我们希望Smarty能够:

  1.     通过用户的给定输入 (一个前缀),通过一个HTTP请求后自动提供建议
  2.     显示一个建议的下拉列表
  3.     当用户输入时更新
  4.     足够快,能够跟得上用户的输入
  5.     导航直观且能够关闭
  6.     可重用

以往没有AngularJS的经验,这个项目是我使用这个框架的入门项目。它真的成为了一次宝贵的学习经验,而且我发现这个框架许多方面相互借鉴地很好且能很好地符合我上面列出的要求。当然,还有一些问题尚在学习过程中!

AngularJS的乐趣所在

我最喜欢Angular的一点是它是如何分解成具有明确目的的概念的。Smarty广泛使用了其中的两个概念——Directives 和 Services。Directive和DOM绑定在了一起,用来管理和元素之间的交互;而Service通过依赖注入的方式为Controller和Directive提供了独立的可以重用的逻辑。

Angular提供了很多内建的Directive和Service,我们在这个项目中使用到了其中的多个。

    为了显示建议(见要求2),我们使用了ngIf 和 ngRepeat 指令来有条件的显示和填充建议下来列表。

    为了实现当用户输入的时候更新建议内容(见要求3),我们使用了ngModel 指令将$scope上前缀变量上输入元素的请求和Scope上的$watch方法双向绑定起来,用来监听前缀的变化。

    我们需要考虑的一件事是这个自动完成功能的更新速度可能跟不上用户的输入速度(见要求4)。因为每当前缀的值发生变化时,Smarty都要发送一个HTTP请求(通过内建的$http Service)。我们决定用 $http 的可选配置参数($http.get(requestUrl, {cache: true}))来缓存结果。这是提升性能的一个很简单的方法。

我们还写了自定义的Directive和Service来满足我们的特定需求:

    smartySuggestor Service:smartySuggestor 提供了一个getSmartySuggestions()函数,用来接受用户生成的前缀作为它的参数,并通过http请求访问我们后端的suggestor服务来得到自动完成的建议。(见要求1)。

    smartyInput Directive: 我们所面临的一个挑战是,定义出一个用户和下拉列表之间的所有可能的交互,并且写测试用例,以确保在开发期间和开发之后,这些功能都是完好的。我们使用一个Directive(smartyInput)来包含用户和下拉列表之间所有可能发生的交互(见要求6),同时,我们使用内建的ng-mouseover 和 ng-click 指令(Directive)来定义下拉列表和鼠标事件之间的交互。

正如我前边所提到的,我们所面临的一个挑战是我们要确保我们没有破坏掉所有用户和下拉列表之间可能发生的交互方式。为了追踪这些用户交互,并确保我们没有在开发的过程中破坏掉它,我们使用了Jasmine测试框架。Jasmine结合这angular-mocks一块儿使用,可以方便我们为smarty写包含描述的测试用例,像我们可以为下拉列表写“点击外部应该会消失”("should disappear on outside click"),可以为请求表单的输入写“按回车时应该填充上合适的值” (“should, on enter, fill with the appropriate value”)。

学习总结

尽管简洁实用的AngularJS框架现在对我来讲,是可以轻松读懂的,但是确实要花些时间来学习。隔离作用域绑定指令符和promise是我学习过程中特别棘手的两项专题。当我研究隔离作用域时,我发现自己十分希望能看到更多的关于人们如何在他们的项目中使用不同绑定的例子,所以下面我为每种绑定类型给出一个例子。
=:本地和父作用域之间的双向数据绑定

控制器:
 

$scope.selected = -1;

HTML:
 

<input type="text" smarty-input index="selected">

SmartyInput指令符:
 

scope: {index: "=", ...}

SmartyInput双向绑定指令符将位于控制器作用域的selected绑定到指令作用域的index索引上面,这样可以使得在index索引(建议列表中当前选定的索引)中的变化结果与指令(例如用户按向上/向下箭头)的相互作用会传播到控制器。

&: 本地与父作用域之间的单向数据绑定

控制器:
 

$scope.setSelected = function(newValue) {...};

HTML:
 

<input type="text" smarty-input select="setSelected(x)">

SmartyInput指令符:
 

scope: {select: "&", ... }...scope.select({"x": parseInt(scope.index) + 1});

SmartyInput指令符将控制器作用域中的setSelected()函数绑定到指令作用域中的select()函数上,这样可以使指令符在不改变setSelected()函数的情况下使用它。
@:将计算表达式绑定到本地作用域

控制器:
 

$scope.prefix = ""

HTML:
 

<div smarty-suggestions prefix="{{prefix}}">

SmartySuggestions指令符:
 

scope: {prefix: "@", ...}

通过SmartySuggestions指令符,可在建议菜单中显示prefix的值,所以此处使用计算表达式{{prefix}}。这种绑定方式在多项复杂表达式中更常用,比如:next-index=“{{selected + 1}}”。

Promises

promise是用于执行异步任务的技术。一个promise具有一个名为then()的方法,该方法在promise执行时会作为被执行的的回调函数的一个参数。当异步任务完成,promise会将一段消息传给那个回调函数。当用户输入的prefix前缀中检测到更改,则promise就会出现在Smarty的代码中,然后我们会用$http执行一个GET请求,用来更新显示给用户建议的列表。

这个过程看起来是这样的:

当$scope.$watch在$scope.prefix(请注意,此处绑定到用户UI输入界面)的值中注册了一个更改,此时会调用getSmartySuggesction()。
 

var promise = smartySuggestor.getSmartySuggestions($scope.prefix);promise.then(function(data) {
  $scope.suggestions = data;});

在getSmartySuggesctions()中,$http.get会返回一个参与服务器响应的promise。
 

function getSmartySuggestions(prefix) {
  requestParams["query"] = escape(prefix.toLowerCase());
  var promise = $http.get(requestUrl(),
    {
      params: requestParams,
      cache: true
    }
  ).then(function(response) {
    return response.data.slice(0, 5).map(function(item) {
      return item.Name;
    });
  });
  return promise;}

服务器响应看起来是这样的:

[{"ID":13,"Name":"Portrait Photography"},{"ID":24,"Name":"Commercial Photography"},{"ID":21,"Name":"Pet Photography"},{"ID":16,"Name":"Event Photography"},{"ID":26,"Name":"Headshot Photography"}]

接下来,我们会调用存在于promise中的then()方法,在解析服务器响应回调中进行传递。then()方法返回一个新的promise,它处理了解析过的响应,并存储到通过getSmartySuggestions()返回的promise中。

解析过的响应看起来是这样的:[“Portrait Photography”, “Commercial Photography”, “Pet Photography”, “Event Photography”, “Headshot Photography”]。

最终,回到$scope.$watch,我们调用promise中的then()方法,为变量suggestions分配这些解析过的响应。
 

var promise = smartySuggestor.getSmartySuggestions($scope.prefix);
promise.then(function(data) {
  $scope.suggestions = data;
});

 

Javascript 相关文章推荐
仅IE不支持setTimeout/setInterval函数的第三个以上参数
May 25 Javascript
js实现动态添加、删除行、onkeyup表格求和示例
Aug 18 Javascript
jquery text(),val(),html()方法区别总结
Nov 04 Javascript
ff下JQuery无法监听input的keyup事件的解决方法
Dec 12 Javascript
javascript中的循环语句for语句深入理解
Apr 04 Javascript
node.js入门教程迷你书、node.js入门web应用开发完全示例
Apr 06 Javascript
基于JQuery打造无缝滚动新闻步骤详解
Mar 31 Javascript
javascript js 操作数组 增删改查的简单实现
Jun 20 Javascript
详解vue的diff算法原理
May 20 Javascript
vue过滤器用法实例分析
Mar 15 Javascript
javascript 代码是如何被压缩的示例代码
May 06 Javascript
jQuery 动态粒子效果示例代码
Jul 07 jQuery
javascript中传统事件与现代事件
Jun 23 #Javascript
浅谈jquery中delegate()与live()
Jun 22 #Javascript
jquery 中ajax执行的优先级
Jun 22 #Javascript
jquery中ready()函数执行的时机和window的load事件比较
Jun 22 #Javascript
jquery中toggle函数交替使用问题
Jun 22 #Javascript
浅谈js 闭包引起的内存泄露问题
Jun 22 #Javascript
js闭包所用的场合以及优缺点分析
Jun 22 #Javascript
You might like
攻克CakePHP系列一 连接MySQL数据库
2008/10/22 PHP
一个简单php扩展介绍与开发教程
2010/08/19 PHP
逆序二维数组插入一元素的php代码
2012/06/08 PHP
PHP中unset,array_splice删除数组中元素的区别
2014/07/28 PHP
PHP管理依赖(dependency)关系工具 Composer 安装与使用
2014/08/18 PHP
php获取、检查类名、函数名、方法名的函数方法
2015/06/25 PHP
利用PHP生成CSV文件简单示例
2016/12/21 PHP
php设计模式之适配器模式原理、用法及注意事项详解
2019/09/24 PHP
jQuery EasyUI API 中文文档 - ValidateBox验证框
2011/10/06 Javascript
javascript学习笔记(五) Array 数组类型介绍
2012/06/19 Javascript
在JS方法中返回多个值的方法汇总
2015/05/20 Javascript
详解JavaScript正则表达式中的global属性的使用
2015/06/16 Javascript
SWFUpload多文件上传及文件个数限制的方法
2016/05/31 Javascript
Json按某个键的值进行排序
2016/12/22 Javascript
jQuery中hover方法搭配css的hover选择器,实现选中元素突出显示方法
2017/05/08 jQuery
基于JavaScript实现前端数据多条件筛选功能
2020/08/19 Javascript
如何快速解决JS或Jquery ajax异步跨域的问题
2018/01/08 jQuery
微信小程序模版渲染详解
2018/01/26 Javascript
vue实现吸顶、锚点和滚动高亮按钮效果
2019/10/21 Javascript
jQuery模仿ToDoList实现简单的待办事项列表
2019/12/30 jQuery
Python NumPy库安装使用笔记
2015/05/18 Python
Python反射和内置方法重写操作详解
2018/08/27 Python
Python实现合并excel表格的方法分析
2019/04/13 Python
Django实现发送邮件功能
2019/07/18 Python
python并发编程 Process对象的其他属性方法join方法详解
2019/08/20 Python
python实现最大优先队列
2019/08/29 Python
利用Opencv实现图片的油画特效实例
2021/02/28 Python
印度首选时尚目的地:Reliance Trends
2018/01/17 全球购物
香港艺人陈冠希创办的潮流品牌:JUICESTORE
2021/03/04 全球购物
大学生怎样写好自荐信
2014/02/25 职场文书
2014年医院十一国庆节活动方案
2014/09/15 职场文书
小学教育见习报告
2014/10/31 职场文书
2016抗战胜利71周年红领巾广播稿
2015/12/18 职场文书
大学生安全教育心得体会
2016/01/15 职场文书
详解PyTorch模型保存与加载
2022/04/28 Python
Android Gradle 插件自定义Plugin实现注意事项
2022/06/16 Java/Android