Pages: 2/282 First page Previous page 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Next page Final page [ View by Articles | List ]
Feb 8
Feb 8
本文目的
我们来看一个小例子,在一个ASP.NET MVC项目中创建一个控制器Home,只有一个Index:


创建对应的强类型视图


运行一下,如果你的RP不是非常不好的情况下,会出现下面的结果:

Highslide JS

生成的是一个Email的链接。看一下email部分对应的html源文件:


对于不求甚解的人来说,这很正常啊,正常的就像1+1=2一样。但对于勤学好问的同学来说,问题来了。

为什么生成的是一个email链接,不是一个纯文本?

因为我用DataType指明了它是email!

那DataType是如何指导Model生成html的?

如果你对这些问题感兴趣,请你看下去。



Model的兄弟--ModelMetadata
      在介绍Model如何能在View中正常显示之前,不得不提一下他的兄弟ModelMetadata这个类。ModelMetadata实现对Model的一些特征进行描述(如Model的类型、Model的值,Model要显示的模板 ),并且实现了对Model的所有属性值进行描述(递归结构)。有了这个兄弟,Model才能知道如何在View中正常显示【注意:这里特指的是用HtmlHelper的系列扩展方法(如Display/DiaplayFor/EditorFor等)方法在View中显示。如果你是在View中直接取Model的值用html显示,你可以暂不用关心ModelMetadata。但!!不要觉得这样你就不用了解ModelMetadata了,因为MVC中还有一个核心与它息息相关---Model绑定与验证,所以我建议你还是先认识一下这位好兄弟】,让我们来看看这个兄弟长什么样:


      然而在MVC中默认使用的却不是这个类,而是它的子类CachedDataAnnotationsModelMetadata(其实中间还隔着一个CachedModelMetadata类,因为该类只是做了简单的封装,为了方便读者理解,在此省略)。CachedDataAnnotationsModelMetadata做的最主要的一件事情就是通过一系列的Compute函数得到Model上注解特性的值,并把这些值赋值到对应的属性。如下:


      注意代码中两个红色的部分,把Model的注解特性存在PrototypeCache里面,这样就可以通过反射得到注解特性的值了。比如文章开始处的DemoModel的属性Email对应的CachedDataAnnotationsModelMetadata对象中 DataTypeName最终被赋值为“EmailAddress”,等介绍完下一位重量级人物后,会详解具体调用过程。

ModelMetadata的创建者ModelMetadataProvider
我们还要来认识一位重量级的人物:ModelMetadata的创建者:


      它是一个纯抽象类。该类的第一级子类非常重要,看一下代码:


      注意红色的部分,正是因为有这样一个处理,用户就可以通过自已自定义扩展实现IMetadataAware接口,对ModelMetadata进行再加工处理。



      根据上面ModelMetadata讲解,我们知道,MVC中默认使用的是CachedDataAnnotationsModelMetadata这个类,于是对应ModelMetadataProvider的最终子类CachedDataAnnotationsModelMetadataProvider。

      当外部想通过GetMetadataForType来得到ModelMetadata时,内部会调用CreateMetadata,再根据原型模式调用CreateMetadataPrototype或CraeteMetadataFromPrototype实现最终创建过程:


       同MVC的路由表RouteTable一样,ModelMetadataProvider也有一个静态的ModelMetadataProviders变量Current来提供默认的ModelMetadataProvider。简化代码如下:


终极解密
知道了这两位重量级的大员后,现在我们回到文章开始的代码:

Html.DisplayFor(model => model.Email)
当View中执行这句时,执行HtmlHelper的扩展函数,正式进入漫长的生成MvcString旅程:
Highslide JS
http://www.cnblogs.com/DotCpp/

     【注意,这个图中代码是经过N重简化而来,实际调用流程复杂无比(全是在TemplateHelpers中跳转),函数参数多如牛毛,实在不忍让大家看的痛苦】

      红色线是程序执行的主流程,后来的执行主场景都是在TemplateHelpers里面完成。

      从黄色线可以看出ModelMetadata是通过调用ModelMetadata本身的静态函数FromLambdExpression--->GetMetadataFromProvider,最终由ModelMetadataProviders完成创建。

     再来看看桔黄色部分。MVC中有一个DefaultDisplayTemplates的类,存储了诸如Boolean/String/Html/Email等等数据类型的模板,MVC最终根据ViewData中的ModelMetadata.DataType的值找到对应的模板,最终完成HTML字符串的输出,作为WebViewPage.ExecutePageHierarchy的一部分(WebViewPage请参看:仅此一文让你明白ASP.NET MVC 之View的显示(仅此一文系列二))。



