简介可以自动完成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 相关文章推荐
struts2 jquery 打造无限层次的树
Oct 23 Javascript
js或css文件后面跟参数的原因说明
Jan 09 Javascript
读jQuery之十三 添加事件和删除事件的核心方法
Aug 23 Javascript
js设置文本框中焦点位置在最后的示例代码(简单实用)
Mar 04 Javascript
JavaScript继承基础讲解(原型链、借用构造函数、混合模式、原型式继承、寄生式继承、寄生组合式继承)
Aug 16 Javascript
EasyUi datagrid 实现表格分页
Feb 10 Javascript
js控制元素显示在屏幕固定位置及监听屏幕高度变化的方法
Aug 11 Javascript
javascript实现dom元素可拖动
Mar 21 Javascript
Mobile Web开发基础之四--处理手机设备的横竖屏问题
Aug 11 Javascript
vue基础之模板和过滤器用法实例分析
Mar 12 Javascript
JavaScript的垃圾回收机制与内存管理
Aug 06 Javascript
详解JavaScript中new操作符的解析和实现
Sep 04 Javascript
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
php抽奖小程序的实现代码
2013/06/18 PHP
分享十款最出色的PHP安全开发库中文详细介绍
2015/03/22 PHP
Laravel 加载第三方类库的方法
2018/04/20 PHP
JavaScript flash复制库类 Zero Clipboard
2011/01/17 Javascript
多个datatable共存造成多个表格的checkbox都被选中
2013/07/11 Javascript
在服务端(Page.Write)调用自定义的JS方法详解
2013/08/09 Javascript
Javascript 绘制 sin 曲线过程附图
2014/08/21 Javascript
fckeditor粘贴Word时弹出窗口取消的方法
2014/10/30 Javascript
TinyMCE汉化及本地上传图片功能实例详解
2016/05/31 Javascript
jquery插件格式实例分析
2016/06/16 Javascript
AngularJS入门教程之 XMLHttpRequest实例讲解
2016/07/27 Javascript
用自定义图片代替原生checkbox实现全选,删除以及提交的方法
2016/10/18 Javascript
Vue.js实现简单动态数据处理
2017/02/13 Javascript
浅谈jquery拼接字符串效率比较高的方法
2017/02/22 Javascript
Vue学习笔记进阶篇之多元素及多组件过渡
2017/07/19 Javascript
利用node.js+mongodb如何搭建一个简单登录注册的功能详解
2017/07/30 Javascript
解决Vue在封装了Axios后手动刷新页面拦截器无效的问题
2018/11/08 Javascript
Nuxt.js 静态资源和打包的操作
2020/11/06 Javascript
javascript中导出与导入实现模块化管理教程
2020/12/03 Javascript
Django中的“惰性翻译”方法的相关使用
2015/07/27 Python
Python selenium文件上传方法汇总
2020/11/19 Python
python读取指定字节长度的文本方法
2019/08/27 Python
Tkinter中复选菜单是否被选中的判断与设置方式
2020/03/04 Python
解决jupyter notebook 出现In[*]的问题
2020/04/13 Python
Python3.7下安装pyqt5的方法步骤(图文)
2020/05/12 Python
python简单实现9宫格图片实例
2020/09/03 Python
家得宝官网:The Home Depot(全球最大的家居装饰专业零售商)
2018/12/17 全球购物
草莓网官网:StrawberryNET
2019/08/21 全球购物
资产经营总监岗位职责
2013/12/04 职场文书
在校大学生的职业生涯规划书
2014/03/14 职场文书
政法干警核心价值观心得体会
2014/09/11 职场文书
个人先进材料范文
2014/12/30 职场文书
2015年妇委会工作总结
2015/05/22 职场文书
汽车修理厂管理制度
2015/08/05 职场文书
2016年元旦寄语
2015/08/17 职场文书
正确的理解和使用Django信号(Signals)
2021/04/14 Python