怎么找只有微信号怎么推广的人地址

[后端人员耍前端系列]AngularJs篇:30分钟快速掌握AngularJs
[后端人员耍前端系列]AngularJs篇:30分钟快速掌握AngularJs
来源:极客头条
  对于前端系列,自然少不了AngularJs的介绍了。在前面文章中,我们介绍了如何使用KnockoutJs来打造一个单页面程序,后面一篇文章将介绍如何使用AngularJs的开发一个单页面应用程序。在开始使用AngularJs开发SPA之前,我觉得有必要详细介绍下AngularJs所涉及的知识点。所有也就有了这篇文章。
二、AngularJs介绍
  AngularJS是Google推出的一款Web应用开发框架。它提供了一系列兼容性良好并可扩展的服务,包括数据绑定、DOM操作、MVC和依赖注入等特性。相信下面图片可以更好地诠释AngularJs具体支持哪些特性。
  &从上图可以发现,AngularJs几乎支持构建一个Web应用的所有内容&&数据绑定、表单验证、路由、依赖注入、控制器、模板和视图等。
  但并不是所有的应用都适合用AngularJs来做。AngularJS主要考虑的是构建CURD应用,但至少90%的Web应用都是CURD应用。哪什么不适合用AngularJs来做呢? 如游戏、图像界面编辑器等应用不适合用AngularJs来构建。
三、AngularJS核心知识点
  接下来,我们就详细介绍了AngularJS的几个核心知识点,其中包括:
指令(directive)和&数据绑定(Data Binding)
模板(Module)
控制器(Controller)
路由(Route)
服务(service)
过滤器(Filter)
3.1 指令和数据绑定
  在没有使用AngularJs的Web应用,要实现前台页面逻辑通过给HTML元素设置ID,然后使用Js或Jquery通过ID来获取HTML DOM元素。而AngularJS不再需要给HTML元素设置ID,而是使用指令的方式来指导HTML元素的行为。这样做的好处是开发人员看到HTML元素以及指令(Directive)就可以理解其行为,而传统设置Id的方式并不能给你带来任何有用的信息,你需要深入去查看对应的Js代码来理解其行为。
  上面介绍了这么多,好像没有正式介绍指令是什么呢?光顾着介绍指令的好处和传统方式的不同了。指令可以理解为声明特殊的标签或属性。AngularJs内置了很多的指令,你所看到的所有以ng开头的所有标签,如ng-app、ng-init、ng-if、ng-model等。
ng-app:用于标识页面是一个AngularJs页面。一般加载HTML的根对象上。
ng-init 用于初始化了一个变量
ng-model:用户在Property和Html控件之间建立双向的数据绑定(Data Binding)。这样Html控件的值改变会反应到Property上,反过来也同样成立。
AngularJs通过表达式的方式将数据绑定到HTML标签内。AngularJs的表达式写在双大括号内:{{expression}}
  下面具体看一个指令的例子:
&!DOCTYPE html&
&html ng-app xmlns="http://www.w3.org/1999/xhtml"&
&meta http-equiv="Content-Type" content="text/ charset=utf-8" /&
&title&Using Directives and Data Binding Syntax&/title&
&body ng-init="name = '欢迎学习AngularJS'"&
Name: &input type="text" ng-model="name" /& {{name}}
&script src="/Scripts/angular.min.js"&&/script&
  效果在线预览:
  从在线预览的页面可以发现,当我们改变输入框的值时,对应的改变会反应到name属性上,从而反应到表达式的值。AngularJs中双向绑定的使用主要是靠ng-model指令来完成的。前面说的都是一些AngularJs内置的指令,其实我们也可以自定义指令。关于这部分内容将会在后面介绍到。
  在Asp.net MVC中提供了两种页面渲染模板,一种是Aspx,另一种是Razor.然而Asp.net MVC的这两种模板都是后端模板,即页面的渲染都是在服务端来完成的。这样不可避免会加重服务器端的压力。AngularJs的模板指的是前端模板。AngularJS有内置的前端模板引擎,即所有页面渲染的操作都是放在浏览器端来渲染的,这也是SPA程序的一个优势所在,所有前端框架都内置了前端模板引擎,将页面的渲染放在前端来做,从而减轻服务端的压力。
  在AngularJs中的模板就是指带有ng-app指令的HTML代码。AngularJs发现Html页面是否需要用AngularJs模板引擎去渲染的标志就是ng-app标签。
  在AngularJs中,我们写的其实也并不是纯的Html页面,而是模板,最终用户看到的Html页面(也就是视图)是通过模板渲染后的结果。
  下面来看下模板的例子:
&!DOCTYPE html&
&html ng-app="mainApp"&
&meta http-equiv="Content-Type" content="text/ charset=utf-8" /&
&title&Template Demo&/title&
&script src="/uploads/rs/376/pbcx3e1z/angular.min.js"&&/script&
(function() {
// 创建模块
var mainApp = angular.module("mainApp",[]);
// 创建控制器,并注入scope
mainApp.controller("tempController", ["$scope", function ($scope) {
$scope.val = "Welcome to Study AngularJs.";
&h2&AngularJS 模块演示&/h2&
&div ng-controller="tempController"&
&div&&input type="text" ng-model="val"&
{{val}}&/div&
  在线预览地址:
3.3 控制器
  其实模板中的例子中,我们就已经定义了名为"tempController"的控制器了。接下来,我们再详细介绍下AngularJs中的控制器。其实AngularJs中控制器的作用与Asp.net MVC中控制器的作用是一样的,都是模型和视图之间的桥梁。而AngularJs的模型对象就是$scope。所以AngularJs控制器知识$scope和视图之间的桥梁,它通过操作$scope对象来改变视图。下面代码演示了控制器的使用:
&!DOCTYPE html&
&html ng-app="mainApp"&
&meta http-equiv="Content-Type" content="text/ charset=utf-8" /&
&title&AngularJS 控制器演示&/title&
&script src="/uploads/rs/376/pbcx3e1z/angular.min.js"&
(function() {
// 创建模块
var mainApp = angular.module("mainApp", []);
mainApp.controller("cntoController", ["$scope", function ($scope) {
var defaultValue = "Learninghard 前端系列";
$scope.val = defaultV
$scope.click = function () {
$scope.val = defaultV
&h2&AngularJS 控制器演示&/h2&
&div ng-controller="cntoController"&
&div&&textarea ng-model="val"&&/textarea&&/div&
&div&{{val}}&/div&
&div&&button ng-click="click()"&重置&/button&&/div&
  在线预览效果:
  之所以说AngularJs框架=MVC+MVVM,是因为AngularJs除了支持双向绑定外(即MVVM特点),还支持路由。在之前介绍的KnockoutJs实现的SPA中,其中路由借用了Asp.net MVC中路由机制。有了AngularJs之后,我们Web前端页面完全可以不用Asp.net MVC来做了,完全可以使用AngularJs框架来做。
  单页Web应用由于没有后端URL资源定位的支持,需要自己实现URL资源定位。AngularJs使用浏览器URL"#"后的字符串来定位资源。路由机制并非在AngularJS核心文件内,你需要另外加入angular-route.min.js脚本。并且创建mainApp模块的时候需要添加对ngRoute的依赖。
  下面让我们具体看看路由的例子来感受下AngularJs中路由的使用。具体的示例代码如下:
主页面&AngularJsRouteDemo.html
&!DOCTYPE html&
&html ng-app="mainApp" xmlns="http://www.w3.org/1999/xhtml"&
&meta http-equiv="Content-Type" content="text/ charset=utf-8" /&
&title&AngularJs路由演示&/title&
&script src="/uploads/rs/376/pbcx3e1z/angular.min.js"&&/script&
&script src="/uploads/rs/376/pbcx3e1z/angular-route.min.js"&&/script&
(function() {
// 设置当前模块依赖,&ngRoute&,用.NET的解就是给这个类库添加&ngRoute&引用
var mainApp = angular.module("mainApp", ['ngRoute']);
mainApp.config(['$routeProvider', function($routeProvider) {
// 路由配置
var route = $routeP
// 指定URL为&/& 控制器:&listController&,模板:&route-list.html&
route.when('/list', { controller: 'listController', templateUrl: 'route-list.html' });
// 注意&/view/:id& 中的 &:id& 用于捕获参数ID
route.when('/view/:id', { controller: 'viewController', templateUrl: 'route-view.html' });
route.when("/", { redirectTo: '/list' });
route.otherwise({ redirectTo: '/list' });
//创建一个提供数据的服务器
mainApp.factory("service", function() {
var list = [
{ id: 1, title: "博客园", url: "" },
{ id: 2, title: "知乎", url: "" },
{ id: 3, title: "codeproject", url: "/" },
{ id: 4, title: "stackoverflow", url: "/" }
return function(id) {
//假如ID为无效值返回所有
var t = 0;
//匹配返回的项目
angular.forEach(list, function(v, i) {
if (v.id == id) t =
return list[t];
// 创建控制器 listController,注入提供数据服务
mainApp.controller("listController", ["$scope", "service", function($scope, service) {
//获取所有数据
$scope.list = service();
// 创建查看控制器 viewController, 注意应为需要获取URL ID参数 我们多设置了一个 依赖注入参数 &$routeParams& 通过它获取传入的 ID参数
mainApp.controller("viewController", ["$scope", "service", '$routeParams', function($scope, service, $routeParams) {
$scope.model = service($routeParams.id || 0) || {};
&div&&a href="#/list"&列表&/a&&/div&
&div ng-view&
列表页面&route-list.html
&ul ng-repeat="item in list"&
&li&&a href="#view/{{item.id}}"&{{item.title}}&/a&&/li&
详细页面 route-view.html
&div&网站ID:{{model.id}}&/div&
&div&网站名称:&a href="{{model.url}}" rel="nofollow"&{{model.title}}&/a&&/div&
&div&访问地址:{{model.url}}&/div&
  在线预览地址:
3.5 自定义指令
&  前面我们已经介绍过指令了。除了AngularJs内置的指令外,我们也可以自定义指令来供我们程序使用。
如果我们在程序中需要对DOM操作的话,我们可以使用指令来完成。下面让我们来看下一个全选复选框的自定义指令的实现:
&!DOCTYPE html&
&html ng-app="mainApp" xmlns="http://www.w3.org/1999/xhtml"&
&meta http-equiv="Content-Type" content="text/ charset=utf-8" /&
&title&AngularJs 指令演示&/title&
&script src="/uploads/rs/376/pbcx3e1z/jquery-1.10.2.min.js"&&/script&
&script src="/uploads/rs/376/pbcx3e1z/angular.min.js"&&/script&
(function(){
var mainApp = angular.module("mainApp", []);
//创建一个提供数据的服务器
mainApp.factory("service", function () {
var list = [
{ id: 1, title: "博客园", url: "" },
{ id: 2, title: "知乎", url: "" },
{ id: 3, title: "codeproject", url: "/" },
{ id: 4, title: "stackoverflow", url: "/" }
return function (id) {
//假如ID为无效值返回所有
var t = 0;
//匹配返回的项目
angular.forEach(list, function (v, i) {
if (v.id == id) t =
return list[t];
mainApp.directive('imCheck', [function () {
restrict: 'A',
replace: false,
link: function (scope, element) {
var all = "thead input[type='checkbox']";
var item = "tbody input[type='checkbox']";
//当点击选择所有项目
element.on("change", all, function () {
var o = $(this).prop("checked");
var tds = element.find(item);
tds.each(function (i, check) {
$(check).prop("checked", o);
//子项修改时的超值
element.on("change", item, function () {
var o = $(this).prop("checked");
var isChecked =
element.find(item).each(function () {
if (!$(this).prop("checked")) {
isChecked =
element.find(all).prop("checked", o && isChecked);
mainApp.controller("dectController", ['$scope', 'service', function ($scope, service) {
$scope.list = service();
&h2&AngularJs 指令演示&/h2&
&table ng-controller="dectController" im-check&
&th&&input type="checkbox"&选择&/th&
&th&网站ID&/th&
&th&网站名称&/th&
&th&链接地址&/th&
&tr ng-repeat="item in list"&
&td&&input type="checkbox"&&/td&
&td&{{item.id}}&/td&
&td&{{item.title}}&/td&
&td&{{item.url}}&/td&
  演示效果:
&  在上面的路由例子和自定义指令中都有用到AngularJs中的服务。我理解AngularJs的服务主要是封装请求数据的内容。就如.NET解决方案的层次结构中的Services层。然后AngularJs中的服务一个很重要的一点是:服务是单例的。一个服务在AngularJS应用中只会被注入实例化一次,并贯穿整个生命周期,与控制器进行通信。即控制器操作$scope对象来改变视图,如果控制器需要请求数据的话,则是调用服务来请求数据的,而服务获得数据可以通过Http服务(AngularJS内置的服务)来请求后端的Web API来获得所需要的数据。
 AngularJS系统内置的服务以$开头,我们也可以自己定义一个服务。定义服务的方式有如下几种:
使用系统内置的$provide服务
使用Module的factory方法
使用Module的service方法
  在前面的例子我们都是以factory方法创建服务的,接下来演示下如何使用$provide服务来创建一个服务,具体的代码如下所示:
&!DOCTYPE html&
&html ng-app="mainApp" xmlns="http://www.w3.org/1999/xhtml"&
&meta http-equiv="Content-Type" content="text/ charset=utf-8" /&
&title&AngularJs 指令演示&/title&
&script src="/uploads/rs/376/pbcx3e1z/jquery-1.10.2.min.js"&&/script&
&script src="/uploads/rs/376/pbcx3e1z/angular.min.js"&&/script&
(function(){
var mainApp = angular.module("mainApp", []).config(['$provide', function($provide){
// 使用系统内置的$provide服务来创建一个提供数据的服务器
$provide.factory("service", function () {
var list = [
{ id: 1, title: "博客园", url: "" },
{ id: 2, title: "知乎", url: "" },
{ id: 3, title: "codeproject", url: "/" },
{ id: 4, title: "stackoverflow", url: "/" }
return function (id) {
//假如ID为无效值返回所有
var t = 0;
//匹配返回的项目
angular.forEach(list, function (v, i) {
if (v.id == id) t =
return list[t];
mainApp.directive('imCheck', [function () {
restrict: 'A',
replace: false,
link: function (scope, element) {
var all = "thead input[type='checkbox']";
var item = "tbody input[type='checkbox']";
//当点击选择所有项目
element.on("change", all, function () {
var o = $(this).prop("checked");
var tds = element.find(item);
tds.each(function (i, check) {
$(check).prop("checked", o);
//子项修改时的超值
element.on("change", item, function () {
var o = $(this).prop("checked");
var isChecked =
element.find(item).each(function () {
if (!$(this).prop("checked")) {
isChecked =
element.find(all).prop("checked", o && isChecked);
mainApp.controller("dectController", ['$scope', 'service', function ($scope, service) {
$scope.list = service();
&h2&AngularJs 指令演示&/h2&
&table ng-controller="dectController" im-check&
&th&&input type="checkbox"&选择&/th&
&th&网站ID&/th&
&th&网站名称&/th&
&th&链接地址&/th&
&tr ng-repeat="item in list"&
&td&&input type="checkbox"&&/td&
&td&{{item.id}}&/td&
&td&{{item.title}}&/td&
&td&{{item.url}}&/td&
  具体的运行效果与上面的效果一样。
3.7 过滤器
&  AngularJs过滤器就是用来格式化数据的,包括排序,筛选、转化数据等操作。下面代码创建了一个反转过滤器。
&!DOCTYPE html&
&html ng-app="mainApp" xmlns="http://www.w3.org/1999/xhtml"&
&meta http-equiv="Content-Type" content="text/ charset=utf-8" /&
&title&AngularJs 过滤器演示&/title&
&script src="/uploads/rs/376/pbcx3e1z/angular.min.js"&&/script&
(function () {
var mainApp = angular.module("mainApp", []);
// 定义反转过滤器,过滤器用来格式化数据(转化,排序,筛选等操作)。
mainApp.filter('reverse', function() {
return function(input, uppercase) {
input = input || '';
var out = "";
for (var i = 0; i & input. i++) {
out = input.charAt(i) +
if (uppercase) {
out = out.toUpperCase();
mainApp.controller("filterController", ['$scope', function($scope) {
$scope.greeting = "AngularJs";
&div ng-controller="filterController"&
&input ng-model="greeting" type="text"&&br&
No filter: {{greeting}}&br&
Reverse: {{greeting|reverse}}&br&
Reverse + uppercase: {{greeting|reverse:true}}&br&
  具体的运行效果:
3.8 前端模块化开发
  前面例子中的实现方式并不是我们在实际开发中推荐的方式,因为上面的例子都是把所有的前端逻辑都放在一个Html文件里面,这不利于后期的维护。一旦业务逻辑一复杂,这个Html文件将会变得复杂,导致跟踪问题和fix bug难度变大。在后端开发过程中,我们经常讲职责单一,将功能相似的代码放在一起。前端开发也同样可以这样做。对应的模块化框架有:RequireJs、SeaJs等。
也可以使用AngularJs内置的模块化来更好地组织代码结构。具体的代码请到本文结尾进行下载。这里给出一张采用模块化开发的截图:
&  到这里,本文的所有内容就结束了,在后面的一篇文章中,我将分享使用AngularJs实现一个简易的权限管理系统。
  更多内容参考:
  本文所有源码下载:
即使是一小步也想与你分享问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
我的问题是,还有哪些框架是MVVM模式的?
请详细介绍一下框架的特点
其实我真正想知道的是,MVVM包括什么?有什么必须具备的特征?是否必须即时?后端是否有这样的东西?
希望就MVVM展开讨论
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
使用Object.defineProperties、 VBScript、 Object.observe,纯事件驱动,兼容IE6,DOM的兼容性处理可与jQuery媲美,体积少
早期的四大MVVM框架,都有大公司引衔:
google出品,思想来自flex,IoC, 脏检测,自定义标签,受限于绑定数量,一般不能超过2000个,入门容易上手难,大量避不开的概念
原来是苹果公司的内部项目,使用Object.defineProperties, 体型庞大,MVVM只是其很少一部分
微软出品,使用函数偷龙转凤,最短编辑长度算法实现DOM的同步,兼容IE6,实现高超,但源码极其难读
微软出品,使用Object.defineProperties,一个庞大的UI库
这一两年冒出来的:
facebook出品,带来virtual dom的革命性概念,受限于视图的规模
API比较精致
使用定时间同步
使用Object.defineProperties实现同步,实现精致,但功能薄弱
最近一个月才冒出来的新东西,网易推出的JS框架,自称AngularJS与React的合体
在知乎又刚刚听说一个,用TypeScript写的
分享到微博?
你好!看起来你挺喜欢这个内容,但是你还没有注册帐号。 当你创建了帐号,我们能准确地追踪你关注的问题,在有新答案或内容的时候收到网页和邮件通知。还能直接向作者咨询更多细节。如果上面的内容有帮助,记得点赞 (????)? 表示感谢。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
扫扫下载 Appvue,angular,avalon这三种MVVM框架之间有什么优缺点? - 博客频道 - CSDN.NET
zhouwangling_的专栏
分类:AngularJS
Vue.js@尤雨溪老师写的一个用于创建 web 交互界面的库,是一个精简的 MVVM。从技术角度讲,Vue.js 专注于 MVVM 模型的ViewModel层。它通过双向数据绑定把View层和Model层连接了起来。实际的 DOM 封装和输出格式都被抽象为了Directives和Filters。Vue.js和其他库相比是一个小而美的库,作者的主要目的是通过一个尽量简单的 API 产生可反映的数据绑定和可组合的视图组件,感觉作者的思路非常清晰。
简单:官方文档很清晰,比 Angular 简单易学。
快速:异步批处理方式更新 DOM。
组合:用解耦的、可复用的组件组合你的应用程序。
紧凑:~18kb min+gzip,且无依赖。
强大:表达式 & 无需声明依赖的可推导属性 (computed properties)。
对模块友好:可以通过 NPM、Bower 或 Duo 安装,不强迫你所有的代码都遵循 Angular 的各种规定,使用场景更加灵活。
新生儿:Vue.js是一个新的项目,日发布的0.10.0 Release
Candidate版本,目前github上面最新的是0.11.4版本,没有angular那么成熟。
影响度不是很大:google了一下,有关于Vue.js多样性或者说丰富性少于其他一些有名的库。
不支持IE8:哈哈不过AngularJS 1.3也抛弃了对IE8的支持,但是@司徒正美老师的avalon是支持IE6+的,应该下了很多努力去优化。这一点对于那些需要支持IE8的项目就不好了,不过这也是web前端开发的一个趋势,像IE低版本就应该退出历史舞台了,通过改变我们的前端思维,而不是顺应那些使用老版本而不去升级的人。@玉伯老师就说过一句话,我觉得说的非常好“这年头,支持IE6、7
早就不再是特性,而是耻辱。努力推动支付宝全面不支持 IE6、7,期待更多兄弟加盟”。
AngularJS最近很火,追随者也很多。Superheroic JavaScript MVW Framework
官方说得很朴素:“完全使用JavaScript编写的客户端技术。同其他历史悠久的Web技术(HTML、CSS和JavaScript)配合使用,使Web应用开发比以往更简单、更快捷“。当你学习它的时候,我相信你会被它的很多新特效所吸引。
动态视图:以前从来没有想过js可以如此扩展HTML的属性,但是AngularJs做到了,它替我们静态的HTML加了很多扩展性功能,有一种让HTML由死变活的感觉。
完善:是一个比较完善的前端MVW框架,包含模板,数据双向绑定,路由,模块化,服务,依赖注入等所有功能,模板功能强大丰富,并且是声明式的,自带了丰富的
Angular 指令。
Google维护:AngularJS有Google来维护,无疑有了一个强大的后台,对于推广和维护明显比Vue.js和avalon有优势,社区也非常活泼,能够很好促进它的发展。
AngularJS & Ionic:Ionic: Advanced HTML5 Hybrid Mobile App
Framework,这俩就是一个好基友,Ionic通过用AngularJS为了创建一个框架,最适合开发的丰富和强大的应用程序。上次于知乎答了一个相关问题:
汤威的回答,详细可以见这里。
大而全:学习起来有难度,对于我来讲学习曲线很曲折,比较难理解一些。
推翻重写:前段时候逛社区发现AngularJS2.0会把之前的推翻重写,两个框架的改变很大,基本是两个框架了,等于是说等到2.0出来后又需要从头开始,不过又说回来,@徐飞老师的[翻译]有关Angular
2.0的一切 · Issue #8 · xufei/blog · GitHub这篇文章很好说明了AngularJS2.0的变化。
不支持IE8以下,貌似2.0变得只支持移动端了,等到出来后再看吧。
Avalon.js是@司徒正美老师所写的个简单易用迷你的MVVM框架,它最早发布于,为解决同一业务逻辑存在各种视图呈现而开发出来的。常常可以看到老师推广他的Avalon.js,出了很多教程,无疑对国内学习Avalon.js的人提供了巨大方便。
在HTML中添加绑定,在JS中用avalon.define定义ViewModel,再调用avalon.scan方法,它就能动了!
(其他MVVM框架,KnockoutJS(IE6), AngularJS(IE9), EmberJS(IE8),
WinJS(IE9) ),另有avalon.mobile,它可以更高效地运行于IE10等新版本浏览器中
没有任何依赖 不到5000行,压缩后不到50KiB
支持管道符风格的过滤函数,方便格式化输出
局部刷新的颗粒度已细化到一个文本节点,特性节点
要操作的节点,在第一次扫描就与视图刷新函数相绑定,并缓存起来,因此没有选择器出场的余地。 让DOM操作的代码近乎绝迹
使用类似CSS的重叠覆盖机制,让各个ViewModel分区交替地渲染页面
节点移除时,智能卸载对应的视图刷新函数,节约内存
操作数据即操作DOM,对ViewModel的操作都会同步到View与Model去
自带AMD模块加载器,省得与其他加载器进行整合。
对数组的过滤没有angular那么方面,avalon的过滤器只能用于ms-text, ms-html
没有英文文档,宣传受到限制(许多人也误把我在博客园的入门教程当成官网)
OniUI的皮肤不够好看,许多人说要配合boostrap,但社区还没有人主动站出来做这事 原文出处:
vue,angular,avalon这三种MVVM框架之间有什么优缺点
zhouwangling_
排名:千里之外
(1)(2)(9)(1)(1)(4)(1)(1)(1)posts - 48,&
comments - 570,&
trackbacks - 0
最近前端圈子里面,发现大家都在热炒概念,什么knockout,angularJs,都被捧成神了,鄙人不才,最近心情也不好,特地写这篇文章来找骂
写代码的码农都知道,Java社区虽然不是一个提出分层思想的,确实贯彻的最好的,如今是个Java开发都不会不知道SSH的开发模式,从MVC到MVVM的概念的热炒,其实真没什么技术进步
(如果你觉得本文言辞激烈,过于愤世嫉俗,实在看不下去,欢迎移步另一位园友的分层进化史科普文章)&
先看什么是MVVM
View一般就是我们平常说的HTML文本的Js模板,里面可以嵌入一些js模板的代码,比如Mustache,比如jstl类似的模板伪代码
ViewModule层里面就是我们对于这个视图区域的一切js可视业务逻辑,举个例子,比如图片走马灯特效,比如表单按钮点击提交,这些自定义事件的注册和处理逻辑都写在ViewModule里面了
Module就更简单了,就是对于纯数据的处理,比如增删改查,与后台CGI做交互
那么什么是MVVM框架呢??一般他们都是这么做的
1.& 定义一串所谓的伪模板代码,例如通过className标注,或者自定义tag的方式,将一段html文本区域给标注声明起来,意思就是喊一嗓子,&喂,兄弟们,这块地方我占了,要拉屎去别处拉去&
2.& 通过类似jstl之类lamda表达式,来做js模板,&拜托伙计,天堂有路你不走,非要自己搞一套,你就不能暴露接口让大家用自己的模板语言,比如Mustache或者jtpl吗?&
3.& 很傻比的封装一串自己的所谓数据模块组件,与不同类型的数据源做数据传输和适配,一般都不会分层很清晰,加入后台数据字段改了,写框架的都没脑子的,从来不做数据字段的自定义适配(举个例子,原来后台传递的字段是person.userName,现在改成了小写,person.username,你就傻逼的去吧模板再改一下吧,其实要解决这个问题,非常简单,在MVVM层中引入一层DO,领域对象层,Module到DO之间还有一层转换就可以搞定这个问题)
4.& 非不暴露自己的自定义事件模型,就是那个观察者模式啦,自己乱七八招在页面上绑定一堆form change之类的事件,以实现View与Module的单向绑定
5.& 所谓的双向绑定,也就是OOP语言中早被烂透了的getter,setter模型,ES5+可以用defineProperty,低版本就需要自己在js object赋值的时间做写死代码方式的处理了
我们再来看细节
1. 双向绑定
号称是最难理解的地方,其实是框架的作者根本就没理解Java社区对于软件开发分层理解的精髓
标准的数据驱动开发,应该如上图所示,在一个View的生命周期内,一个ViewModule会管理一个DomainObject(业务模型),一个DO可能包括多个Module数据模型,一个Module可能来自多个数据源,而不是想很多所谓的MVVM框架那样强迫一个M来一个数据源
按照上图标准分层方式来划分的好处,在于,逻辑清晰,Module层粒度够细,可以被多次复用
DO层与VM层View层属于一一对应关系,方便对数据做增删改查的同步
每一层应该是独立的,非一定要使用MVVM框架的紧耦合,可以用自己使用不同的js插件或者模块实现MVVM
我们抛弃框架,单纯的看数据,其实我们要解决的问题很简单
a) 当DO对象属性放生变化时候,通知View更新
b) 当View上表单值放生变化时,通知DO更新,并异步通知队列同步到数据源
先来看问题a,这个最简单,DO是一个基本的Javascript Object,我们在View上的模板显示是这个Object.property,
改变一个Object对象的方式无非几种,一种是
a) 显示Object.property = &我是傻逼&
b) xxxx.methodName(Object, &property&, &我是傻逼&)
c) xxxx.merge(Object, {&property&: &我是傻逼&})
如果是a的情况,ES5+,可以通过设置Object.defefineProperty(&property&,{set: functiono(){},get:function(){}}),来做赋值和取值的监控触发
对于IE8一下,因为js不支持运算符重载,所以暂时没有好的办法,所以如果只考虑移动端的话,直接defineProperty就全部搞定,如果是要考虑PC的话,就不建议开发者使用直接赋值的方式,参考java的开发模式,也是推荐OOP时候,使用set方式赋值,而不是直接=赋值
当然了,如果你非要兼容IE8一下的话,用定时器做轮训,配合for in 反射,通过脏数据与原始备份对比的方法也是一种办法,不过这种办法在当前页面非常耗性能,由于IE8一下不支持多线程,HTML5 worker,如果未来flash 插件支持多线程的话,倒是可以用js和flash插件做线程交互的方式做脏数据检测
如果是b的情况,那就太简单了,在methodName里面触发对于该属性修改的回调即可,如何注册回调呢,首先我们要实现一个类似Dom Event的自定义对象的Event模型,然后通过类似Dom Event的注册事件方式,注册观察者,订阅事件,当执行了methodName时候,发送消息,通知所有订阅者执行回调
如果是c的情况,类似b一样处理
这样一看,双向数据绑定的问题就非常简单的解决了
我们再来看另外一个MVVM的问题,非简单数据模型,复合数据模型(DO的属性值不是一个string,而是一个Object,且这个Object可能还嵌套多层Obejct的时候)的处理办法,这个一般的MVVM框架直接不考虑,或者通过长字段名的方式绕过这个问题
这个问题是这样的,早在10几年前,java structs框架流行的时候就出现了,当一个表单,出现需要对两个Java Bean做update操作时候,一个bean是user,一个bean是成绩
对应的表单字段名,就是 user表.name,user表.id,score表.point,
在struct2里面,处理逻辑是把 &点&作为特殊符号,在做form序列化时候,非包含点的字段的值都是string,包含点的字段是一个Object,比如刚才的form序列化之后结果就是 { user: {id :&& , name: &&}, score: {id: &&, point: &&}}
同理在MVVM实现时,也是一样,认为点是分割对象的关键字,这样我们就可以实现把多个对象嵌套到View模板里面,实现复合Object的双向映射
最后一个问题,也就是高级MVVM编程里面必须要面对的问题,就是自定义事件的广播和冒泡,我看过大多数的MVVM框架,对于广播,这块有部分实现了,但是对于冒泡一个都没实现
其实这个真的不是很复杂的问题,事件广播,这个最简单,三岁小孩都能写,我们在注册回调时候,不是有一个事件队列吗,在回调时候,通过特殊标记位,控制是否继续扩散广播,还是执行完毕终止即可
而自定义事件的冒泡要骚骚复杂一些,他是由于OOP编程里面的继承和包含关系引申而来的,我们先说包含关系,前面说了MVVM框架里面,都会声明一块地方为VM控制区域,一般垃圾的框架都不会考虑,VM嵌套的情况,因为图简单吗
但是实际开发过程中,你会遇到很多这种情况,就是VM复用的问题,一般都是发现使用了MVVM框架之后,发现VM定义的太大,没法复用,如果要复用VM就又发现VM定义的太小,出现需要VM嵌套的情况没法用
其实简单,我们知道DOM事件是有冒泡的,VM同理,只要在自定义事件模型里面定义了VM的父子关系,或者同级关联关系,即可实现VM的自定义事件的广播和冒泡,另外也解决了VM复用的问题,可以让代码颗粒度更小
另外那种,声明式编程这种老掉牙的概念就真的别在吵了,还记得10几年前的structs的tag吗,js圈子里面这种通过自定义tag,自定义className,自定义属性,挂载js来自定识别执行逻辑的例子大把皆是,还是建议广大前端开发,不要浮躁,多像java社区学习,多多从根本上了解分层理念的精髓,不要听了吹牛逼,听风就是雨,还是多了解原理才是真理啊
最近心情很不好,股票大跌,公司的事情你懂的,写这篇文档纯属没事找事,欢迎广大道友开骂,来陪我大战三百回合
阅读(...) 评论()

我要回帖

更多关于 微信号怎么添加好友 的文章

 

随机推荐