结语
      本文只是用了ModelMetadata的一个DataType属性做为例子,让你了解在Model中添加注解特性是如何被ModelMetadata使用的。还有其它很多Model注解特性(如ReadOnlyAttribute/RequiredAttribute/UIHintAttribute等等)都和该原理类似。

      其实ModelMetadata在view显示中的作用是有限的,因为很多开发人员都不喜欢用这种前台显示方式,尤其随着json的大量使用,与JQUERY等前台的完美结合。但它有属于它的舞台----Model绑定与验证,敬请期待!

     希望新手看的明白,老手多提意见。如果你觉得对你有帮助,请让更多人知道它:)
Feb 7
问题:
Quotation

项目上线后发现一个问题,项目记录流水的时间是取自本地的时间new Date(),之前一直正常,最近发现异常
经过日志发现时终端设备时区设置异常,但诡异的是终端APPrequest提交的时间戳是正常的……
撸一撸chun
日志中显示记录流水时间是:2017-02-07 08:16:55,为伦敦时间,
而正确的时间应该是2017/2/7 16:16:55,这就导致终端APP界面显示异常,
但request提交的是时间转换的时间戳:Math.round(new Date("2017-02-07 08:16:55".replace(/-/g, '/')).getTime()/1000)


why

什么是时间戳(timestamp)?它和时区(timezone)又有什么关系?初学者可能一开始很难搞懂时间戳这个概念,就像这期《程序员的日常》漫画中的主人公一样。

Highslide JS
漫画注释

从漫画中举的例子来看,这里的时间戳,指的就是Unix时间戳(Unix timestamp)。它也被称为Unix时间(Unix time)、POSIX时间(POSIX time),是一种时间表示方式,定义为从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数。因此,严格来说,不管你处在地球上的哪个地方,任意时间点的时间戳都是相同的。这点有利于线上和客户端分布式应用统一追踪时间信息。

Unix时间戳不仅被使用在Unix系统、类Unix系统中,也在许多其他操作系统中被广泛采用。但是,这并不意味着目前的时间戳规范会一直持续使用下去。 因为到2038年1月19日时,Unix时间戳就会因为32位内存溢出(32-bit overflow)而无法继续使用。因此,在这一天之前,上千万的网络应用要么采用新的时间戳规范,要么迁移到64位系统,后者可以给时间戳争取“一点”时间。


Jan 5

let no="u0000u0000u0000u0000u0000u0000u0000Ou0000u0000u0000u0000u0000u0000u0000u0000"
no = no.replace(/\u0000/g,"");

  \u0000是unicode表示的一个特殊字符,也就是二进制的0,在c里面用这个字符作为字符串结束的标志。
