在過去的幾個月裡,我一直遨遊於Angular的世界。如今回想起來,很難想像在沒有類似於Angular.js, Backbone.js以及其夥伴Underscore.js這些資料綁定框架下我每天如何去編寫一個大型前端應用。我不敢相信我已經用它們完成了那件工作。
可能我有點小偏見,但考慮到我一直在做的應用是在瀏覽器中實現Photoshop類型的編輯器,它呈現相同的數據有幾種完全不一樣的方式。
- 圖層以圖形化的形式呈現,佔據了螢幕的大部分。它們列於一個面板內,你可以刪除它們。
- 當你選取一個圖層時,它的邊緣會被虛線包圍,同時會高亮顯示於清單中。
- 類似地,圖層在面板中的尺寸和它們的大小這些屬性取決於畫布。
- 我上面提到的面板是可以拖曳,折疊,關閉的。
如果不是像Augular的框架,這種種類的互動、資料連結和視圖同步很容易變成一個持續的惡夢。有能力修正一個地方的模型和用Augular修正所有相關的視圖聽起來幾乎像在騙人。新增、消除或改動一個層次只是一個改變物件的問題。層次,x =10,完成。並沒有地方需要手動作廢棄視圖、手工修改在DOM的層次中的每一個實例,甚至是因為這個問題而去與DOM互動。
Augular讓我們可以去到我們從未想過的地方,像設定一串使我們能夠在現有的環境下做出申請的鍵盤捷徑。舉個例子,文件編輯捷徑(像?B:用於切換黑體文本)只是使我們能夠編輯一個文件層面。
同樣地,我們為這些快捷鍵附加了一個描述(透過一個我們創建的服務進行註冊),然後我們可以顯示一個快捷鍵的列表,同時還有它們的描述,在一個便利條上。此外,我們寫了一個指令使得我們可以將單獨的DOM元素與它們的快捷鍵綁在一起,當你的滑鼠在元素上停留一會,會出現一個提示,讓你知道此時可用的快捷鍵。
- Angular能讓我們做到我們做夢也想不到的事。
老實說,這就好像我們已經不是在寫一個web應用程式。 web只是媒介。當我們增進了我們對Angular的理解後,程式碼變得更加模組化,更加獨立,並且更加連接互動。它很自然地變得更Angular了。
然後透過Augular,我的意思是在Augular背後的那些高度互動的豐富的應用開發哲學。 javascript,一個讓我們能夠開發那些一段時間前我們還覺得不可能的一部分軟體的相似的東西。
我們甚至有能力去開發一個成熟的用於修改DOM變成歷史中現在選中的點的歷史控制板,並讓它工作得很好。至少可以這麼說,當你興奮的返回歷史控制板查看那些與Augular能力相關的數據在你的視圖工作中完美的更新每一個微小的細節。
那並不總是容易的,基本程式碼總是變成一場無可控制的混亂。
的確,在過去幾週我們一直在更新並且將我們的前端整個架構重寫。在我們開始重新編寫以前,看看自從0.10.6以來,將Angular更新得有優勢的過程。如果你看了變更日誌,你就知道這是一個相當長的過程。
在這個重構的過程裡,我們從以錯誤的方法對待Angular,轉變為以Angular的方式對待Angular。
在我們的案例中,錯誤的方法包含了許多的問題,我們不得不在此時,在使我們的程式碼基礎到達可愛狀態之前,解決它們。
在全域作用域宣告控制器(Controllers)
這是一個 Angular 初學者容易做的例子。如果你熟悉 Angular,你也會熟悉這種模式。
// winds up on window.LoginCtrl ... var LoginCtrl = function ($scope, dep1, dep2) { // scope defaults }; LoginCtrl.prototype.resetPassword = function () { // reset password button click handler }; // more on this one later LoginCtrl.$inject = ['$scope', dep1', 'dep2'];
這段程式碼沒有包含在閉包中,或者說,所有的聲明都在根作用域,全域的 window 物件上,混蛋啊。用正宗的 Angular 方式來寫的話是使用它提供的模組 api ( module API)。但如你所見,即使是文件和建議步驟任然過時地建議你使用全域作用域:
這樣做,極棒的事情將會出現。
// A Controller for your app var XmplController = function($scope, greeter, user) { $scope.greeting = greeter.greet(user.name); }
-- Angular.js文档
使用模块(modules)允许我们以下面的方式重写控制器(controllers):
angular.module('myApp').controller('loginCtrl', [ '$scope', 'dep1', 'dep2', function ($scope, dep1, dep2) { 'use strict'; // scope defaults $scope.resetPassword = function () { // reset password button click handler }; } ]);
我发现使用 Angular 控制器的漂亮做法是你必须在所有地方使用控制器方法(controller function),因为你需要控器的依赖注入,而且控制器提供了新的作用域,绑定我们从需求到封装我们所有的脚本文件成为自调用函数表达式( self-invoking function expressions),像这样 (function(){})()。
依赖$injection
在最早的例子中你可能已经注意到了, 依赖是使用$inject注入的. 另一方面,大部份的模块API, 允许你传入一个函数作为参数, 或者一个包含了依赖的数组作为参数, 其后面跟着一个依赖于这些依赖的函数. 这是在Angular中我不喜欢的一点 , 但这应该是它文档的过错. 在文档中的大部份例子认为你并不需要一个数组形式的参数; 但现实是,你是需要的。 如果你在使用一个压缩器压缩你的代码之前, 没有运行ngmin , 事情将会变得糟糕.
由于你没有使用数组格式['$scope',...]明确声明你的依赖包,你看上去简洁的方法参数将会被缩略成类似于b,c,d,e的样子,有效地扼杀了Angular的依赖注入能力。我认为他们构建框架的思路存在了重大的失误,这与我在非常不喜欢 Require.js 和他们麻烦的 AMD 模块最后的推论是相似的。
如果他不能在产品中使用,它还有什么用?
我的这种态度是因为你在产品中所使用的框架里,有一部分代码是已经写死了的。这对于开发中经常用到、产品中偶尔用到的实用工具,诸如控制台和错误报告,是很好的。如果语法上的甜头(可读性)只用在开发中,就会变得没有任何意义。
这些破事让我很愤怒, 现在发泄完了. 谈谈$符吧...
减少 jQuery扩散
深入的讲, 这个应用是 "类Angular程序", 也就是说它只是包裹于Angular之中, 大多数DOM 交互是经由jQuery处理的, 这给Angular带来相当多的争论。
如果今天我要从头开始写一款Angular.js应用,我不会立即包含进jQuery。我会强迫自己使用 angular.element 来代替。
如果jQuery存在的话,angular.element这个API将包装它,同时它给Angular团队实现 jQuery的API提供了可以替代的选择,名为jqLite。这并不是说 jQuery不好,或者说我们需要另一个某种实现,来映射它们的API。只是因为使用jQuery显得不是那么有Angular的思想。
让我们来看一个具体的,愚蠢的,例子。在controller被声明的地方,它使用jQuery来做元素之上的类操作。
div.foo(ng-controller='fooCtrl') angular.module('foo').controller('fooCtrl', function ($scope) { $('.foo').addClass('foo-init'); $scope.$watch('something', function () { $('.foo').toggleClass('foo-something-else'); }); });
然而,我们可以用我们期望的方法来使用Angular,替代之。
angular.module('foo').controller('fooCtrl', function ($scope, $element) { $element.addClass('foo-init'); $scope.$watch('something', function () { $element.toggleClass('foo-something-else'); }); });
最后一行你不能直接,或者通过jQuery来操作DOM(改变属性,增添事件监听器)。你应该使用指令来替代。那篇文章很棒,去读读看。
如果你仍然jQuery化了,有许多文章可以一读,例如这篇迁移指南,还有我的关于怎样使用jQuery的批判性思考 这篇文章。
我不是要声明我们准备完全移除 jQuery 。我们有其他更重要的目标,例如,发布我们的产品。这个时候,删除 jQuery 的依赖还是很有意义的。这样做能够使我们的控制器得到简化,我们创建处理 DOM 的指令,使用 angular.element 即使它实际上映射着 jQuery 。
我们依赖着有点恶心的 jQuery UI,我们当然不只是为了它的对话框而使用它,它还有很多用途。例如,拖动一个列表项然后把它放到一个已排序的列表中,如果不使用 jQuery UI,这将牵涉到一大堆代码。因此,实际上,对于 jQuery UI 来说,并没有真正很好的替代品。拖拽的功能可以通过一个轻量级的拖拽库 angular-dragon-drop 来替代,但是,对于元素排序插件,还是得依赖 jQuery UI 。
管理代码库
还有一个我们在迁移中需要解决的问题是整个代码库都挤在一个单一的大文件中。这个文件包含了所有控制器、所有服务、所有指令以及每个控制器的特定代码。我指出一点使得我们可以准确地把每个文件只包含一个组件。目前,我们有很少的文件,却包含了不知一个组件。大多数是因为一个指令使用一个服务来与外界共享数据。
尽管和 Angular 无关,我们还是把我们的 CSS 样式表(stylesheet)模块化。我们为每个组件中使用的 CSS 类名前面都加上了两个字的前缀。例如, .pn- 作为前缀,代表面板(panel); .ly- 前缀,代表着图层(layer)等等。这样做的直接好处就是,你不需要再费劲地想哪个组件的 CSS 类是怎样的了。因为你已经为它们设置了命名空间,你就很少会重复用到某一个 CSS 类名了。另一个好处就是减少了嵌套,我们以前曾经用 #layoutEditor div.layer .handle div 这样复杂的选择器表达式,而现在,我们只需要 .ly-handle-content 就可以了。深度的嵌套现在只发生在额外的选择器覆盖上,例如 .foobar[disabled]:hover,或者,最坏的情况下,像 .foo-bar .br-baz 。
下面是一些我们定下的 CSS 类命名规则:
- 用两个字符来描述组件名:.ly-、.dd-、.dg-等等
- 采用 .ly-foo-barname 来代替嵌套命名 .ly-foo .bar
- 避免内联样式,总是使用 CSS 类名。这能够减少不界面的一致性,提高语义解释能力
- 不要在 CSS 中使用 ID 来赋值
在实现了这套面向组件的 CSS 声明方法后,我又想了很久“the class soup way”。
Angular 强制你写好的代码,但是更深一层说,它强制你去思考。一会儿后,它就像一个服务器端的实现,或者成为一个不堪忍受的“黑客大会”。这些都取决于你这么选择。
接近完美
让我们来解析一下我们应用程序的各部件的其中之一,层。
div.cv-layer( ng-repeat="layer in page.layers | reverse", ap-layer, ng-mousedown="selectLayer(layer.id)", ng-mouseup="selectLayer(layer.id)", ng-dblclick="doubleClickLayer(layer)", ng-hide="layer.invisible" )
這裡,我們使用了cv-layer類,也就是說這個元素是canvas組件的一部分(canvas指的使我們繪製層的地方,不要和HTML5canvas混淆)。然後,我們 在foreach類似的循環裡面 使用ngRepeat標籤來為每一個層的建立一個相似的元素。並且透過一個我們所寫的反向的filter來傳遞,所以,最後一個層位於最上部,而且對用戶可見。 apLayer標籤,其實是為了繪製層的任務所採用的,不論是一個圖片,或者是某些文字,HTML,或別的東西。 event標籤(ng-mousedown, ng-mouseup, ng-dblclick) 只是簡單的為事件做代理而用,這些事件將被我們的層選擇服務來處理。最後,ngHide這個標籤,我想就不必多言了吧。
這麼一大堆功能(譯者註:有點誇張了),而Angular成功的使它看上去如此簡單,用可讀的HTML,從某種程度上就告訴了你它們是怎麼回事。更多的是,它使得你可以分解開不同的需要考慮的問題,從而你能夠寫出來簡潔的程式碼,不需要一次把所有的事情都考慮在內。簡言之,它降低了複雜度(譯者註:其實Angular本身就很複雜,呵呵),讓複雜變的簡單。而讓“難以簡單度量的問題”,變的可能。
我期待不久會有更多關於Angular程式碼的文章。特別是,我樂於探討一些在升級我的程式碼的時候,所遇到的一些邊緣的案例,如何解決其中的問題,同時讓其餘的部分同樣運作。

Javascript 是一个非常有个性的语言. 无论是从代码的组织, 还是代码的编程范式, 还是面向对象理论都独具一格. 而很早就在争论的Javascript 是不是面向对象语言这个问题, 显然已有答案. 但是, 即使 Javascript 叱咤风云二十年, 如果想要看懂 jQuery, Angularjs, 甚至是 React 等流行框架, 观看《黑马云课堂JavaScript 高级框架设计视频教程》就对了。

在如今信息时代,网站已经成为人们获取信息和交流的重要工具。一个响应式的网站能够适应各种设备,为用户提供优质的体验,成为了现代网站开发的热点。本篇文章将介绍如何使用PHP和AngularJS搭建一个响应式网站,从而提供优质的用户体验。PHP介绍PHP是一种开源的服务器端编程语言,非常适用于Web开发。PHP具有很多优点,如易于学习、跨平台、丰富的工具库、开发效

随着互联网的不断发展,Web应用已成为企业信息化建设的重要组成部分,也是现代化工作的必要手段。为了使Web应用能够便于开发、维护和扩展,开发人员需要选择适合自己开发需求的技术框架和编程语言。PHP和AngularJS是两种非常流行的Web开发技术,它们分别是服务器端和客户端的解决方案,通过结合使用可以大大提高Web应用的开发效率和使用体验。PHP的优势PHP

随着互联网的普及,越来越多的人在使用网络进行文件传输和共享。然而,由于各种原因,使用传统的FTP等方式进行文件管理无法满足现代用户的需求。因此,建立一个易用、高效、安全的在线文件管理平台已成为了一种趋势。本文介绍的在线文件管理平台,基于PHP和AngularJS,能够方便地进行文件上传、下载、编辑、删除等操作,并且提供了一系列强大的功能,例如文件共享、搜索、

随着Web应用程序的普及,前端框架AngularJS变得越来越受欢迎。AngularJS是一个由Google开发的JavaScript框架,它可以帮助你构建具有动态Web应用程序功能的Web应用程序。另一方面,对于后端编程,PHP是非常受欢迎的编程语言。如果您正在使用PHP进行服务器端编程,那么结合AngularJS使用PHP将可以为您的网站带来更多的动态效

随着Web技术的飞速发展,单页Web应用程序(SinglePageApplication,SPA)已经成为一种越来越流行的Web应用程序模型。相比于传统的多页Web应用程序,SPA的最大优势在于用户感受更加流畅,同时服务器端的计算压力也大幅减少。在本文中,我们将介绍如何使用Flask和AngularJS构建一个简单的SPA。Flask是一款轻量级的Py

随着互联网的普及和发展,前端开发已变得越来越重要。作为前端开发人员,我们需要了解并掌握各种开发工具和技术。其中,PHP和AngularJS是两种非常有用和流行的工具。在本文中,我们将介绍如何使用这两种工具进行前端开发。一、PHP介绍PHP是一种流行的开源服务器端脚本语言,它适用于Web开发,可以在Web服务器和各种操作系统上运行。PHP的优点是简单、快速、便


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Dreamweaver CS6
視覺化網頁開發工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境