当前位置: 代码迷 >> 综合 >> 移动开发中3个js库的介绍:Apache Cordova,Knockout 及 iScroll
  详细解决方案

移动开发中3个js库的介绍:Apache Cordova,Knockout 及 iScroll

热度:82   发布时间:2024-01-16 21:17:37.0

  • Apache Cordova

    • Apache Cordova是一套设备API,允许移动应用的开发者使用JavaScript来访问本地设备的功能,比如摄像头、加速计。它可以与UI框架(如jQuery Mobile 或 Dojo Mobile 或 Sencha Touch)等相结合使用,这些UI框架可以使用HTML、CSS和JavaScript开发智能手机应用。
    • 在使用Cordova API时,应用程序的构建可以无需本地代码(如Java或对象C等),使用的是Web技术
    • 由于这些JavaScript API在多个设备平台上是一致的,而且是基于Web标准创建的,因此应用程序的移植很方便,基本不做什么改变
    • Cordova提供了一套统一的JavaScript库供调用,它支持iOS、Android、Blackberry、Windows Phone、Palm WebOS、Bada和Symbian

  • Knockout

    • Knockout是一个轻量级的UI类库,通过应用MVVM模式使JavaScript前端UI简单化
    • Knockout是一个以数据模型(data model)为基础的能够帮助你创建富文本,响应显示和编辑用户界面的JavaScript类库。任何时候如果你的UI需要自动更新(比如:更新依赖于用户的行为或者外部数据源的改变),KO能够很简单的帮你实现并且很容易维护
    • 开发人员如果用过Silverlight或者WPF可能会知道KO是MVVM模式的一个例子。如果熟悉 Ruby on Rails 或其它MVC技术可能会发现它是一个带有声明式语法的MVC实时form。换句话说,你可以把KO当成通过编辑JSON数据来制作UI用户界面的一种方式

    • Knockout有如下4大重要概念:

      • 声明式绑定 (Declarative Bindings):使用简明易读的语法很容易地将模型(model)数据关联到DOM元素上
      • UI界面自动刷新 (Automatic UI Refresh):当您的模型状态(model state)改变时,您的UI界面将自动更新
      • 依赖跟踪 (Dependency Tracking):为转变和联合数据,在你的模型数据之间隐式建立关系
      • 模板 (Templating):为您的模型数据快速编写复杂的可嵌套的UI

    • 额外的好处:

      • 纯JavaScript类库 – 兼容任何服务器端和客户端技术
      • 可添加到Web程序最上部 – 不需要大的架构改变
      • Comprehensive suite of specifications (采用行为驱动开发) - 意味着在新的浏览器和平台上可以很容易通过验证

    • 如何使用它

      • 简单来说:声明你的数据作为一个JavaScript 模型对象(model object),然后将DOM 元素或者模板(templates)绑定到它上面
      • 来看一个具体的例子:
        • 想想在一个页面上,航空旅客可以为他们的旅行升级高级食物套餐,当他们选择一个套餐的时候,页面立即显示套餐的描述和价格。首先,声明可用的套餐:
          • var availableMeals = [{ mealName: 'Standard', description: 'Dry crusts of bread', extraCost: 0 },{ mealName: 'Premium', description: 'Fresh bread with cheese', extraCost: 9.95 },{ mealName: 'Deluxe', description: 'Caviar and vintage Dr Pepper', extraCost: 18.50 }];
        • 如果想让这3个选项显示到页面上,我们可以绑定一个下拉菜单(例如:<select>元素)到这个数据上。例如:
          • <h3>Meal upgrades</h3>
            <p>Make your flight more bearable by selecting a meal to match your social and economic status.</p>
            Chosen meal: <select data-bind="options: availableMeals,optionsText: 'mealName'"></select>
        • 启用Knockout并使你的绑定生效,在availableMeals变量声明之后添加如下代码:
          • var viewModel = {/* we'll populate this in a moment */
            };ko.applyBindings(viewModel); // Makes Knockout get to work
            // 注意:ko. applyBindings需要在上述HTML之后应用才有效
        • 现在你的页面将render成如下的样子:


        • 响应选择
        • 下一步,声明一个简单的data model来描述旅客已经选择的套餐,添加一个属性到当前的view model上:
          • var viewModel = {chosenMeal: ko.observable(availableMeals[0])
            };
          • ko.observable是什么?它是KO里的一个基础概念。UI可以监控(observe)它的值并且回应它的变化。这里我们设置chosenMeal是UI可以监控已经选择的套餐,并初始化它,使用availableMeal里的第一个值作为它的默认值(例如:Standard)
        • 让我们将chosenMeal 关联到下拉菜单上,仅仅是更新<select>的data-bind属性,告诉它让<select>元素的值读取/写入chosenMeal这个模型属性:
          • Chosen meal: <select data-bind="options: availableMeals,optionsText: 'mealName',value: chosenMeal"></select>
        • 理论上说,我们现在可以读/写chosenMeal 属性了,但是我们不知道它的作用。让我们来显示已选择套餐的描述和价格:
          • <p>You've chosen:<b data-bind="text: chosenMeal().description"></b>(price: <span data-bind='text: chosenMeal().extraCost'></span>)
            </p>
        • 于是,套餐信息和价格,将根据用户选择不同的套餐项而自动更新:


        • 最后一件事:如果能将价格格式化成带有货币符号的就好了,声明一个JavaScript函数就可以实现了:
          • function formatPrice(price) {return price == 0 ? "Free" : "$" + price.toFixed(2);
            }
        • 界面显示结果将变得好看多了:


        • Price的格式化展示了,你可以在你的绑定里写任何JavaScript代码,KO仍然能探测到你的绑定依赖代码。这就展示了当你的model改变时,KO如何只进行局部更新而不用重新render整个页面 – 仅仅是有依赖值改变的那部分
        • 链式的observables也是支持的(例如:总价依赖于价格和数量)。当链改变的时候,依赖的下游部分将会重新执行,同时所有相关的UI将自动更新。不需要在各个observables之间声明关联关系,KO框架会在运行时自动执行的
        • 你可以从 observables 和 observable arrays 获取更多信息。上面的例子非常简单,没有覆盖很多KO的功能。你可以获取更多的内嵌的绑定和模板绑定
        • knockout和jQuery (或Prototype等)是竞争关系还是能一起使用?
          • 所有人都喜欢jQuery! 它是一个在页面里操作元素和事件的框架,非常出色并且易使用,在DOM操作上肯定使用jQuery,knockout解决不同的问题
          • 如果页面要求复杂,仅仅使用jQuery需要花费更多的代码。 例如:一个表格里显示一个列表,然后统计列表的数量,Add按钮在数据行TR小于5调的时候启用,否则就禁用。jQuery 没有基本的数据模型的概念,所以需要获取数据的数量(从table/div或者专门定义的CSS class),如果需要在某些SPAN里显示数据的数量,当添加新数据的时候,你还要记得更新这个SPAN的text。当然,你还要判断当总数>=5条的时候禁用Add按钮。 然后,如果还要实现Delete功能的时候,你不得不指出哪一个DOM元素被点击以后需要改变
        • Knockout的实现有何不同?
          • 使用knockout非常简单。将你的数据描绘成一个JavaScript数组对象myItems,然后使用模板(template)转化这个数组到表格里(或者一组DIV)。不管什么时候数组改变, UI界面也会响应改变(不用指出如何插入新行<tr>或在哪里插入),剩余的工作就是同步了。例如:你可以声明绑定如下一个SPAN显示数据数量(可以放在页面的任何地方,不一定非要在template里):
            • There are <span data-bind="text: myItems().count"></span> items
          • 就是这些!你不需要写代码去更新它,它的更新依赖于数组myItems的改变。同样, Add按钮的启用和禁用依赖于数组myItems的长度,如下:
            • <button data-bind="enable: myItems().count < 5">Add</button>
          • 之后,如果你要实现Delete功能,不必指出如何操作UI元素,只需要修改数据模型就可以了
          • 总结:knockout没有和jQuery或类似的DOM 操作API对抗竞争。knockout提供了一个关联数据模型和用户界面的高级功能。knockout本身不依赖jQuery,但是你可以一起同时使用jQuery, 生动平缓的UI改变需要真正使用jQuery
        • 下载安装
          • 纯 js ,直接下载引入即可
          • 开启模板绑定,只需再引入两个 js 文件即可,正确的引用顺序:
            • <script type='text/javascript' src='jquery-1.4.2.min.js'></script>
              <script type='text/javascript' src='jquery-tmpl.js'></script>
              <script type='text/javascript' src='knockout-1.2.1.js'></script>

    • MVVM

      • 想理解 MVVM 先去看 WPF(注意一个概念,先前的 WFX 即是后面的 .NET Framework 3.0)
      • 看完 WPF 再去看 MVP
      • 看完 MVP 再理解一下 MVP 和 MVC 的不同:MVC 有什么缺陷?MVP 解决了这些缺陷吗?MVP是如何解决这些缺陷的?

      • MVVM是Model-View-ViewModel的简写。微软的WPF带来了新的技术体验,如Sliverlight、音频、视频、3D、动画……,这导致了软件UI层更加细节化、可定制化。同时,在技术层面,WPF也带来了 诸如Binding、Dependency Property、Routed Events、Command、DataTemplate、ControlTemplate等新特性。MVVM(Model-View-ViewModel)框架的由来便是MVP(Model-View-Presenter)模式与WPF结合的应用方式时发展演变过来的一种新型架构框架。它立足于原有MVP框架并且把WPF的新特性揉合进去,以应对客户日益复杂的需求变化

      • MVVM 架构图


        • MVVM 主要优点
          • 低耦合
            • 视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变
          • 高可重用性
            • 你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑
          • 独立开发
            • 开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xaml代码
          • 独立测试
            • 界面素来是比较难于测试的,而现在测试可以针对ViewModel来写

    • 设计模式的发展(MVC—>MVP—>MVVM)

      • 最基础的 MVC , 缺陷 : View层会直接从Model层拉数据,导致View层依赖Model层,带来团队开发和功能复用、测试上的一系列缺陷
      • MVP 改Controler 层为 Presenter 层,不允许View 层直接访问Model层,再加一层 adapter,多出来的逻辑在 Presenter 层里实现
      • MVVM 则进一步改进 MVP, 引入 数据绑定  的概念,在View 层和Model 层之间再加入一层为 特定View 量身定制的 Model层,这层就被称为 ViewModel层,即:MVVM中后面的VM
        • View绑定到ViewModel,然后执行一些命令在向它请求一个动作。而反过来,ViewModel跟Model通讯,告诉它更新来响应UI。这样便使得为应用构建UI非常的容易。往一个应用程序上贴一个界面越容易,外观设计师就越容易使用Blend来创建一个漂亮的界面。同时,当UI和功能越来越松耦合的时候,功能的可测试性就越来越强

  • iScroll

    • iscroll.js是Matteo Spinelli开发的一个js文件,使用原生js编写,不依赖与任何js框架。旨在解决移动webkit系浏览器的区域滚动问题,兼容mobile safari、android默认浏览器、safari、chrome、firefox5+、opera11+、IE9+及其他webkit核心浏览器

    • 什么是移动webkit系浏览器的区域滚动问题

      • 我们在pc端web开发中,有时会用固定某一区域的宽度和高度,然后使用overflow:auto,使其内容在该区域内滚动
      • iphone默认浏览器(mobile safari)也支持固定区域的滚动,但必须双指滑动操作,而且没有滚动条。mobile safari中的单指滑动只针对页面级别,不针对页面元素。这样的操作体验很麻烦,而且很多用户根本不知道双指能够区域滑动
      • android自带浏览器也支持区域滚动,且可以单指滑动操作,但是滑动起来卡的半死半活,很不流畅
      • 使用iscroll,可以完美解决上述问题了,不仅可以在iphone和android上单指滑动,而且滑动起来流畅之极,酣畅淋漓。滑动过程中也有漂亮的滚动条提示,让你舒心不已

    • 固定定位

      • 固定定位不是iscroll的原生用法,而是使用iscroll协助解决固定定位问题
      • 话说iphone很先进,但就是不支持position:fixed。这下苦了我们了,固定定位怎么解决啊,我们会经常遇到固定标题栏、固定工具栏等情况啊!!
      • 使用iscroll协助解决:首先获取浏览器窗口高度;然后获取固定工具栏的高度;接着将除固定工具栏之外的内容全部放在一个固定区域内,该固定区域的高度=窗口高度-工具栏高度;之后对固定区域使用iscroll。这样,整个html页面的高度正好等于窗口高度,页面级别不会出现滚动,工具栏就一直固定在当前的位置。在固定区域内滑动,可以查看页面其他内容,不会影响工具栏的定位

    • 鼠标滚轮滚动

      • iscroll支持在pc端浏览器中使用鼠标滚轮控制区域滚动,但操作起来很不灵敏。这是由于iscroll对鼠标滚轮事件做了拦截,然后缩小了滚轮的滚动距离,详见iscroll4.js源代码608-609行:
        • wheelDeltaX = e.wheelDeltaX / 12;//控制X轴鼠标滚轮速度 
          wheelDeltaY = e.wheelDeltaY / 12;//控制Y轴鼠标滚轮速度
      •  iscroll将每次的滚轮距离缩小为系统默认距离的12分之一,难怪滚起来很慢,感觉不灵敏。只需要将12改成1,滚轮的滚动速度就恢复正常了。你也可以根据实际需要设置成其他值

    • 输入框聚焦不灵敏、无法选择文字

      • 使用了iscroll之后,你会发现点击输入框时不灵敏,经常无法聚焦;页面文字也无法选择和复制。这是由于iscroll要监听鼠标事件和触摸事件来进行滚动,所以禁止了浏览器的默认行为,详见源代码92行:
        • onBeforeScrollStart: function (e) { e.preventDefault(); },
      • iscroll不分青红皂白,禁止了浏览器的一切默认行为,导致上述问题。所以我们需要稍作修改:
        • onBeforeScrollStart: function (e) { 
          var target = e.target; 
          while (target.nodeType != 1) target = target.parentNode; 
          if (target.tagName != ‘SELECT’ && target.tagName != ‘INPUT’ && target.tagName != ‘TEXTAREA’) 
          e.preventDefault(); 
          }, 
      • 判断触发事件的元素是不是input、select、textarea等表单输入类元素,如果不是就阻止默认行为。这样保证了输入类元素能正确快速聚焦。 
        在上述修改中追加一个条件 target.tagName != ‘body’或者直接将onBeforeScrollStart修改为null,即可做到鼠标选取文字,但这样的修改会导致iscroll滚动失效或不灵敏,所以无法选取文字这个问题先放一边吧。如你有更好的方法,欢迎回复

    • select元素操作不灵敏或操作后白屏

      • 使用iscroll后,还有一个较麻烦的问题,就是select元素点击不灵敏(滚动之后点击select,经常无响应);有时点击有反应了,下拉菜单显示却错位(pc端);选择一项之后,页面直接变成了空白(iphone、android中)或者页面位置向上偏离,滚动区域位置出现偏离
      • 说白了,就是导致select没法用。为此我调试了很久,最后发现了问题所在:iscroll默认使用的是css的transform变形中的translate3d实现区域滚动,每次滚动实际是改变translate3d中的y轴值,实际的dom位置并没有发生变化。translate3d会导致页面的焦点错误,系统级下拉菜单的显示则会导致其出现显示偏离
      • 控制滚动模式的代码在67行:useTransform: true。好在iscroll提供了另一种滚动方式,基于绝对定位位置变化的滚动。修改为useTransform: false之后,iscroll就会使用对定位位方式来实现滚动,该方式是我们在web开发中模拟动画的最常用方式,滚动之后dom的实际位置也同步发生了变化,不会出现错位偏离现象
      • 在pc端主流浏览器、iphone、android2.2下测试,select问题完美解决
      • 不过需要注意,使用对position决定定位后,滚动区的宽度默认会自适应内容宽度,而不是父元素的100%,所以最好将滚动区域宽度设为100%

    • 美中不足

      • iscroll是小而精的经典作品,名字也带着apple范。但唯一美中不足的是,只能使用id调用
  相关解决方案