正是因为这个原因,造成调用某些方法的时候字符串被截断。例子:
<textarea id="ff"></textarea>
<script>
var x = 'xxx\u0000yyy';
alert(x);
alert(x.length);
var elm = document.getElementByIdx('ff');
elm.value = x;
y = x.replace('\u0000', ' ');
alert(y);
alert(y == 'xxx\u0000yyy');
alert(y == 'xxx yyy');
alert(elm.value.length);
alert(elm.value == 'xxx\u0000yyy');
alert(elm.value == 'xxx yyy);
</script>
本身声明这个字符串的时候是可以接受\u0000的,所以长度什么的都对
但是通过alert调用的时候,字符串就被截断,认为到\u0000就结束了
同样当作一个字符串赋值给一个textarea的时候,也被截断了(IE6)。
对于firefox,不被截断,textarea.value的值就是'xxx\u0000yyy'
Dec 22
使用AJAX封装HTTPS请求,对request数据进行JavaScript加密库Crypto-JS加密,对于response数据库进行解密,可以参考:AES(高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准)
参考文档:
https://www.npmjs.com/package/crypto-js
https://my.oschina.net/jack230230/blog/69826
Dec 22
HybridAPP中,H5页面在ios系统中页面会被拖动,出现webview的底部颜色,引入此插件完美解决问题,不依赖任何第三方库!如果页面中有需要滚动的div元素,增加css样式-webkit-overflow-scrolling: touch;即可
,请访问:https://github.com/freedomdebug/iNoBounce
Oct 17
Vue.js 是用于构建交互式的 Web 界面的库。它提供了 MVVM 数据绑定和一个可组合的组件系统,具有简单、灵活的 API。从技术上讲, Vue.js 集中在 MVVM 模式上的视图模型层,并通过双向数据绑定连接视图和模型。实际的 DOM 操作和输出格式被抽象出来成指令和过滤器。相比其它的 MVVM 框架,Vue.js 更容易上手。

Vue.js 是一个用于创建 Web 交互界面的库。它让你通过简单而灵活的 API 创建由数据驱动的 UI 组件。

适用人群
即便您已经熟悉了一些这类的库或框架,我们还是推荐您继续阅读接下来的概览,因为您对它们的认识也许和它们在 Vue.js 语境下的定义不尽相同。

学习前提
Vue.js 的 API 是参考了 AngularJS、KnockoutJS、Ractive.js、Rivets.js。所以建议学习前,对上述 4 个框架系统做些了解。

Vue.js是一个在谷歌的哥们用了一段时间angularjs之后甚感不爽,例如脏watch,factory,service,provider之类不清晰,然后自己也diy了一把,基于观测者模式,指令,filter重新造另一个轮子,当然这个轮子能否持续下去还要看社会是否会持续火热了
Oct 11
一、service引导

刚开始学习Angular的时候,经常被误解和被初学者问到的组件是 service(), factory(), 和 provide()这几个方法之间的差别。This is where we'll start the twenty-five days of Angular calendar.

二、service

在Angular里面,services作为单例对象在需要到的时候被创建,只有在应用生命周期结束的时候(关闭浏览器)才会被清除。而controllers在不需要的时候就会被销毁了。

这就是为什么使用controllers在应用里面传递数据不可靠的原因,特别是使用routing的时候。Services are designed to be the glue between controllers, the minions of data, the slaves of functionality, the worker-bees of our application(就是说services在应用的controllers、 方法、数据之前起到了很关键的作用)



现在我们开始看怎么创建service。每个方法我们都会看到下面两个一样的参数:

name-我们要定义的service的名字

function-service方法

他们都创建了相同的底层对象类型。实例化后,他们都创建了一个service,这些对象没有什么功能上的差别。

1、factory()

Angular里面创建service最简单的方式是使用factory()方法。


factory()让我们通过返回一个包含service方法和数据的对象来定义一个service。在service方法里面我们可以注入services,比如 $http 和 $q等。


在应用里面使用factory()方法

在应用里面可以很容易地使用factory ,需要到的时候简单地注入就可以了


什么时候使用factory()方法

在service里面当我们仅仅需要的是一个方法和数据的集合且不需要处理复杂的逻辑的时候,factory()是一个非常不错的选择。

注意:需要使用.config()来配置service的时候不能使用factory()方法

2、service()
service()通过构造函数的方式让我们创建service,我们可以使用原型模式替代javaScript原始的对象来定义service。

和factory()方法一样我们也可以在函数的定义里面看到服务的注入


这里的功能和使用factory()方法的方式一样,service()方法会持有构造函数创建的对象。

在应用里面使用service()方法



什么时候适合使用service()方法

service()方法很适合使用在功能控制比较多的service里面

注意:需要使用.config()来配置service的时候不能使用service()方法


3、provider()

provider()是创建service最底层的方式,这也是唯一一个可以使用.config()方法配置创建service的方法

不像上面提到的方法那样,我们在定义的this.$get()方法里面进行依赖注入


在应用里面使用provider()方法

为了给service进行配置,我们可以将provider注入到.config()方法里面


这样我们就可以和其他方式一样在应用里面使用这个service了


什么时候使用provider()方法

当我们希望在应用开始前对service进行配置的时候就需要使用到provider()。比如,我们需要配置services在不同的部署环境里面(开发,演示,生产)使用不同的后端处理的时候就可以使用到了

当我们打算发布开源provider()也是首选创建service的方法,这样就可以使用配置的方式来配置services而不是将配置数据硬编码写到代码里面。

还可以看看这篇翻译:http://www.oschina.net/translate/top-10-mistakes-angularjs-developers-make



点击查看完整的代码:https://gist.github.com/auser/7743235
Pages: 2/282 First page Previous page 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Next page Final page [ View by Articles | List ]